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