1 /* 2 * Copyright (c) 2015-2017, 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 (void)cpu_state; 150 151 /* Tegra SoC specific handler */ 152 if (tegra_soc_cpu_standby(cpu_state) != PSCI_E_SUCCESS) 153 ERROR("%s failed\n", __func__); 154 155 /* 156 * Enter standby state 157 * dsb is good practice before using wfi to enter low power states 158 */ 159 dsb(); 160 wfi(); 161 } 162 163 /******************************************************************************* 164 * Handler called when an affinity instance is about to be turned on. The 165 * level and mpidr determine the affinity instance. 166 ******************************************************************************/ 167 int32_t tegra_pwr_domain_on(u_register_t mpidr) 168 { 169 return tegra_soc_pwr_domain_on(mpidr); 170 } 171 172 /******************************************************************************* 173 * Handler called when a power domain is about to be turned off. The 174 * target_state encodes the power state that each level should transition to. 175 ******************************************************************************/ 176 void tegra_pwr_domain_off(const psci_power_state_t *target_state) 177 { 178 (void)tegra_soc_pwr_domain_off(target_state); 179 } 180 181 /******************************************************************************* 182 * Handler called when a power domain is about to be suspended. The 183 * target_state encodes the power state that each level should transition to. 184 * This handler is called with SMP and data cache enabled, when 185 * HW_ASSISTED_COHERENCY = 0 186 ******************************************************************************/ 187 void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 188 { 189 tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); 190 } 191 192 /******************************************************************************* 193 * Handler called when a power domain is about to be suspended. The 194 * target_state encodes the power state that each level should transition to. 195 ******************************************************************************/ 196 void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) 197 { 198 (void)tegra_soc_pwr_domain_suspend(target_state); 199 200 /* Disable console if we are entering deep sleep. */ 201 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 202 PSTATE_ID_SOC_POWERDN) { 203 (void)console_uninit(); 204 } 205 206 /* disable GICC */ 207 tegra_gic_cpuif_deactivate(); 208 } 209 210 /******************************************************************************* 211 * Handler called at the end of the power domain suspend sequence. The 212 * target_state encodes the power state that each level should transition to. 213 ******************************************************************************/ 214 __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t 215 *target_state) 216 { 217 uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; 218 uint64_t rmr_el3 = 0; 219 220 /* call the chip's power down handler */ 221 (void)tegra_soc_pwr_domain_power_down_wfi(target_state); 222 223 /* 224 * If we are in fake system suspend mode, ensure we start doing 225 * procedures that help in looping back towards system suspend exit 226 * instead of calling WFI by requesting a warm reset. 227 * Else, just call WFI to enter low power state. 228 */ 229 if ((tegra_fake_system_suspend != 0U) && 230 (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) { 231 232 /* warm reboot */ 233 rmr_el3 = read_rmr_el3(); 234 write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU); 235 236 } else { 237 /* enter power down state */ 238 wfi(); 239 } 240 241 /* we can never reach here */ 242 panic(); 243 } 244 245 /******************************************************************************* 246 * Handler called when a power domain has just been powered on after 247 * being turned off earlier. The target_state encodes the low power state that 248 * each level has woken up from. 249 ******************************************************************************/ 250 void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) 251 { 252 const plat_params_from_bl2_t *plat_params; 253 uint32_t console_clock; 254 255 /* 256 * Initialize the GIC cpu and distributor interfaces 257 */ 258 plat_gic_setup(); 259 260 /* 261 * Check if we are exiting from deep sleep. 262 */ 263 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 264 PSTATE_ID_SOC_POWERDN) { 265 266 /* 267 * Reference clock used by the FPGAs is a lot slower. 268 */ 269 if (tegra_platform_is_fpga()) { 270 console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; 271 } else { 272 console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; 273 } 274 275 /* Initialize the runtime console */ 276 if (tegra_console_base != 0ULL) { 277 (void)console_init(tegra_console_base, console_clock, 278 TEGRA_CONSOLE_BAUDRATE); 279 } 280 281 /* 282 * Restore Memory Controller settings as it loses state 283 * during system suspend. 284 */ 285 tegra_memctrl_restore_settings(); 286 287 /* 288 * Security configuration to allow DRAM/device access. 289 */ 290 plat_params = bl31_get_plat_params(); 291 tegra_memctrl_tzdram_setup(plat_params->tzdram_base, 292 (uint32_t)plat_params->tzdram_size); 293 294 /* 295 * Set up the TZRAM memory aperture to allow only secure world 296 * access 297 */ 298 tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE); 299 } 300 301 /* 302 * Reset hardware settings. 303 */ 304 (void)tegra_soc_pwr_domain_on_finish(target_state); 305 } 306 307 /******************************************************************************* 308 * Handler called when a power domain has just been powered on after 309 * having been suspended earlier. The target_state encodes the low power state 310 * that each level has woken up from. 311 ******************************************************************************/ 312 void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 313 { 314 tegra_pwr_domain_on_finish(target_state); 315 } 316 317 /******************************************************************************* 318 * Handler called when the system wants to be powered off 319 ******************************************************************************/ 320 __dead2 void tegra_system_off(void) 321 { 322 INFO("Powering down system...\n"); 323 324 tegra_soc_prepare_system_off(); 325 } 326 327 /******************************************************************************* 328 * Handler called when the system wants to be restarted. 329 ******************************************************************************/ 330 __dead2 void tegra_system_reset(void) 331 { 332 INFO("Restarting system...\n"); 333 334 /* per-SoC system reset handler */ 335 (void)tegra_soc_prepare_system_reset(); 336 337 /* 338 * Program the PMC in order to restart the system. 339 */ 340 tegra_pmc_system_reset(); 341 } 342 343 /******************************************************************************* 344 * Handler called to check the validity of the power state parameter. 345 ******************************************************************************/ 346 int32_t tegra_validate_power_state(uint32_t power_state, 347 psci_power_state_t *req_state) 348 { 349 assert(req_state != NULL); 350 351 return tegra_soc_validate_power_state(power_state, req_state); 352 } 353 354 /******************************************************************************* 355 * Platform handler called to check the validity of the non secure entrypoint. 356 ******************************************************************************/ 357 int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint) 358 { 359 int32_t ret = PSCI_E_INVALID_ADDRESS; 360 361 /* 362 * Check if the non secure entrypoint lies within the non 363 * secure DRAM. 364 */ 365 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) { 366 ret = PSCI_E_SUCCESS; 367 } 368 369 return ret; 370 } 371 372 /******************************************************************************* 373 * Export the platform handlers to enable psci to invoke them 374 ******************************************************************************/ 375 static const plat_psci_ops_t tegra_plat_psci_ops = { 376 .cpu_standby = tegra_cpu_standby, 377 .pwr_domain_on = tegra_pwr_domain_on, 378 .pwr_domain_off = tegra_pwr_domain_off, 379 .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 380 .pwr_domain_suspend = tegra_pwr_domain_suspend, 381 .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 382 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 383 .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, 384 .system_off = tegra_system_off, 385 .system_reset = tegra_system_reset, 386 .validate_power_state = tegra_validate_power_state, 387 .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 388 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 389 }; 390 391 /******************************************************************************* 392 * Export the platform specific power ops and initialize Power Controller 393 ******************************************************************************/ 394 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 395 const plat_psci_ops_t **psci_ops) 396 { 397 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 398 399 /* 400 * Flush entrypoint variable to PoC since it will be 401 * accessed after a reset with the caches turned off. 402 */ 403 tegra_sec_entry_point = sec_entrypoint; 404 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 405 406 /* 407 * Reset hardware settings. 408 */ 409 (void)tegra_soc_pwr_domain_on_finish(&target_state); 410 411 /* 412 * Initialize PSCI ops struct 413 */ 414 *psci_ops = &tegra_plat_psci_ops; 415 416 return 0; 417 } 418 419 /******************************************************************************* 420 * Platform handler to calculate the proper target power level at the 421 * specified affinity level 422 ******************************************************************************/ 423 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 424 const plat_local_state_t *states, 425 unsigned int ncpu) 426 { 427 return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 428 } 429