1333d66cfSSamuel Holland /* 2a1d349beSSamuel Holland * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. 3333d66cfSSamuel Holland * 4333d66cfSSamuel Holland * SPDX-License-Identifier: BSD-3-Clause 5333d66cfSSamuel Holland */ 6333d66cfSSamuel Holland 77db0c960SAndre Przywara #include <assert.h> 809d40e0eSAntonio Nino Diaz 9333d66cfSSamuel Holland #include <platform_def.h> 1009d40e0eSAntonio Nino Diaz 1109d40e0eSAntonio Nino Diaz #include <arch_helpers.h> 1209d40e0eSAntonio Nino Diaz #include <common/debug.h> 1309d40e0eSAntonio Nino Diaz #include <drivers/delay_timer.h> 1409d40e0eSAntonio Nino Diaz #include <lib/mmio.h> 1509d40e0eSAntonio Nino Diaz #include <lib/utils_def.h> 1609d40e0eSAntonio Nino Diaz #include <plat/common/platform.h> 1709d40e0eSAntonio Nino Diaz 18333d66cfSSamuel Holland #include <sunxi_cpucfg.h> 197db0c960SAndre Przywara #include <sunxi_mmap.h> 204ec1a239SAndre Przywara #include <sunxi_private.h> 21333d66cfSSamuel Holland 22*018c1d87SMikhail Kalashnikov #ifndef SUNXI_C0_CPU_CTRL_REG 23*018c1d87SMikhail Kalashnikov #define SUNXI_C0_CPU_CTRL_REG(n) 0 24*018c1d87SMikhail Kalashnikov #define SUNXI_CPU_UNK_REG(n) 0 25*018c1d87SMikhail Kalashnikov #define SUNXI_CPU_CTRL_REG(n) 0 26*018c1d87SMikhail Kalashnikov #endif 27*018c1d87SMikhail Kalashnikov 28333d66cfSSamuel Holland static void sunxi_cpu_disable_power(unsigned int cluster, unsigned int core) 29333d66cfSSamuel Holland { 30333d66cfSSamuel Holland if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff) 31333d66cfSSamuel Holland return; 32333d66cfSSamuel Holland 3327f9616fSAndre Przywara VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core); 34333d66cfSSamuel Holland 35333d66cfSSamuel Holland mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff); 36333d66cfSSamuel Holland } 37333d66cfSSamuel Holland 38333d66cfSSamuel Holland static void sunxi_cpu_enable_power(unsigned int cluster, unsigned int core) 39333d66cfSSamuel Holland { 40333d66cfSSamuel Holland if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0) 41333d66cfSSamuel Holland return; 42333d66cfSSamuel Holland 4327f9616fSAndre Przywara VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core); 44333d66cfSSamuel Holland 45333d66cfSSamuel Holland /* Power enable sequence from original Allwinner sources */ 46333d66cfSSamuel Holland mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe); 47333d66cfSSamuel Holland mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xf8); 48333d66cfSSamuel Holland mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xe0); 49333d66cfSSamuel Holland mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x80); 50333d66cfSSamuel Holland mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0x00); 5186a7429eSIcenowy Zheng udelay(1); 52333d66cfSSamuel Holland } 53333d66cfSSamuel Holland 54a1d349beSSamuel Holland /* We can't turn ourself off like this, but it works for other cores. */ 55a1d349beSSamuel Holland static void sunxi_cpu_off(u_register_t mpidr) 56333d66cfSSamuel Holland { 575d4bd66dSSamuel Holland unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); 585d4bd66dSSamuel Holland unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); 597db0c960SAndre Przywara 6027f9616fSAndre Przywara VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core); 61333d66cfSSamuel Holland 62*018c1d87SMikhail Kalashnikov if (sunxi_cpucfg_has_per_cluster_regs()) { 63333d66cfSSamuel Holland /* Deassert DBGPWRDUP */ 64333d66cfSSamuel Holland mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); 657db0c960SAndre Przywara /* Activate the core output clamps, but not for core 0. */ 66*018c1d87SMikhail Kalashnikov if (core != 0) { 67*018c1d87SMikhail Kalashnikov mmio_setbits_32(SUNXI_POWEROFF_GATING_REG(cluster), 68*018c1d87SMikhail Kalashnikov BIT(core)); 69*018c1d87SMikhail Kalashnikov } 70333d66cfSSamuel Holland /* Assert CPU power-on reset */ 71333d66cfSSamuel Holland mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 72333d66cfSSamuel Holland /* Remove power from the CPU */ 73333d66cfSSamuel Holland sunxi_cpu_disable_power(cluster, core); 74*018c1d87SMikhail Kalashnikov } else { 75*018c1d87SMikhail Kalashnikov /* power down(?) debug core */ 76*018c1d87SMikhail Kalashnikov mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8)); 77*018c1d87SMikhail Kalashnikov /* ??? Activate the core output clamps, but not for core 0 */ 78*018c1d87SMikhail Kalashnikov if (core != 0) { 79*018c1d87SMikhail Kalashnikov mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(1)); 80*018c1d87SMikhail Kalashnikov } 81*018c1d87SMikhail Kalashnikov /* ??? Assert CPU power-on reset ??? */ 82*018c1d87SMikhail Kalashnikov mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); 83*018c1d87SMikhail Kalashnikov /* Remove power from the CPU */ 84*018c1d87SMikhail Kalashnikov sunxi_cpu_disable_power(cluster, core); 85*018c1d87SMikhail Kalashnikov } 867db0c960SAndre Przywara } 877db0c960SAndre Przywara 885d4bd66dSSamuel Holland void sunxi_cpu_on(u_register_t mpidr) 89333d66cfSSamuel Holland { 905d4bd66dSSamuel Holland unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); 915d4bd66dSSamuel Holland unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); 925d4bd66dSSamuel Holland 9327f9616fSAndre Przywara VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core); 94333d66cfSSamuel Holland 95*018c1d87SMikhail Kalashnikov if (sunxi_cpucfg_has_per_cluster_regs()) { 96333d66cfSSamuel Holland /* Assert CPU core reset */ 97333d66cfSSamuel Holland mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); 98333d66cfSSamuel Holland /* Assert CPU power-on reset */ 99333d66cfSSamuel Holland mmio_clrbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 100333d66cfSSamuel Holland /* Set CPU to start in AArch64 mode */ 101080939f9SIcenowy Zheng mmio_setbits_32(SUNXI_AA64nAA32_REG(cluster), 102080939f9SIcenowy Zheng BIT(SUNXI_AA64nAA32_OFFSET + core)); 103333d66cfSSamuel Holland /* Apply power to the CPU */ 104333d66cfSSamuel Holland sunxi_cpu_enable_power(cluster, core); 105333d66cfSSamuel Holland /* Release the core output clamps */ 106333d66cfSSamuel Holland mmio_clrbits_32(SUNXI_POWEROFF_GATING_REG(cluster), BIT(core)); 107333d66cfSSamuel Holland /* Deassert CPU power-on reset */ 108333d66cfSSamuel Holland mmio_setbits_32(SUNXI_POWERON_RST_REG(cluster), BIT(core)); 109333d66cfSSamuel Holland /* Deassert CPU core reset */ 110333d66cfSSamuel Holland mmio_setbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core)); 111333d66cfSSamuel Holland /* Assert DBGPWRDUP */ 112333d66cfSSamuel Holland mmio_setbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core)); 113*018c1d87SMikhail Kalashnikov } else { 114*018c1d87SMikhail Kalashnikov /* Assert CPU core reset */ 115*018c1d87SMikhail Kalashnikov mmio_clrbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0)); 116*018c1d87SMikhail Kalashnikov /* ??? Assert CPU power-on reset ??? */ 117*018c1d87SMikhail Kalashnikov mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); 118*018c1d87SMikhail Kalashnikov 119*018c1d87SMikhail Kalashnikov /* Set CPU to start in AArch64 mode */ 120*018c1d87SMikhail Kalashnikov mmio_setbits_32(SUNXI_CPU_CTRL_REG(core), BIT(0)); 121*018c1d87SMikhail Kalashnikov 122*018c1d87SMikhail Kalashnikov /* Apply power to the CPU */ 123*018c1d87SMikhail Kalashnikov sunxi_cpu_enable_power(cluster, core); 124*018c1d87SMikhail Kalashnikov 125*018c1d87SMikhail Kalashnikov /* ??? Release the core output clamps ??? */ 126*018c1d87SMikhail Kalashnikov mmio_clrbits_32(SUNXI_CPU_UNK_REG(core), BIT(1)); 127*018c1d87SMikhail Kalashnikov /* ??? Deassert CPU power-on reset ??? */ 128*018c1d87SMikhail Kalashnikov mmio_setbits_32(SUNXI_CPU_UNK_REG(core), BIT(0)); 129*018c1d87SMikhail Kalashnikov /* Deassert CPU core reset */ 130*018c1d87SMikhail Kalashnikov mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(0)); 131*018c1d87SMikhail Kalashnikov /* power up(?) debug core */ 132*018c1d87SMikhail Kalashnikov mmio_setbits_32(SUNXI_C0_CPU_CTRL_REG(core), BIT(8)); 133*018c1d87SMikhail Kalashnikov } 134333d66cfSSamuel Holland } 135333d66cfSSamuel Holland 136a1d349beSSamuel Holland void sunxi_cpu_power_off_others(void) 137333d66cfSSamuel Holland { 138a1d349beSSamuel Holland u_register_t self = read_mpidr(); 1395d4bd66dSSamuel Holland unsigned int cluster; 1405d4bd66dSSamuel Holland unsigned int core; 1415d4bd66dSSamuel Holland 1425d4bd66dSSamuel Holland for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; ++cluster) { 1435d4bd66dSSamuel Holland for (core = 0; core < PLATFORM_MAX_CPUS_PER_CLUSTER; ++core) { 1445d4bd66dSSamuel Holland u_register_t mpidr = (cluster << MPIDR_AFF1_SHIFT) | 1455d4bd66dSSamuel Holland (core << MPIDR_AFF0_SHIFT) | 1465d4bd66dSSamuel Holland BIT(31); 147a1d349beSSamuel Holland if (mpidr != self) 1485d4bd66dSSamuel Holland sunxi_cpu_off(mpidr); 1495d4bd66dSSamuel Holland } 150333d66cfSSamuel Holland } 151333d66cfSSamuel Holland } 152