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