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_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 int tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 54 { 55 return PSCI_E_NOT_SUPPORTED; 56 } 57 58 int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) 59 { 60 return PSCI_E_NOT_SUPPORTED; 61 } 62 63 int tegra_soc_pwr_domain_on(u_register_t mpidr) 64 { 65 return PSCI_E_SUCCESS; 66 } 67 68 int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) 69 { 70 return PSCI_E_SUCCESS; 71 } 72 73 int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) 74 { 75 return PSCI_E_SUCCESS; 76 } 77 78 int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) 79 { 80 return PSCI_E_SUCCESS; 81 } 82 83 int tegra_soc_prepare_system_reset(void) 84 { 85 return PSCI_E_SUCCESS; 86 } 87 88 __dead2 void tegra_soc_prepare_system_off(void) 89 { 90 ERROR("Tegra System Off: operation not handled.\n"); 91 panic(); 92 } 93 94 plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, 95 const plat_local_state_t *states, 96 unsigned int ncpu) 97 { 98 plat_local_state_t target = PLAT_MAX_OFF_STATE, temp; 99 100 assert(ncpu); 101 102 do { 103 temp = *states++; 104 if ((temp < target)) 105 target = temp; 106 } while (--ncpu); 107 108 return target; 109 } 110 111 /******************************************************************************* 112 * This handler is called by the PSCI implementation during the `SYSTEM_SUSPEND` 113 * call to get the `power_state` parameter. This allows the platform to encode 114 * the appropriate State-ID field within the `power_state` parameter which can 115 * be utilized in `pwr_domain_suspend()` to suspend to system affinity level. 116 ******************************************************************************/ 117 void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state) 118 { 119 /* all affinities use system suspend state id */ 120 for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) 121 req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN; 122 } 123 124 /******************************************************************************* 125 * Handler called when an affinity instance is about to enter standby. 126 ******************************************************************************/ 127 void tegra_cpu_standby(plat_local_state_t cpu_state) 128 { 129 /* 130 * Enter standby state 131 * dsb is good practice before using wfi to enter low power states 132 */ 133 dsb(); 134 wfi(); 135 } 136 137 /******************************************************************************* 138 * Handler called when an affinity instance is about to be turned on. The 139 * level and mpidr determine the affinity instance. 140 ******************************************************************************/ 141 int tegra_pwr_domain_on(u_register_t mpidr) 142 { 143 return tegra_soc_pwr_domain_on(mpidr); 144 } 145 146 /******************************************************************************* 147 * Handler called when a power domain is about to be turned off. The 148 * target_state encodes the power state that each level should transition to. 149 ******************************************************************************/ 150 void tegra_pwr_domain_off(const psci_power_state_t *target_state) 151 { 152 tegra_soc_pwr_domain_off(target_state); 153 } 154 155 /******************************************************************************* 156 * Handler called when a power domain is about to be suspended. The 157 * target_state encodes the power state that each level should transition to. 158 * This handler is called with SMP and data cache enabled, when 159 * HW_ASSISTED_COHERENCY = 0 160 ******************************************************************************/ 161 void tegra_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 162 { 163 tegra_soc_pwr_domain_suspend_pwrdown_early(target_state); 164 } 165 166 /******************************************************************************* 167 * Handler called when a power domain is about to be suspended. The 168 * target_state encodes the power state that each level should transition to. 169 ******************************************************************************/ 170 void tegra_pwr_domain_suspend(const psci_power_state_t *target_state) 171 { 172 tegra_soc_pwr_domain_suspend(target_state); 173 174 /* Disable console if we are entering deep sleep. */ 175 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 176 PSTATE_ID_SOC_POWERDN) 177 console_uninit(); 178 179 /* disable GICC */ 180 tegra_gic_cpuif_deactivate(); 181 } 182 183 /******************************************************************************* 184 * Handler called at the end of the power domain suspend sequence. The 185 * target_state encodes the power state that each level should transition to. 186 ******************************************************************************/ 187 __dead2 void tegra_pwr_domain_power_down_wfi(const psci_power_state_t 188 *target_state) 189 { 190 uint8_t pwr_state = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; 191 uint64_t rmr_el3 = 0; 192 193 /* call the chip's power down handler */ 194 tegra_soc_pwr_domain_power_down_wfi(target_state); 195 196 /* 197 * If we are in fake system suspend mode, ensure we start doing 198 * procedures that help in looping back towards system suspend exit 199 * instead of calling WFI by requesting a warm reset. 200 * Else, just call WFI to enter low power state. 201 */ 202 if ((tegra_fake_system_suspend != 0U) && 203 (pwr_state == (uint8_t)PSTATE_ID_SOC_POWERDN)) { 204 205 /* warm reboot */ 206 rmr_el3 = read_rmr_el3(); 207 write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU); 208 209 } else { 210 /* enter power down state */ 211 wfi(); 212 } 213 214 /* we can never reach here */ 215 panic(); 216 } 217 218 /******************************************************************************* 219 * Handler called when a power domain has just been powered on after 220 * being turned off earlier. The target_state encodes the low power state that 221 * each level has woken up from. 222 ******************************************************************************/ 223 void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state) 224 { 225 plat_params_from_bl2_t *plat_params; 226 uint32_t console_clock; 227 228 /* 229 * Initialize the GIC cpu and distributor interfaces 230 */ 231 plat_gic_setup(); 232 233 /* 234 * Check if we are exiting from deep sleep. 235 */ 236 if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 237 PSTATE_ID_SOC_POWERDN) { 238 239 /* 240 * Reference clock used by the FPGAs is a lot slower. 241 */ 242 if (tegra_platform_is_fpga() == 1U) { 243 console_clock = TEGRA_BOOT_UART_CLK_13_MHZ; 244 } else { 245 console_clock = TEGRA_BOOT_UART_CLK_408_MHZ; 246 } 247 248 /* Initialize the runtime console */ 249 if (tegra_console_base != (uint64_t)0) { 250 console_init(tegra_console_base, console_clock, 251 TEGRA_CONSOLE_BAUDRATE); 252 } 253 254 /* 255 * Restore Memory Controller settings as it loses state 256 * during system suspend. 257 */ 258 tegra_memctrl_restore_settings(); 259 260 /* 261 * Security configuration to allow DRAM/device access. 262 */ 263 plat_params = bl31_get_plat_params(); 264 tegra_memctrl_tzdram_setup(plat_params->tzdram_base, 265 plat_params->tzdram_size); 266 267 /* 268 * Set up the TZRAM memory aperture to allow only secure world 269 * access 270 */ 271 tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE); 272 } 273 274 /* 275 * Reset hardware settings. 276 */ 277 tegra_soc_pwr_domain_on_finish(target_state); 278 } 279 280 /******************************************************************************* 281 * Handler called when a power domain has just been powered on after 282 * having been suspended earlier. The target_state encodes the low power state 283 * that each level has woken up from. 284 ******************************************************************************/ 285 void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state) 286 { 287 tegra_pwr_domain_on_finish(target_state); 288 } 289 290 /******************************************************************************* 291 * Handler called when the system wants to be powered off 292 ******************************************************************************/ 293 __dead2 void tegra_system_off(void) 294 { 295 INFO("Powering down system...\n"); 296 297 tegra_soc_prepare_system_off(); 298 } 299 300 /******************************************************************************* 301 * Handler called when the system wants to be restarted. 302 ******************************************************************************/ 303 __dead2 void tegra_system_reset(void) 304 { 305 INFO("Restarting system...\n"); 306 307 /* per-SoC system reset handler */ 308 tegra_soc_prepare_system_reset(); 309 310 /* 311 * Program the PMC in order to restart the system. 312 */ 313 tegra_pmc_system_reset(); 314 } 315 316 /******************************************************************************* 317 * Handler called to check the validity of the power state parameter. 318 ******************************************************************************/ 319 int32_t tegra_validate_power_state(unsigned int power_state, 320 psci_power_state_t *req_state) 321 { 322 assert(req_state); 323 324 return tegra_soc_validate_power_state(power_state, req_state); 325 } 326 327 /******************************************************************************* 328 * Platform handler called to check the validity of the non secure entrypoint. 329 ******************************************************************************/ 330 int tegra_validate_ns_entrypoint(uintptr_t entrypoint) 331 { 332 /* 333 * Check if the non secure entrypoint lies within the non 334 * secure DRAM. 335 */ 336 if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) 337 return PSCI_E_SUCCESS; 338 339 return PSCI_E_INVALID_ADDRESS; 340 } 341 342 /******************************************************************************* 343 * Export the platform handlers to enable psci to invoke them 344 ******************************************************************************/ 345 static const plat_psci_ops_t tegra_plat_psci_ops = { 346 .cpu_standby = tegra_cpu_standby, 347 .pwr_domain_on = tegra_pwr_domain_on, 348 .pwr_domain_off = tegra_pwr_domain_off, 349 .pwr_domain_suspend_pwrdown_early = tegra_pwr_domain_suspend_pwrdown_early, 350 .pwr_domain_suspend = tegra_pwr_domain_suspend, 351 .pwr_domain_on_finish = tegra_pwr_domain_on_finish, 352 .pwr_domain_suspend_finish = tegra_pwr_domain_suspend_finish, 353 .pwr_domain_pwr_down_wfi = tegra_pwr_domain_power_down_wfi, 354 .system_off = tegra_system_off, 355 .system_reset = tegra_system_reset, 356 .validate_power_state = tegra_validate_power_state, 357 .validate_ns_entrypoint = tegra_validate_ns_entrypoint, 358 .get_sys_suspend_power_state = tegra_get_sys_suspend_power_state, 359 }; 360 361 /******************************************************************************* 362 * Export the platform specific power ops and initialize Power Controller 363 ******************************************************************************/ 364 int plat_setup_psci_ops(uintptr_t sec_entrypoint, 365 const plat_psci_ops_t **psci_ops) 366 { 367 psci_power_state_t target_state = { { PSCI_LOCAL_STATE_RUN } }; 368 369 /* 370 * Flush entrypoint variable to PoC since it will be 371 * accessed after a reset with the caches turned off. 372 */ 373 tegra_sec_entry_point = sec_entrypoint; 374 flush_dcache_range((uint64_t)&tegra_sec_entry_point, sizeof(uint64_t)); 375 376 /* 377 * Reset hardware settings. 378 */ 379 tegra_soc_pwr_domain_on_finish(&target_state); 380 381 /* 382 * Initialize PSCI ops struct 383 */ 384 *psci_ops = &tegra_plat_psci_ops; 385 386 return 0; 387 } 388 389 /******************************************************************************* 390 * Platform handler to calculate the proper target power level at the 391 * specified affinity level 392 ******************************************************************************/ 393 plat_local_state_t plat_get_target_pwr_state(unsigned int lvl, 394 const plat_local_state_t *states, 395 unsigned int ncpu) 396 { 397 return tegra_soc_get_target_pwr_state(lvl, states, ncpu); 398 } 399