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
sunxi_cpu_disable_power(unsigned int cluster,unsigned int core)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
sunxi_cpu_enable_power(unsigned int cluster,unsigned int core)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. */
sunxi_cpu_off(u_register_t mpidr)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
sunxi_cpu_on(u_register_t mpidr)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
sunxi_cpu_power_off_others(void)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