Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
kernel_linux
提交
0d0ffa94
K
kernel_linux
项目概览
OpenHarmony
/
kernel_linux
上一次同步 4 年多
通知
15
Star
8
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
kernel_linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
0d0ffa94
编写于
2月 01, 2013
作者:
W
Will Deacon
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-rmk/virt/psci' into for-arm-soc/virt/mach
上级
9e02e394
2bdd424f
变更
7
显示空白变更内容
内联
并排
Showing
7 changed file
with
338 addition
and
0 deletion
+338
-0
Documentation/devicetree/bindings/arm/psci.txt
Documentation/devicetree/bindings/arm/psci.txt
+55
-0
arch/arm/Kconfig
arch/arm/Kconfig
+10
-0
arch/arm/include/asm/opcodes-sec.h
arch/arm/include/asm/opcodes-sec.h
+24
-0
arch/arm/include/asm/opcodes.h
arch/arm/include/asm/opcodes.h
+1
-0
arch/arm/include/asm/psci.h
arch/arm/include/asm/psci.h
+36
-0
arch/arm/kernel/Makefile
arch/arm/kernel/Makefile
+1
-0
arch/arm/kernel/psci.c
arch/arm/kernel/psci.c
+211
-0
未找到文件。
Documentation/devicetree/bindings/arm/psci.txt
0 → 100644
浏览文件 @
0d0ffa94
* Power State Coordination Interface (PSCI)
Firmware implementing the PSCI functions described in ARM document number
ARM DEN 0022A ("Power State Coordination Interface System Software on ARM
processors") can be used by Linux to initiate various CPU-centric power
operations.
Issue A of the specification describes functions for CPU suspend, hotplug
and migration of secure software.
Functions are invoked by trapping to the privilege level of the PSCI
firmware (specified as part of the binding below) and passing arguments
in a manner similar to that specified by AAPCS:
r0 => 32-bit Function ID / return value
{r1 - r3} => Parameters
Note that the immediate field of the trapping instruction must be set
to #0.
Main node required properties:
- compatible : Must be "arm,psci"
- method : The method of calling the PSCI firmware. Permitted
values are:
"smc" : SMC #0, with the register assignments specified
in this binding.
"hvc" : HVC #0, with the register assignments specified
in this binding.
Main node optional properties:
- cpu_suspend : Function ID for CPU_SUSPEND operation
- cpu_off : Function ID for CPU_OFF operation
- cpu_on : Function ID for CPU_ON operation
- migrate : Function ID for MIGRATE operation
Example:
psci {
compatible = "arm,psci";
method = "smc";
cpu_suspend = <0x95c10000>;
cpu_off = <0x95c10001>;
cpu_on = <0x95c10002>;
migrate = <0x95c10003>;
};
arch/arm/Kconfig
浏览文件 @
0d0ffa94
...
@@ -1622,6 +1622,16 @@ config HOTPLUG_CPU
...
@@ -1622,6 +1622,16 @@ config HOTPLUG_CPU
Say Y here to experiment with turning CPUs off and on. CPUs
Say Y here to experiment with turning CPUs off and on. CPUs
can be controlled through /sys/devices/system/cpu.
can be controlled through /sys/devices/system/cpu.
config ARM_PSCI
bool "Support for the ARM Power State Coordination Interface (PSCI)"
depends on CPU_V7
help
Say Y here if you want Linux to communicate with system firmware
implementing the PSCI specification for CPU-centric power
management operations described in ARM document number ARM DEN
0022A ("Power State Coordination Interface System Software on
ARM processors").
config LOCAL_TIMERS
config LOCAL_TIMERS
bool "Use local timer interrupts"
bool "Use local timer interrupts"
depends on SMP
depends on SMP
...
...
arch/arm/include/asm/opcodes-sec.h
0 → 100644
浏览文件 @
0d0ffa94
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Copyright (C) 2012 ARM Limited
*/
#ifndef __ASM_ARM_OPCODES_SEC_H
#define __ASM_ARM_OPCODES_SEC_H
#include <asm/opcodes.h>
#define __SMC(imm4) __inst_arm_thumb32( \
0xE1600070 | (((imm4) & 0xF) << 0), \
0xF7F08000 | (((imm4) & 0xF) << 16) \
)
#endif
/* __ASM_ARM_OPCODES_SEC_H */
arch/arm/include/asm/opcodes.h
浏览文件 @
0d0ffa94
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
#define __ASM_ARM_OPCODES_H
#define __ASM_ARM_OPCODES_H
#ifndef __ASSEMBLY__
#ifndef __ASSEMBLY__
#include <linux/linkage.h>
extern
asmlinkage
unsigned
int
arm_check_condition
(
u32
opcode
,
u32
psr
);
extern
asmlinkage
unsigned
int
arm_check_condition
(
u32
opcode
,
u32
psr
);
#endif
#endif
...
...
arch/arm/include/asm/psci.h
0 → 100644
浏览文件 @
0d0ffa94
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Copyright (C) 2012 ARM Limited
*/
#ifndef __ASM_ARM_PSCI_H
#define __ASM_ARM_PSCI_H
#define PSCI_POWER_STATE_TYPE_STANDBY 0
#define PSCI_POWER_STATE_TYPE_POWER_DOWN 1
struct
psci_power_state
{
u16
id
;
u8
type
;
u8
affinity_level
;
};
struct
psci_operations
{
int
(
*
cpu_suspend
)(
struct
psci_power_state
state
,
unsigned
long
entry_point
);
int
(
*
cpu_off
)(
struct
psci_power_state
state
);
int
(
*
cpu_on
)(
unsigned
long
cpuid
,
unsigned
long
entry_point
);
int
(
*
migrate
)(
unsigned
long
cpuid
);
};
extern
struct
psci_operations
psci_ops
;
#endif
/* __ASM_ARM_PSCI_H */
arch/arm/kernel/Makefile
浏览文件 @
0d0ffa94
...
@@ -82,5 +82,6 @@ obj-$(CONFIG_DEBUG_LL) += debug.o
...
@@ -82,5 +82,6 @@ obj-$(CONFIG_DEBUG_LL) += debug.o
obj-$(CONFIG_EARLY_PRINTK)
+=
early_printk.o
obj-$(CONFIG_EARLY_PRINTK)
+=
early_printk.o
obj-$(CONFIG_ARM_VIRT_EXT)
+=
hyp-stub.o
obj-$(CONFIG_ARM_VIRT_EXT)
+=
hyp-stub.o
obj-$(CONFIG_ARM_PSCI)
+=
psci.o
extra-y
:=
$
(
head-y
)
vmlinux.lds
extra-y
:=
$
(
head-y
)
vmlinux.lds
arch/arm/kernel/psci.c
0 → 100644
浏览文件 @
0d0ffa94
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Copyright (C) 2012 ARM Limited
*
* Author: Will Deacon <will.deacon@arm.com>
*/
#define pr_fmt(fmt) "psci: " fmt
#include <linux/init.h>
#include <linux/of.h>
#include <asm/compiler.h>
#include <asm/errno.h>
#include <asm/opcodes-sec.h>
#include <asm/opcodes-virt.h>
#include <asm/psci.h>
struct
psci_operations
psci_ops
;
static
int
(
*
invoke_psci_fn
)(
u32
,
u32
,
u32
,
u32
);
enum
psci_function
{
PSCI_FN_CPU_SUSPEND
,
PSCI_FN_CPU_ON
,
PSCI_FN_CPU_OFF
,
PSCI_FN_MIGRATE
,
PSCI_FN_MAX
,
};
static
u32
psci_function_id
[
PSCI_FN_MAX
];
#define PSCI_RET_SUCCESS 0
#define PSCI_RET_EOPNOTSUPP -1
#define PSCI_RET_EINVAL -2
#define PSCI_RET_EPERM -3
static
int
psci_to_linux_errno
(
int
errno
)
{
switch
(
errno
)
{
case
PSCI_RET_SUCCESS
:
return
0
;
case
PSCI_RET_EOPNOTSUPP
:
return
-
EOPNOTSUPP
;
case
PSCI_RET_EINVAL
:
return
-
EINVAL
;
case
PSCI_RET_EPERM
:
return
-
EPERM
;
};
return
-
EINVAL
;
}
#define PSCI_POWER_STATE_ID_MASK 0xffff
#define PSCI_POWER_STATE_ID_SHIFT 0
#define PSCI_POWER_STATE_TYPE_MASK 0x1
#define PSCI_POWER_STATE_TYPE_SHIFT 16
#define PSCI_POWER_STATE_AFFL_MASK 0x3
#define PSCI_POWER_STATE_AFFL_SHIFT 24
static
u32
psci_power_state_pack
(
struct
psci_power_state
state
)
{
return
((
state
.
id
&
PSCI_POWER_STATE_ID_MASK
)
<<
PSCI_POWER_STATE_ID_SHIFT
)
|
((
state
.
type
&
PSCI_POWER_STATE_TYPE_MASK
)
<<
PSCI_POWER_STATE_TYPE_SHIFT
)
|
((
state
.
affinity_level
&
PSCI_POWER_STATE_AFFL_MASK
)
<<
PSCI_POWER_STATE_AFFL_SHIFT
);
}
/*
* The following two functions are invoked via the invoke_psci_fn pointer
* and will not be inlined, allowing us to piggyback on the AAPCS.
*/
static
noinline
int
__invoke_psci_fn_hvc
(
u32
function_id
,
u32
arg0
,
u32
arg1
,
u32
arg2
)
{
asm
volatile
(
__asmeq
(
"%0"
,
"r0"
)
__asmeq
(
"%1"
,
"r1"
)
__asmeq
(
"%2"
,
"r2"
)
__asmeq
(
"%3"
,
"r3"
)
__HVC
(
0
)
:
"+r"
(
function_id
)
:
"r"
(
arg0
),
"r"
(
arg1
),
"r"
(
arg2
));
return
function_id
;
}
static
noinline
int
__invoke_psci_fn_smc
(
u32
function_id
,
u32
arg0
,
u32
arg1
,
u32
arg2
)
{
asm
volatile
(
__asmeq
(
"%0"
,
"r0"
)
__asmeq
(
"%1"
,
"r1"
)
__asmeq
(
"%2"
,
"r2"
)
__asmeq
(
"%3"
,
"r3"
)
__SMC
(
0
)
:
"+r"
(
function_id
)
:
"r"
(
arg0
),
"r"
(
arg1
),
"r"
(
arg2
));
return
function_id
;
}
static
int
psci_cpu_suspend
(
struct
psci_power_state
state
,
unsigned
long
entry_point
)
{
int
err
;
u32
fn
,
power_state
;
fn
=
psci_function_id
[
PSCI_FN_CPU_SUSPEND
];
power_state
=
psci_power_state_pack
(
state
);
err
=
invoke_psci_fn
(
fn
,
power_state
,
entry_point
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_cpu_off
(
struct
psci_power_state
state
)
{
int
err
;
u32
fn
,
power_state
;
fn
=
psci_function_id
[
PSCI_FN_CPU_OFF
];
power_state
=
psci_power_state_pack
(
state
);
err
=
invoke_psci_fn
(
fn
,
power_state
,
0
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_cpu_on
(
unsigned
long
cpuid
,
unsigned
long
entry_point
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_CPU_ON
];
err
=
invoke_psci_fn
(
fn
,
cpuid
,
entry_point
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
int
psci_migrate
(
unsigned
long
cpuid
)
{
int
err
;
u32
fn
;
fn
=
psci_function_id
[
PSCI_FN_MIGRATE
];
err
=
invoke_psci_fn
(
fn
,
cpuid
,
0
,
0
);
return
psci_to_linux_errno
(
err
);
}
static
const
struct
of_device_id
psci_of_match
[]
__initconst
=
{
{
.
compatible
=
"arm,psci"
,
},
{},
};
static
int
__init
psci_init
(
void
)
{
struct
device_node
*
np
;
const
char
*
method
;
u32
id
;
np
=
of_find_matching_node
(
NULL
,
psci_of_match
);
if
(
!
np
)
return
0
;
pr_info
(
"probing function IDs from device-tree
\n
"
);
if
(
of_property_read_string
(
np
,
"method"
,
&
method
))
{
pr_warning
(
"missing
\"
method
\"
property
\n
"
);
goto
out_put_node
;
}
if
(
!
strcmp
(
"hvc"
,
method
))
{
invoke_psci_fn
=
__invoke_psci_fn_hvc
;
}
else
if
(
!
strcmp
(
"smc"
,
method
))
{
invoke_psci_fn
=
__invoke_psci_fn_smc
;
}
else
{
pr_warning
(
"invalid
\"
method
\"
property: %s
\n
"
,
method
);
goto
out_put_node
;
}
if
(
!
of_property_read_u32
(
np
,
"cpu_suspend"
,
&
id
))
{
psci_function_id
[
PSCI_FN_CPU_SUSPEND
]
=
id
;
psci_ops
.
cpu_suspend
=
psci_cpu_suspend
;
}
if
(
!
of_property_read_u32
(
np
,
"cpu_off"
,
&
id
))
{
psci_function_id
[
PSCI_FN_CPU_OFF
]
=
id
;
psci_ops
.
cpu_off
=
psci_cpu_off
;
}
if
(
!
of_property_read_u32
(
np
,
"cpu_on"
,
&
id
))
{
psci_function_id
[
PSCI_FN_CPU_ON
]
=
id
;
psci_ops
.
cpu_on
=
psci_cpu_on
;
}
if
(
!
of_property_read_u32
(
np
,
"migrate"
,
&
id
))
{
psci_function_id
[
PSCI_FN_MIGRATE
]
=
id
;
psci_ops
.
migrate
=
psci_migrate
;
}
out_put_node:
of_node_put
(
np
);
return
0
;
}
early_initcall
(
psci_init
);
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录