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