/******************************************************************************* * RockChip handler called when a power domain is about to be suspended. The * target_state encodes the power state that each level should transition to. ******************************************************************************/ void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state) { uint32_t lvl; plat_local_state_t lvl_state; int ret; if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) return; if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) rockchip_soc_sys_pwr_dm_suspend(); else rockchip_soc_cores_pwr_dm_suspend(); /* Prevent interrupts from spuriously waking up this cpu */ plat_rockchip_gic_cpuif_disable(); /* Perform the common cluster specific operations */ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) plat_cci_disable(); if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) return; for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { lvl_state = target_state->pwr_domain_state[lvl]; ret = rockchip_soc_hlvl_pwr_dm_suspend(lvl, lvl_state); if (ret == PSCI_E_NOT_SUPPORTED) break; } }
/******************************************************************************* * RockChip handler called when a power domain has just been powered on after * being turned off earlier. The target_state encodes the low power state that * each level has woken up from. ******************************************************************************/ void rockchip_pwr_domain_on_finish(const psci_power_state_t *target_state) { uint32_t lvl; plat_local_state_t lvl_state; int ret; assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { lvl_state = target_state->pwr_domain_state[lvl]; ret = rockchip_soc_hlvl_pwr_dm_on_finish(lvl, lvl_state); if (ret == PSCI_E_NOT_SUPPORTED) break; } rockchip_soc_cores_pwr_dm_on_finish(); /* Perform the common cluster specific operations */ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { /* Enable coherency if this cluster was off */ plat_cci_enable(); } /* Enable the gic cpu interface */ plat_rockchip_gic_pcpu_init(); /* Program the gic per-cpu distributor or re-distributor interface */ plat_rockchip_gic_cpuif_enable(); }
/******************************************************************************* * RockChip handler called when a power domain is about to be suspended. The * target_state encodes the power state that each level should transition to. ******************************************************************************/ void rockchip_pwr_domain_suspend(const psci_power_state_t *target_state) { uint32_t lvl; plat_local_state_t lvl_state; if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) return; if (rockchip_ops) { if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE && rockchip_ops->sys_pwr_dm_suspend) { rockchip_ops->sys_pwr_dm_suspend(); } else if (rockchip_ops->cores_pwr_dm_suspend) { rockchip_ops->cores_pwr_dm_suspend(); } } /* Prevent interrupts from spuriously waking up this cpu */ plat_rockchip_gic_cpuif_disable(); /* Perform the common cluster specific operations */ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) plat_cci_disable(); if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) return; if (!rockchip_ops || !rockchip_ops->hlvl_pwr_dm_suspend) return; for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { lvl_state = target_state->pwr_domain_state[lvl]; rockchip_ops->hlvl_pwr_dm_suspend(lvl, lvl_state); } }
/******************************************************************************* * RockChip handler called when a power domain is about to be turned off. The * target_state encodes the power state that each level should transition to. ******************************************************************************/ void rockchip_pwr_domain_off(const psci_power_state_t *target_state) { uint32_t lvl; plat_local_state_t lvl_state; assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); plat_rockchip_gic_cpuif_disable(); if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) plat_cci_disable(); if (!rockchip_ops || !rockchip_ops->cores_pwr_dm_off) return; rockchip_ops->cores_pwr_dm_off(); if (!rockchip_ops->hlvl_pwr_dm_off) return; for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { lvl_state = target_state->pwr_domain_state[lvl]; rockchip_ops->hlvl_pwr_dm_off(lvl, lvl_state); } }
static void __dead2 rockchip_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) { if ((RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) && (rockchip_ops)) { if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE && rockchip_ops->sys_pwr_down_wfi) rockchip_ops->sys_pwr_down_wfi(target_state); } psci_power_down_wfi(); }
/******************************************************************************* * RockChip handler called when a power domain has just been powered on after * having been suspended earlier. The target_state encodes the low power state * that each level has woken up from. * TODO: At the moment we reuse the on finisher and reinitialize the secure * context. Need to implement a separate suspend finisher. ******************************************************************************/ void rockchip_pwr_domain_suspend_finish(const psci_power_state_t *target_state) { uint32_t lvl; plat_local_state_t lvl_state; /* Nothing to be done on waking up from retention from CPU level */ if (RK_CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) return; /* Perform system domain restore if woken up from system suspend */ if (!rockchip_ops) goto comm_finish; if (RK_SYSTEM_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { if (rockchip_ops->sys_pwr_dm_resume) rockchip_ops->sys_pwr_dm_resume(); goto comm_finish; } if (rockchip_ops->hlvl_pwr_dm_resume) { for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { lvl_state = target_state->pwr_domain_state[lvl]; rockchip_ops->hlvl_pwr_dm_resume(lvl, lvl_state); } } if (rockchip_ops->cores_pwr_dm_resume) rockchip_ops->cores_pwr_dm_resume(); /* * Program the gic per-cpu distributor or re-distributor interface. * For sys power domain operation, resuming of the gic needs to operate * in rockchip_ops->sys_pwr_dm_resume, according to the sys power mode * implements. */ plat_rockchip_gic_cpuif_enable(); comm_finish: /* Perform the common cluster specific operations */ if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { /* Enable coherency if this cluster was off */ plat_cci_enable(); } }
/******************************************************************************* * RockChip handler called when a power domain is about to be turned off. The * target_state encodes the power state that each level should transition to. ******************************************************************************/ void rockchip_pwr_domain_off(const psci_power_state_t *target_state) { uint32_t lvl; plat_local_state_t lvl_state; int ret; assert(RK_CORE_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE); plat_rockchip_gic_cpuif_disable(); if (RK_CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) plat_cci_disable(); rockchip_soc_cores_pwr_dm_off(); for (lvl = MPIDR_AFFLVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { lvl_state = target_state->pwr_domain_state[lvl]; ret = rockchip_soc_hlvl_pwr_dm_off(lvl, lvl_state); if (ret == PSCI_E_NOT_SUPPORTED) break; } }