|
|
@ -26,6 +26,38 @@ |
|
|
|
#define SYSTEM_PWR_STATE(state) \ |
|
|
|
((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) |
|
|
|
|
|
|
|
#define PSTATE_WIDTH 4 |
|
|
|
#define PSTATE_MASK ((1 << PSTATE_WIDTH) - 1) |
|
|
|
|
|
|
|
#define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ |
|
|
|
(((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \ |
|
|
|
((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \ |
|
|
|
((lvl0_state) << (PSTATE_ID_SHIFT)) | \ |
|
|
|
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ |
|
|
|
((type) << PSTATE_TYPE_SHIFT)) |
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 hikey960_pwr_idle_states[] = { |
|
|
|
/* State-id - 0x001 */ |
|
|
|
MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, |
|
|
|
PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), |
|
|
|
/* State-id - 0x002 */ |
|
|
|
MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, |
|
|
|
PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), |
|
|
|
/* State-id - 0x003 */ |
|
|
|
MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, |
|
|
|
PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), |
|
|
|
/* State-id - 0x033 */ |
|
|
|
MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE, |
|
|
|
PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), |
|
|
|
0, |
|
|
|
}; |
|
|
|
|
|
|
|
#define DMAC_GLB_REG_SEC 0x694 |
|
|
|
#define AXI_CONF_BASE 0x820 |
|
|
|
|
|
|
@ -36,16 +68,21 @@ static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) |
|
|
|
unsigned long scr; |
|
|
|
unsigned int val = 0; |
|
|
|
|
|
|
|
assert(cpu_state == PLAT_MAX_RET_STATE); |
|
|
|
assert(cpu_state == PLAT_MAX_STB_STATE || |
|
|
|
cpu_state == PLAT_MAX_RET_STATE); |
|
|
|
|
|
|
|
scr = read_scr_el3(); |
|
|
|
|
|
|
|
/* Enable Physical IRQ and FIQ to wake the CPU*/ |
|
|
|
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); |
|
|
|
|
|
|
|
set_retention_ticks(val); |
|
|
|
if (cpu_state == PLAT_MAX_RET_STATE) |
|
|
|
set_retention_ticks(val); |
|
|
|
|
|
|
|
wfi(); |
|
|
|
clr_retention_ticks(val); |
|
|
|
|
|
|
|
if (cpu_state == PLAT_MAX_RET_STATE) |
|
|
|
clr_retention_ticks(val); |
|
|
|
|
|
|
|
/*
|
|
|
|
* Restore SCR to the original value, synchronisazion of |
|
|
@ -124,38 +161,34 @@ static void __dead2 hikey960_system_reset(void) |
|
|
|
int hikey960_validate_power_state(unsigned int power_state, |
|
|
|
psci_power_state_t *req_state) |
|
|
|
{ |
|
|
|
int pstate = psci_get_pstate_type(power_state); |
|
|
|
int pwr_lvl = psci_get_pstate_pwrlvl(power_state); |
|
|
|
unsigned int state_id; |
|
|
|
int i; |
|
|
|
|
|
|
|
assert(req_state); |
|
|
|
|
|
|
|
if (pwr_lvl > PLAT_MAX_PWR_LVL) |
|
|
|
return PSCI_E_INVALID_PARAMS; |
|
|
|
|
|
|
|
/* Sanity check the requested state */ |
|
|
|
if (pstate == PSTATE_TYPE_STANDBY) { |
|
|
|
/*
|
|
|
|
* It's possible to enter standby only on power level 0 |
|
|
|
* Ignore any other power level. |
|
|
|
*/ |
|
|
|
if (pwr_lvl != MPIDR_AFFLVL0) |
|
|
|
return PSCI_E_INVALID_PARAMS; |
|
|
|
|
|
|
|
req_state->pwr_domain_state[MPIDR_AFFLVL0] = |
|
|
|
PLAT_MAX_RET_STATE; |
|
|
|
} else { |
|
|
|
for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) |
|
|
|
req_state->pwr_domain_state[i] = |
|
|
|
PLAT_MAX_OFF_STATE; |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* We expect the 'state id' to be zero. |
|
|
|
* 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. |
|
|
|
*/ |
|
|
|
if (psci_get_pstate_id(power_state)) |
|
|
|
for (i = 0; !!hikey960_pwr_idle_states[i]; i++) { |
|
|
|
if (power_state == hikey960_pwr_idle_states[i]) |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
/* Return error if entry not found in the idle state array */ |
|
|
|
if (!hikey960_pwr_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 & PSTATE_MASK; |
|
|
|
state_id >>= PSTATE_WIDTH; |
|
|
|
} |
|
|
|
|
|
|
|
return PSCI_E_SUCCESS; |
|
|
|
} |
|
|
|
|
|
|
|