PSCI: Demonstrate support for composite power states

This patch adds support to the Juno and FVP ports for composite power states
with both the original and extended state-id power-state formats. Both the
platform ports use the recommended state-id encoding as specified in
Section 6.5 of the PSCI specification (ARM DEN 0022C). The platform build flag
ARM_RECOM_STATE_ID_ENC is used to include this support.

By default, to maintain backwards compatibility, the original power state
parameter format is used and the state-id field is expected to be zero.

Change-Id: Ie721b961957eaecaca5bf417a30952fe0627ef10
This commit is contained in:
Soby Mathew 2015-04-16 14:49:09 +01:00 committed by Achin Gupta
parent 38dce70f51
commit 2204afded5
6 changed files with 145 additions and 0 deletions

View File

@ -394,6 +394,14 @@ map is explained in the [Firmware Design].
this option, `arm_rotprivk_rsa.pem` must be specified as `ROT_KEY` when
creating the certificates.
* `ARM_RECOM_STATE_ID_ENC`: The PSCI1.0 specification recommends an encoding
for the construction of composite state-ID in the power-state parameter.
The existing PSCI clients currently do not support this encoding of
State-ID yet. Hence this flag is used to configure whether to use the
recommended State-ID encoding or not. The default value of this flag is 0,
in which case the platform is configured to expect NULL in the State-ID
field of power-state parameter.
#### ARM CSS platform specific build options
* `CSS_DETECT_PRE_1_7_0_SCP`: Boolean flag to detect SCP version

View File

@ -148,6 +148,35 @@ CASSERT(PLAT_PCPU_DATA_SIZE == sizeof(arm_cpu_data_t),
#endif /* IMAGE_BL31 */
#if ARM_RECOM_STATE_ID_ENC
/*
* Macros used to parse state information from State-ID if it is using the
* recommended encoding for State-ID.
*/
#define ARM_LOCAL_PSTATE_WIDTH 4
#define ARM_LOCAL_PSTATE_MASK ((1 << ARM_LOCAL_PSTATE_WIDTH) - 1)
/* Macros to construct the composite power state */
/* Make composite power state parameter till power level 0 */
#if PSCI_EXTENDED_STATE_ID
#define arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
(((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
#else
#define arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
(((lvl0_state) << PSTATE_ID_SHIFT) | \
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
((type) << PSTATE_TYPE_SHIFT))
#endif /* __PSCI_EXTENDED_STATE_ID__ */
/* Make composite power state parameter till power level 1 */
#define arm_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
(((lvl1_state) << ARM_LOCAL_PSTATE_WIDTH) | \
arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
#endif /* __ARM_RECOM_STATE_ID_ENC__ */
/* CCI utility functions */
void arm_cci_init(void);

View File

@ -49,6 +49,27 @@ typedef volatile struct mailbox {
unsigned long value __aligned(CACHE_WRITEBACK_GRANULE);
} mailbox_t;
#if ARM_RECOM_STATE_ID_ENC
/*
* The table storing the valid idle power states. Ensure that the
* array entries are populated in ascending order of state-id to
* enable us to use binary search during power state validation.
* The table must be terminated by a NULL entry.
*/
const unsigned int arm_pm_idle_states[] = {
/* State-id - 0x01 */
arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET,
ARM_PWR_LVL0, PSTATE_TYPE_STANDBY),
/* State-id - 0x02 */
arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF,
ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
/* State-id - 0x22 */
arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
0,
};
#endif
/*******************************************************************************
* Private FVP function to program the mailbox for a cpu before it is released
* from reset.

View File

@ -46,6 +46,23 @@ endif
# Process flags
$(eval $(call add_define,ARM_TSP_RAM_LOCATION_ID))
# For the original power-state parameter format, the State-ID can be encoded
# according to the recommended encoding or zero. This flag determines which
# State-ID encoding to be parsed.
ARM_RECOM_STATE_ID_ENC := 0
# If the PSCI_EXTENDED_STATE_ID is set, then the recommended state ID need to
# be used. Else throw a build error.
ifeq (${PSCI_EXTENDED_STATE_ID}, 1)
ifeq (${ARM_RECOM_STATE_ID_ENC}, 0)
$(error "Incompatible STATE_ID build option specified")
endif
endif
# Process ARM_RECOM_STATE_ID_ENC flag
$(eval $(call assert_boolean,ARM_RECOM_STATE_ID_ENC))
$(eval $(call add_define,ARM_RECOM_STATE_ID_ENC))
PLAT_INCLUDES += -Iinclude/common/tbbr \
-Iinclude/plat/arm/common \
-Iinclude/plat/arm/common/aarch64

View File

@ -31,8 +31,15 @@
#include <arch_helpers.h>
#include <assert.h>
#include <errno.h>
#include <plat_arm.h>
#include <psci.h>
#if ARM_RECOM_STATE_ID_ENC
extern unsigned int arm_pm_idle_states[];
#endif /* __ARM_RECOM_STATE_ID_ENC__ */
#if !ARM_RECOM_STATE_ID_ENC
/*******************************************************************************
* ARM standard platform handler called to check the validity of the power state
* parameter.
@ -74,3 +81,45 @@ int arm_validate_power_state(unsigned int power_state,
return PSCI_E_SUCCESS;
}
#else
/*******************************************************************************
* ARM standard platform handler called to check the validity of the power
* state parameter. The power state parameter has to be a composite power
* state.
******************************************************************************/
int arm_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
unsigned int state_id;
int i;
assert(req_state);
/*
* Currently we are using a linear search for finding the matching
* entry in the idle power state array. This can be made a binary
* search if the number of entries justify the additional complexity.
*/
for (i = 0; !!arm_pm_idle_states[i]; i++) {
if (power_state == arm_pm_idle_states[i])
break;
}
/* Return error if entry not found in the idle state array */
if (!arm_pm_idle_states[i])
return PSCI_E_INVALID_PARAMS;
i = 0;
state_id = psci_get_pstate_id(power_state);
/* Parse the State ID and populate the state info parameter */
while (state_id) {
req_state->pwr_domain_state[i++] = state_id &
ARM_LOCAL_PSTATE_MASK;
state_id >>= ARM_LOCAL_PSTATE_WIDTH;
}
return PSCI_E_SUCCESS;
}
#endif /* __ARM_RECOM_STATE_ID_ENC__ */

View File

@ -43,6 +43,27 @@
unsigned long wakeup_address;
#if ARM_RECOM_STATE_ID_ENC
/*
* The table storing the valid idle power states. Ensure that the
* array entries are populated in ascending order of state-id to
* enable us to use binary search during power state validation.
* The table must be terminated by a NULL entry.
*/
const unsigned int arm_pm_idle_states[] = {
/* State-id - 0x01 */
arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_RET,
ARM_PWR_LVL0, PSTATE_TYPE_STANDBY),
/* State-id - 0x02 */
arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_RUN, ARM_LOCAL_STATE_OFF,
ARM_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
/* State-id - 0x22 */
arm_make_pwrstate_lvl1(ARM_LOCAL_STATE_OFF, ARM_LOCAL_STATE_OFF,
ARM_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
0,
};
#endif
/*******************************************************************************
* Private function to program the mailbox for a cpu before it is released
* from reset.