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