1 /* 2 * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3 * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <string.h> 10 11 #include <arch.h> 12 #include <arch_helpers.h> 13 #include <common/bl_common.h> 14 #include <common/debug.h> 15 #include <context.h> 16 #include <cortex_a57.h> 17 #include <denver.h> 18 #include <lib/el3_runtime/context_mgmt.h> 19 #include <lib/psci/psci.h> 20 #include <plat/common/platform.h> 21 22 #include <mce.h> 23 #include <smmu.h> 24 #include <stdbool.h> 25 #include <t18x_ari.h> 26 #include <tegra186_private.h> 27 #include <tegra_private.h> 28 29 extern void memcpy16(void *dest, const void *src, unsigned int length); 30 31 /* state id mask */ 32 #define TEGRA186_STATE_ID_MASK 0xFU 33 /* constants to get power state's wake time */ 34 #define TEGRA186_WAKE_TIME_MASK 0x0FFFFFF0U 35 #define TEGRA186_WAKE_TIME_SHIFT 4U 36 /* default core wake mask for CPU_SUSPEND */ 37 #define TEGRA186_CORE_WAKE_MASK 0x180cU 38 /* context size to save during system suspend */ 39 #define TEGRA186_SE_CONTEXT_SIZE 3U 40 41 static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE]; 42 static struct tegra_psci_percpu_data { 43 uint32_t wake_time; 44 } __aligned(CACHE_WRITEBACK_GRANULE) tegra_percpu_data[PLATFORM_CORE_COUNT]; 45 46 int32_t tegra_soc_validate_power_state(uint32_t power_state, 47 psci_power_state_t *req_state) 48 { 49 uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK; 50 uint32_t cpu = plat_my_core_pos(); 51 int32_t ret = PSCI_E_SUCCESS; 52 53 /* save the core wake time (in TSC ticks)*/ 54 tegra_percpu_data[cpu].wake_time = (power_state & TEGRA186_WAKE_TIME_MASK) 55 << TEGRA186_WAKE_TIME_SHIFT; 56 57 /* 58 * Clean percpu_data[cpu] to DRAM. This needs to be done to ensure that 59 * the correct value is read in tegra_soc_pwr_domain_suspend(), which 60 * is called with caches disabled. It is possible to read a stale value 61 * from DRAM in that function, because the L2 cache is not flushed 62 * unless the cluster is entering CC6/CC7. 63 */ 64 clean_dcache_range((uint64_t)&tegra_percpu_data[cpu], 65 sizeof(tegra_percpu_data[cpu])); 66 67 /* Sanity check the requested state id */ 68 switch (state_id) { 69 case PSTATE_ID_CORE_IDLE: 70 case PSTATE_ID_CORE_POWERDN: 71 72 /* Core powerdown request */ 73 req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id; 74 req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; 75 76 break; 77 78 default: 79 ERROR("%s: unsupported state id (%d)\n", __func__, state_id); 80 ret = PSCI_E_INVALID_PARAMS; 81 break; 82 } 83 84 return ret; 85 } 86 87 int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) 88 { 89 (void)cpu_state; 90 return PSCI_E_SUCCESS; 91 } 92 93 int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) 94 { 95 const plat_local_state_t *pwr_domain_state; 96 uint8_t stateid_afflvl0, stateid_afflvl2; 97 uint32_t cpu = plat_my_core_pos(); 98 const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 99 mce_cstate_info_t cstate_info = { 0 }; 100 uint64_t smmu_ctx_base; 101 uint32_t val; 102 103 /* get the state ID */ 104 pwr_domain_state = target_state->pwr_domain_state; 105 stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & 106 TEGRA186_STATE_ID_MASK; 107 stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & 108 TEGRA186_STATE_ID_MASK; 109 110 if ((stateid_afflvl0 == PSTATE_ID_CORE_IDLE) || 111 (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN)) { 112 113 /* Enter CPU idle/powerdown */ 114 val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ? 115 (uint32_t)TEGRA_ARI_CORE_C6 : (uint32_t)TEGRA_ARI_CORE_C7; 116 (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, (uint64_t)val, 117 tegra_percpu_data[cpu].wake_time, 0U); 118 119 } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 120 121 /* save SE registers */ 122 se_regs[0] = mmio_read_32(TEGRA_SE0_BASE + 123 SE_MUTEX_WATCHDOG_NS_LIMIT); 124 se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE + 125 RNG_MUTEX_WATCHDOG_NS_LIMIT); 126 se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE + 127 PKA_MUTEX_WATCHDOG_NS_LIMIT); 128 129 /* save 'Secure Boot' Processor Feature Config Register */ 130 val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG); 131 mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val); 132 133 /* save SMMU context to TZDRAM */ 134 smmu_ctx_base = params_from_bl2->tzdram_base + 135 tegra186_get_smmu_ctx_offset(); 136 tegra_smmu_save_context((uintptr_t)smmu_ctx_base); 137 138 /* Prepare for system suspend */ 139 cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7; 140 cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC7; 141 cstate_info.system_state_force = 1; 142 cstate_info.update_wake_mask = 1; 143 mce_update_cstate_info(&cstate_info); 144 145 /* Loop until system suspend is allowed */ 146 do { 147 val = (uint32_t)mce_command_handler( 148 (uint64_t)MCE_CMD_IS_SC7_ALLOWED, 149 (uint64_t)TEGRA_ARI_CORE_C7, 150 MCE_CORE_SLEEP_TIME_INFINITE, 151 0U); 152 } while (val == 0U); 153 154 /* Instruct the MCE to enter system suspend state */ 155 (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, 156 (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U); 157 158 /* set system suspend state for house-keeping */ 159 tegra186_set_system_suspend_entry(); 160 161 } else { 162 ; /* do nothing */ 163 } 164 165 return PSCI_E_SUCCESS; 166 } 167 168 /******************************************************************************* 169 * Helper function to check if this is the last ON CPU in the cluster 170 ******************************************************************************/ 171 static bool tegra_last_cpu_in_cluster(const plat_local_state_t *states, 172 uint32_t ncpu) 173 { 174 plat_local_state_t target; 175 bool last_on_cpu = true; 176 uint32_t num_cpus = ncpu, pos = 0; 177 178 do { 179 target = states[pos]; 180 if (target != PLAT_MAX_OFF_STATE) { 181 last_on_cpu = false; 182 } 183 --num_cpus; 184 pos++; 185 } while (num_cpus != 0U); 186 187 return last_on_cpu; 188 } 189 190 /******************************************************************************* 191 * Helper function to get target power state for the cluster 192 ******************************************************************************/ 193 static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states, 194 uint32_t ncpu) 195 { 196 uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK; 197 uint32_t cpu = plat_my_core_pos(); 198 int32_t ret; 199 plat_local_state_t target = states[core_pos]; 200 mce_cstate_info_t cstate_info = { 0 }; 201 202 /* CPU suspend */ 203 if (target == PSTATE_ID_CORE_POWERDN) { 204 /* Program default wake mask */ 205 cstate_info.wake_mask = TEGRA186_CORE_WAKE_MASK; 206 cstate_info.update_wake_mask = 1; 207 mce_update_cstate_info(&cstate_info); 208 209 /* Check if CCx state is allowed. */ 210 ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED, 211 (uint64_t)TEGRA_ARI_CORE_C7, 212 tegra_percpu_data[cpu].wake_time, 213 0U); 214 if (ret == 0) { 215 target = PSCI_LOCAL_STATE_RUN; 216 } 217 } 218 219 /* CPU off */ 220 if (target == PLAT_MAX_OFF_STATE) { 221 /* Enable cluster powerdn from last CPU in the cluster */ 222 if (tegra_last_cpu_in_cluster(states, ncpu)) { 223 /* Enable CC7 state and turn off wake mask */ 224 cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7; 225 cstate_info.update_wake_mask = 1; 226 mce_update_cstate_info(&cstate_info); 227 228 /* Check if CCx state is allowed. */ 229 ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED, 230 (uint64_t)TEGRA_ARI_CORE_C7, 231 MCE_CORE_SLEEP_TIME_INFINITE, 232 0U); 233 if (ret == 0) { 234 target = PSCI_LOCAL_STATE_RUN; 235 } 236 237 } else { 238 239 /* Turn off wake_mask */ 240 cstate_info.update_wake_mask = 1; 241 mce_update_cstate_info(&cstate_info); 242 target = PSCI_LOCAL_STATE_RUN; 243 } 244 } 245 246 return target; 247 } 248 249 /******************************************************************************* 250 * Platform handler to calculate the proper target power level at the 251 * specified affinity level 252 ******************************************************************************/ 253 plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, 254 const plat_local_state_t *states, 255 uint32_t ncpu) 256 { 257 plat_local_state_t target = PSCI_LOCAL_STATE_RUN; 258 uint32_t cpu = plat_my_core_pos(); 259 260 /* System Suspend */ 261 if ((lvl == (uint32_t)MPIDR_AFFLVL2) && 262 (states[cpu] == PSTATE_ID_SOC_POWERDN)) { 263 target = PSTATE_ID_SOC_POWERDN; 264 } 265 266 /* CPU off, CPU suspend */ 267 if (lvl == (uint32_t)MPIDR_AFFLVL1) { 268 target = tegra_get_afflvl1_pwr_state(states, ncpu); 269 } 270 271 /* target cluster/system state */ 272 return target; 273 } 274 275 int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) 276 { 277 const plat_local_state_t *pwr_domain_state = 278 target_state->pwr_domain_state; 279 const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 280 uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & 281 TEGRA186_STATE_ID_MASK; 282 uint64_t val; 283 284 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 285 /* 286 * The TZRAM loses power when we enter system suspend. To 287 * allow graceful exit from system suspend, we need to copy 288 * BL3-1 over to TZDRAM. 289 */ 290 val = params_from_bl2->tzdram_base + 291 tegra186_get_cpu_reset_handler_size(); 292 memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE, 293 (uintptr_t)BL31_END - (uintptr_t)BL31_BASE); 294 } 295 296 return PSCI_E_SUCCESS; 297 } 298 299 int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 300 { 301 return PSCI_E_NOT_SUPPORTED; 302 } 303 304 int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) 305 { 306 int32_t ret = PSCI_E_SUCCESS; 307 uint64_t target_cpu = mpidr & MPIDR_CPU_MASK; 308 uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >> 309 MPIDR_AFFINITY_BITS; 310 311 if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) { 312 313 ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr); 314 ret = PSCI_E_NOT_PRESENT; 315 316 } else { 317 /* construct the target CPU # */ 318 target_cpu |= (target_cluster << 2); 319 320 (void)mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U); 321 } 322 323 return ret; 324 } 325 326 int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) 327 { 328 uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; 329 uint8_t stateid_afflvl0 = target_state->pwr_domain_state[MPIDR_AFFLVL0]; 330 mce_cstate_info_t cstate_info = { 0 }; 331 uint64_t impl, val; 332 const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); 333 334 impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 335 336 /* 337 * Enable ECC and Parity Protection for Cortex-A57 CPUs (Tegra186 338 * A02p and beyond). 339 */ 340 if ((plat_params->l2_ecc_parity_prot_dis != 1) && (impl != DENVER_IMPL)) { 341 342 val = read_l2ctlr_el1(); 343 val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT; 344 write_l2ctlr_el1(val); 345 } 346 347 /* 348 * Reset power state info for CPUs when onlining, we set 349 * deepest power when offlining a core but that may not be 350 * requested by non-secure sw which controls idle states. It 351 * will re-init this info from non-secure software when the 352 * core come online. 353 */ 354 if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) { 355 356 cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC1; 357 cstate_info.update_wake_mask = 1; 358 mce_update_cstate_info(&cstate_info); 359 } 360 361 /* 362 * Check if we are exiting from deep sleep and restore SE 363 * context if we are. 364 */ 365 if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 366 367 mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT, 368 se_regs[0]); 369 mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT, 370 se_regs[1]); 371 mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT, 372 se_regs[2]); 373 374 /* Init SMMU */ 375 tegra_smmu_init(); 376 377 /* 378 * Reset power state info for the last core doing SC7 379 * entry and exit, we set deepest power state as CC7 380 * and SC7 for SC7 entry which may not be requested by 381 * non-secure SW which controls idle states. 382 */ 383 cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC7; 384 cstate_info.system = (uint32_t)TEGRA_ARI_SYSTEM_SC1; 385 cstate_info.update_wake_mask = 1; 386 mce_update_cstate_info(&cstate_info); 387 } 388 389 return PSCI_E_SUCCESS; 390 } 391 392 int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) 393 { 394 uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK; 395 396 (void)target_state; 397 398 /* Disable Denver's DCO operations */ 399 if (impl == DENVER_IMPL) { 400 denver_disable_dco(); 401 } 402 403 /* Turn off CPU */ 404 (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, 405 (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U); 406 407 return PSCI_E_SUCCESS; 408 } 409 410 __dead2 void tegra_soc_prepare_system_off(void) 411 { 412 /* power off the entire system */ 413 mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF); 414 415 wfi(); 416 417 /* wait for the system to power down */ 418 for (;;) { 419 ; 420 } 421 } 422 423 int32_t tegra_soc_prepare_system_reset(void) 424 { 425 mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT); 426 427 return PSCI_E_SUCCESS; 428 } 429