1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <arch_helpers.h> 10*91f16700Schasinglulu #include <common/debug.h> 11*91f16700Schasinglulu #include <lib/mmio.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <pmc.h> 14*91f16700Schasinglulu #include <tegra_def.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #define RESET_ENABLE 0x10U 17*91f16700Schasinglulu 18*91f16700Schasinglulu /* Module IDs used during power ungate procedure */ 19*91f16700Schasinglulu static const uint32_t pmc_cpu_powergate_id[4] = { 20*91f16700Schasinglulu 14, /* CPU 0 */ 21*91f16700Schasinglulu 9, /* CPU 1 */ 22*91f16700Schasinglulu 10, /* CPU 2 */ 23*91f16700Schasinglulu 11 /* CPU 3 */ 24*91f16700Schasinglulu }; 25*91f16700Schasinglulu 26*91f16700Schasinglulu /******************************************************************************* 27*91f16700Schasinglulu * Power ungate CPU to start the boot process. CPU reset vectors must be 28*91f16700Schasinglulu * populated before calling this function. 29*91f16700Schasinglulu ******************************************************************************/ 30*91f16700Schasinglulu void tegra_pmc_cpu_on(int32_t cpu) 31*91f16700Schasinglulu { 32*91f16700Schasinglulu uint32_t val; 33*91f16700Schasinglulu 34*91f16700Schasinglulu /* 35*91f16700Schasinglulu * Check if CPU is already power ungated 36*91f16700Schasinglulu */ 37*91f16700Schasinglulu val = tegra_pmc_read_32(PMC_PWRGATE_STATUS); 38*91f16700Schasinglulu if ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U) { 39*91f16700Schasinglulu /* 40*91f16700Schasinglulu * The PMC deasserts the START bit when it starts the power 41*91f16700Schasinglulu * ungate process. Loop till no power toggle is in progress. 42*91f16700Schasinglulu */ 43*91f16700Schasinglulu do { 44*91f16700Schasinglulu val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE); 45*91f16700Schasinglulu } while ((val & PMC_TOGGLE_START) != 0U); 46*91f16700Schasinglulu 47*91f16700Schasinglulu /* 48*91f16700Schasinglulu * Start the power ungate procedure 49*91f16700Schasinglulu */ 50*91f16700Schasinglulu val = pmc_cpu_powergate_id[cpu] | PMC_TOGGLE_START; 51*91f16700Schasinglulu tegra_pmc_write_32(PMC_PWRGATE_TOGGLE, val); 52*91f16700Schasinglulu 53*91f16700Schasinglulu /* 54*91f16700Schasinglulu * The PMC deasserts the START bit when it starts the power 55*91f16700Schasinglulu * ungate process. Loop till powergate START bit is asserted. 56*91f16700Schasinglulu */ 57*91f16700Schasinglulu do { 58*91f16700Schasinglulu val = tegra_pmc_read_32(PMC_PWRGATE_TOGGLE); 59*91f16700Schasinglulu } while ((val & (1U << 8)) != 0U); 60*91f16700Schasinglulu 61*91f16700Schasinglulu /* loop till the CPU is power ungated */ 62*91f16700Schasinglulu do { 63*91f16700Schasinglulu val = tegra_pmc_read_32(PMC_PWRGATE_STATUS); 64*91f16700Schasinglulu } while ((val & (1U << pmc_cpu_powergate_id[cpu])) == 0U); 65*91f16700Schasinglulu } 66*91f16700Schasinglulu } 67*91f16700Schasinglulu 68*91f16700Schasinglulu /******************************************************************************* 69*91f16700Schasinglulu * Setup CPU vectors for resume from deep sleep 70*91f16700Schasinglulu ******************************************************************************/ 71*91f16700Schasinglulu void tegra_pmc_cpu_setup(uint64_t reset_addr) 72*91f16700Schasinglulu { 73*91f16700Schasinglulu uint32_t val; 74*91f16700Schasinglulu 75*91f16700Schasinglulu tegra_pmc_write_32(PMC_SECURE_SCRATCH34, 76*91f16700Schasinglulu ((uint32_t)reset_addr & 0xFFFFFFFFU) | 1U); 77*91f16700Schasinglulu val = (uint32_t)(reset_addr >> 32U); 78*91f16700Schasinglulu tegra_pmc_write_32(PMC_SECURE_SCRATCH35, val & 0x7FFU); 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu /******************************************************************************* 82*91f16700Schasinglulu * Lock CPU vectors to restrict further writes 83*91f16700Schasinglulu ******************************************************************************/ 84*91f16700Schasinglulu void tegra_pmc_lock_cpu_vectors(void) 85*91f16700Schasinglulu { 86*91f16700Schasinglulu uint32_t val; 87*91f16700Schasinglulu 88*91f16700Schasinglulu /* lock PMC_SECURE_SCRATCH22 */ 89*91f16700Schasinglulu val = tegra_pmc_read_32(PMC_SECURE_DISABLE2); 90*91f16700Schasinglulu val |= PMC_SECURE_DISABLE2_WRITE22_ON; 91*91f16700Schasinglulu tegra_pmc_write_32(PMC_SECURE_DISABLE2, val); 92*91f16700Schasinglulu 93*91f16700Schasinglulu /* lock PMC_SECURE_SCRATCH34/35 */ 94*91f16700Schasinglulu val = tegra_pmc_read_32(PMC_SECURE_DISABLE3); 95*91f16700Schasinglulu val |= (PMC_SECURE_DISABLE3_WRITE34_ON | 96*91f16700Schasinglulu PMC_SECURE_DISABLE3_WRITE35_ON); 97*91f16700Schasinglulu tegra_pmc_write_32(PMC_SECURE_DISABLE3, val); 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu /******************************************************************************* 101*91f16700Schasinglulu * Find out if this is the last standing CPU 102*91f16700Schasinglulu ******************************************************************************/ 103*91f16700Schasinglulu bool tegra_pmc_is_last_on_cpu(void) 104*91f16700Schasinglulu { 105*91f16700Schasinglulu int i, cpu = read_mpidr() & MPIDR_CPU_MASK; 106*91f16700Schasinglulu uint32_t val = tegra_pmc_read_32(PMC_PWRGATE_STATUS); 107*91f16700Schasinglulu bool status = true; 108*91f16700Schasinglulu 109*91f16700Schasinglulu /* check if this is the last standing CPU */ 110*91f16700Schasinglulu for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) { 111*91f16700Schasinglulu 112*91f16700Schasinglulu /* skip the current CPU */ 113*91f16700Schasinglulu if (i == cpu) 114*91f16700Schasinglulu continue; 115*91f16700Schasinglulu 116*91f16700Schasinglulu /* are other CPUs already power gated? */ 117*91f16700Schasinglulu if ((val & ((uint32_t)1 << pmc_cpu_powergate_id[i])) != 0U) { 118*91f16700Schasinglulu status = false; 119*91f16700Schasinglulu } 120*91f16700Schasinglulu } 121*91f16700Schasinglulu 122*91f16700Schasinglulu return status; 123*91f16700Schasinglulu } 124*91f16700Schasinglulu 125*91f16700Schasinglulu /******************************************************************************* 126*91f16700Schasinglulu * Handler to be called on exiting System suspend. Right now only DPD registers 127*91f16700Schasinglulu * are cleared. 128*91f16700Schasinglulu ******************************************************************************/ 129*91f16700Schasinglulu void tegra_pmc_resume(void) 130*91f16700Schasinglulu { 131*91f16700Schasinglulu 132*91f16700Schasinglulu /* Clear DPD sample */ 133*91f16700Schasinglulu mmio_write_32((TEGRA_PMC_BASE + PMC_IO_DPD_SAMPLE), 0x0); 134*91f16700Schasinglulu 135*91f16700Schasinglulu /* Clear DPD Enable */ 136*91f16700Schasinglulu mmio_write_32((TEGRA_PMC_BASE + PMC_DPD_ENABLE_0), 0x0); 137*91f16700Schasinglulu } 138*91f16700Schasinglulu 139*91f16700Schasinglulu /******************************************************************************* 140*91f16700Schasinglulu * Restart the system 141*91f16700Schasinglulu ******************************************************************************/ 142*91f16700Schasinglulu __dead2 void tegra_pmc_system_reset(void) 143*91f16700Schasinglulu { 144*91f16700Schasinglulu uint32_t reg; 145*91f16700Schasinglulu 146*91f16700Schasinglulu reg = tegra_pmc_read_32(PMC_CONFIG); 147*91f16700Schasinglulu reg |= RESET_ENABLE; /* restart */ 148*91f16700Schasinglulu tegra_pmc_write_32(PMC_CONFIG, reg); 149*91f16700Schasinglulu wfi(); 150*91f16700Schasinglulu 151*91f16700Schasinglulu ERROR("Tegra System Reset: operation not handled.\n"); 152*91f16700Schasinglulu panic(); 153*91f16700Schasinglulu } 154