1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <arch.h> 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <stdbool.h> 10*91f16700Schasinglulu #include <string.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <arch_helpers.h> 13*91f16700Schasinglulu #include <bpmp_ipc.h> 14*91f16700Schasinglulu #include <common/bl_common.h> 15*91f16700Schasinglulu #include <common/debug.h> 16*91f16700Schasinglulu #include <context.h> 17*91f16700Schasinglulu #include <drivers/delay_timer.h> 18*91f16700Schasinglulu #include <denver.h> 19*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 20*91f16700Schasinglulu #include <lib/psci/psci.h> 21*91f16700Schasinglulu #include <mce.h> 22*91f16700Schasinglulu #include <mce_private.h> 23*91f16700Schasinglulu #include <memctrl_v2.h> 24*91f16700Schasinglulu #include <plat/common/platform.h> 25*91f16700Schasinglulu #include <se.h> 26*91f16700Schasinglulu #include <smmu.h> 27*91f16700Schasinglulu #include <t194_nvg.h> 28*91f16700Schasinglulu #include <tegra194_private.h> 29*91f16700Schasinglulu #include <tegra_platform.h> 30*91f16700Schasinglulu #include <tegra_private.h> 31*91f16700Schasinglulu 32*91f16700Schasinglulu extern uint32_t __tegra194_cpu_reset_handler_data, 33*91f16700Schasinglulu __tegra194_cpu_reset_handler_end; 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* TZDRAM offset for saving SMMU context */ 36*91f16700Schasinglulu #define TEGRA194_SMMU_CTX_OFFSET 16U 37*91f16700Schasinglulu 38*91f16700Schasinglulu /* state id mask */ 39*91f16700Schasinglulu #define TEGRA194_STATE_ID_MASK 0xFU 40*91f16700Schasinglulu /* constants to get power state's wake time */ 41*91f16700Schasinglulu #define TEGRA194_WAKE_TIME_MASK 0x0FFFFFF0U 42*91f16700Schasinglulu #define TEGRA194_WAKE_TIME_SHIFT 4U 43*91f16700Schasinglulu /* default core wake mask for CPU_SUSPEND */ 44*91f16700Schasinglulu #define TEGRA194_CORE_WAKE_MASK 0x180cU 45*91f16700Schasinglulu 46*91f16700Schasinglulu static struct t19x_psci_percpu_data { 47*91f16700Schasinglulu uint32_t wake_time; 48*91f16700Schasinglulu } __aligned(CACHE_WRITEBACK_GRANULE) t19x_percpu_data[PLATFORM_CORE_COUNT]; 49*91f16700Schasinglulu 50*91f16700Schasinglulu int32_t tegra_soc_validate_power_state(uint32_t power_state, 51*91f16700Schasinglulu psci_power_state_t *req_state) 52*91f16700Schasinglulu { 53*91f16700Schasinglulu uint8_t state_id = (uint8_t)psci_get_pstate_id(power_state) & 54*91f16700Schasinglulu TEGRA194_STATE_ID_MASK; 55*91f16700Schasinglulu uint32_t cpu = plat_my_core_pos(); 56*91f16700Schasinglulu int32_t ret = PSCI_E_SUCCESS; 57*91f16700Schasinglulu 58*91f16700Schasinglulu /* save the core wake time (in TSC ticks)*/ 59*91f16700Schasinglulu t19x_percpu_data[cpu].wake_time = (power_state & TEGRA194_WAKE_TIME_MASK) 60*91f16700Schasinglulu << TEGRA194_WAKE_TIME_SHIFT; 61*91f16700Schasinglulu 62*91f16700Schasinglulu /* 63*91f16700Schasinglulu * Clean t19x_percpu_data[cpu] to DRAM. This needs to be done to ensure 64*91f16700Schasinglulu * that the correct value is read in tegra_soc_pwr_domain_suspend(), 65*91f16700Schasinglulu * which is called with caches disabled. It is possible to read a stale 66*91f16700Schasinglulu * value from DRAM in that function, because the L2 cache is not flushed 67*91f16700Schasinglulu * unless the cluster is entering CC6/CC7. 68*91f16700Schasinglulu */ 69*91f16700Schasinglulu clean_dcache_range((uint64_t)&t19x_percpu_data[cpu], 70*91f16700Schasinglulu sizeof(t19x_percpu_data[cpu])); 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Sanity check the requested state id */ 73*91f16700Schasinglulu switch (state_id) { 74*91f16700Schasinglulu case PSTATE_ID_CORE_IDLE: 75*91f16700Schasinglulu 76*91f16700Schasinglulu if (psci_get_pstate_type(power_state) != PSTATE_TYPE_STANDBY) { 77*91f16700Schasinglulu ret = PSCI_E_INVALID_PARAMS; 78*91f16700Schasinglulu break; 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* Core idle request */ 82*91f16700Schasinglulu req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; 83*91f16700Schasinglulu req_state->pwr_domain_state[MPIDR_AFFLVL1] = PSCI_LOCAL_STATE_RUN; 84*91f16700Schasinglulu break; 85*91f16700Schasinglulu 86*91f16700Schasinglulu default: 87*91f16700Schasinglulu ERROR("%s: unsupported state id (%d)\n", __func__, state_id); 88*91f16700Schasinglulu ret = PSCI_E_INVALID_PARAMS; 89*91f16700Schasinglulu break; 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu return ret; 93*91f16700Schasinglulu } 94*91f16700Schasinglulu 95*91f16700Schasinglulu int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) 96*91f16700Schasinglulu { 97*91f16700Schasinglulu uint32_t cpu = plat_my_core_pos(); 98*91f16700Schasinglulu mce_cstate_info_t cstate_info = { 0 }; 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* Program default wake mask */ 101*91f16700Schasinglulu cstate_info.wake_mask = TEGRA194_CORE_WAKE_MASK; 102*91f16700Schasinglulu cstate_info.update_wake_mask = 1; 103*91f16700Schasinglulu mce_update_cstate_info(&cstate_info); 104*91f16700Schasinglulu 105*91f16700Schasinglulu /* Enter CPU idle */ 106*91f16700Schasinglulu (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, 107*91f16700Schasinglulu (uint64_t)TEGRA_NVG_CORE_C6, 108*91f16700Schasinglulu t19x_percpu_data[cpu].wake_time, 109*91f16700Schasinglulu 0U); 110*91f16700Schasinglulu 111*91f16700Schasinglulu return PSCI_E_SUCCESS; 112*91f16700Schasinglulu } 113*91f16700Schasinglulu 114*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) 115*91f16700Schasinglulu { 116*91f16700Schasinglulu const plat_local_state_t *pwr_domain_state; 117*91f16700Schasinglulu uint8_t stateid_afflvl2; 118*91f16700Schasinglulu plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 119*91f16700Schasinglulu uint64_t mc_ctx_base; 120*91f16700Schasinglulu uint32_t val; 121*91f16700Schasinglulu mce_cstate_info_t sc7_cstate_info = { 122*91f16700Schasinglulu .cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6, 123*91f16700Schasinglulu .ccplex = (uint32_t)TEGRA_NVG_CG_CG7, 124*91f16700Schasinglulu .system = (uint32_t)TEGRA_NVG_SYSTEM_SC7, 125*91f16700Schasinglulu .system_state_force = 1U, 126*91f16700Schasinglulu .update_wake_mask = 1U, 127*91f16700Schasinglulu }; 128*91f16700Schasinglulu int32_t ret = 0; 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* get the state ID */ 131*91f16700Schasinglulu pwr_domain_state = target_state->pwr_domain_state; 132*91f16700Schasinglulu stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & 133*91f16700Schasinglulu TEGRA194_STATE_ID_MASK; 134*91f16700Schasinglulu 135*91f16700Schasinglulu if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 136*91f16700Schasinglulu 137*91f16700Schasinglulu /* save 'Secure Boot' Processor Feature Config Register */ 138*91f16700Schasinglulu val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG); 139*91f16700Schasinglulu mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val); 140*91f16700Schasinglulu 141*91f16700Schasinglulu /* save MC context */ 142*91f16700Schasinglulu mc_ctx_base = params_from_bl2->tzdram_base + 143*91f16700Schasinglulu tegra194_get_mc_ctx_offset(); 144*91f16700Schasinglulu tegra_mc_save_context((uintptr_t)mc_ctx_base); 145*91f16700Schasinglulu 146*91f16700Schasinglulu /* 147*91f16700Schasinglulu * Suspend SE, RNG1 and PKA1 only on silcon and fpga, 148*91f16700Schasinglulu * since VDK does not support atomic se ctx save 149*91f16700Schasinglulu */ 150*91f16700Schasinglulu if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { 151*91f16700Schasinglulu ret = tegra_se_suspend(); 152*91f16700Schasinglulu assert(ret == 0); 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu /* Prepare for system suspend */ 156*91f16700Schasinglulu mce_update_cstate_info(&sc7_cstate_info); 157*91f16700Schasinglulu 158*91f16700Schasinglulu do { 159*91f16700Schasinglulu val = (uint32_t)mce_command_handler( 160*91f16700Schasinglulu (uint32_t)MCE_CMD_IS_SC7_ALLOWED, 161*91f16700Schasinglulu (uint32_t)TEGRA_NVG_CORE_C7, 162*91f16700Schasinglulu MCE_CORE_SLEEP_TIME_INFINITE, 163*91f16700Schasinglulu 0U); 164*91f16700Schasinglulu } while (val == 0U); 165*91f16700Schasinglulu 166*91f16700Schasinglulu /* Instruct the MCE to enter system suspend state */ 167*91f16700Schasinglulu ret = mce_command_handler( 168*91f16700Schasinglulu (uint64_t)MCE_CMD_ENTER_CSTATE, 169*91f16700Schasinglulu (uint64_t)TEGRA_NVG_CORE_C7, 170*91f16700Schasinglulu MCE_CORE_SLEEP_TIME_INFINITE, 171*91f16700Schasinglulu 0U); 172*91f16700Schasinglulu assert(ret == 0); 173*91f16700Schasinglulu 174*91f16700Schasinglulu /* set system suspend state for house-keeping */ 175*91f16700Schasinglulu tegra194_set_system_suspend_entry(); 176*91f16700Schasinglulu } 177*91f16700Schasinglulu 178*91f16700Schasinglulu return PSCI_E_SUCCESS; 179*91f16700Schasinglulu } 180*91f16700Schasinglulu 181*91f16700Schasinglulu /******************************************************************************* 182*91f16700Schasinglulu * Helper function to check if this is the last ON CPU in the cluster 183*91f16700Schasinglulu ******************************************************************************/ 184*91f16700Schasinglulu static bool tegra_last_on_cpu_in_cluster(const plat_local_state_t *states, 185*91f16700Schasinglulu uint32_t ncpu) 186*91f16700Schasinglulu { 187*91f16700Schasinglulu plat_local_state_t target; 188*91f16700Schasinglulu bool last_on_cpu = true; 189*91f16700Schasinglulu uint32_t num_cpus = ncpu, pos = 0; 190*91f16700Schasinglulu 191*91f16700Schasinglulu do { 192*91f16700Schasinglulu target = states[pos]; 193*91f16700Schasinglulu if (target != PLAT_MAX_OFF_STATE) { 194*91f16700Schasinglulu last_on_cpu = false; 195*91f16700Schasinglulu } 196*91f16700Schasinglulu --num_cpus; 197*91f16700Schasinglulu pos++; 198*91f16700Schasinglulu } while (num_cpus != 0U); 199*91f16700Schasinglulu 200*91f16700Schasinglulu return last_on_cpu; 201*91f16700Schasinglulu } 202*91f16700Schasinglulu 203*91f16700Schasinglulu /******************************************************************************* 204*91f16700Schasinglulu * Helper function to get target power state for the cluster 205*91f16700Schasinglulu ******************************************************************************/ 206*91f16700Schasinglulu static plat_local_state_t tegra_get_afflvl1_pwr_state(const plat_local_state_t *states, 207*91f16700Schasinglulu uint32_t ncpu) 208*91f16700Schasinglulu { 209*91f16700Schasinglulu uint32_t core_pos = (uint32_t)read_mpidr() & (uint32_t)MPIDR_CPU_MASK; 210*91f16700Schasinglulu plat_local_state_t target = states[core_pos]; 211*91f16700Schasinglulu mce_cstate_info_t cstate_info = { 0 }; 212*91f16700Schasinglulu 213*91f16700Schasinglulu /* CPU off */ 214*91f16700Schasinglulu if (target == PLAT_MAX_OFF_STATE) { 215*91f16700Schasinglulu 216*91f16700Schasinglulu /* Enable cluster powerdn from last CPU in the cluster */ 217*91f16700Schasinglulu if (tegra_last_on_cpu_in_cluster(states, ncpu)) { 218*91f16700Schasinglulu 219*91f16700Schasinglulu /* Enable CC6 state and turn off wake mask */ 220*91f16700Schasinglulu cstate_info.cluster = (uint32_t)TEGRA_NVG_CLUSTER_CC6; 221*91f16700Schasinglulu cstate_info.ccplex = (uint32_t)TEGRA_NVG_CG_CG7; 222*91f16700Schasinglulu cstate_info.system_state_force = 1; 223*91f16700Schasinglulu cstate_info.update_wake_mask = 1U; 224*91f16700Schasinglulu mce_update_cstate_info(&cstate_info); 225*91f16700Schasinglulu 226*91f16700Schasinglulu } else { 227*91f16700Schasinglulu 228*91f16700Schasinglulu /* Turn off wake_mask */ 229*91f16700Schasinglulu cstate_info.update_wake_mask = 1U; 230*91f16700Schasinglulu mce_update_cstate_info(&cstate_info); 231*91f16700Schasinglulu target = PSCI_LOCAL_STATE_RUN; 232*91f16700Schasinglulu } 233*91f16700Schasinglulu } 234*91f16700Schasinglulu 235*91f16700Schasinglulu return target; 236*91f16700Schasinglulu } 237*91f16700Schasinglulu 238*91f16700Schasinglulu /******************************************************************************* 239*91f16700Schasinglulu * Platform handler to calculate the proper target power level at the 240*91f16700Schasinglulu * specified affinity level 241*91f16700Schasinglulu ******************************************************************************/ 242*91f16700Schasinglulu plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl, 243*91f16700Schasinglulu const plat_local_state_t *states, 244*91f16700Schasinglulu uint32_t ncpu) 245*91f16700Schasinglulu { 246*91f16700Schasinglulu plat_local_state_t target = PSCI_LOCAL_STATE_RUN; 247*91f16700Schasinglulu uint32_t cpu = plat_my_core_pos(); 248*91f16700Schasinglulu 249*91f16700Schasinglulu /* System Suspend */ 250*91f16700Schasinglulu if ((lvl == (uint32_t)MPIDR_AFFLVL2) && (states[cpu] == PSTATE_ID_SOC_POWERDN)) { 251*91f16700Schasinglulu target = PSTATE_ID_SOC_POWERDN; 252*91f16700Schasinglulu } 253*91f16700Schasinglulu 254*91f16700Schasinglulu /* CPU off, CPU suspend */ 255*91f16700Schasinglulu if (lvl == (uint32_t)MPIDR_AFFLVL1) { 256*91f16700Schasinglulu target = tegra_get_afflvl1_pwr_state(states, ncpu); 257*91f16700Schasinglulu } 258*91f16700Schasinglulu 259*91f16700Schasinglulu /* target cluster/system state */ 260*91f16700Schasinglulu return target; 261*91f16700Schasinglulu } 262*91f16700Schasinglulu 263*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) 264*91f16700Schasinglulu { 265*91f16700Schasinglulu const plat_local_state_t *pwr_domain_state = 266*91f16700Schasinglulu target_state->pwr_domain_state; 267*91f16700Schasinglulu plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 268*91f16700Schasinglulu uint8_t stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & 269*91f16700Schasinglulu TEGRA194_STATE_ID_MASK; 270*91f16700Schasinglulu uint64_t src_len_in_bytes = (uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE; 271*91f16700Schasinglulu uint64_t val; 272*91f16700Schasinglulu int32_t ret = PSCI_E_SUCCESS; 273*91f16700Schasinglulu 274*91f16700Schasinglulu if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 275*91f16700Schasinglulu val = params_from_bl2->tzdram_base + 276*91f16700Schasinglulu tegra194_get_cpu_reset_handler_size(); 277*91f16700Schasinglulu 278*91f16700Schasinglulu /* initialise communication channel with BPMP */ 279*91f16700Schasinglulu ret = tegra_bpmp_ipc_init(); 280*91f16700Schasinglulu assert(ret == 0); 281*91f16700Schasinglulu 282*91f16700Schasinglulu /* Enable SE clock before SE context save */ 283*91f16700Schasinglulu ret = tegra_bpmp_ipc_enable_clock(TEGRA194_CLK_SE); 284*91f16700Schasinglulu assert(ret == 0); 285*91f16700Schasinglulu 286*91f16700Schasinglulu /* 287*91f16700Schasinglulu * It is very unlikely that the BL31 image would be 288*91f16700Schasinglulu * bigger than 2^32 bytes 289*91f16700Schasinglulu */ 290*91f16700Schasinglulu assert(src_len_in_bytes < UINT32_MAX); 291*91f16700Schasinglulu 292*91f16700Schasinglulu if (tegra_se_calculate_save_sha256(BL31_BASE, 293*91f16700Schasinglulu (uint32_t)src_len_in_bytes) != 0) { 294*91f16700Schasinglulu ERROR("Hash calculation failed. Reboot\n"); 295*91f16700Schasinglulu (void)tegra_soc_prepare_system_reset(); 296*91f16700Schasinglulu } 297*91f16700Schasinglulu 298*91f16700Schasinglulu /* 299*91f16700Schasinglulu * The TZRAM loses power when we enter system suspend. To 300*91f16700Schasinglulu * allow graceful exit from system suspend, we need to copy 301*91f16700Schasinglulu * BL3-1 over to TZDRAM. 302*91f16700Schasinglulu */ 303*91f16700Schasinglulu val = params_from_bl2->tzdram_base + 304*91f16700Schasinglulu tegra194_get_cpu_reset_handler_size(); 305*91f16700Schasinglulu memcpy((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE, 306*91f16700Schasinglulu src_len_in_bytes); 307*91f16700Schasinglulu 308*91f16700Schasinglulu /* Disable SE clock after SE context save */ 309*91f16700Schasinglulu ret = tegra_bpmp_ipc_disable_clock(TEGRA194_CLK_SE); 310*91f16700Schasinglulu assert(ret == 0); 311*91f16700Schasinglulu } 312*91f16700Schasinglulu 313*91f16700Schasinglulu return ret; 314*91f16700Schasinglulu } 315*91f16700Schasinglulu 316*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 317*91f16700Schasinglulu { 318*91f16700Schasinglulu return PSCI_E_NOT_SUPPORTED; 319*91f16700Schasinglulu } 320*91f16700Schasinglulu 321*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) 322*91f16700Schasinglulu { 323*91f16700Schasinglulu uint64_t target_cpu = mpidr & MPIDR_CPU_MASK; 324*91f16700Schasinglulu uint64_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >> 325*91f16700Schasinglulu MPIDR_AFFINITY_BITS; 326*91f16700Schasinglulu int32_t ret = 0; 327*91f16700Schasinglulu 328*91f16700Schasinglulu if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) { 329*91f16700Schasinglulu ERROR("%s: unsupported CPU (0x%lx)\n", __func__ , mpidr); 330*91f16700Schasinglulu return PSCI_E_NOT_PRESENT; 331*91f16700Schasinglulu } 332*91f16700Schasinglulu 333*91f16700Schasinglulu /* construct the target CPU # */ 334*91f16700Schasinglulu target_cpu += (target_cluster << 1U); 335*91f16700Schasinglulu 336*91f16700Schasinglulu ret = mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U); 337*91f16700Schasinglulu if (ret < 0) { 338*91f16700Schasinglulu return PSCI_E_DENIED; 339*91f16700Schasinglulu } 340*91f16700Schasinglulu 341*91f16700Schasinglulu return PSCI_E_SUCCESS; 342*91f16700Schasinglulu } 343*91f16700Schasinglulu 344*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) 345*91f16700Schasinglulu { 346*91f16700Schasinglulu const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); 347*91f16700Schasinglulu uint8_t enable_ccplex_lock_step = params_from_bl2->enable_ccplex_lock_step; 348*91f16700Schasinglulu uint8_t stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; 349*91f16700Schasinglulu cpu_context_t *ctx = cm_get_context(NON_SECURE); 350*91f16700Schasinglulu uint64_t actlr_elx; 351*91f16700Schasinglulu 352*91f16700Schasinglulu /* 353*91f16700Schasinglulu * Reset power state info for CPUs when onlining, we set 354*91f16700Schasinglulu * deepest power when offlining a core but that may not be 355*91f16700Schasinglulu * requested by non-secure sw which controls idle states. It 356*91f16700Schasinglulu * will re-init this info from non-secure software when the 357*91f16700Schasinglulu * core come online. 358*91f16700Schasinglulu */ 359*91f16700Schasinglulu actlr_elx = read_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1)); 360*91f16700Schasinglulu actlr_elx &= ~DENVER_CPU_PMSTATE_MASK; 361*91f16700Schasinglulu actlr_elx |= DENVER_CPU_PMSTATE_C1; 362*91f16700Schasinglulu write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx)); 363*91f16700Schasinglulu 364*91f16700Schasinglulu /* 365*91f16700Schasinglulu * Check if we are exiting from deep sleep and restore SE 366*91f16700Schasinglulu * context if we are. 367*91f16700Schasinglulu */ 368*91f16700Schasinglulu if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 369*91f16700Schasinglulu 370*91f16700Schasinglulu #if ENABLE_STRICT_CHECKING_MODE 371*91f16700Schasinglulu /* 372*91f16700Schasinglulu * Enable strict checking after programming the GSC for 373*91f16700Schasinglulu * enabling TZSRAM and TZDRAM 374*91f16700Schasinglulu */ 375*91f16700Schasinglulu mce_enable_strict_checking(); 376*91f16700Schasinglulu #endif 377*91f16700Schasinglulu 378*91f16700Schasinglulu /* Init SMMU */ 379*91f16700Schasinglulu tegra_smmu_init(); 380*91f16700Schasinglulu 381*91f16700Schasinglulu /* Resume SE, RNG1 and PKA1 */ 382*91f16700Schasinglulu tegra_se_resume(); 383*91f16700Schasinglulu 384*91f16700Schasinglulu /* 385*91f16700Schasinglulu * Program XUSB STREAMIDs 386*91f16700Schasinglulu * ====================== 387*91f16700Schasinglulu * T19x XUSB has support for XUSB virtualization. It will 388*91f16700Schasinglulu * have one physical function (PF) and four Virtual functions 389*91f16700Schasinglulu * (VF) 390*91f16700Schasinglulu * 391*91f16700Schasinglulu * There were below two SIDs for XUSB until T186. 392*91f16700Schasinglulu * 1) #define TEGRA_SID_XUSB_HOST 0x1bU 393*91f16700Schasinglulu * 2) #define TEGRA_SID_XUSB_DEV 0x1cU 394*91f16700Schasinglulu * 395*91f16700Schasinglulu * We have below four new SIDs added for VF(s) 396*91f16700Schasinglulu * 3) #define TEGRA_SID_XUSB_VF0 0x5dU 397*91f16700Schasinglulu * 4) #define TEGRA_SID_XUSB_VF1 0x5eU 398*91f16700Schasinglulu * 5) #define TEGRA_SID_XUSB_VF2 0x5fU 399*91f16700Schasinglulu * 6) #define TEGRA_SID_XUSB_VF3 0x60U 400*91f16700Schasinglulu * 401*91f16700Schasinglulu * When virtualization is enabled then we have to disable SID 402*91f16700Schasinglulu * override and program above SIDs in below newly added SID 403*91f16700Schasinglulu * registers in XUSB PADCTL MMIO space. These registers are 404*91f16700Schasinglulu * TZ protected and so need to be done in ATF. 405*91f16700Schasinglulu * 406*91f16700Schasinglulu * a) #define XUSB_PADCTL_HOST_AXI_STREAMID_PF_0 (0x136cU) 407*91f16700Schasinglulu * b) #define XUSB_PADCTL_DEV_AXI_STREAMID_PF_0 (0x139cU) 408*91f16700Schasinglulu * c) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_0 (0x1370U) 409*91f16700Schasinglulu * d) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_1 (0x1374U) 410*91f16700Schasinglulu * e) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_2 (0x1378U) 411*91f16700Schasinglulu * f) #define XUSB_PADCTL_HOST_AXI_STREAMID_VF_3 (0x137cU) 412*91f16700Schasinglulu * 413*91f16700Schasinglulu * This change disables SID override and programs XUSB SIDs 414*91f16700Schasinglulu * in above registers to support both virtualization and 415*91f16700Schasinglulu * non-virtualization platforms 416*91f16700Schasinglulu */ 417*91f16700Schasinglulu if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { 418*91f16700Schasinglulu 419*91f16700Schasinglulu mmio_write_32(TEGRA_XUSB_PADCTL_BASE + 420*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_HOST); 421*91f16700Schasinglulu assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + 422*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_HOST); 423*91f16700Schasinglulu mmio_write_32(TEGRA_XUSB_PADCTL_BASE + 424*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_0, TEGRA_SID_XUSB_VF0); 425*91f16700Schasinglulu assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + 426*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_0) == TEGRA_SID_XUSB_VF0); 427*91f16700Schasinglulu mmio_write_32(TEGRA_XUSB_PADCTL_BASE + 428*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_1, TEGRA_SID_XUSB_VF1); 429*91f16700Schasinglulu assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + 430*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_1) == TEGRA_SID_XUSB_VF1); 431*91f16700Schasinglulu mmio_write_32(TEGRA_XUSB_PADCTL_BASE + 432*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_2, TEGRA_SID_XUSB_VF2); 433*91f16700Schasinglulu assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + 434*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_2) == TEGRA_SID_XUSB_VF2); 435*91f16700Schasinglulu mmio_write_32(TEGRA_XUSB_PADCTL_BASE + 436*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_3, TEGRA_SID_XUSB_VF3); 437*91f16700Schasinglulu assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + 438*91f16700Schasinglulu XUSB_PADCTL_HOST_AXI_STREAMID_VF_3) == TEGRA_SID_XUSB_VF3); 439*91f16700Schasinglulu mmio_write_32(TEGRA_XUSB_PADCTL_BASE + 440*91f16700Schasinglulu XUSB_PADCTL_DEV_AXI_STREAMID_PF_0, TEGRA_SID_XUSB_DEV); 441*91f16700Schasinglulu assert(mmio_read_32(TEGRA_XUSB_PADCTL_BASE + 442*91f16700Schasinglulu XUSB_PADCTL_DEV_AXI_STREAMID_PF_0) == TEGRA_SID_XUSB_DEV); 443*91f16700Schasinglulu } 444*91f16700Schasinglulu } 445*91f16700Schasinglulu 446*91f16700Schasinglulu /* 447*91f16700Schasinglulu * Enable dual execution optimized translations for all ELx. 448*91f16700Schasinglulu */ 449*91f16700Schasinglulu if (enable_ccplex_lock_step != 0U) { 450*91f16700Schasinglulu actlr_elx = read_actlr_el3(); 451*91f16700Schasinglulu actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL3; 452*91f16700Schasinglulu write_actlr_el3(actlr_elx); 453*91f16700Schasinglulu 454*91f16700Schasinglulu actlr_elx = read_actlr_el2(); 455*91f16700Schasinglulu actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL2; 456*91f16700Schasinglulu write_actlr_el2(actlr_elx); 457*91f16700Schasinglulu 458*91f16700Schasinglulu actlr_elx = read_actlr_el1(); 459*91f16700Schasinglulu actlr_elx |= DENVER_CPU_ENABLE_DUAL_EXEC_EL1; 460*91f16700Schasinglulu write_actlr_el1(actlr_elx); 461*91f16700Schasinglulu } 462*91f16700Schasinglulu 463*91f16700Schasinglulu return PSCI_E_SUCCESS; 464*91f16700Schasinglulu } 465*91f16700Schasinglulu 466*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state) 467*91f16700Schasinglulu { 468*91f16700Schasinglulu /* Do not power off the boot CPU */ 469*91f16700Schasinglulu if (plat_is_my_cpu_primary()) { 470*91f16700Schasinglulu return PSCI_E_DENIED; 471*91f16700Schasinglulu } 472*91f16700Schasinglulu 473*91f16700Schasinglulu return PSCI_E_SUCCESS; 474*91f16700Schasinglulu } 475*91f16700Schasinglulu 476*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) 477*91f16700Schasinglulu { 478*91f16700Schasinglulu uint64_t impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; 479*91f16700Schasinglulu int32_t ret = 0; 480*91f16700Schasinglulu 481*91f16700Schasinglulu (void)target_state; 482*91f16700Schasinglulu 483*91f16700Schasinglulu /* Disable Denver's DCO operations */ 484*91f16700Schasinglulu if (impl == DENVER_IMPL) { 485*91f16700Schasinglulu denver_disable_dco(); 486*91f16700Schasinglulu } 487*91f16700Schasinglulu 488*91f16700Schasinglulu /* Turn off CPU */ 489*91f16700Schasinglulu ret = mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, 490*91f16700Schasinglulu (uint64_t)TEGRA_NVG_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U); 491*91f16700Schasinglulu assert(ret == 0); 492*91f16700Schasinglulu 493*91f16700Schasinglulu return PSCI_E_SUCCESS; 494*91f16700Schasinglulu } 495*91f16700Schasinglulu 496*91f16700Schasinglulu __dead2 void tegra_soc_prepare_system_off(void) 497*91f16700Schasinglulu { 498*91f16700Schasinglulu /* System power off */ 499*91f16700Schasinglulu mce_system_shutdown(); 500*91f16700Schasinglulu 501*91f16700Schasinglulu wfi(); 502*91f16700Schasinglulu 503*91f16700Schasinglulu /* wait for the system to power down */ 504*91f16700Schasinglulu for (;;) { 505*91f16700Schasinglulu ; 506*91f16700Schasinglulu } 507*91f16700Schasinglulu } 508*91f16700Schasinglulu 509*91f16700Schasinglulu int32_t tegra_soc_prepare_system_reset(void) 510*91f16700Schasinglulu { 511*91f16700Schasinglulu /* System reboot */ 512*91f16700Schasinglulu mce_system_reboot(); 513*91f16700Schasinglulu 514*91f16700Schasinglulu return PSCI_E_SUCCESS; 515*91f16700Schasinglulu } 516