ARM: dts: sun7i: a20: bananapro: Fix ethernet phy-mode
[linux-2.6-microblaze.git] / arch / arm / mach-zx / platsmp.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2014 Linaro Ltd.
4  * Copyright (C) 2014 ZTE Corporation.
5  */
6
7 #include <linux/delay.h>
8 #include <linux/errno.h>
9 #include <linux/init.h>
10 #include <linux/io.h>
11 #include <linux/jiffies.h>
12 #include <linux/of.h>
13 #include <linux/of_address.h>
14 #include <linux/smp.h>
15
16 #include <asm/cacheflush.h>
17 #include <asm/cp15.h>
18 #include <asm/fncpy.h>
19 #include <asm/proc-fns.h>
20 #include <asm/smp_scu.h>
21 #include <asm/smp_plat.h>
22
23 #include "core.h"
24
25 #define AON_SYS_CTRL_RESERVED1          0xa8
26
27 #define BUS_MATRIX_REMAP_CONFIG         0x00
28
29 #define PCU_CPU0_CTRL                   0x00
30 #define PCU_CPU1_CTRL                   0x04
31 #define PCU_CPU1_ST                     0x0c
32 #define PCU_GLOBAL_CTRL                 0x14
33 #define PCU_EXPEND_CONTROL              0x34
34
35 #define ZX_IRAM_BASE                    0x00200000
36
37 static void __iomem *pcu_base;
38 static void __iomem *matrix_base;
39 static void __iomem *scu_base;
40
41 void __init zx_smp_prepare_cpus(unsigned int max_cpus)
42 {
43         struct device_node *np;
44         unsigned long base = 0;
45         void __iomem *aonsysctrl_base;
46         void __iomem *sys_iram;
47
48         base = scu_a9_get_base();
49         scu_base = ioremap(base, SZ_256);
50         if (!scu_base) {
51                 pr_err("%s: failed to map scu\n", __func__);
52                 return;
53         }
54
55         scu_enable(scu_base);
56
57         np = of_find_compatible_node(NULL, NULL, "zte,sysctrl");
58         if (!np) {
59                 pr_err("%s: failed to find sysctrl node\n", __func__);
60                 return;
61         }
62
63         aonsysctrl_base = of_iomap(np, 0);
64         if (!aonsysctrl_base) {
65                 pr_err("%s: failed to map aonsysctrl\n", __func__);
66                 of_node_put(np);
67                 return;
68         }
69
70         /*
71          * Write the address of secondary startup into the
72          * system-wide flags register. The BootMonitor waits
73          * until it receives a soft interrupt, and then the
74          * secondary CPU branches to this address.
75          */
76         __raw_writel(__pa_symbol(zx_secondary_startup),
77                      aonsysctrl_base + AON_SYS_CTRL_RESERVED1);
78
79         iounmap(aonsysctrl_base);
80         of_node_put(np);
81
82         np = of_find_compatible_node(NULL, NULL, "zte,zx296702-pcu");
83         pcu_base = of_iomap(np, 0);
84         of_node_put(np);
85         WARN_ON(!pcu_base);
86
87         np = of_find_compatible_node(NULL, NULL, "zte,zx-bus-matrix");
88         matrix_base = of_iomap(np, 0);
89         of_node_put(np);
90         WARN_ON(!matrix_base);
91
92         /* Map the first 4 KB IRAM for suspend usage */
93         sys_iram = __arm_ioremap_exec(ZX_IRAM_BASE, PAGE_SIZE, false);
94         zx_secondary_startup_pa = __pa_symbol(zx_secondary_startup);
95         fncpy(sys_iram, &zx_resume_jump, zx_suspend_iram_sz);
96 }
97
98 static int zx_boot_secondary(unsigned int cpu, struct task_struct *idle)
99 {
100         static bool first_boot = true;
101
102         if (first_boot) {
103                 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
104                 first_boot = false;
105                 return 0;
106         }
107
108         /* Swap the base address mapping between IRAM and IROM */
109         writel_relaxed(0x1, matrix_base + BUS_MATRIX_REMAP_CONFIG);
110
111         /* Power on CPU1 */
112         writel_relaxed(0x0, pcu_base + PCU_CPU1_CTRL);
113
114         /* Wait for power on ack */
115         while (readl_relaxed(pcu_base + PCU_CPU1_ST) & 0x4)
116                 cpu_relax();
117
118         /* Swap back the mapping of IRAM and IROM */
119         writel_relaxed(0x0, matrix_base + BUS_MATRIX_REMAP_CONFIG);
120
121         return 0;
122 }
123
124 #ifdef CONFIG_HOTPLUG_CPU
125 static inline void cpu_enter_lowpower(void)
126 {
127         unsigned int v;
128
129         asm volatile(
130                 "mcr    p15, 0, %1, c7, c5, 0\n"
131         "       mcr     p15, 0, %1, c7, c10, 4\n"
132         /*
133          * Turn off coherency
134          */
135         "       mrc     p15, 0, %0, c1, c0, 1\n"
136         "       bic     %0, %0, %3\n"
137         "       mcr     p15, 0, %0, c1, c0, 1\n"
138         "       mrc     p15, 0, %0, c1, c0, 0\n"
139         "       bic     %0, %0, %2\n"
140         "       mcr     p15, 0, %0, c1, c0, 0\n"
141           : "=&r" (v)
142           : "r" (0), "Ir" (CR_C), "Ir" (0x40)
143           : "cc");
144 }
145
146 static int zx_cpu_kill(unsigned int cpu)
147 {
148         unsigned long timeout = jiffies + msecs_to_jiffies(2000);
149
150         writel_relaxed(0x2, pcu_base + PCU_CPU1_CTRL);
151
152         while ((readl_relaxed(pcu_base + PCU_CPU1_ST) & 0x3) != 0x0) {
153                 if (time_after(jiffies, timeout)) {
154                         pr_err("*** cpu1 poweroff timeout\n");
155                         break;
156                 }
157         }
158         return 1;
159 }
160
161 static void zx_cpu_die(unsigned int cpu)
162 {
163         scu_power_mode(scu_base, SCU_PM_POWEROFF);
164         cpu_enter_lowpower();
165
166         while (1)
167                 cpu_do_idle();
168 }
169 #endif
170
171 static void zx_secondary_init(unsigned int cpu)
172 {
173         scu_power_mode(scu_base, SCU_PM_NORMAL);
174 }
175
176 static const struct smp_operations zx_smp_ops __initconst = {
177         .smp_prepare_cpus       = zx_smp_prepare_cpus,
178         .smp_secondary_init     = zx_secondary_init,
179         .smp_boot_secondary     = zx_boot_secondary,
180 #ifdef CONFIG_HOTPLUG_CPU
181         .cpu_kill               = zx_cpu_kill,
182         .cpu_die                = zx_cpu_die,
183 #endif
184 };
185
186 CPU_METHOD_OF_DECLARE(zx_smp, "zte,zx296702-smp", &zx_smp_ops);