1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. 4*91f16700Schasinglulu * 5*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 6*91f16700Schasinglulu */ 7*91f16700Schasinglulu 8*91f16700Schasinglulu #include <assert.h> 9*91f16700Schasinglulu #include <cortex_a57.h> 10*91f16700Schasinglulu #include <arch_helpers.h> 11*91f16700Schasinglulu #include <common/debug.h> 12*91f16700Schasinglulu #include <drivers/delay_timer.h> 13*91f16700Schasinglulu #include <lib/mmio.h> 14*91f16700Schasinglulu #include <lib/psci/psci.h> 15*91f16700Schasinglulu #include <plat/common/platform.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <bpmp.h> 18*91f16700Schasinglulu #include <flowctrl.h> 19*91f16700Schasinglulu #include <lib/utils.h> 20*91f16700Schasinglulu #include <memctrl.h> 21*91f16700Schasinglulu #include <pmc.h> 22*91f16700Schasinglulu #include <platform_def.h> 23*91f16700Schasinglulu #include <security_engine.h> 24*91f16700Schasinglulu #include <tegra_def.h> 25*91f16700Schasinglulu #include <tegra_private.h> 26*91f16700Schasinglulu #include <tegra_platform.h> 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* 29*91f16700Schasinglulu * Register used to clear CPU reset signals. Each CPU has two reset 30*91f16700Schasinglulu * signals: CPU reset (3:0) and Core reset (19:16). 31*91f16700Schasinglulu */ 32*91f16700Schasinglulu #define CPU_CMPLX_RESET_CLR 0x454 33*91f16700Schasinglulu #define CPU_CORE_RESET_MASK 0x10001 34*91f16700Schasinglulu 35*91f16700Schasinglulu /* Clock and Reset controller registers for system clock's settings */ 36*91f16700Schasinglulu #define SCLK_RATE 0x30 37*91f16700Schasinglulu #define SCLK_BURST_POLICY 0x28 38*91f16700Schasinglulu #define SCLK_BURST_POLICY_DEFAULT 0x10000000 39*91f16700Schasinglulu 40*91f16700Schasinglulu static int cpu_powergate_mask[PLATFORM_MAX_CPUS_PER_CLUSTER]; 41*91f16700Schasinglulu static bool tegra_bpmp_available = true; 42*91f16700Schasinglulu 43*91f16700Schasinglulu int32_t tegra_soc_validate_power_state(unsigned int power_state, 44*91f16700Schasinglulu psci_power_state_t *req_state) 45*91f16700Schasinglulu { 46*91f16700Schasinglulu int state_id = psci_get_pstate_id(power_state); 47*91f16700Schasinglulu const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); 48*91f16700Schasinglulu 49*91f16700Schasinglulu /* Sanity check the requested state id */ 50*91f16700Schasinglulu switch (state_id) { 51*91f16700Schasinglulu case PSTATE_ID_CORE_POWERDN: 52*91f16700Schasinglulu /* 53*91f16700Schasinglulu * Core powerdown request only for afflvl 0 54*91f16700Schasinglulu */ 55*91f16700Schasinglulu req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id & 0xff; 56*91f16700Schasinglulu 57*91f16700Schasinglulu break; 58*91f16700Schasinglulu 59*91f16700Schasinglulu case PSTATE_ID_CLUSTER_IDLE: 60*91f16700Schasinglulu 61*91f16700Schasinglulu /* 62*91f16700Schasinglulu * Cluster idle request for afflvl 0 63*91f16700Schasinglulu */ 64*91f16700Schasinglulu req_state->pwr_domain_state[MPIDR_AFFLVL0] = PSTATE_ID_CORE_POWERDN; 65*91f16700Schasinglulu req_state->pwr_domain_state[MPIDR_AFFLVL1] = state_id; 66*91f16700Schasinglulu break; 67*91f16700Schasinglulu 68*91f16700Schasinglulu case PSTATE_ID_SOC_POWERDN: 69*91f16700Schasinglulu 70*91f16700Schasinglulu /* 71*91f16700Schasinglulu * sc7entry-fw must be present in the system when the bpmp 72*91f16700Schasinglulu * firmware is not present, for a successful System Suspend 73*91f16700Schasinglulu * entry. 74*91f16700Schasinglulu */ 75*91f16700Schasinglulu if (!tegra_bpmp_init() && !plat_params->sc7entry_fw_base) 76*91f16700Schasinglulu return PSCI_E_NOT_SUPPORTED; 77*91f16700Schasinglulu 78*91f16700Schasinglulu /* 79*91f16700Schasinglulu * System powerdown request only for afflvl 2 80*91f16700Schasinglulu */ 81*91f16700Schasinglulu for (uint32_t i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++) 82*91f16700Schasinglulu req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; 83*91f16700Schasinglulu 84*91f16700Schasinglulu req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = 85*91f16700Schasinglulu PLAT_SYS_SUSPEND_STATE_ID; 86*91f16700Schasinglulu 87*91f16700Schasinglulu break; 88*91f16700Schasinglulu 89*91f16700Schasinglulu default: 90*91f16700Schasinglulu ERROR("%s: unsupported state id (%d)\n", __func__, state_id); 91*91f16700Schasinglulu return PSCI_E_INVALID_PARAMS; 92*91f16700Schasinglulu } 93*91f16700Schasinglulu 94*91f16700Schasinglulu return PSCI_E_SUCCESS; 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu /******************************************************************************* 98*91f16700Schasinglulu * Platform handler to calculate the proper target power level at the 99*91f16700Schasinglulu * specified affinity level. 100*91f16700Schasinglulu ******************************************************************************/ 101*91f16700Schasinglulu plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl, 102*91f16700Schasinglulu const plat_local_state_t *states, 103*91f16700Schasinglulu unsigned int ncpu) 104*91f16700Schasinglulu { 105*91f16700Schasinglulu plat_local_state_t target = PSCI_LOCAL_STATE_RUN; 106*91f16700Schasinglulu int cpu = plat_my_core_pos(); 107*91f16700Schasinglulu int core_pos = read_mpidr() & MPIDR_CPU_MASK; 108*91f16700Schasinglulu uint32_t bpmp_reply, data[3], val; 109*91f16700Schasinglulu int ret; 110*91f16700Schasinglulu 111*91f16700Schasinglulu /* get the power state at this level */ 112*91f16700Schasinglulu if (lvl == MPIDR_AFFLVL1) 113*91f16700Schasinglulu target = *(states + core_pos); 114*91f16700Schasinglulu if (lvl == MPIDR_AFFLVL2) 115*91f16700Schasinglulu target = *(states + cpu); 116*91f16700Schasinglulu 117*91f16700Schasinglulu if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_IDLE)) { 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* initialize the bpmp interface */ 120*91f16700Schasinglulu ret = tegra_bpmp_init(); 121*91f16700Schasinglulu if (ret != 0U) { 122*91f16700Schasinglulu 123*91f16700Schasinglulu /* 124*91f16700Schasinglulu * flag to indicate that BPMP firmware is not 125*91f16700Schasinglulu * available and the CPU has to handle entry/exit 126*91f16700Schasinglulu * for all power states 127*91f16700Schasinglulu */ 128*91f16700Schasinglulu tegra_bpmp_available = false; 129*91f16700Schasinglulu 130*91f16700Schasinglulu /* Cluster idle not allowed */ 131*91f16700Schasinglulu target = PSCI_LOCAL_STATE_RUN; 132*91f16700Schasinglulu 133*91f16700Schasinglulu /******************************************* 134*91f16700Schasinglulu * BPMP is not present, so handle CC6 entry 135*91f16700Schasinglulu * from the CPU 136*91f16700Schasinglulu ******************************************/ 137*91f16700Schasinglulu 138*91f16700Schasinglulu /* check if cluster idle state has been enabled */ 139*91f16700Schasinglulu val = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL); 140*91f16700Schasinglulu if (val == ENABLE_CLOSED_LOOP) { 141*91f16700Schasinglulu /* 142*91f16700Schasinglulu * Acquire the cluster idle lock to stop 143*91f16700Schasinglulu * other CPUs from powering up. 144*91f16700Schasinglulu */ 145*91f16700Schasinglulu tegra_fc_ccplex_pgexit_lock(); 146*91f16700Schasinglulu 147*91f16700Schasinglulu /* Cluster idle only from the last standing CPU */ 148*91f16700Schasinglulu if (tegra_pmc_is_last_on_cpu() && tegra_fc_is_ccx_allowed()) { 149*91f16700Schasinglulu /* Cluster idle allowed */ 150*91f16700Schasinglulu target = PSTATE_ID_CLUSTER_IDLE; 151*91f16700Schasinglulu } else { 152*91f16700Schasinglulu /* release cluster idle lock */ 153*91f16700Schasinglulu tegra_fc_ccplex_pgexit_unlock(); 154*91f16700Schasinglulu } 155*91f16700Schasinglulu } 156*91f16700Schasinglulu } else { 157*91f16700Schasinglulu 158*91f16700Schasinglulu /* Cluster power-down */ 159*91f16700Schasinglulu data[0] = (uint32_t)cpu; 160*91f16700Schasinglulu data[1] = TEGRA_PM_CC6; 161*91f16700Schasinglulu data[2] = TEGRA_PM_SC1; 162*91f16700Schasinglulu ret = tegra_bpmp_send_receive_atomic(MRQ_DO_IDLE, 163*91f16700Schasinglulu (void *)&data, (int)sizeof(data), 164*91f16700Schasinglulu (void *)&bpmp_reply, 165*91f16700Schasinglulu (int)sizeof(bpmp_reply)); 166*91f16700Schasinglulu 167*91f16700Schasinglulu /* check if cluster power down is allowed */ 168*91f16700Schasinglulu if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) { 169*91f16700Schasinglulu 170*91f16700Schasinglulu /* Cluster power down not allowed */ 171*91f16700Schasinglulu target = PSCI_LOCAL_STATE_RUN; 172*91f16700Schasinglulu } 173*91f16700Schasinglulu } 174*91f16700Schasinglulu 175*91f16700Schasinglulu } else if (((lvl == MPIDR_AFFLVL2) || (lvl == MPIDR_AFFLVL1)) && 176*91f16700Schasinglulu (target == PSTATE_ID_SOC_POWERDN)) { 177*91f16700Schasinglulu 178*91f16700Schasinglulu /* System Suspend */ 179*91f16700Schasinglulu target = PSTATE_ID_SOC_POWERDN; 180*91f16700Schasinglulu 181*91f16700Schasinglulu } else { 182*91f16700Schasinglulu ; /* do nothing */ 183*91f16700Schasinglulu } 184*91f16700Schasinglulu 185*91f16700Schasinglulu return target; 186*91f16700Schasinglulu } 187*91f16700Schasinglulu 188*91f16700Schasinglulu int32_t tegra_soc_cpu_standby(plat_local_state_t cpu_state) 189*91f16700Schasinglulu { 190*91f16700Schasinglulu (void)cpu_state; 191*91f16700Schasinglulu return PSCI_E_SUCCESS; 192*91f16700Schasinglulu } 193*91f16700Schasinglulu 194*91f16700Schasinglulu int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) 195*91f16700Schasinglulu { 196*91f16700Schasinglulu u_register_t mpidr = read_mpidr(); 197*91f16700Schasinglulu const plat_local_state_t *pwr_domain_state = 198*91f16700Schasinglulu target_state->pwr_domain_state; 199*91f16700Schasinglulu unsigned int stateid_afflvl2 = pwr_domain_state[MPIDR_AFFLVL2]; 200*91f16700Schasinglulu unsigned int stateid_afflvl1 = pwr_domain_state[MPIDR_AFFLVL1]; 201*91f16700Schasinglulu unsigned int stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0]; 202*91f16700Schasinglulu uint32_t cfg; 203*91f16700Schasinglulu int ret = PSCI_E_SUCCESS; 204*91f16700Schasinglulu uint32_t val; 205*91f16700Schasinglulu 206*91f16700Schasinglulu if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 207*91f16700Schasinglulu 208*91f16700Schasinglulu assert((stateid_afflvl0 == PLAT_MAX_OFF_STATE) || 209*91f16700Schasinglulu (stateid_afflvl0 == PSTATE_ID_SOC_POWERDN)); 210*91f16700Schasinglulu assert((stateid_afflvl1 == PLAT_MAX_OFF_STATE) || 211*91f16700Schasinglulu (stateid_afflvl1 == PSTATE_ID_SOC_POWERDN)); 212*91f16700Schasinglulu 213*91f16700Schasinglulu /* Suspend se/se2 and pka1 for T210 B01 and se for T210 */ 214*91f16700Schasinglulu if (tegra_se_suspend() != 0) { 215*91f16700Schasinglulu ret = PSCI_E_INTERN_FAIL; 216*91f16700Schasinglulu } 217*91f16700Schasinglulu 218*91f16700Schasinglulu } else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) { 219*91f16700Schasinglulu 220*91f16700Schasinglulu assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN); 221*91f16700Schasinglulu 222*91f16700Schasinglulu if (!tegra_bpmp_available) { 223*91f16700Schasinglulu 224*91f16700Schasinglulu /* 225*91f16700Schasinglulu * When disabled, DFLL loses its state. Enable 226*91f16700Schasinglulu * open loop state for the DFLL as we dont want 227*91f16700Schasinglulu * garbage values being written to the pmic 228*91f16700Schasinglulu * when we enter cluster idle state. 229*91f16700Schasinglulu */ 230*91f16700Schasinglulu mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL, 231*91f16700Schasinglulu ENABLE_OPEN_LOOP); 232*91f16700Schasinglulu 233*91f16700Schasinglulu /* Find if the platform uses OVR2/MAX77621 PMIC */ 234*91f16700Schasinglulu cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG); 235*91f16700Schasinglulu if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) { 236*91f16700Schasinglulu /* OVR2 */ 237*91f16700Schasinglulu 238*91f16700Schasinglulu /* PWM tristate */ 239*91f16700Schasinglulu val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); 240*91f16700Schasinglulu val |= PINMUX_PWM_TRISTATE; 241*91f16700Schasinglulu mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val); 242*91f16700Schasinglulu 243*91f16700Schasinglulu /* 244*91f16700Schasinglulu * SCRATCH201[1] is being used to identify CPU 245*91f16700Schasinglulu * PMIC in warmboot code. 246*91f16700Schasinglulu * 0 : OVR2 247*91f16700Schasinglulu * 1 : MAX77621 248*91f16700Schasinglulu */ 249*91f16700Schasinglulu tegra_pmc_write_32(PMC_SCRATCH201, 0x0); 250*91f16700Schasinglulu } else { 251*91f16700Schasinglulu /* MAX77621 */ 252*91f16700Schasinglulu tegra_pmc_write_32(PMC_SCRATCH201, 0x2); 253*91f16700Schasinglulu } 254*91f16700Schasinglulu } 255*91f16700Schasinglulu 256*91f16700Schasinglulu /* Prepare for cluster idle */ 257*91f16700Schasinglulu tegra_fc_cluster_idle(mpidr); 258*91f16700Schasinglulu 259*91f16700Schasinglulu } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) { 260*91f16700Schasinglulu 261*91f16700Schasinglulu /* Prepare for cpu powerdn */ 262*91f16700Schasinglulu tegra_fc_cpu_powerdn(mpidr); 263*91f16700Schasinglulu 264*91f16700Schasinglulu } else { 265*91f16700Schasinglulu ERROR("%s: Unknown state id (%d, %d, %d)\n", __func__, 266*91f16700Schasinglulu stateid_afflvl2, stateid_afflvl1, stateid_afflvl0); 267*91f16700Schasinglulu ret = PSCI_E_NOT_SUPPORTED; 268*91f16700Schasinglulu } 269*91f16700Schasinglulu 270*91f16700Schasinglulu return ret; 271*91f16700Schasinglulu } 272*91f16700Schasinglulu 273*91f16700Schasinglulu static void tegra_reset_all_dma_masters(void) 274*91f16700Schasinglulu { 275*91f16700Schasinglulu uint32_t val, mask; 276*91f16700Schasinglulu 277*91f16700Schasinglulu /* 278*91f16700Schasinglulu * Reset all possible DMA masters in the system. 279*91f16700Schasinglulu */ 280*91f16700Schasinglulu val = GPU_RESET_BIT; 281*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET, val); 282*91f16700Schasinglulu 283*91f16700Schasinglulu val = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT | 284*91f16700Schasinglulu NVJPG_RESET_BIT | NVDEC_RESET_BIT; 285*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y, val); 286*91f16700Schasinglulu 287*91f16700Schasinglulu val = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT | 288*91f16700Schasinglulu VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT | 289*91f16700Schasinglulu SDMMC2_RESET_BIT; 290*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L, val); 291*91f16700Schasinglulu 292*91f16700Schasinglulu val = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT; 293*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H, val); 294*91f16700Schasinglulu 295*91f16700Schasinglulu val = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT | 296*91f16700Schasinglulu PCIE_RESET_BIT | SDMMC3_RESET_BIT; 297*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U, val); 298*91f16700Schasinglulu 299*91f16700Schasinglulu val = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT; 300*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V, val); 301*91f16700Schasinglulu 302*91f16700Schasinglulu /* 303*91f16700Schasinglulu * If any of the DMA masters are still alive, assume 304*91f16700Schasinglulu * that the system has been compromised and reboot. 305*91f16700Schasinglulu */ 306*91f16700Schasinglulu val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET); 307*91f16700Schasinglulu mask = GPU_RESET_BIT; 308*91f16700Schasinglulu if ((val & mask) != mask) 309*91f16700Schasinglulu tegra_pmc_system_reset(); 310*91f16700Schasinglulu 311*91f16700Schasinglulu mask = NVENC_RESET_BIT | TSECB_RESET_BIT | APE_RESET_BIT | 312*91f16700Schasinglulu NVJPG_RESET_BIT | NVDEC_RESET_BIT; 313*91f16700Schasinglulu val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_Y); 314*91f16700Schasinglulu if ((val & mask) != mask) 315*91f16700Schasinglulu tegra_pmc_system_reset(); 316*91f16700Schasinglulu 317*91f16700Schasinglulu mask = HOST1X_RESET_BIT | ISP_RESET_BIT | USBD_RESET_BIT | 318*91f16700Schasinglulu VI_RESET_BIT | SDMMC4_RESET_BIT | SDMMC1_RESET_BIT | 319*91f16700Schasinglulu SDMMC2_RESET_BIT; 320*91f16700Schasinglulu val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_L); 321*91f16700Schasinglulu if ((val & mask) != mask) 322*91f16700Schasinglulu tegra_pmc_system_reset(); 323*91f16700Schasinglulu 324*91f16700Schasinglulu mask = USB2_RESET_BIT | APBDMA_RESET_BIT | AHBDMA_RESET_BIT; 325*91f16700Schasinglulu val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_H); 326*91f16700Schasinglulu if ((val & mask) != mask) 327*91f16700Schasinglulu tegra_pmc_system_reset(); 328*91f16700Schasinglulu 329*91f16700Schasinglulu mask = XUSB_DEV_RESET_BIT | XUSB_HOST_RESET_BIT | TSEC_RESET_BIT | 330*91f16700Schasinglulu PCIE_RESET_BIT | SDMMC3_RESET_BIT; 331*91f16700Schasinglulu val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_U); 332*91f16700Schasinglulu if ((val & mask) != mask) 333*91f16700Schasinglulu tegra_pmc_system_reset(); 334*91f16700Schasinglulu 335*91f16700Schasinglulu val = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_RST_DEV_SET_V); 336*91f16700Schasinglulu mask = SE_RESET_BIT | HDA_RESET_BIT | SATA_RESET_BIT; 337*91f16700Schasinglulu if ((val & mask) != mask) 338*91f16700Schasinglulu tegra_pmc_system_reset(); 339*91f16700Schasinglulu } 340*91f16700Schasinglulu 341*91f16700Schasinglulu int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) 342*91f16700Schasinglulu { 343*91f16700Schasinglulu u_register_t mpidr = read_mpidr(); 344*91f16700Schasinglulu const plat_local_state_t *pwr_domain_state = 345*91f16700Schasinglulu target_state->pwr_domain_state; 346*91f16700Schasinglulu unsigned int stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL]; 347*91f16700Schasinglulu const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); 348*91f16700Schasinglulu uint32_t val; 349*91f16700Schasinglulu 350*91f16700Schasinglulu if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { 351*91f16700Schasinglulu 352*91f16700Schasinglulu if (tegra_chipid_is_t210_b01()) { 353*91f16700Schasinglulu /* Save tzram contents */ 354*91f16700Schasinglulu tegra_se_save_tzram(); 355*91f16700Schasinglulu } 356*91f16700Schasinglulu 357*91f16700Schasinglulu /* de-init the interface */ 358*91f16700Schasinglulu tegra_bpmp_suspend(); 359*91f16700Schasinglulu 360*91f16700Schasinglulu /* 361*91f16700Schasinglulu * The CPU needs to load the System suspend entry firmware 362*91f16700Schasinglulu * if nothing is running on the BPMP. 363*91f16700Schasinglulu */ 364*91f16700Schasinglulu if (!tegra_bpmp_available) { 365*91f16700Schasinglulu 366*91f16700Schasinglulu /* 367*91f16700Schasinglulu * BPMP firmware is not running on the co-processor, so 368*91f16700Schasinglulu * we need to explicitly load the firmware to enable 369*91f16700Schasinglulu * entry/exit to/from System Suspend and set the BPMP 370*91f16700Schasinglulu * on its way. 371*91f16700Schasinglulu */ 372*91f16700Schasinglulu 373*91f16700Schasinglulu /* Power off BPMP before we proceed */ 374*91f16700Schasinglulu tegra_fc_bpmp_off(); 375*91f16700Schasinglulu 376*91f16700Schasinglulu /* bond out IRAM banks B, C and D */ 377*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_U, 378*91f16700Schasinglulu IRAM_B_LOCK_BIT | IRAM_C_LOCK_BIT | 379*91f16700Schasinglulu IRAM_D_LOCK_BIT); 380*91f16700Schasinglulu 381*91f16700Schasinglulu /* bond out APB/AHB DMAs */ 382*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + TEGRA_BOND_OUT_H, 383*91f16700Schasinglulu APB_DMA_LOCK_BIT | AHB_DMA_LOCK_BIT); 384*91f16700Schasinglulu 385*91f16700Schasinglulu /* Power off BPMP before we proceed */ 386*91f16700Schasinglulu tegra_fc_bpmp_off(); 387*91f16700Schasinglulu 388*91f16700Schasinglulu /* 389*91f16700Schasinglulu * Reset all the hardware blocks that can act as DMA 390*91f16700Schasinglulu * masters on the bus. 391*91f16700Schasinglulu */ 392*91f16700Schasinglulu tegra_reset_all_dma_masters(); 393*91f16700Schasinglulu 394*91f16700Schasinglulu /* 395*91f16700Schasinglulu * Mark PMC as accessible to the non-secure world 396*91f16700Schasinglulu * to allow the COP to execute System Suspend 397*91f16700Schasinglulu * sequence 398*91f16700Schasinglulu */ 399*91f16700Schasinglulu val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); 400*91f16700Schasinglulu val &= ~PMC_SECURITY_EN_BIT; 401*91f16700Schasinglulu mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); 402*91f16700Schasinglulu 403*91f16700Schasinglulu /* clean up IRAM of any cruft */ 404*91f16700Schasinglulu zeromem((void *)(uintptr_t)TEGRA_IRAM_BASE, 405*91f16700Schasinglulu TEGRA_IRAM_A_SIZE); 406*91f16700Schasinglulu 407*91f16700Schasinglulu /* Copy the firmware to BPMP's internal RAM */ 408*91f16700Schasinglulu (void)memcpy((void *)(uintptr_t)TEGRA_IRAM_BASE, 409*91f16700Schasinglulu (const void *)(plat_params->sc7entry_fw_base + SC7ENTRY_FW_HEADER_SIZE_BYTES), 410*91f16700Schasinglulu plat_params->sc7entry_fw_size - SC7ENTRY_FW_HEADER_SIZE_BYTES); 411*91f16700Schasinglulu 412*91f16700Schasinglulu /* Power on the BPMP and execute from IRAM base */ 413*91f16700Schasinglulu tegra_fc_bpmp_on(TEGRA_IRAM_BASE); 414*91f16700Schasinglulu 415*91f16700Schasinglulu /* Wait until BPMP powers up */ 416*91f16700Schasinglulu do { 417*91f16700Schasinglulu val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET); 418*91f16700Schasinglulu } while (val != SIGN_OF_LIFE); 419*91f16700Schasinglulu } 420*91f16700Schasinglulu 421*91f16700Schasinglulu /* enter system suspend */ 422*91f16700Schasinglulu tegra_fc_soc_powerdn(mpidr); 423*91f16700Schasinglulu } 424*91f16700Schasinglulu 425*91f16700Schasinglulu return PSCI_E_SUCCESS; 426*91f16700Schasinglulu } 427*91f16700Schasinglulu 428*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state) 429*91f16700Schasinglulu { 430*91f16700Schasinglulu return PSCI_E_NOT_SUPPORTED; 431*91f16700Schasinglulu } 432*91f16700Schasinglulu 433*91f16700Schasinglulu int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) 434*91f16700Schasinglulu { 435*91f16700Schasinglulu const plat_params_from_bl2_t *plat_params = bl31_get_plat_params(); 436*91f16700Schasinglulu uint32_t cfg; 437*91f16700Schasinglulu uint32_t val, entrypoint = 0; 438*91f16700Schasinglulu uint64_t offset; 439*91f16700Schasinglulu 440*91f16700Schasinglulu /* platform parameter passed by the previous bootloader */ 441*91f16700Schasinglulu if (plat_params->l2_ecc_parity_prot_dis != 1) { 442*91f16700Schasinglulu /* Enable ECC Parity Protection for Cortex-A57 CPUs */ 443*91f16700Schasinglulu val = read_l2ctlr_el1(); 444*91f16700Schasinglulu val |= (uint64_t)CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT; 445*91f16700Schasinglulu write_l2ctlr_el1(val); 446*91f16700Schasinglulu } 447*91f16700Schasinglulu 448*91f16700Schasinglulu /* 449*91f16700Schasinglulu * Check if we are exiting from SOC_POWERDN. 450*91f16700Schasinglulu */ 451*91f16700Schasinglulu if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] == 452*91f16700Schasinglulu PLAT_SYS_SUSPEND_STATE_ID) { 453*91f16700Schasinglulu 454*91f16700Schasinglulu /* 455*91f16700Schasinglulu * Security engine resume 456*91f16700Schasinglulu */ 457*91f16700Schasinglulu if (tegra_chipid_is_t210_b01()) { 458*91f16700Schasinglulu tegra_se_resume(); 459*91f16700Schasinglulu } 460*91f16700Schasinglulu 461*91f16700Schasinglulu /* 462*91f16700Schasinglulu * Lock scratch registers which hold the CPU vectors 463*91f16700Schasinglulu */ 464*91f16700Schasinglulu tegra_pmc_lock_cpu_vectors(); 465*91f16700Schasinglulu 466*91f16700Schasinglulu /* 467*91f16700Schasinglulu * Enable WRAP to INCR burst type conversions for 468*91f16700Schasinglulu * incoming requests on the AXI slave ports. 469*91f16700Schasinglulu */ 470*91f16700Schasinglulu val = mmio_read_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG); 471*91f16700Schasinglulu val &= ~ENABLE_UNSUP_TX_ERRORS; 472*91f16700Schasinglulu val |= ENABLE_WRAP_TO_INCR_BURSTS; 473*91f16700Schasinglulu mmio_write_32(TEGRA_MSELECT_BASE + MSELECT_CONFIG, val); 474*91f16700Schasinglulu 475*91f16700Schasinglulu /* 476*91f16700Schasinglulu * Restore Boot and Power Management Processor (BPMP) reset 477*91f16700Schasinglulu * address and reset it, if it is supported by the platform. 478*91f16700Schasinglulu */ 479*91f16700Schasinglulu if (!tegra_bpmp_available) { 480*91f16700Schasinglulu tegra_fc_bpmp_off(); 481*91f16700Schasinglulu } else { 482*91f16700Schasinglulu entrypoint = tegra_pmc_read_32(PMC_SCRATCH39); 483*91f16700Schasinglulu tegra_fc_bpmp_on(entrypoint); 484*91f16700Schasinglulu 485*91f16700Schasinglulu /* initialise the interface */ 486*91f16700Schasinglulu tegra_bpmp_resume(); 487*91f16700Schasinglulu } 488*91f16700Schasinglulu 489*91f16700Schasinglulu if (plat_params->sc7entry_fw_base != 0U) { 490*91f16700Schasinglulu /* sc7entry-fw is part of TZDRAM area */ 491*91f16700Schasinglulu offset = plat_params->tzdram_base - plat_params->sc7entry_fw_base; 492*91f16700Schasinglulu tegra_memctrl_tzdram_setup(plat_params->sc7entry_fw_base, 493*91f16700Schasinglulu plat_params->tzdram_size + offset); 494*91f16700Schasinglulu } 495*91f16700Schasinglulu 496*91f16700Schasinglulu if (!tegra_chipid_is_t210_b01()) { 497*91f16700Schasinglulu /* restrict PMC access to secure world */ 498*91f16700Schasinglulu val = mmio_read_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE); 499*91f16700Schasinglulu val |= PMC_SECURITY_EN_BIT; 500*91f16700Schasinglulu mmio_write_32(TEGRA_MISC_BASE + APB_SLAVE_SECURITY_ENABLE, val); 501*91f16700Schasinglulu } 502*91f16700Schasinglulu } 503*91f16700Schasinglulu 504*91f16700Schasinglulu /* 505*91f16700Schasinglulu * Check if we are exiting cluster idle state 506*91f16700Schasinglulu */ 507*91f16700Schasinglulu if (target_state->pwr_domain_state[MPIDR_AFFLVL1] == 508*91f16700Schasinglulu PSTATE_ID_CLUSTER_IDLE) { 509*91f16700Schasinglulu 510*91f16700Schasinglulu if (!tegra_bpmp_available) { 511*91f16700Schasinglulu 512*91f16700Schasinglulu /* PWM un-tristate */ 513*91f16700Schasinglulu cfg = mmio_read_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_OUTPUT_CFG); 514*91f16700Schasinglulu if (cfg & DFLL_OUTPUT_CFG_CLK_EN_BIT) { 515*91f16700Schasinglulu val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); 516*91f16700Schasinglulu val &= ~PINMUX_PWM_TRISTATE; 517*91f16700Schasinglulu mmio_write_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM, val); 518*91f16700Schasinglulu 519*91f16700Schasinglulu /* make sure the setting took effect */ 520*91f16700Schasinglulu val = mmio_read_32(TEGRA_MISC_BASE + PINMUX_AUX_DVFS_PWM); 521*91f16700Schasinglulu assert((val & PINMUX_PWM_TRISTATE) == 0U); 522*91f16700Schasinglulu } 523*91f16700Schasinglulu 524*91f16700Schasinglulu /* 525*91f16700Schasinglulu * Restore operation mode for the DFLL ring 526*91f16700Schasinglulu * oscillator 527*91f16700Schasinglulu */ 528*91f16700Schasinglulu mmio_write_32(TEGRA_CL_DVFS_BASE + DVFS_DFLL_CTRL, 529*91f16700Schasinglulu ENABLE_CLOSED_LOOP); 530*91f16700Schasinglulu 531*91f16700Schasinglulu /* release cluster idle lock */ 532*91f16700Schasinglulu tegra_fc_ccplex_pgexit_unlock(); 533*91f16700Schasinglulu } 534*91f16700Schasinglulu } 535*91f16700Schasinglulu 536*91f16700Schasinglulu /* 537*91f16700Schasinglulu * Mark this CPU as ON in the cpu_powergate_mask[], 538*91f16700Schasinglulu * so that we use Flow Controller for all subsequent 539*91f16700Schasinglulu * power ups. 540*91f16700Schasinglulu */ 541*91f16700Schasinglulu cpu_powergate_mask[plat_my_core_pos()] = 1; 542*91f16700Schasinglulu 543*91f16700Schasinglulu /* 544*91f16700Schasinglulu * T210 has a dedicated ARMv7 boot and power mgmt processor, BPMP. It's 545*91f16700Schasinglulu * used for power management and boot purposes. Inform the BPMP that 546*91f16700Schasinglulu * we have completed the cluster power up. 547*91f16700Schasinglulu */ 548*91f16700Schasinglulu tegra_fc_lock_active_cluster(); 549*91f16700Schasinglulu 550*91f16700Schasinglulu /* 551*91f16700Schasinglulu * Resume PMC hardware block for Tegra210 platforms 552*91f16700Schasinglulu */ 553*91f16700Schasinglulu if (!tegra_chipid_is_t210_b01()) { 554*91f16700Schasinglulu tegra_pmc_resume(); 555*91f16700Schasinglulu } 556*91f16700Schasinglulu 557*91f16700Schasinglulu return PSCI_E_SUCCESS; 558*91f16700Schasinglulu } 559*91f16700Schasinglulu 560*91f16700Schasinglulu int tegra_soc_pwr_domain_on(u_register_t mpidr) 561*91f16700Schasinglulu { 562*91f16700Schasinglulu int cpu = mpidr & MPIDR_CPU_MASK; 563*91f16700Schasinglulu uint32_t mask = CPU_CORE_RESET_MASK << cpu; 564*91f16700Schasinglulu 565*91f16700Schasinglulu /* Deassert CPU reset signals */ 566*91f16700Schasinglulu mmio_write_32(TEGRA_CAR_RESET_BASE + CPU_CMPLX_RESET_CLR, mask); 567*91f16700Schasinglulu 568*91f16700Schasinglulu /* Turn on CPU using flow controller or PMC */ 569*91f16700Schasinglulu if (cpu_powergate_mask[cpu] == 0) { 570*91f16700Schasinglulu tegra_pmc_cpu_on(cpu); 571*91f16700Schasinglulu } else { 572*91f16700Schasinglulu tegra_fc_cpu_on(cpu); 573*91f16700Schasinglulu } 574*91f16700Schasinglulu 575*91f16700Schasinglulu return PSCI_E_SUCCESS; 576*91f16700Schasinglulu } 577*91f16700Schasinglulu 578*91f16700Schasinglulu int32_t tegra_soc_pwr_domain_off_early(const psci_power_state_t *target_state) 579*91f16700Schasinglulu { 580*91f16700Schasinglulu /* Do not power off the boot CPU */ 581*91f16700Schasinglulu if (plat_is_my_cpu_primary()) { 582*91f16700Schasinglulu return PSCI_E_DENIED; 583*91f16700Schasinglulu } 584*91f16700Schasinglulu 585*91f16700Schasinglulu return PSCI_E_SUCCESS; 586*91f16700Schasinglulu } 587*91f16700Schasinglulu 588*91f16700Schasinglulu int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) 589*91f16700Schasinglulu { 590*91f16700Schasinglulu tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK); 591*91f16700Schasinglulu return PSCI_E_SUCCESS; 592*91f16700Schasinglulu } 593*91f16700Schasinglulu 594*91f16700Schasinglulu int tegra_soc_prepare_system_reset(void) 595*91f16700Schasinglulu { 596*91f16700Schasinglulu /* 597*91f16700Schasinglulu * Set System Clock (SCLK) to POR default so that the clock source 598*91f16700Schasinglulu * for the PMC APB clock would not be changed due to system reset. 599*91f16700Schasinglulu */ 600*91f16700Schasinglulu mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_BURST_POLICY, 601*91f16700Schasinglulu SCLK_BURST_POLICY_DEFAULT); 602*91f16700Schasinglulu mmio_write_32((uintptr_t)TEGRA_CAR_RESET_BASE + SCLK_RATE, 0); 603*91f16700Schasinglulu 604*91f16700Schasinglulu /* Wait 1 ms to make sure clock source/device logic is stabilized. */ 605*91f16700Schasinglulu mdelay(1); 606*91f16700Schasinglulu 607*91f16700Schasinglulu /* 608*91f16700Schasinglulu * Program the PMC in order to restart the system. 609*91f16700Schasinglulu */ 610*91f16700Schasinglulu tegra_pmc_system_reset(); 611*91f16700Schasinglulu 612*91f16700Schasinglulu return PSCI_E_SUCCESS; 613*91f16700Schasinglulu } 614*91f16700Schasinglulu 615*91f16700Schasinglulu __dead2 void tegra_soc_prepare_system_off(void) 616*91f16700Schasinglulu { 617*91f16700Schasinglulu ERROR("Tegra System Off: operation not handled.\n"); 618*91f16700Schasinglulu panic(); 619*91f16700Schasinglulu } 620