1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2021, 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 <platform_def.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_helpers.h> 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <drivers/delay_timer.h> 14*91f16700Schasinglulu #include <lib/mmio.h> 15*91f16700Schasinglulu #include <lib/utils_def.h> 16*91f16700Schasinglulu #include <plat/common/platform.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include <sunxi_cpucfg.h> 19*91f16700Schasinglulu #include <sunxi_mmap.h> 20*91f16700Schasinglulu #include <sunxi_private.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #ifndef SUNXI_C0_CPU_CTRL_REG 23*91f16700Schasinglulu #define SUNXI_C0_CPU_CTRL_REG(n) 0 24*91f16700Schasinglulu #define SUNXI_CPU_UNK_REG(n) 0 25*91f16700Schasinglulu #define SUNXI_CPU_CTRL_REG(n) 0 26*91f16700Schasinglulu #endif 27*91f16700Schasinglulu 28*91f16700Schasinglulu static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) 29*91f16700Schasinglulu { 30*91f16700Schasinglulu if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) 31*91f16700Schasinglulu return; 32*91f16700Schasinglulu 33*91f16700Schasinglulu VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core); 34*91f16700Schasinglulu 35*91f16700Schasinglulu mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff); 36*91f16700Schasinglulu } 37*91f16700Schasinglulu 38*91f16700Schasinglulu static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) 39*91f16700Schasinglulu { 40*91f16700Schasinglulu if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0) 41*91f16700Schasinglulu return; 42*91f16700Schasinglulu 43*91f16700Schasinglulu VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core); 44*91f16700Schasinglulu 45*91f16700Schasinglulu /* Power enable sequence from original Allwinner sources */ 46*91f16700Schasinglulu mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe); 47*91f16700Schasinglulu mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8); 48*91f16700Schasinglulu mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0); 49*91f16700Schasinglulu mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80); 50*91f16700Schasinglulu mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); 51*91f16700Schasinglulu udelay(1); 52*91f16700Schasinglulu } 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* We can't turn ourself off like this, but it works for other cores. */ 55*91f16700Schasinglulu static void sunxi_cpu_off(u_register_t mpidr) 56*91f16700Schasinglulu { 57*91f16700Schasinglulu unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); 58*91f16700Schasinglulu unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); 59*91f16700Schasinglulu 60*91f16700Schasinglulu VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core); 61*91f16700Schasinglulu 62*91f16700Schasinglulu if (sunxi_cpucfg_has_per_cluster_regs()) { 63*91f16700Schasinglulu /* Deassert DBGPWRDUP */ 64*91f16700Schasinglulu mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); 65*91f16700Schasinglulu /* Activate the core output clamps, but not for core 0. */ 66*91f16700Schasinglulu if (core != 0) { 67*91f16700Schasinglulu mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), 68*91f16700Schasinglulu BIT(core)); 69*91f16700Schasinglulu } 70*91f16700Schasinglulu /* Assert CPU power-on reset */ 71*91f16700Schasinglulu mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 72*91f16700Schasinglulu /* Remove power from the CPU */ 73*91f16700Schasinglulu sunxi_cpu_disable_power(cluster, core); 74*91f16700Schasinglulu } else { 75*91f16700Schasinglulu /* power down(?) debug core */ 76*91f16700Schasinglulu mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8)); 77*91f16700Schasinglulu /* ??? Activate the core output clamps, but not for core 0 */ 78*91f16700Schasinglulu if (core != 0) { 79*91f16700Schasinglulu mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(1)); 80*91f16700Schasinglulu } 81*91f16700Schasinglulu /* ??? Assert CPU power-on reset ??? */ 82*91f16700Schasinglulu mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); 83*91f16700Schasinglulu /* Remove power from the CPU */ 84*91f16700Schasinglulu sunxi_cpu_disable_power(cluster, core); 85*91f16700Schasinglulu } 86*91f16700Schasinglulu } 87*91f16700Schasinglulu 88*91f16700Schasinglulu void sunxi_cpu_on(u_register_t mpidr) 89*91f16700Schasinglulu { 90*91f16700Schasinglulu unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); 91*91f16700Schasinglulu unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); 92*91f16700Schasinglulu 93*91f16700Schasinglulu VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core); 94*91f16700Schasinglulu 95*91f16700Schasinglulu if (sunxi_cpucfg_has_per_cluster_regs()) { 96*91f16700Schasinglulu /* Assert CPU core reset */ 97*91f16700Schasinglulu mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); 98*91f16700Schasinglulu /* Assert CPU power-on reset */ 99*91f16700Schasinglulu mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 100*91f16700Schasinglulu /* Set CPU to start in AArch64 mode */ 101*91f16700Schasinglulu mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster), 102*91f16700Schasinglulu BIT(SUNXI_AA64nAA32_OFFSET + core)); 103*91f16700Schasinglulu /* Apply power to the CPU */ 104*91f16700Schasinglulu sunxi_cpu_enable_power(cluster, core); 105*91f16700Schasinglulu /* Release the core output clamps */ 106*91f16700Schasinglulu mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); 107*91f16700Schasinglulu /* Deassert CPU power-on reset */ 108*91f16700Schasinglulu mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 109*91f16700Schasinglulu /* Deassert CPU core reset */ 110*91f16700Schasinglulu mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); 111*91f16700Schasinglulu /* Assert DBGPWRDUP */ 112*91f16700Schasinglulu mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); 113*91f16700Schasinglulu } else { 114*91f16700Schasinglulu /* Assert CPU core reset */ 115*91f16700Schasinglulu mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0)); 116*91f16700Schasinglulu /* ??? Assert CPU power-on reset ??? */ 117*91f16700Schasinglulu mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* Set CPU to start in AArch64 mode */ 120*91f16700Schasinglulu mmio_setbits_32(SUNXI_CPU_CTRL_REG(core), BIT(0)); 121*91f16700Schasinglulu 122*91f16700Schasinglulu /* Apply power to the CPU */ 123*91f16700Schasinglulu sunxi_cpu_enable_power(cluster, core); 124*91f16700Schasinglulu 125*91f16700Schasinglulu /* ??? Release the core output clamps ??? */ 126*91f16700Schasinglulu mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(1)); 127*91f16700Schasinglulu /* ??? Deassert CPU power-on reset ??? */ 128*91f16700Schasinglulu mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); 129*91f16700Schasinglulu /* Deassert CPU core reset */ 130*91f16700Schasinglulu mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0)); 131*91f16700Schasinglulu /* power up(?) debug core */ 132*91f16700Schasinglulu mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8)); 133*91f16700Schasinglulu } 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu void sunxi_cpu_power_off_others(void) 137*91f16700Schasinglulu { 138*91f16700Schasinglulu u_register_t self = read_mpidr(); 139*91f16700Schasinglulu unsigned int cluster; 140*91f16700Schasinglulu unsigned int core; 141*91f16700Schasinglulu 142*91f16700Schasinglulu for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) { 143*91f16700Schasinglulu for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) { 144*91f16700Schasinglulu u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) | 145*91f16700Schasinglulu (core << MPIDR_AFF0_SHIFT) | 146*91f16700Schasinglulu BIT(31); 147*91f16700Schasinglulu if (mpidr != self) 148*91f16700Schasinglulu sunxi_cpu_off(mpidr); 149*91f16700Schasinglulu } 150*91f16700Schasinglulu } 151*91f16700Schasinglulu } 152