diff options
Diffstat (limited to 'plat/nvidia/tegra/common/tegra_pm.c')
-rw-r--r-- | plat/nvidia/tegra/common/tegra_pm.c | 172 |
1 files changed, 48 insertions, 124 deletions
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c index 39dc42c5b..ec34a850d 100644 --- a/plat/nvidia/tegra/common/tegra_pm.c +++ b/plat/nvidia/tegra/common/tegra_pm.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -27,104 +28,13 @@ extern uint64_t tegra_bl31_phys_base; extern uint64_t tegra_sec_entry_point; -/* - * The following platform setup functions are weakly defined. They - * provide typical implementations that will be overridden by a SoC. - */ -#pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early -#pragma weak tegra_soc_cpu_standby -#pragma weak tegra_soc_pwr_domain_suspend -#pragma weak tegra_soc_pwr_domain_on -#pragma weak tegra_soc_pwr_domain_off -#pragma weak tegra_soc_pwr_domain_on_finish -#pragma weak tegra_soc_pwr_domain_power_down_wfi -#pragma weak tegra_soc_prepare_system_reset -#pragma weak tegra_soc_prepare_system_off -#pragma weak tegra_soc_get_target_pwr_state - -int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) -{ - return PSCI_E_NOT_SUPPORTED; -} - -int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) -{ - (void)cpu_state; - return PSCI_E_SUCCESS; -} - -int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) -{ - (void)target_state; - return PSCI_E_NOT_SUPPORTED; -} - -int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) -{ - (void)mpidr; - return PSCI_E_SUCCESS; -} - -int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) -{ - (void)target_state; - return PSCI_E_SUCCESS; -} - -int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) -{ - (void)target_state; - return PSCI_E_SUCCESS; -} - -int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) -{ - (void)target_state; - return PSCI_E_SUCCESS; -} - -int32_t tegra_soc_prepare_system_reset(void) -{ - return PSCI_E_SUCCESS; -} - -__dead2 void tegra_soc_prepare_system_off(void) -{ - ERROR("Tegra System Off: operation not handled.\n"); - panic(); -} - -plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, - const plat_local_state_t *states, - uint32_t ncpu) -{ - plat_local_state_t target = PLAT_MAX_OFF_STATE, temp; - uint32_t num_cpu = ncpu; - const plat_local_state_t *local_state = states; - - (void)lvl; - - assert(ncpu != 0U); - - do { - temp = *local_state; - if ((temp < target)) { - target = temp; - } - --num_cpu; - local_state++; - } while (num_cpu != 0U); - - return target; -} - /******************************************************************************* * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` * call to get the `power_state` parameter. This allows the platform to encode * the appropriate State-ID field within the `power_state` parameter which can * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. ******************************************************************************/ -void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) +static void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) { /* all affinities use system suspend state id */ for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { @@ -135,7 +45,7 @@ void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) /******************************************************************************* * Handler called when an affinity instance is about to enter standby. ******************************************************************************/ -void tegra_cpu_standby(plat_local_state_t cpu_state) +static void tegra_cpu_standby(plat_local_state_t cpu_state) { u_register_t saved_scr_el3; @@ -174,7 +84,7 @@ void tegra_cpu_standby(plat_local_state_t cpu_state) * Handler called when an affinity instance is about to be turned on. The * level and mpidr determine the affinity instance. ******************************************************************************/ -int32_t tegra_pwr_domain_on(u_register_t mpidr) +static int32_t tegra_pwr_domain_on(u_register_t mpidr) { return tegra_soc_pwr_domain_on(mpidr); } @@ -183,9 +93,12 @@ int32_t tegra_pwr_domain_on(u_register_t mpidr) * 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 tegra_pwr_domain_off(const psci_power_state_t *target_state) +static void tegra_pwr_domain_off(const psci_power_state_t *target_state) { (void)tegra_soc_pwr_domain_off(target_state); + + /* disable GICC */ + tegra_gic_cpuif_deactivate(); } /******************************************************************************* @@ -203,17 +116,10 @@ void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_sta * 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 tegra_pwr_domain_suspend(const psci_power_state_t *target_state) +static void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) { (void)tegra_soc_pwr_domain_suspend(target_state); - /* Disable console if we are entering deep sleep. */ - if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == - PSTATE_ID_SOC_POWERDN) { - (void)console_flush(); - console_switch_state(0); - } - /* disable GICC */ tegra_gic_cpuif_deactivate(); } @@ -222,12 +128,20 @@ void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) * Handler called at the end of the power domain suspend sequence. The * target_state encodes the power state that each level should transition to. ******************************************************************************/ -__dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t +static __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) { /* call the chip's power down handler */ (void)tegra_soc_pwr_domain_power_down_wfi(target_state); + /* Disable console if we are entering deep sleep. */ + if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == + PSTATE_ID_SOC_POWERDN) { + INFO("%s: complete. Entering System Suspend...\n", __func__); + console_flush(); + console_switch_state(0); + } + wfi(); panic(); } @@ -237,21 +151,23 @@ __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t * being turned off earlier. The target_state encodes the low power state that * each level has woken up from. ******************************************************************************/ -void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) +static void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) { const plat_params_from_bl2_t *plat_params; /* - * Initialize the GIC cpu and distributor interfaces - */ - tegra_gic_pcpu_init(); - - /* * Check if we are exiting from deep sleep. */ if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == PSTATE_ID_SOC_POWERDN) { + /* + * On entering System Suspend state, the GIC loses power + * completely. Initialize the GIC global distributor and + * GIC cpu interfaces. + */ + tegra_gic_init(); + /* Restart console output. */ console_switch_state(CONSOLE_FLAG_RUNTIME); @@ -268,11 +184,11 @@ void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) tegra_memctrl_tzdram_setup(plat_params->tzdram_base, (uint32_t)plat_params->tzdram_size); + } else { /* - * Set up the TZRAM memory aperture to allow only secure world - * access + * Initialize the GIC cpu and distributor interfaces */ - tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE); + tegra_gic_pcpu_init(); } /* @@ -286,7 +202,7 @@ void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) * having been suspended earlier. The target_state encodes the low power state * that each level has woken up from. ******************************************************************************/ -void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) +static void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) { tegra_pwr_domain_on_finish(target_state); } @@ -294,7 +210,7 @@ void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) /******************************************************************************* * Handler called when the system wants to be powered off ******************************************************************************/ -__dead2 void tegra_system_off(void) +static __dead2 void tegra_system_off(void) { INFO("Powering down system...\n"); @@ -304,23 +220,23 @@ __dead2 void tegra_system_off(void) /******************************************************************************* * Handler called when the system wants to be restarted. ******************************************************************************/ -__dead2 void tegra_system_reset(void) +static __dead2 void tegra_system_reset(void) { INFO("Restarting system...\n"); /* per-SoC system reset handler */ (void)tegra_soc_prepare_system_reset(); - /* - * Program the PMC in order to restart the system. - */ - tegra_pmc_system_reset(); + /* wait for the system to reset */ + for (;;) { + ; + } } /******************************************************************************* * Handler called to check the validity of the power state parameter. ******************************************************************************/ -int32_t tegra_validate_power_state(uint32_t power_state, +static int32_t tegra_validate_power_state(uint32_t power_state, psci_power_state_t *req_state) { assert(req_state != NULL); @@ -331,7 +247,7 @@ int32_t tegra_validate_power_state(uint32_t power_state, /******************************************************************************* * Platform handler called to check the validity of the non secure entrypoint. ******************************************************************************/ -int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) +static int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) { int32_t ret = PSCI_E_INVALID_ADDRESS; @@ -349,7 +265,7 @@ int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) /******************************************************************************* * Export the platform handlers to enable psci to invoke them ******************************************************************************/ -static const plat_psci_ops_t tegra_plat_psci_ops = { +static plat_psci_ops_t tegra_plat_psci_ops = { .cpu_standby = tegra_cpu_standby, .pwr_domain_on = tegra_pwr_domain_on, .pwr_domain_off = tegra_pwr_domain_off, @@ -386,6 +302,14 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint, (void)tegra_soc_pwr_domain_on_finish(&target_state); /* + * Disable System Suspend if the platform does not + * support it + */ + if (!plat_supports_system_suspend()) { + tegra_plat_psci_ops.get_sys_suspend_power_state = NULL; + } + + /* * Initialize PSCI ops struct */ *psci_ops = &tegra_plat_psci_ops; |