Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
7a1b2794
Commit
7a1b2794
authored
8 years ago
by
danh-arm
Committed by
GitHub
8 years ago
Browse files
Options
Download
Plain Diff
Merge pull request #702 from jeenu-arm/psci-node-hw-state
Support for PSCI NODE_HW_STATE
parents
368d4ebf
3cc17aae
master
v2.5
v2.5-rc1
v2.5-rc0
v2.4
v2.4-rc2
v2.4-rc1
v2.4-rc0
v2.3
v2.3-rc2
v2.3-rc1
v2.3-rc0
v2.2
v2.2-rc2
v2.2-rc1
v2.2-rc0
v2.1
v2.1-rc1
v2.1-rc0
v2.0
v2.0-rc0
v1.6
v1.6-rc1
v1.6-rc0
v1.5
v1.5-rc3
v1.5-rc2
v1.5-rc1
v1.5-rc0
v1.4
v1.4-rc0
v1.3
v1.3_rc2
v1.3_rc1
v1.3-rc0
arm_cca_v0.2
arm_cca_v0.1
No related merge requests found
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
docs/firmware-design.md
+1
-1
docs/firmware-design.md
docs/porting-guide.md
+14
-0
docs/porting-guide.md
include/lib/psci/psci.h
+16
-0
include/lib/psci/psci.h
include/plat/arm/css/common/css_def.h
+10
-0
include/plat/arm/css/common/css_def.h
include/plat/arm/css/common/css_pm.h
+1
-0
include/plat/arm/css/common/css_pm.h
lib/psci/psci_main.c
+31
-0
lib/psci/psci_main.c
lib/psci/psci_private.h
+1
-0
lib/psci/psci_private.h
lib/psci/psci_setup.c
+2
-0
lib/psci/psci_setup.c
plat/arm/board/fvp/fvp_pm.c
+38
-1
plat/arm/board/fvp/fvp_pm.c
plat/arm/board/juno/juno_pm.c
+3
-2
plat/arm/board/juno/juno_pm.c
plat/arm/css/common/css_pm.c
+39
-1
plat/arm/css/common/css_pm.c
plat/arm/css/common/css_scpi.c
+69
-0
plat/arm/css/common/css_scpi.c
plat/arm/css/common/css_scpi.h
+28
-1
plat/arm/css/common/css_scpi.h
with
253 additions
and
6 deletions
+253
-6
docs/firmware-design.md
View file @
7a1b2794
...
@@ -716,7 +716,7 @@ required support.
...
@@ -716,7 +716,7 @@ required support.
|
`PSCI_FEATURES`
| Yes | |
|
`PSCI_FEATURES`
| Yes | |
|
`CPU_FREEZE`
| No | |
|
`CPU_FREEZE`
| No | |
|
`CPU_DEFAULT_SUSPEND`
| No | |
|
`CPU_DEFAULT_SUSPEND`
| No | |
|
`
CPU
_HW_STATE`
|
No
| |
|
`
NODE
_HW_STATE`
|
Yes
*
| |
|
`SYSTEM_SUSPEND`
| Yes
*
| |
|
`SYSTEM_SUSPEND`
| Yes
*
| |
|
`PSCI_SET_SUSPEND_MODE`
| No | |
|
`PSCI_SET_SUSPEND_MODE`
| No | |
|
`PSCI_STAT_RESIDENCY`
| Yes
*
| |
|
`PSCI_STAT_RESIDENCY`
| Yes
*
| |
...
...
This diff is collapsed.
Click to expand it.
docs/porting-guide.md
View file @
7a1b2794
...
@@ -1832,6 +1832,20 @@ This function can also be used in case the platform wants to support local
...
@@ -1832,6 +1832,20 @@ This function can also be used in case the platform wants to support local
power state encoding for
`power_state`
parameter of PSCI_STAT_COUNT/RESIDENCY
power state encoding for
`power_state`
parameter of PSCI_STAT_COUNT/RESIDENCY
APIs as described in Section 5.18 of [PSCI].
APIs as described in Section 5.18 of [PSCI].
#### plat_psci_ops.get_node_hw_state()
This is an optional function. If implemented this function is intended to return
the power state of a node (identified by the first parameter, the
`MPIDR`
) in
the power domain topology (identified by the second parameter,
`power_level`
),
as retrieved from a power controller or equivalent component on the platform.
Upon successful completion, the implementation must map and return the final
status among
`HW_ON`
,
`HW_OFF`
or
`HW_STANDBY`
. Upon encountering failures, it
must return either
`PSCI_E_INVALID_PARAMS`
or
`PSCI_E_NOT_SUPPORTED`
as
appropriate.
Implementations are not expected to handle
`power_levels`
greater than
`PLAT_MAX_PWR_LVL`
.
3.
6 Interrupt Management framework (in BL31)
3.
6 Interrupt Management framework (in BL31)
----------------------------------------------
----------------------------------------------
BL31 implements an Interrupt Management Framework (IMF) to manage interrupts
BL31 implements an Interrupt Management Framework (IMF) to manage interrupts
...
...
This diff is collapsed.
Click to expand it.
include/lib/psci/psci.h
View file @
7a1b2794
...
@@ -78,6 +78,8 @@
...
@@ -78,6 +78,8 @@
#define PSCI_SYSTEM_OFF 0x84000008
#define PSCI_SYSTEM_OFF 0x84000008
#define PSCI_SYSTEM_RESET 0x84000009
#define PSCI_SYSTEM_RESET 0x84000009
#define PSCI_FEATURES 0x8400000A
#define PSCI_FEATURES 0x8400000A
#define PSCI_NODE_HW_STATE_AARCH32 0x8400000d
#define PSCI_NODE_HW_STATE_AARCH64 0xc400000d
#define PSCI_SYSTEM_SUSPEND_AARCH32 0x8400000E
#define PSCI_SYSTEM_SUSPEND_AARCH32 0x8400000E
#define PSCI_SYSTEM_SUSPEND_AARCH64 0xc400000E
#define PSCI_SYSTEM_SUSPEND_AARCH64 0xc400000E
#define PSCI_STAT_RESIDENCY_AARCH32 0x84000010
#define PSCI_STAT_RESIDENCY_AARCH32 0x84000010
...
@@ -199,6 +201,17 @@ typedef enum {
...
@@ -199,6 +201,17 @@ typedef enum {
AFF_STATE_ON_PENDING
=
2
AFF_STATE_ON_PENDING
=
2
}
aff_info_state_t
;
}
aff_info_state_t
;
/*
* These are the power states reported by PSCI_NODE_HW_STATE API for the
* specified CPU. The definitions of these states can be found in Section 5.15.3
* of PSCI specification (ARM DEN 0022C).
*/
typedef
enum
{
HW_ON
=
0
,
HW_OFF
=
1
,
HW_STANDBY
=
2
}
node_hw_state_t
;
/*
/*
* Macro to represent invalid affinity level within PSCI.
* Macro to represent invalid affinity level within PSCI.
*/
*/
...
@@ -293,6 +306,7 @@ typedef struct plat_psci_ops {
...
@@ -293,6 +306,7 @@ typedef struct plat_psci_ops {
int
(
*
translate_power_state_by_mpidr
)(
u_register_t
mpidr
,
int
(
*
translate_power_state_by_mpidr
)(
u_register_t
mpidr
,
unsigned
int
power_state
,
unsigned
int
power_state
,
psci_power_state_t
*
output_state
);
psci_power_state_t
*
output_state
);
int
(
*
get_node_hw_state
)(
u_register_t
mpidr
,
unsigned
int
power_level
);
}
plat_psci_ops_t
;
}
plat_psci_ops_t
;
/*******************************************************************************
/*******************************************************************************
...
@@ -330,6 +344,8 @@ int psci_affinity_info(u_register_t target_affinity,
...
@@ -330,6 +344,8 @@ int psci_affinity_info(u_register_t target_affinity,
int
psci_migrate
(
u_register_t
target_cpu
);
int
psci_migrate
(
u_register_t
target_cpu
);
int
psci_migrate_info_type
(
void
);
int
psci_migrate_info_type
(
void
);
long
psci_migrate_info_up_cpu
(
void
);
long
psci_migrate_info_up_cpu
(
void
);
int
psci_node_hw_state
(
u_register_t
target_cpu
,
unsigned
int
power_level
);
int
psci_features
(
unsigned
int
psci_fid
);
int
psci_features
(
unsigned
int
psci_fid
);
void
__dead2
psci_power_down_wfi
(
void
);
void
__dead2
psci_power_down_wfi
(
void
);
void
psci_arch_setup
(
void
);
void
psci_arch_setup
(
void
);
...
...
This diff is collapsed.
Click to expand it.
include/plat/arm/css/common/css_def.h
View file @
7a1b2794
...
@@ -148,5 +148,15 @@
...
@@ -148,5 +148,15 @@
/* Trusted mailbox base address common to all CSS */
/* Trusted mailbox base address common to all CSS */
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE
/*
* Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP
* command
*/
#define CSS_CLUSTER_PWR_STATE_ON 0
#define CSS_CLUSTER_PWR_STATE_OFF 3
#define CSS_CPU_PWR_STATE_ON 1
#define CSS_CPU_PWR_STATE_OFF 0
#define CSS_CPU_PWR_STATE(state, n) (((state) >> (n)) & 1)
#endif
/* __CSS_DEF_H__ */
#endif
/* __CSS_DEF_H__ */
This diff is collapsed.
Click to expand it.
include/plat/arm/css/common/css_pm.h
View file @
7a1b2794
...
@@ -45,5 +45,6 @@ void __dead2 css_system_off(void);
...
@@ -45,5 +45,6 @@ void __dead2 css_system_off(void);
void
__dead2
css_system_reset
(
void
);
void
__dead2
css_system_reset
(
void
);
void
css_cpu_standby
(
plat_local_state_t
cpu_state
);
void
css_cpu_standby
(
plat_local_state_t
cpu_state
);
void
css_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
);
void
css_get_sys_suspend_power_state
(
psci_power_state_t
*
req_state
);
int
css_node_hw_state
(
u_register_t
mpidr
,
unsigned
int
power_level
);
#endif
/* __CSS_PM_H__ */
#endif
/* __CSS_PM_H__ */
This diff is collapsed.
Click to expand it.
lib/psci/psci_main.c
View file @
7a1b2794
...
@@ -295,6 +295,31 @@ long psci_migrate_info_up_cpu(void)
...
@@ -295,6 +295,31 @@ long psci_migrate_info_up_cpu(void)
return
resident_cpu_mpidr
;
return
resident_cpu_mpidr
;
}
}
int
psci_node_hw_state
(
u_register_t
target_cpu
,
unsigned
int
power_level
)
{
int
rc
;
/* Validate target_cpu */
rc
=
psci_validate_mpidr
(
target_cpu
);
if
(
rc
!=
PSCI_E_SUCCESS
)
return
PSCI_E_INVALID_PARAMS
;
/* Validate power_level against PLAT_MAX_PWR_LVL */
if
(
power_level
>
PLAT_MAX_PWR_LVL
)
return
PSCI_E_INVALID_PARAMS
;
/*
* Dispatch this call to platform to query power controller, and pass on
* to the caller what it returns
*/
assert
(
psci_plat_pm_ops
->
get_node_hw_state
);
rc
=
psci_plat_pm_ops
->
get_node_hw_state
(
target_cpu
,
power_level
);
assert
((
rc
>=
HW_ON
&&
rc
<=
HW_STANDBY
)
||
rc
==
PSCI_E_NOT_SUPPORTED
||
rc
==
PSCI_E_INVALID_PARAMS
);
return
rc
;
}
int
psci_features
(
unsigned
int
psci_fid
)
int
psci_features
(
unsigned
int
psci_fid
)
{
{
unsigned
int
local_caps
=
psci_caps
;
unsigned
int
local_caps
=
psci_caps
;
...
@@ -378,6 +403,9 @@ u_register_t psci_smc_handler(uint32_t smc_fid,
...
@@ -378,6 +403,9 @@ u_register_t psci_smc_handler(uint32_t smc_fid,
case
PSCI_MIG_INFO_UP_CPU_AARCH32
:
case
PSCI_MIG_INFO_UP_CPU_AARCH32
:
return
psci_migrate_info_up_cpu
();
return
psci_migrate_info_up_cpu
();
case
PSCI_NODE_HW_STATE_AARCH32
:
return
psci_node_hw_state
(
x1
,
x2
);
case
PSCI_SYSTEM_SUSPEND_AARCH32
:
case
PSCI_SYSTEM_SUSPEND_AARCH32
:
return
psci_system_suspend
(
x1
,
x2
);
return
psci_system_suspend
(
x1
,
x2
);
...
@@ -422,6 +450,9 @@ u_register_t psci_smc_handler(uint32_t smc_fid,
...
@@ -422,6 +450,9 @@ u_register_t psci_smc_handler(uint32_t smc_fid,
case
PSCI_MIG_INFO_UP_CPU_AARCH64
:
case
PSCI_MIG_INFO_UP_CPU_AARCH64
:
return
psci_migrate_info_up_cpu
();
return
psci_migrate_info_up_cpu
();
case
PSCI_NODE_HW_STATE_AARCH64
:
return
psci_node_hw_state
(
x1
,
x2
);
case
PSCI_SYSTEM_SUSPEND_AARCH64
:
case
PSCI_SYSTEM_SUSPEND_AARCH64
:
return
psci_system_suspend
(
x1
,
x2
);
return
psci_system_suspend
(
x1
,
x2
);
...
...
This diff is collapsed.
Click to expand it.
lib/psci/psci_private.h
View file @
7a1b2794
...
@@ -68,6 +68,7 @@
...
@@ -68,6 +68,7 @@
define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \
define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \
define_psci_cap(PSCI_MIG_AARCH64) | \
define_psci_cap(PSCI_MIG_AARCH64) | \
define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \
define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \
define_psci_cap(PSCI_NODE_HW_STATE_AARCH64) | \
define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64) | \
define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64) | \
define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64) | \
define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64) | \
define_psci_cap(PSCI_STAT_COUNT_AARCH64))
define_psci_cap(PSCI_STAT_COUNT_AARCH64))
...
...
This diff is collapsed.
Click to expand it.
lib/psci/psci_setup.c
View file @
7a1b2794
...
@@ -263,6 +263,8 @@ int psci_setup(uintptr_t mailbox_ep)
...
@@ -263,6 +263,8 @@ int psci_setup(uintptr_t mailbox_ep)
psci_caps
|=
define_psci_cap
(
PSCI_SYSTEM_OFF
);
psci_caps
|=
define_psci_cap
(
PSCI_SYSTEM_OFF
);
if
(
psci_plat_pm_ops
->
system_reset
)
if
(
psci_plat_pm_ops
->
system_reset
)
psci_caps
|=
define_psci_cap
(
PSCI_SYSTEM_RESET
);
psci_caps
|=
define_psci_cap
(
PSCI_SYSTEM_RESET
);
if
(
psci_plat_pm_ops
->
get_node_hw_state
)
psci_caps
|=
define_psci_cap
(
PSCI_NODE_HW_STATE_AARCH64
);
#if ENABLE_PSCI_STAT
#if ENABLE_PSCI_STAT
psci_caps
|=
define_psci_cap
(
PSCI_STAT_RESIDENCY_AARCH64
);
psci_caps
|=
define_psci_cap
(
PSCI_STAT_RESIDENCY_AARCH64
);
...
...
This diff is collapsed.
Click to expand it.
plat/arm/board/fvp/fvp_pm.c
View file @
7a1b2794
...
@@ -287,6 +287,42 @@ static void __dead2 fvp_system_reset(void)
...
@@ -287,6 +287,42 @@ static void __dead2 fvp_system_reset(void)
panic
();
panic
();
}
}
static
int
fvp_node_hw_state
(
u_register_t
target_cpu
,
unsigned
int
power_level
)
{
unsigned
int
psysr
;
int
ret
;
/*
* The format of 'power_level' is implementation-defined, but 0 must
* mean a CPU. We also allow 1 to denote the cluster
*/
if
(
power_level
!=
ARM_PWR_LVL0
&&
power_level
!=
ARM_PWR_LVL1
)
return
PSCI_E_INVALID_PARAMS
;
/*
* Read the status of the given MPDIR from FVP power controller. The
* power controller only gives us on/off status, so map that to expected
* return values of the PSCI call
*/
psysr
=
fvp_pwrc_read_psysr
(
target_cpu
);
if
(
psysr
==
PSYSR_INVALID
)
return
PSCI_E_INVALID_PARAMS
;
switch
(
power_level
)
{
case
ARM_PWR_LVL0
:
ret
=
(
psysr
&
PSYSR_AFF_L0
)
?
HW_ON
:
HW_OFF
;
break
;
case
ARM_PWR_LVL1
:
ret
=
(
psysr
&
PSYSR_AFF_L1
)
?
HW_ON
:
HW_OFF
;
break
;
default:
assert
(
0
);
}
return
ret
;
}
/*******************************************************************************
/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform layer will take care of registering the handlers with PSCI.
* platform layer will take care of registering the handlers with PSCI.
...
@@ -301,5 +337,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
...
@@ -301,5 +337,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
.
system_off
=
fvp_system_off
,
.
system_off
=
fvp_system_off
,
.
system_reset
=
fvp_system_reset
,
.
system_reset
=
fvp_system_reset
,
.
validate_power_state
=
arm_validate_power_state
,
.
validate_power_state
=
arm_validate_power_state
,
.
validate_ns_entrypoint
=
arm_validate_ns_entrypoint
.
validate_ns_entrypoint
=
arm_validate_ns_entrypoint
,
.
get_node_hw_state
=
fvp_node_hw_state
};
};
This diff is collapsed.
Click to expand it.
plat/arm/board/juno/juno_pm.c
View file @
7a1b2794
/*
/*
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2015
-2016
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -88,5 +88,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
...
@@ -88,5 +88,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
.
validate_power_state
=
juno_validate_power_state
,
.
validate_power_state
=
juno_validate_power_state
,
.
validate_ns_entrypoint
=
arm_validate_ns_entrypoint
,
.
validate_ns_entrypoint
=
arm_validate_ns_entrypoint
,
.
get_sys_suspend_power_state
=
css_get_sys_suspend_power_state
,
.
get_sys_suspend_power_state
=
css_get_sys_suspend_power_state
,
.
translate_power_state_by_mpidr
=
juno_translate_power_state_by_mpidr
.
translate_power_state_by_mpidr
=
juno_translate_power_state_by_mpidr
,
.
get_node_hw_state
=
css_node_hw_state
};
};
This diff is collapsed.
Click to expand it.
plat/arm/css/common/css_pm.c
View file @
7a1b2794
...
@@ -298,6 +298,43 @@ void css_get_sys_suspend_power_state(psci_power_state_t *req_state)
...
@@ -298,6 +298,43 @@ void css_get_sys_suspend_power_state(psci_power_state_t *req_state)
req_state
->
pwr_domain_state
[
i
]
=
ARM_LOCAL_STATE_OFF
;
req_state
->
pwr_domain_state
[
i
]
=
ARM_LOCAL_STATE_OFF
;
}
}
/*******************************************************************************
* Handler to query CPU/cluster power states from SCP
******************************************************************************/
int
css_node_hw_state
(
u_register_t
mpidr
,
unsigned
int
power_level
)
{
int
rc
,
element
;
unsigned
int
cpu_state
,
cluster_state
;
/*
* The format of 'power_level' is implementation-defined, but 0 must
* mean a CPU. We also allow 1 to denote the cluster
*/
if
(
power_level
!=
ARM_PWR_LVL0
&&
power_level
!=
ARM_PWR_LVL1
)
return
PSCI_E_INVALID_PARAMS
;
/* Query SCP */
rc
=
scpi_get_css_power_state
(
mpidr
,
&
cpu_state
,
&
cluster_state
);
if
(
rc
!=
0
)
return
PSCI_E_INVALID_PARAMS
;
/* Map power states of CPU and cluster to expected PSCI return codes */
if
(
power_level
==
ARM_PWR_LVL0
)
{
/*
* The CPU state returned by SCP is an 8-bit bit mask
* corresponding to each CPU in the cluster
*/
element
=
mpidr
&
MPIDR_AFFLVL_MASK
;
return
CSS_CPU_PWR_STATE
(
cpu_state
,
element
)
==
CSS_CPU_PWR_STATE_ON
?
HW_ON
:
HW_OFF
;
}
else
{
assert
(
cluster_state
==
CSS_CLUSTER_PWR_STATE_ON
||
cluster_state
==
CSS_CLUSTER_PWR_STATE_OFF
);
return
cluster_state
==
CSS_CLUSTER_PWR_STATE_ON
?
HW_ON
:
HW_OFF
;
}
}
/*******************************************************************************
/*******************************************************************************
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* Export the platform handlers via plat_arm_psci_pm_ops. The ARM Standard
* platform will take care of registering the handlers with PSCI.
* platform will take care of registering the handlers with PSCI.
...
@@ -312,5 +349,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
...
@@ -312,5 +349,6 @@ const plat_psci_ops_t plat_arm_psci_pm_ops = {
.
system_off
=
css_system_off
,
.
system_off
=
css_system_off
,
.
system_reset
=
css_system_reset
,
.
system_reset
=
css_system_reset
,
.
validate_power_state
=
arm_validate_power_state
,
.
validate_power_state
=
arm_validate_power_state
,
.
validate_ns_entrypoint
=
arm_validate_ns_entrypoint
.
validate_ns_entrypoint
=
arm_validate_ns_entrypoint
,
.
get_node_hw_state
=
css_node_hw_state
};
};
This diff is collapsed.
Click to expand it.
plat/arm/css/common/css_scpi.c
View file @
7a1b2794
...
@@ -41,11 +41,18 @@
...
@@ -41,11 +41,18 @@
#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_SCP_COM_SHARED_MEM_BASE \
+ 0x100)
+ 0x100)
/* Header and payload addresses for commands from AP to SCP */
#define SCPI_CMD_HEADER_AP_TO_SCP \
#define SCPI_CMD_HEADER_AP_TO_SCP \
((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
((scpi_cmd_t *) SCPI_SHARED_MEM_AP_TO_SCP)
#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
#define SCPI_CMD_PAYLOAD_AP_TO_SCP \
((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
((void *) (SCPI_SHARED_MEM_AP_TO_SCP + sizeof(scpi_cmd_t)))
/* Header and payload addresses for responses from SCP to AP */
#define SCPI_RES_HEADER_SCP_TO_AP \
((scpi_cmd_t *) SCPI_SHARED_MEM_SCP_TO_AP)
#define SCPI_RES_PAYLOAD_SCP_TO_AP \
((void *) (SCPI_SHARED_MEM_SCP_TO_AP + sizeof(scpi_cmd_t)))
/* ID of the MHU slot used for the SCPI protocol */
/* ID of the MHU slot used for the SCPI protocol */
#define SCPI_MHU_SLOT_ID 0
#define SCPI_MHU_SLOT_ID 0
...
@@ -163,6 +170,68 @@ void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
...
@@ -163,6 +170,68 @@ void scpi_set_css_power_state(unsigned mpidr, scpi_power_state_t cpu_state,
scpi_secure_message_end
();
scpi_secure_message_end
();
}
}
/*
* Query and obtain CSS power state from SCP.
*
* In response to the query, SCP returns power states of all CPUs in all
* clusters of the system. The returned response is then filtered based on the
* supplied MPIDR. Power states of requested cluster and CPUs within are updated
* via. supplied non-NULL pointer arguments.
*
* Returns 0 on success, or -1 on errors.
*/
int
scpi_get_css_power_state
(
unsigned
int
mpidr
,
unsigned
int
*
cpu_state_p
,
unsigned
int
*
cluster_state_p
)
{
scpi_cmd_t
*
cmd
;
scpi_cmd_t
response
;
int
power_state
,
cpu
,
cluster
,
rc
=
-
1
;
/*
* Extract CPU and cluster membership of the given MPIDR. SCPI caters
* for only up to 0xf clusters, and 8 CPUs per cluster
*/
cpu
=
mpidr
&
MPIDR_AFFLVL_MASK
;
cluster
=
(
mpidr
>>
MPIDR_AFF1_SHIFT
)
&
MPIDR_AFFLVL_MASK
;
if
(
cpu
>=
8
||
cluster
>=
0xf
)
return
-
1
;
scpi_secure_message_start
();
/* Populate request headers */
cmd
=
memset
(
SCPI_CMD_HEADER_AP_TO_SCP
,
0
,
sizeof
(
*
cmd
));
cmd
->
id
=
SCPI_CMD_GET_CSS_POWER_STATE
;
/*
* Send message and wait for SCP's response
*/
scpi_secure_message_send
(
0
);
scpi_secure_message_receive
(
&
response
);
if
(
response
.
status
!=
SCP_OK
)
goto
exit
;
/* Validate SCP response */
if
(
!
CHECK_RESPONSE
(
response
,
cluster
))
goto
exit
;
/* Extract power states for required cluster */
power_state
=
*
(((
uint16_t
*
)
SCPI_RES_PAYLOAD_SCP_TO_AP
)
+
cluster
);
if
(
CLUSTER_ID
(
power_state
)
!=
cluster
)
goto
exit
;
/* Update power state via. pointers */
if
(
cluster_state_p
)
*
cluster_state_p
=
CLUSTER_POWER_STATE
(
power_state
);
if
(
cpu_state_p
)
*
cpu_state_p
=
CPU_POWER_STATE
(
power_state
);
rc
=
0
;
exit:
scpi_secure_message_end
();
return
rc
;
}
uint32_t
scpi_sys_power_state
(
scpi_system_state_t
system_state
)
uint32_t
scpi_sys_power_state
(
scpi_system_state_t
system_state
)
{
{
scpi_cmd_t
*
cmd
;
scpi_cmd_t
*
cmd
;
...
...
This diff is collapsed.
Click to expand it.
plat/arm/css/common/css_scpi.h
View file @
7a1b2794
/*
/*
* Copyright (c) 2014-201
5
, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2014-201
6
, ARM Limited and Contributors. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
...
@@ -81,9 +81,34 @@ typedef uint32_t scpi_status_t;
...
@@ -81,9 +81,34 @@ typedef uint32_t scpi_status_t;
typedef
enum
{
typedef
enum
{
SCPI_CMD_SCP_READY
=
0x01
,
SCPI_CMD_SCP_READY
=
0x01
,
SCPI_CMD_SET_CSS_POWER_STATE
=
0x03
,
SCPI_CMD_SET_CSS_POWER_STATE
=
0x03
,
SCPI_CMD_GET_CSS_POWER_STATE
=
0x04
,
SCPI_CMD_SYS_POWER_STATE
=
0x05
SCPI_CMD_SYS_POWER_STATE
=
0x05
}
scpi_command_t
;
}
scpi_command_t
;
/*
* Macros to parse SCP response to GET_CSS_POWER_STATE command
*
* [3:0] : cluster ID
* [7:4] : cluster state: 0 = on; 3 = off; rest are reserved
* [15:8]: on/off state for individual CPUs in the cluster
*
* Payload is in little-endian
*/
#define CLUSTER_ID(_resp) ((_resp) & 0xf)
#define CLUSTER_POWER_STATE(_resp) (((_resp) >> 4) & 0xf)
/* Result is a bit mask of CPU on/off states in the cluster */
#define CPU_POWER_STATE(_resp) (((_resp) >> 8) & 0xff)
/*
* For GET_CSS_POWER_STATE, SCP returns the power states of every cluster. The
* size of response depends on the number of clusters in the system. The
* SCP-to-AP payload contains 2 bytes per cluster. Make sure the response is
* large enough to contain power states of a given cluster
*/
#define CHECK_RESPONSE(_resp, _clus) \
(_resp.size >= (((_clus) + 1) * 2))
typedef
enum
{
typedef
enum
{
scpi_power_on
=
0
,
scpi_power_on
=
0
,
scpi_power_retention
=
1
,
scpi_power_retention
=
1
,
...
@@ -101,6 +126,8 @@ extern void scpi_set_css_power_state(unsigned mpidr,
...
@@ -101,6 +126,8 @@ extern void scpi_set_css_power_state(unsigned mpidr,
scpi_power_state_t
cpu_state
,
scpi_power_state_t
cpu_state
,
scpi_power_state_t
cluster_state
,
scpi_power_state_t
cluster_state
,
scpi_power_state_t
css_state
);
scpi_power_state_t
css_state
);
int
scpi_get_css_power_state
(
unsigned
int
mpidr
,
unsigned
int
*
cpu_state_p
,
unsigned
int
*
cluster_state_p
);
uint32_t
scpi_sys_power_state
(
scpi_system_state_t
system_state
);
uint32_t
scpi_sys_power_state
(
scpi_system_state_t
system_state
);
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help