xref: /rk3399_ARM-atf/plat/allwinner/common/sunxi_cpu_ops.c (revision e603983d3703a0c9cee3f43baf550ca397e20b34)
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