1 /* 2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 10 #include <platform_def.h> 11 12 #include <arch_helpers.h> 13 #include <common/bl_common.h> 14 #include <common/debug.h> 15 #include <context.h> 16 #include <drivers/console.h> 17 #include <lib/el3_runtime/context_mgmt.h> 18 #include <lib/mmio.h> 19 #include <lib/psci/psci.h> 20 #include <plat/common/platform.h> 21 22 #include <memctrl.h> 23 #include <pmc.h> 24 #include <tegra_def.h> 25 #include <tegra_platform.h> 26 #include <tegra_private.h> 27 28 extern uint64_t tegra_bl31_phys_base; 29 extern uint64_t tegra_sec_entry_point; 30 31 /******************************************************************************* 32 * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` 33 * call to get the `power_state` parameter. This allows the platform to encode 34 * the appropriate State-ID field within the `power_state` parameter which can 35 * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. 36 ******************************************************************************/ 37 void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) 38 { 39 /* all affinities use system suspend state id */ 40 for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { 41 req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN; 42 } 43 } 44 45 /******************************************************************************* 46 * Handler called when an affinity instance is about to enter standby. 47 ******************************************************************************/ 48 void tegra_cpu_standby(plat_local_state_t cpu_state) 49 { 50 u_register_t saved_scr_el3; 51 52 (void)cpu_state; 53 54 /* Tegra SoC specific handler */ 55 if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS) 56 ERROR("%s failed\n", __func__); 57 58 saved_scr_el3 = read_scr_el3(); 59 60 /* 61 * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the 62 * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1', 63 * irrespective of the value of the PSTATE.I bit value. 64 */ 65 write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT); 66 67 /* 68 * Enter standby state 69 * 70 * dsb & isb is good practice before using wfi to enter low power states 71 */ 72 dsb(); 73 isb(); 74 wfi(); 75 76 /* 77 * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3 78 * handling any further interrupts 79 */ 80 write_scr_el3(saved_scr_el3); 81 } 82 83 /******************************************************************************* 84 * Handler called when an affinity instance is about to be turned on. The 85 * level and mpidr determine the affinity instance. 86 ******************************************************************************/ 87 int32_t tegra_pwr_domain_on(u_register_t mpidr) 88 { 89 return tegra_soc_pwr_domain_on(mpidr); 90 } 91 92 /******************************************************************************* 93 * Handler called when a power domain is about to be turned off. The 94 * target_state encodes the power state that each level should transition to. 95 ******************************************************************************/ 96 void tegra_pwr_domain_off(const psci_power_state_t *target_state) 97 { 98 (void)tegra_soc_pwr_domain_off(target_state); 99 } 100 101 /******************************************************************************* 102 * Handler called when a power domain is about to be suspended. The 103 * target_state encodes the power state that each level should transition to. 104 * This handler is called with SMP and data cache enabled, when 105 * HW_ASSISTED_COHERENCY = 0 106 ******************************************************************************/ 107 void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 108 { 109 tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); 110 } 111 112 /******************************************************************************* 113 * Handler called when a power domain is about to be suspended. The 114 * target_state encodes the power state that each level should transition to. 115 ******************************************************************************/ 116 void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) 117 { 118 (void)tegra_soc_pwr_domain_suspend(target_state); 119 120 /* Disable console if we are entering deep sleep. */ 121 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 122 PSTATE_ID_SOC_POWERDN) { 123 (void)console_flush(); 124 console_switch_state(0); 125 } 126 127 /* disable GICC */ 128 tegra_gic_cpuif_deactivate(); 129 } 130 131 /******************************************************************************* 132 * Handler called at the end of the power domain suspend sequence. The 133 * target_state encodes the power state that each level should transition to. 134 ******************************************************************************/ 135 __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t 136 *target_state) 137 { 138 /* call the chip's power down handler */ 139 (void)tegra_soc_pwr_domain_power_down_wfi(target_state); 140 141 wfi(); 142 panic(); 143 } 144 145 /******************************************************************************* 146 * Handler called when a power domain has just been powered on after 147 * being turned off earlier. The target_state encodes the low power state that 148 * each level has woken up from. 149 ******************************************************************************/ 150 void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) 151 { 152 const plat_params_from_bl2_t *plat_params; 153 154 /* 155 * Check if we are exiting from deep sleep. 156 */ 157 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 158 PSTATE_ID_SOC_POWERDN) { 159 160 /* 161 * On entering System Suspend state, the GIC loses power 162 * completely. Initialize the GIC global distributor and 163 * GIC cpu interfaces. 164 */ 165 tegra_gic_init(); 166 167 /* Restart console output. */ 168 console_switch_state(CONSOLE_FLAG_RUNTIME); 169 170 /* 171 * Restore Memory Controller settings as it loses state 172 * during system suspend. 173 */ 174 tegra_memctrl_restore_settings(); 175 176 /* 177 * Security configuration to allow DRAM/device access. 178 */ 179 plat_params = bl31_get_plat_params(); 180 tegra_memctrl_tzdram_setup(plat_params->tzdram_base, 181 (uint32_t)plat_params->tzdram_size); 182 183 } else { 184 /* 185 * Initialize the GIC cpu and distributor interfaces 186 */ 187 tegra_gic_pcpu_init(); 188 } 189 190 /* 191 * Reset hardware settings. 192 */ 193 (void)tegra_soc_pwr_domain_on_finish(target_state); 194 } 195 196 /******************************************************************************* 197 * Handler called when a power domain has just been powered on after 198 * having been suspended earlier. The target_state encodes the low power state 199 * that each level has woken up from. 200 ******************************************************************************/ 201 void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 202 { 203 tegra_pwr_domain_on_finish(target_state); 204 } 205 206 /******************************************************************************* 207 * Handler called when the system wants to be powered off 208 ******************************************************************************/ 209 __dead2 void tegra_system_off(void) 210 { 211 INFO("Powering down system...\n"); 212 213 tegra_soc_prepare_system_off(); 214 } 215 216 /******************************************************************************* 217 * Handler called when the system wants to be restarted. 218 ******************************************************************************/ 219 __dead2 void tegra_system_reset(void) 220 { 221 INFO("Restarting system...\n"); 222 223 /* per-SoC system reset handler */ 224 (void)tegra_soc_prepare_system_reset(); 225 226 /* wait for the system to reset */ 227 for (;;) { 228 ; 229 } 230 } 231 232 /******************************************************************************* 233 * Handler called to check the validity of the power state parameter. 234 ******************************************************************************/ 235 int32_t tegra_validate_power_state(uint32_t power_state, 236 psci_power_state_t *req_state) 237 { 238 assert(req_state != NULL); 239 240 return tegra_soc_validate_power_state(power_state, req_state); 241 } 242 243 /******************************************************************************* 244 * Platform handler called to check the validity of the non secure entrypoint. 245 ******************************************************************************/ 246 int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) 247 { 248 int32_t ret = PSCI_E_INVALID_ADDRESS; 249 250 /* 251 * Check if the non secure entrypoint lies within the non 252 * secure DRAM. 253 */ 254 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { 255 ret = PSCI_E_SUCCESS; 256 } 257 258 return ret; 259 } 260 261 /******************************************************************************* 262 * Export the platform handlers to enable psci to invoke them 263 ******************************************************************************/ 264 static plat_psci_ops_t tegra_plat_psci_ops = { 265 .cpu_standby = tegra_cpu_standby, 266 .pwr_domain_on = tegra_pwr_domain_on, 267 .pwr_domain_off = tegra_pwr_domain_off, 268 .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 269 .pwr_domain_suspend = tegra_pwr_domain_suspend, 270 .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 271 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 272 .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, 273 .system_off = tegra_system_off, 274 .system_reset = tegra_system_reset, 275 .validate_power_state = tegra_validate_power_state, 276 .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 277 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 278 }; 279 280 /******************************************************************************* 281 * Export the platform specific power ops and initialize Power Controller 282 ******************************************************************************/ 283 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 284 const plat_psci_ops_t **psci_ops) 285 { 286 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 287 288 /* 289 * Flush entrypoint variable to PoC since it will be 290 * accessed after a reset with the caches turned off. 291 */ 292 tegra_sec_entry_point = sec_entrypoint; 293 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 294 295 /* 296 * Reset hardware settings. 297 */ 298 (void)tegra_soc_pwr_domain_on_finish(&target_state); 299 300 /* 301 * Disable System Suspend if the platform does not 302 * support it 303 */ 304 if (!plat_supports_system_suspend()) { 305 tegra_plat_psci_ops.get_sys_suspend_power_state = NULL; 306 } 307 308 /* 309 * Initialize PSCI ops struct 310 */ 311 *psci_ops = &tegra_plat_psci_ops; 312 313 return 0; 314 } 315 316 /******************************************************************************* 317 * Platform handler to calculate the proper target power level at the 318 * specified affinity level 319 ******************************************************************************/ 320 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 321 const plat_local_state_t *states, 322 unsigned int ncpu) 323 { 324 return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 325 } 326