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 /* 184 * Set up the TZRAM memory aperture to allow only secure world 185 * access 186 */ 187 tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE); 188 } else { 189 /* 190 * Initialize the GIC cpu and distributor interfaces 191 */ 192 tegra_gic_pcpu_init(); 193 } 194 195 /* 196 * Reset hardware settings. 197 */ 198 (void)tegra_soc_pwr_domain_on_finish(target_state); 199 } 200 201 /******************************************************************************* 202 * Handler called when a power domain has just been powered on after 203 * having been suspended earlier. The target_state encodes the low power state 204 * that each level has woken up from. 205 ******************************************************************************/ 206 void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 207 { 208 tegra_pwr_domain_on_finish(target_state); 209 } 210 211 /******************************************************************************* 212 * Handler called when the system wants to be powered off 213 ******************************************************************************/ 214 __dead2 void tegra_system_off(void) 215 { 216 INFO("Powering down system...\n"); 217 218 tegra_soc_prepare_system_off(); 219 } 220 221 /******************************************************************************* 222 * Handler called when the system wants to be restarted. 223 ******************************************************************************/ 224 __dead2 void tegra_system_reset(void) 225 { 226 INFO("Restarting system...\n"); 227 228 /* per-SoC system reset handler */ 229 (void)tegra_soc_prepare_system_reset(); 230 231 /* wait for the system to reset */ 232 for (;;) { 233 ; 234 } 235 } 236 237 /******************************************************************************* 238 * Handler called to check the validity of the power state parameter. 239 ******************************************************************************/ 240 int32_t tegra_validate_power_state(uint32_t power_state, 241 psci_power_state_t *req_state) 242 { 243 assert(req_state != NULL); 244 245 return tegra_soc_validate_power_state(power_state, req_state); 246 } 247 248 /******************************************************************************* 249 * Platform handler called to check the validity of the non secure entrypoint. 250 ******************************************************************************/ 251 int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) 252 { 253 int32_t ret = PSCI_E_INVALID_ADDRESS; 254 255 /* 256 * Check if the non secure entrypoint lies within the non 257 * secure DRAM. 258 */ 259 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { 260 ret = PSCI_E_SUCCESS; 261 } 262 263 return ret; 264 } 265 266 /******************************************************************************* 267 * Export the platform handlers to enable psci to invoke them 268 ******************************************************************************/ 269 static plat_psci_ops_t tegra_plat_psci_ops = { 270 .cpu_standby = tegra_cpu_standby, 271 .pwr_domain_on = tegra_pwr_domain_on, 272 .pwr_domain_off = tegra_pwr_domain_off, 273 .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 274 .pwr_domain_suspend = tegra_pwr_domain_suspend, 275 .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 276 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 277 .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, 278 .system_off = tegra_system_off, 279 .system_reset = tegra_system_reset, 280 .validate_power_state = tegra_validate_power_state, 281 .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 282 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 283 }; 284 285 /******************************************************************************* 286 * Export the platform specific power ops and initialize Power Controller 287 ******************************************************************************/ 288 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 289 const plat_psci_ops_t **psci_ops) 290 { 291 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 292 293 /* 294 * Flush entrypoint variable to PoC since it will be 295 * accessed after a reset with the caches turned off. 296 */ 297 tegra_sec_entry_point = sec_entrypoint; 298 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 299 300 /* 301 * Reset hardware settings. 302 */ 303 (void)tegra_soc_pwr_domain_on_finish(&target_state); 304 305 /* 306 * Disable System Suspend if the platform does not 307 * support it 308 */ 309 if (!plat_supports_system_suspend()) { 310 tegra_plat_psci_ops.get_sys_suspend_power_state = NULL; 311 } 312 313 /* 314 * Initialize PSCI ops struct 315 */ 316 *psci_ops = &tegra_plat_psci_ops; 317 318 return 0; 319 } 320 321 /******************************************************************************* 322 * Platform handler to calculate the proper target power level at the 323 * specified affinity level 324 ******************************************************************************/ 325 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 326 const plat_local_state_t *states, 327 unsigned int ncpu) 328 { 329 return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 330 } 331