1 /* 2 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020-2023, 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 static 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 static 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 static 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 * Return error if CPU off sequence is not allowed for the current core. 96 ******************************************************************************/ 97 static int tegra_pwr_domain_off_early(const psci_power_state_t *target_state) 98 { 99 return tegra_soc_pwr_domain_off_early(target_state); 100 } 101 102 /******************************************************************************* 103 * Handler called when a power domain is about to be turned off. The 104 * target_state encodes the power state that each level should transition to. 105 ******************************************************************************/ 106 static void tegra_pwr_domain_off(const psci_power_state_t *target_state) 107 { 108 (void)tegra_soc_pwr_domain_off(target_state); 109 110 /* disable GICC */ 111 tegra_gic_cpuif_deactivate(); 112 } 113 114 /******************************************************************************* 115 * Handler called when a power domain is about to be suspended. The 116 * target_state encodes the power state that each level should transition to. 117 * This handler is called with SMP and data cache enabled, when 118 * HW_ASSISTED_COHERENCY = 0 119 ******************************************************************************/ 120 void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 121 { 122 tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); 123 } 124 125 /******************************************************************************* 126 * Handler called when a power domain is about to be suspended. The 127 * target_state encodes the power state that each level should transition to. 128 ******************************************************************************/ 129 static void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) 130 { 131 (void)tegra_soc_pwr_domain_suspend(target_state); 132 133 /* disable GICC */ 134 tegra_gic_cpuif_deactivate(); 135 } 136 137 /******************************************************************************* 138 * Handler called at the end of the power domain suspend sequence. The 139 * target_state encodes the power state that each level should transition to. 140 ******************************************************************************/ 141 static __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t 142 *target_state) 143 { 144 /* call the chip's power down handler */ 145 (void)tegra_soc_pwr_domain_power_down_wfi(target_state); 146 147 /* Disable console if we are entering deep sleep. */ 148 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 149 PSTATE_ID_SOC_POWERDN) { 150 INFO("%s: complete. Entering System Suspend...\n", __func__); 151 console_flush(); 152 console_switch_state(0); 153 } 154 155 wfi(); 156 panic(); 157 } 158 159 /******************************************************************************* 160 * Handler called when a power domain has just been powered on after 161 * being turned off earlier. The target_state encodes the low power state that 162 * each level has woken up from. 163 ******************************************************************************/ 164 static void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) 165 { 166 const plat_params_from_bl2_t *plat_params; 167 168 /* 169 * Check if we are exiting from deep sleep. 170 */ 171 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 172 PSTATE_ID_SOC_POWERDN) { 173 174 /* 175 * On entering System Suspend state, the GIC loses power 176 * completely. Initialize the GIC global distributor and 177 * GIC cpu interfaces. 178 */ 179 tegra_gic_init(); 180 181 /* Restart console output. */ 182 console_switch_state(CONSOLE_FLAG_RUNTIME); 183 184 /* 185 * Restore Memory Controller settings as it loses state 186 * during system suspend. 187 */ 188 tegra_memctrl_restore_settings(); 189 190 /* 191 * Security configuration to allow DRAM/device access. 192 */ 193 plat_params = bl31_get_plat_params(); 194 tegra_memctrl_tzdram_setup(plat_params->tzdram_base, 195 (uint32_t)plat_params->tzdram_size); 196 197 } else { 198 /* 199 * Initialize the GIC cpu and distributor interfaces 200 */ 201 tegra_gic_pcpu_init(); 202 } 203 204 /* 205 * Reset hardware settings. 206 */ 207 (void)tegra_soc_pwr_domain_on_finish(target_state); 208 } 209 210 /******************************************************************************* 211 * Handler called when a power domain has just been powered on after 212 * having been suspended earlier. The target_state encodes the low power state 213 * that each level has woken up from. 214 ******************************************************************************/ 215 static void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 216 { 217 tegra_pwr_domain_on_finish(target_state); 218 } 219 220 /******************************************************************************* 221 * Handler called when the system wants to be powered off 222 ******************************************************************************/ 223 static __dead2 void tegra_system_off(void) 224 { 225 INFO("Powering down system...\n"); 226 227 tegra_soc_prepare_system_off(); 228 } 229 230 /******************************************************************************* 231 * Handler called when the system wants to be restarted. 232 ******************************************************************************/ 233 static __dead2 void tegra_system_reset(void) 234 { 235 INFO("Restarting system...\n"); 236 237 /* per-SoC system reset handler */ 238 (void)tegra_soc_prepare_system_reset(); 239 240 /* wait for the system to reset */ 241 for (;;) { 242 ; 243 } 244 } 245 246 /******************************************************************************* 247 * Handler called to check the validity of the power state parameter. 248 ******************************************************************************/ 249 static int32_t tegra_validate_power_state(uint32_t power_state, 250 psci_power_state_t *req_state) 251 { 252 assert(req_state != NULL); 253 254 return tegra_soc_validate_power_state(power_state, req_state); 255 } 256 257 /******************************************************************************* 258 * Platform handler called to check the validity of the non secure entrypoint. 259 ******************************************************************************/ 260 static int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) 261 { 262 int32_t ret = PSCI_E_INVALID_ADDRESS; 263 264 /* 265 * Check if the non secure entrypoint lies within the non 266 * secure DRAM. 267 */ 268 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { 269 ret = PSCI_E_SUCCESS; 270 } 271 272 return ret; 273 } 274 275 /******************************************************************************* 276 * Export the platform handlers to enable psci to invoke them 277 ******************************************************************************/ 278 static plat_psci_ops_t tegra_plat_psci_ops = { 279 .cpu_standby = tegra_cpu_standby, 280 .pwr_domain_on = tegra_pwr_domain_on, 281 .pwr_domain_off_early = tegra_pwr_domain_off_early, 282 .pwr_domain_off = tegra_pwr_domain_off, 283 .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 284 .pwr_domain_suspend = tegra_pwr_domain_suspend, 285 .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 286 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 287 .pwr_domain_pwr_down = tegra_pwr_domain_power_down_wfi, 288 .system_off = tegra_system_off, 289 .system_reset = tegra_system_reset, 290 .validate_power_state = tegra_validate_power_state, 291 .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 292 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 293 }; 294 295 /******************************************************************************* 296 * Export the platform specific power ops and initialize Power Controller 297 ******************************************************************************/ 298 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 299 const plat_psci_ops_t **psci_ops) 300 { 301 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 302 303 /* 304 * Flush entrypoint variable to PoC since it will be 305 * accessed after a reset with the caches turned off. 306 */ 307 tegra_sec_entry_point = sec_entrypoint; 308 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 309 310 /* 311 * Reset hardware settings. 312 */ 313 (void)tegra_soc_pwr_domain_on_finish(&target_state); 314 315 /* 316 * Disable System Suspend if the platform does not 317 * support it 318 */ 319 if (!plat_supports_system_suspend()) { 320 tegra_plat_psci_ops.get_sys_suspend_power_state = NULL; 321 } 322 323 /* 324 * Initialize PSCI ops struct 325 */ 326 *psci_ops = &tegra_plat_psci_ops; 327 328 return 0; 329 } 330 331 /******************************************************************************* 332 * Platform handler to calculate the proper target power level at the 333 * specified affinity level 334 ******************************************************************************/ 335 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 336 const plat_local_state_t *states, 337 unsigned int ncpu) 338 { 339 return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 340 } 341