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