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