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