1 /* 2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <debug.h> 8 #include <mmio.h> 9 #include <platform_def.h> 10 #include <sunxi_mmap.h> 11 #include <sunxi_cpucfg.h> 12 #include <sunxi_private.h> 13 #include <utils_def.h> 14 15 static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) 16 { 17 if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) 18 return; 19 20 VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core); 21 22 mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff); 23 } 24 25 static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) 26 { 27 if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0) 28 return; 29 30 VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core); 31 32 /* Power enable sequence from original Allwinner sources */ 33 mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe); 34 mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8); 35 mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0); 36 mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80); 37 mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); 38 } 39 40 void sunxi_cpu_off(unsigned int cluster, unsigned int core) 41 { 42 VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core); 43 44 /* Deassert DBGPWRDUP */ 45 mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); 46 /* Activate the core output clamps */ 47 mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); 48 /* Assert CPU power-on reset */ 49 mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 50 /* Remove power from the CPU */ 51 sunxi_cpu_disable_power(cluster, core); 52 } 53 54 void sunxi_cpu_on(unsigned int cluster, unsigned int core) 55 { 56 VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core); 57 58 /* Assert CPU core reset */ 59 mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); 60 /* Assert CPU power-on reset */ 61 mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 62 /* Set CPU to start in AArch64 mode */ 63 mmio_setbits_32(SUNXI_CPUCFG_CLS_CTRL_REG0(cluster), BIT(24 + core)); 64 /* Apply power to the CPU */ 65 sunxi_cpu_enable_power(cluster, core); 66 /* Release the core output clamps */ 67 mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); 68 /* Deassert CPU power-on reset */ 69 mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 70 /* Deassert CPU core reset */ 71 mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); 72 /* Assert DBGPWRDUP */ 73 mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); 74 } 75 76 void sunxi_disable_secondary_cpus(unsigned int primary_cpu) 77 { 78 for (unsigned int cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu += 1) { 79 if (cpu == primary_cpu) 80 continue; 81 sunxi_cpu_off(cpu / PLATFORM_MAX_CPUS_PER_CLUSTER, 82 cpu % PLATFORM_MAX_CPUS_PER_CLUSTER); 83 } 84 } 85