1 /* 2 * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #include <platform_def.h> 10 11 #include <arch_helpers.h> 12 #include <common/bl_common.h> 13 #include <common/debug.h> 14 #include <context.h> 15 #include <drivers/console.h> 16 #include <lib/el3_runtime/context_mgmt.h> 17 #include <lib/mmio.h> 18 #include <lib/psci/psci.h> 19 #include <plat/common/platform.h> 20 21 #include <memctrl.h> 22 #include <pmc.h> 23 #include <tegra_def.h> 24 #include <tegra_platform.h> 25 #include <tegra_private.h> 26 27 extern uint64_t tegra_bl31_phys_base; 28 extern uint64_t tegra_sec_entry_point; 29 30 /* 31 * tegra_fake_system_suspend acts as a boolean var controlling whether 32 * we are going to take fake system suspend code or normal system suspend code 33 * path. This variable is set inside the sip call handlers,when the kernel 34 * requests a SIP call to set the suspend debug flags. 35 */ 36 uint8_t tegra_fake_system_suspend; 37 38 /* 39 * The following platform setup functions are weakly defined. They 40 * provide typical implementations that will be overridden by a SoC. 41 */ 42 #pragma weak tegra_soc_pwr_domain_suspend_pwrdown_early 43 #pragma weak tegra_soc_cpu_standby 44 #pragma weak tegra_soc_pwr_domain_suspend 45 #pragma weak tegra_soc_pwr_domain_on 46 #pragma weak tegra_soc_pwr_domain_off 47 #pragma weak tegra_soc_pwr_domain_on_finish 48 #pragma weak tegra_soc_pwr_domain_power_down_wfi 49 #pragma weak tegra_soc_prepare_system_reset 50 #pragma weak tegra_soc_prepare_system_off 51 #pragma weak tegra_soc_get_target_pwr_state 52 53 int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 54 { 55 return PSCI_E_NOT_SUPPORTED; 56 } 57 58 int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) 59 { 60 (void)cpu_state; 61 return PSCI_E_SUCCESS; 62 } 63 64 int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) 65 { 66 (void)target_state; 67 return PSCI_E_NOT_SUPPORTED; 68 } 69 70 int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) 71 { 72 (void)mpidr; 73 return PSCI_E_SUCCESS; 74 } 75 76 int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) 77 { 78 (void)target_state; 79 return PSCI_E_SUCCESS; 80 } 81 82 int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) 83 { 84 (void)target_state; 85 return PSCI_E_SUCCESS; 86 } 87 88 int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) 89 { 90 (void)target_state; 91 return PSCI_E_SUCCESS; 92 } 93 94 int32_t tegra_soc_prepare_system_reset(void) 95 { 96 return PSCI_E_SUCCESS; 97 } 98 99 __dead2 void tegra_soc_prepare_system_off(void) 100 { 101 ERROR("Tegra System Off: operation not handled.\n"); 102 panic(); 103 } 104 105 plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, 106 const plat_local_state_t *states, 107 uint32_t ncpu) 108 { 109 plat_local_state_t target = PLAT_MAX_OFF_STATE, temp; 110 uint32_t num_cpu = ncpu; 111 const plat_local_state_t *local_state = states; 112 113 (void)lvl; 114 115 assert(ncpu != 0U); 116 117 do { 118 temp = *local_state; 119 if ((temp < target)) { 120 target = temp; 121 } 122 --num_cpu; 123 local_state++; 124 } while (num_cpu != 0U); 125 126 return target; 127 } 128 129 /******************************************************************************* 130 * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` 131 * call to get the `power_state` parameter. This allows the platform to encode 132 * the appropriate State-ID field within the `power_state` parameter which can 133 * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. 134 ******************************************************************************/ 135 void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) 136 { 137 /* all affinities use system suspend state id */ 138 for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) { 139 req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN; 140 } 141 } 142 143 /******************************************************************************* 144 * Handler called when an affinity instance is about to enter standby. 145 ******************************************************************************/ 146 void tegra_cpu_standby(plat_local_state_t cpu_state) 147 { 148 u_register_t saved_scr_el3; 149 150 (void)cpu_state; 151 152 /* Tegra SoC specific handler */ 153 if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS) 154 ERROR("%s failed\n", __func__); 155 156 saved_scr_el3 = read_scr_el3(); 157 158 /* 159 * As per ARM ARM D1.17.2, any physical IRQ interrupt received by the 160 * PE will be treated as a wake-up event, if SCR_EL3.IRQ is set to '1', 161 * irrespective of the value of the PSTATE.I bit value. 162 */ 163 write_scr_el3(saved_scr_el3 | SCR_IRQ_BIT); 164 165 /* 166 * Enter standby state 167 * 168 * dsb & isb is good practice before using wfi to enter low power states 169 */ 170 dsb(); 171 isb(); 172 wfi(); 173 174 /* 175 * Restore saved scr_el3 that has IRQ bit cleared as we don't want EL3 176 * handling any further interrupts 177 */ 178 write_scr_el3(saved_scr_el3); 179 } 180 181 /******************************************************************************* 182 * Handler called when an affinity instance is about to be turned on. The 183 * level and mpidr determine the affinity instance. 184 ******************************************************************************/ 185 int32_t tegra_pwr_domain_on(u_register_t mpidr) 186 { 187 return tegra_soc_pwr_domain_on(mpidr); 188 } 189 190 /******************************************************************************* 191 * Handler called when a power domain is about to be turned off. The 192 * target_state encodes the power state that each level should transition to. 193 ******************************************************************************/ 194 void tegra_pwr_domain_off(const psci_power_state_t *target_state) 195 { 196 (void)tegra_soc_pwr_domain_off(target_state); 197 } 198 199 /******************************************************************************* 200 * Handler called when a power domain is about to be suspended. The 201 * target_state encodes the power state that each level should transition to. 202 * This handler is called with SMP and data cache enabled, when 203 * HW_ASSISTED_COHERENCY = 0 204 ******************************************************************************/ 205 void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 206 { 207 tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); 208 } 209 210 /******************************************************************************* 211 * Handler called when a power domain is about to be suspended. The 212 * target_state encodes the power state that each level should transition to. 213 ******************************************************************************/ 214 void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) 215 { 216 (void)tegra_soc_pwr_domain_suspend(target_state); 217 218 /* Disable console if we are entering deep sleep. */ 219 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 220 PSTATE_ID_SOC_POWERDN) { 221 (void)console_flush(); 222 console_switch_state(0); 223 } 224 225 /* disable GICC */ 226 tegra_gic_cpuif_deactivate(); 227 } 228 229 /******************************************************************************* 230 * Handler called at the end of the power domain suspend sequence. The 231 * target_state encodes the power state that each level should transition to. 232 ******************************************************************************/ 233 __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t 234 *target_state) 235 { 236 uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; 237 uint64_t rmr_el3 = 0; 238 239 /* call the chip's power down handler */ 240 (void)tegra_soc_pwr_domain_power_down_wfi(target_state); 241 242 /* 243 * If we are in fake system suspend mode, ensure we start doing 244 * procedures that help in looping back towards system suspend exit 245 * instead of calling WFI by requesting a warm reset. 246 * Else, just call WFI to enter low power state. 247 */ 248 if ((tegra_fake_system_suspend != 0U) && 249 (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) { 250 251 /* warm reboot */ 252 rmr_el3 = read_rmr_el3(); 253 write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU); 254 255 } else { 256 /* enter power down state */ 257 wfi(); 258 } 259 260 /* we can never reach here */ 261 panic(); 262 } 263 264 /******************************************************************************* 265 * Handler called when a power domain has just been powered on after 266 * being turned off earlier. The target_state encodes the low power state that 267 * each level has woken up from. 268 ******************************************************************************/ 269 void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) 270 { 271 const plat_params_from_bl2_t *plat_params; 272 273 /* 274 * Initialize the GIC cpu and distributor interfaces 275 */ 276 tegra_gic_init(); 277 278 /* 279 * Check if we are exiting from deep sleep. 280 */ 281 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 282 PSTATE_ID_SOC_POWERDN) { 283 284 /* Restart console output. */ 285 console_switch_state(CONSOLE_FLAG_RUNTIME); 286 287 /* 288 * Restore Memory Controller settings as it loses state 289 * during system suspend. 290 */ 291 tegra_memctrl_restore_settings(); 292 293 /* 294 * Security configuration to allow DRAM/device access. 295 */ 296 plat_params = bl31_get_plat_params(); 297 tegra_memctrl_tzdram_setup(plat_params->tzdram_base, 298 (uint32_t)plat_params->tzdram_size); 299 300 /* 301 * Set up the TZRAM memory aperture to allow only secure world 302 * access 303 */ 304 tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE); 305 } 306 307 /* 308 * Reset hardware settings. 309 */ 310 (void)tegra_soc_pwr_domain_on_finish(target_state); 311 } 312 313 /******************************************************************************* 314 * Handler called when a power domain has just been powered on after 315 * having been suspended earlier. The target_state encodes the low power state 316 * that each level has woken up from. 317 ******************************************************************************/ 318 void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 319 { 320 tegra_pwr_domain_on_finish(target_state); 321 } 322 323 /******************************************************************************* 324 * Handler called when the system wants to be powered off 325 ******************************************************************************/ 326 __dead2 void tegra_system_off(void) 327 { 328 INFO("Powering down system...\n"); 329 330 tegra_soc_prepare_system_off(); 331 } 332 333 /******************************************************************************* 334 * Handler called when the system wants to be restarted. 335 ******************************************************************************/ 336 __dead2 void tegra_system_reset(void) 337 { 338 INFO("Restarting system...\n"); 339 340 /* per-SoC system reset handler */ 341 (void)tegra_soc_prepare_system_reset(); 342 343 /* 344 * Program the PMC in order to restart the system. 345 */ 346 tegra_pmc_system_reset(); 347 } 348 349 /******************************************************************************* 350 * Handler called to check the validity of the power state parameter. 351 ******************************************************************************/ 352 int32_t tegra_validate_power_state(uint32_t power_state, 353 psci_power_state_t *req_state) 354 { 355 assert(req_state != NULL); 356 357 return tegra_soc_validate_power_state(power_state, req_state); 358 } 359 360 /******************************************************************************* 361 * Platform handler called to check the validity of the non secure entrypoint. 362 ******************************************************************************/ 363 int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) 364 { 365 int32_t ret = PSCI_E_INVALID_ADDRESS; 366 367 /* 368 * Check if the non secure entrypoint lies within the non 369 * secure DRAM. 370 */ 371 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { 372 ret = PSCI_E_SUCCESS; 373 } 374 375 return ret; 376 } 377 378 /******************************************************************************* 379 * Export the platform handlers to enable psci to invoke them 380 ******************************************************************************/ 381 static const plat_psci_ops_t tegra_plat_psci_ops = { 382 .cpu_standby = tegra_cpu_standby, 383 .pwr_domain_on = tegra_pwr_domain_on, 384 .pwr_domain_off = tegra_pwr_domain_off, 385 .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 386 .pwr_domain_suspend = tegra_pwr_domain_suspend, 387 .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 388 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 389 .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, 390 .system_off = tegra_system_off, 391 .system_reset = tegra_system_reset, 392 .validate_power_state = tegra_validate_power_state, 393 .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 394 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 395 }; 396 397 /******************************************************************************* 398 * Export the platform specific power ops and initialize Power Controller 399 ******************************************************************************/ 400 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 401 const plat_psci_ops_t **psci_ops) 402 { 403 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 404 405 /* 406 * Flush entrypoint variable to PoC since it will be 407 * accessed after a reset with the caches turned off. 408 */ 409 tegra_sec_entry_point = sec_entrypoint; 410 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 411 412 /* 413 * Reset hardware settings. 414 */ 415 (void)tegra_soc_pwr_domain_on_finish(&target_state); 416 417 /* 418 * Initialize PSCI ops struct 419 */ 420 *psci_ops = &tegra_plat_psci_ops; 421 422 return 0; 423 } 424 425 /******************************************************************************* 426 * Platform handler to calculate the proper target power level at the 427 * specified affinity level 428 ******************************************************************************/ 429 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 430 const plat_local_state_t *states, 431 unsigned int ncpu) 432 { 433 return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 434 } 435