blob: fc0acfa07f74c4d0c83cca234bcd4893c790dda4 [file] [log] [blame]
Chen-Yu Tsai745373e2018-01-17 16:46:47 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018 Chen-Yu Tsai
4 *
5 * Chen-Yu Tsai <wens@csie.org>
6 *
7 * arch/arm/mach-sunxi/mc_smp.c
8 *
9 * Based on Allwinner code, arch/arm/mach-exynos/mcpm-exynos.c, and
10 * arch/arm/mach-hisi/platmcpm.c
11 * Cluster cache enable trampoline code adapted from MCPM framework
12 */
13
14#include <linux/arm-cci.h>
15#include <linux/cpu_pm.h>
16#include <linux/delay.h>
17#include <linux/io.h>
Chen-Yu Tsai7cbea632018-01-17 16:46:51 +080018#include <linux/iopoll.h>
19#include <linux/irqchip/arm-gic.h>
Chen-Yu Tsai745373e2018-01-17 16:46:47 +080020#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/of_device.h>
23#include <linux/smp.h>
24
25#include <asm/cacheflush.h>
26#include <asm/cp15.h>
27#include <asm/cputype.h>
28#include <asm/idmap.h>
29#include <asm/smp_plat.h>
30#include <asm/suspend.h>
31
32#define SUNXI_CPUS_PER_CLUSTER 4
33#define SUNXI_NR_CLUSTERS 2
34
Chen-Yu Tsai7cbea632018-01-17 16:46:51 +080035#define POLL_USEC 100
36#define TIMEOUT_USEC 100000
37
Chen-Yu Tsai745373e2018-01-17 16:46:47 +080038#define CPUCFG_CX_CTRL_REG0(c) (0x10 * (c))
39#define CPUCFG_CX_CTRL_REG0_L1_RST_DISABLE(n) BIT(n)
40#define CPUCFG_CX_CTRL_REG0_L1_RST_DISABLE_ALL 0xf
41#define CPUCFG_CX_CTRL_REG0_L2_RST_DISABLE_A7 BIT(4)
42#define CPUCFG_CX_CTRL_REG0_L2_RST_DISABLE_A15 BIT(0)
43#define CPUCFG_CX_CTRL_REG1(c) (0x10 * (c) + 0x4)
44#define CPUCFG_CX_CTRL_REG1_ACINACTM BIT(0)
Chen-Yu Tsai7cbea632018-01-17 16:46:51 +080045#define CPUCFG_CX_STATUS(c) (0x30 + 0x4 * (c))
46#define CPUCFG_CX_STATUS_STANDBYWFI(n) BIT(16 + (n))
47#define CPUCFG_CX_STATUS_STANDBYWFIL2 BIT(0)
Chen-Yu Tsai745373e2018-01-17 16:46:47 +080048#define CPUCFG_CX_RST_CTRL(c) (0x80 + 0x4 * (c))
49#define CPUCFG_CX_RST_CTRL_DBG_SOC_RST BIT(24)
50#define CPUCFG_CX_RST_CTRL_ETM_RST(n) BIT(20 + (n))
51#define CPUCFG_CX_RST_CTRL_ETM_RST_ALL (0xf << 20)
52#define CPUCFG_CX_RST_CTRL_DBG_RST(n) BIT(16 + (n))
53#define CPUCFG_CX_RST_CTRL_DBG_RST_ALL (0xf << 16)
54#define CPUCFG_CX_RST_CTRL_H_RST BIT(12)
55#define CPUCFG_CX_RST_CTRL_L2_RST BIT(8)
56#define CPUCFG_CX_RST_CTRL_CX_RST(n) BIT(4 + (n))
57#define CPUCFG_CX_RST_CTRL_CORE_RST(n) BIT(n)
58
59#define PRCM_CPU_PO_RST_CTRL(c) (0x4 + 0x4 * (c))
60#define PRCM_CPU_PO_RST_CTRL_CORE(n) BIT(n)
61#define PRCM_CPU_PO_RST_CTRL_CORE_ALL 0xf
62#define PRCM_PWROFF_GATING_REG(c) (0x100 + 0x4 * (c))
63#define PRCM_PWROFF_GATING_REG_CLUSTER BIT(4)
64#define PRCM_PWROFF_GATING_REG_CORE(n) BIT(n)
65#define PRCM_PWR_SWITCH_REG(c, cpu) (0x140 + 0x10 * (c) + 0x4 * (cpu))
66#define PRCM_CPU_SOFT_ENTRY_REG 0x164
67
68static void __iomem *cpucfg_base;
69static void __iomem *prcm_base;
70
71static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster)
72{
73 struct device_node *node;
74 int cpu = cluster * SUNXI_CPUS_PER_CLUSTER + core;
75
76 node = of_cpu_device_node_get(cpu);
77
78 /* In case of_cpu_device_node_get fails */
79 if (!node)
80 node = of_get_cpu_node(cpu, NULL);
81
82 if (!node) {
83 /*
84 * There's no point in returning an error, since we
85 * would be mid way in a core or cluster power sequence.
86 */
87 pr_err("%s: Couldn't get CPU cluster %u core %u device node\n",
88 __func__, cluster, core);
89
90 return false;
91 }
92
93 return of_device_is_compatible(node, "arm,cortex-a15");
94}
95
96static int sunxi_cpu_power_switch_set(unsigned int cpu, unsigned int cluster,
97 bool enable)
98{
99 u32 reg;
100
101 /* control sequence from Allwinner A80 user manual v1.2 PRCM section */
102 reg = readl(prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
103 if (enable) {
104 if (reg == 0x00) {
105 pr_debug("power clamp for cluster %u cpu %u already open\n",
106 cluster, cpu);
107 return 0;
108 }
109
110 writel(0xff, prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
111 udelay(10);
112 writel(0xfe, prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
113 udelay(10);
114 writel(0xf8, prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
115 udelay(10);
116 writel(0xf0, prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
117 udelay(10);
118 writel(0x00, prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
119 udelay(10);
120 } else {
121 writel(0xff, prcm_base + PRCM_PWR_SWITCH_REG(cluster, cpu));
122 udelay(10);
123 }
124
125 return 0;
126}
127
128static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster)
129{
130 u32 reg;
131
Chen-Yu Tsai7cbea632018-01-17 16:46:51 +0800132 pr_debug("%s: cluster %u cpu %u\n", __func__, cluster, cpu);
Chen-Yu Tsai745373e2018-01-17 16:46:47 +0800133 if (cpu >= SUNXI_CPUS_PER_CLUSTER || cluster >= SUNXI_NR_CLUSTERS)
134 return -EINVAL;
135
136 /* assert processor power-on reset */
137 reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
138 reg &= ~PRCM_CPU_PO_RST_CTRL_CORE(cpu);
139 writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
140
141 /* Cortex-A7: hold L1 reset disable signal low */
142 if (!sunxi_core_is_cortex_a15(cpu, cluster)) {
143 reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster));
144 reg &= ~CPUCFG_CX_CTRL_REG0_L1_RST_DISABLE(cpu);
145 writel(reg, cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster));
146 }
147
148 /* assert processor related resets */
149 reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
150 reg &= ~CPUCFG_CX_RST_CTRL_DBG_RST(cpu);
151
152 /*
153 * Allwinner code also asserts resets for NEON on A15. According
154 * to ARM manuals, asserting power-on reset is sufficient.
155 */
156 if (!sunxi_core_is_cortex_a15(cpu, cluster))
157 reg &= ~CPUCFG_CX_RST_CTRL_ETM_RST(cpu);
158
159 writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
160
161 /* open power switch */
162 sunxi_cpu_power_switch_set(cpu, cluster, true);
163
164 /* clear processor power gate */
165 reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
166 reg &= ~PRCM_PWROFF_GATING_REG_CORE(cpu);
167 writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
168 udelay(20);
169
170 /* de-assert processor power-on reset */
171 reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
172 reg |= PRCM_CPU_PO_RST_CTRL_CORE(cpu);
173 writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
174
175 /* de-assert all processor resets */
176 reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
177 reg |= CPUCFG_CX_RST_CTRL_DBG_RST(cpu);
178 reg |= CPUCFG_CX_RST_CTRL_CORE_RST(cpu);
179 if (!sunxi_core_is_cortex_a15(cpu, cluster))
180 reg |= CPUCFG_CX_RST_CTRL_ETM_RST(cpu);
181 else
182 reg |= CPUCFG_CX_RST_CTRL_CX_RST(cpu); /* NEON */
183 writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
184
185 return 0;
186}
187
188static int sunxi_cluster_powerup(unsigned int cluster)
189{
190 u32 reg;
191
192 pr_debug("%s: cluster %u\n", __func__, cluster);
193 if (cluster >= SUNXI_NR_CLUSTERS)
194 return -EINVAL;
195
196 /* assert ACINACTM */
197 reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
198 reg |= CPUCFG_CX_CTRL_REG1_ACINACTM;
199 writel(reg, cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
200
201 /* assert cluster processor power-on resets */
202 reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
203 reg &= ~PRCM_CPU_PO_RST_CTRL_CORE_ALL;
204 writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
205
206 /* assert cluster resets */
207 reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
208 reg &= ~CPUCFG_CX_RST_CTRL_DBG_SOC_RST;
209 reg &= ~CPUCFG_CX_RST_CTRL_DBG_RST_ALL;
210 reg &= ~CPUCFG_CX_RST_CTRL_H_RST;
211 reg &= ~CPUCFG_CX_RST_CTRL_L2_RST;
212
213 /*
214 * Allwinner code also asserts resets for NEON on A15. According
215 * to ARM manuals, asserting power-on reset is sufficient.
216 */
217 if (!sunxi_core_is_cortex_a15(0, cluster))
218 reg &= ~CPUCFG_CX_RST_CTRL_ETM_RST_ALL;
219
220 writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
221
222 /* hold L1/L2 reset disable signals low */
223 reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster));
224 if (sunxi_core_is_cortex_a15(0, cluster)) {
225 /* Cortex-A15: hold L2RSTDISABLE low */
226 reg &= ~CPUCFG_CX_CTRL_REG0_L2_RST_DISABLE_A15;
227 } else {
228 /* Cortex-A7: hold L1RSTDISABLE and L2RSTDISABLE low */
229 reg &= ~CPUCFG_CX_CTRL_REG0_L1_RST_DISABLE_ALL;
230 reg &= ~CPUCFG_CX_CTRL_REG0_L2_RST_DISABLE_A7;
231 }
232 writel(reg, cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster));
233
234 /* clear cluster power gate */
235 reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
236 reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER;
237 writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
238 udelay(20);
239
240 /* de-assert cluster resets */
241 reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
242 reg |= CPUCFG_CX_RST_CTRL_DBG_SOC_RST;
243 reg |= CPUCFG_CX_RST_CTRL_H_RST;
244 reg |= CPUCFG_CX_RST_CTRL_L2_RST;
245 writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
246
247 /* de-assert ACINACTM */
248 reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
249 reg &= ~CPUCFG_CX_CTRL_REG1_ACINACTM;
250 writel(reg, cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
251
252 return 0;
253}
254
255/*
256 * This bit is shared between the initial nocache_trampoline call to
257 * enable CCI-400 and proper cluster cache disable before power down.
258 */
259static void sunxi_cluster_cache_disable_without_axi(void)
260{
261 if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A15) {
262 /*
263 * On the Cortex-A15 we need to disable
264 * L2 prefetching before flushing the cache.
265 */
266 asm volatile(
267 "mcr p15, 1, %0, c15, c0, 3\n"
268 "isb\n"
269 "dsb"
270 : : "r" (0x400));
271 }
272
273 /* Flush all cache levels for this cluster. */
274 v7_exit_coherency_flush(all);
275
276 /*
277 * Disable cluster-level coherency by masking
278 * incoming snoops and DVM messages:
279 */
280 cci_disable_port_by_cpu(read_cpuid_mpidr());
281}
282
283static int sunxi_mc_smp_cpu_table[SUNXI_NR_CLUSTERS][SUNXI_CPUS_PER_CLUSTER];
284static int sunxi_mc_smp_first_comer;
285
286/*
287 * Enable cluster-level coherency, in preparation for turning on the MMU.
288 *
289 * Also enable regional clock gating and L2 data latency settings for
290 * Cortex-A15. These settings are from the vendor kernel.
291 */
292static void __naked sunxi_mc_smp_cluster_cache_enable(void)
293{
294 asm volatile (
295 "mrc p15, 0, r1, c0, c0, 0\n"
296 "movw r2, #" __stringify(ARM_CPU_PART_MASK & 0xffff) "\n"
297 "movt r2, #" __stringify(ARM_CPU_PART_MASK >> 16) "\n"
298 "and r1, r1, r2\n"
299 "movw r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 & 0xffff) "\n"
300 "movt r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 >> 16) "\n"
301 "cmp r1, r2\n"
302 "bne not_a15\n"
303
304 /* The following is Cortex-A15 specific */
305
306 /* ACTLR2: Enable CPU regional clock gates */
307 "mrc p15, 1, r1, c15, c0, 4\n"
308 "orr r1, r1, #(0x1<<31)\n"
309 "mcr p15, 1, r1, c15, c0, 4\n"
310
311 /* L2ACTLR */
312 "mrc p15, 1, r1, c15, c0, 0\n"
313 /* Enable L2, GIC, and Timer regional clock gates */
314 "orr r1, r1, #(0x1<<26)\n"
315 /* Disable clean/evict from being pushed to external */
316 "orr r1, r1, #(0x1<<3)\n"
317 "mcr p15, 1, r1, c15, c0, 0\n"
318
319 /* L2CTRL: L2 data RAM latency */
320 "mrc p15, 1, r1, c9, c0, 2\n"
321 "bic r1, r1, #(0x7<<0)\n"
322 "orr r1, r1, #(0x3<<0)\n"
323 "mcr p15, 1, r1, c9, c0, 2\n"
324
325 /* End of Cortex-A15 specific setup */
326 "not_a15:\n"
327
328 /* Get value of sunxi_mc_smp_first_comer */
329 "adr r1, first\n"
330 "ldr r0, [r1]\n"
331 "ldr r0, [r1, r0]\n"
332
333 /* Skip cci_enable_port_for_self if not first comer */
334 "cmp r0, #0\n"
335 "bxeq lr\n"
336 "b cci_enable_port_for_self\n"
337
338 ".align 2\n"
339 "first: .word sunxi_mc_smp_first_comer - .\n"
340 );
341}
342
343static void __naked sunxi_mc_smp_secondary_startup(void)
344{
345 asm volatile(
346 "bl sunxi_mc_smp_cluster_cache_enable\n"
347 "b secondary_startup"
348 /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */
349 :: "i" (sunxi_mc_smp_cluster_cache_enable)
350 );
351}
352
353static DEFINE_SPINLOCK(boot_lock);
354
355static bool sunxi_mc_smp_cluster_is_down(unsigned int cluster)
356{
357 int i;
358
359 for (i = 0; i < SUNXI_CPUS_PER_CLUSTER; i++)
360 if (sunxi_mc_smp_cpu_table[cluster][i])
361 return false;
362 return true;
363}
364
365static int sunxi_mc_smp_boot_secondary(unsigned int l_cpu, struct task_struct *idle)
366{
367 unsigned int mpidr, cpu, cluster;
368
369 mpidr = cpu_logical_map(l_cpu);
370 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
371 cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
372
373 if (!cpucfg_base)
374 return -ENODEV;
375 if (cluster >= SUNXI_NR_CLUSTERS || cpu >= SUNXI_CPUS_PER_CLUSTER)
376 return -EINVAL;
377
378 spin_lock_irq(&boot_lock);
379
380 if (sunxi_mc_smp_cpu_table[cluster][cpu])
381 goto out;
382
383 if (sunxi_mc_smp_cluster_is_down(cluster)) {
384 sunxi_mc_smp_first_comer = true;
385 sunxi_cluster_powerup(cluster);
386 } else {
387 sunxi_mc_smp_first_comer = false;
388 }
389
390 /* This is read by incoming CPUs with their cache and MMU disabled */
391 sync_cache_w(&sunxi_mc_smp_first_comer);
392 sunxi_cpu_powerup(cpu, cluster);
393
394out:
395 sunxi_mc_smp_cpu_table[cluster][cpu]++;
396 spin_unlock_irq(&boot_lock);
397
398 return 0;
399}
400
Chen-Yu Tsai7cbea632018-01-17 16:46:51 +0800401#ifdef CONFIG_HOTPLUG_CPU
402static void sunxi_cluster_cache_disable(void)
403{
404 unsigned int cluster = MPIDR_AFFINITY_LEVEL(read_cpuid_mpidr(), 1);
405 u32 reg;
406
407 pr_debug("%s: cluster %u\n", __func__, cluster);
408
409 sunxi_cluster_cache_disable_without_axi();
410
411 /* last man standing, assert ACINACTM */
412 reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
413 reg |= CPUCFG_CX_CTRL_REG1_ACINACTM;
414 writel(reg, cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
415}
416
417static void sunxi_mc_smp_cpu_die(unsigned int l_cpu)
418{
419 unsigned int mpidr, cpu, cluster;
420 bool last_man;
421
422 mpidr = cpu_logical_map(l_cpu);
423 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
424 cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
425 pr_debug("%s: cluster %u cpu %u\n", __func__, cluster, cpu);
426
427 spin_lock(&boot_lock);
428 sunxi_mc_smp_cpu_table[cluster][cpu]--;
429 if (sunxi_mc_smp_cpu_table[cluster][cpu] == 1) {
430 /* A power_up request went ahead of us. */
431 pr_debug("%s: aborting due to a power up request\n",
432 __func__);
433 spin_unlock(&boot_lock);
434 return;
435 } else if (sunxi_mc_smp_cpu_table[cluster][cpu] > 1) {
436 pr_err("Cluster %d CPU%d boots multiple times\n",
437 cluster, cpu);
438 BUG();
439 }
440
441 last_man = sunxi_mc_smp_cluster_is_down(cluster);
442 spin_unlock(&boot_lock);
443
444 gic_cpu_if_down(0);
445 if (last_man)
446 sunxi_cluster_cache_disable();
447 else
448 v7_exit_coherency_flush(louis);
449
450 for (;;)
451 wfi();
452}
453
454static int sunxi_cpu_powerdown(unsigned int cpu, unsigned int cluster)
455{
456 u32 reg;
457
458 pr_debug("%s: cluster %u cpu %u\n", __func__, cluster, cpu);
459 if (cpu >= SUNXI_CPUS_PER_CLUSTER || cluster >= SUNXI_NR_CLUSTERS)
460 return -EINVAL;
461
462 /* gate processor power */
463 reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
464 reg |= PRCM_PWROFF_GATING_REG_CORE(cpu);
465 writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
466 udelay(20);
467
468 /* close power switch */
469 sunxi_cpu_power_switch_set(cpu, cluster, false);
470
471 return 0;
472}
473
474static int sunxi_cluster_powerdown(unsigned int cluster)
475{
476 u32 reg;
477
478 pr_debug("%s: cluster %u\n", __func__, cluster);
479 if (cluster >= SUNXI_NR_CLUSTERS)
480 return -EINVAL;
481
482 /* assert cluster resets or system will hang */
483 pr_debug("%s: assert cluster reset\n", __func__);
484 reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
485 reg &= ~CPUCFG_CX_RST_CTRL_DBG_SOC_RST;
486 reg &= ~CPUCFG_CX_RST_CTRL_H_RST;
487 reg &= ~CPUCFG_CX_RST_CTRL_L2_RST;
488 writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
489
490 /* gate cluster power */
491 pr_debug("%s: gate cluster power\n", __func__);
492 reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
493 reg |= PRCM_PWROFF_GATING_REG_CLUSTER;
494 writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
495 udelay(20);
496
497 return 0;
498}
499
500static int sunxi_mc_smp_cpu_kill(unsigned int l_cpu)
501{
502 unsigned int mpidr, cpu, cluster;
503 unsigned int tries, count;
504 int ret = 0;
505 u32 reg;
506
507 mpidr = cpu_logical_map(l_cpu);
508 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
509 cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
510
511 /* This should never happen */
512 if (WARN_ON(cluster >= SUNXI_NR_CLUSTERS ||
513 cpu >= SUNXI_CPUS_PER_CLUSTER))
514 return 0;
515
516 /* wait for CPU core to die and enter WFI */
517 count = TIMEOUT_USEC / POLL_USEC;
518 spin_lock_irq(&boot_lock);
519 for (tries = 0; tries < count; tries++) {
520 spin_unlock_irq(&boot_lock);
521 usleep_range(POLL_USEC / 2, POLL_USEC);
522 spin_lock_irq(&boot_lock);
523
524 /*
525 * If the user turns off a bunch of cores at the same
526 * time, the kernel might call cpu_kill before some of
527 * them are ready. This is because boot_lock serializes
528 * both cpu_die and cpu_kill callbacks. Either one could
529 * run first. We should wait for cpu_die to complete.
530 */
531 if (sunxi_mc_smp_cpu_table[cluster][cpu])
532 continue;
533
534 reg = readl(cpucfg_base + CPUCFG_CX_STATUS(cluster));
535 if (reg & CPUCFG_CX_STATUS_STANDBYWFI(cpu))
536 break;
537 }
538
539 if (tries >= count) {
540 ret = ETIMEDOUT;
541 goto out;
542 }
543
544 /* power down CPU core */
545 sunxi_cpu_powerdown(cpu, cluster);
546
547 if (!sunxi_mc_smp_cluster_is_down(cluster))
548 goto out;
549
550 /* wait for cluster L2 WFI */
551 ret = readl_poll_timeout(cpucfg_base + CPUCFG_CX_STATUS(cluster), reg,
552 reg & CPUCFG_CX_STATUS_STANDBYWFIL2,
553 POLL_USEC, TIMEOUT_USEC);
554 if (ret) {
555 /*
556 * Ignore timeout on the cluster. Leaving the cluster on
557 * will not affect system execution, just use a bit more
558 * power. But returning an error here will only confuse
559 * the user as the CPU has already been shutdown.
560 */
561 ret = 0;
562 goto out;
563 }
564
565 /* Power down cluster */
566 sunxi_cluster_powerdown(cluster);
567
568out:
569 spin_unlock_irq(&boot_lock);
570 pr_debug("%s: cluster %u cpu %u powerdown: %d\n",
571 __func__, cluster, cpu, ret);
572 return !ret;
573}
574
575#endif
576
Chen-Yu Tsai745373e2018-01-17 16:46:47 +0800577static const struct smp_operations sunxi_mc_smp_smp_ops __initconst = {
578 .smp_boot_secondary = sunxi_mc_smp_boot_secondary,
Chen-Yu Tsai7cbea632018-01-17 16:46:51 +0800579#ifdef CONFIG_HOTPLUG_CPU
580 .cpu_die = sunxi_mc_smp_cpu_die,
581 .cpu_kill = sunxi_mc_smp_cpu_kill,
582#endif
Chen-Yu Tsai745373e2018-01-17 16:46:47 +0800583};
584
585static bool __init sunxi_mc_smp_cpu_table_init(void)
586{
587 unsigned int mpidr, cpu, cluster;
588
589 mpidr = read_cpuid_mpidr();
590 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
591 cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
592
593 if (cluster >= SUNXI_NR_CLUSTERS || cpu >= SUNXI_CPUS_PER_CLUSTER) {
594 pr_err("%s: boot CPU is out of bounds!\n", __func__);
595 return false;
596 }
597 sunxi_mc_smp_cpu_table[cluster][cpu] = 1;
598 return true;
599}
600
601/*
602 * Adapted from arch/arm/common/mc_smp_entry.c
603 *
604 * We need the trampoline code to enable CCI-400 on the first cluster
605 */
606typedef typeof(cpu_reset) phys_reset_t;
607
608static void __init __naked sunxi_mc_smp_resume(void)
609{
610 asm volatile(
611 "bl sunxi_mc_smp_cluster_cache_enable\n"
612 "b cpu_resume"
613 /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */
614 :: "i" (sunxi_mc_smp_cluster_cache_enable)
615 );
616}
617
618static int __init nocache_trampoline(unsigned long __unused)
619{
620 phys_reset_t phys_reset;
621
622 setup_mm_for_reboot();
623 sunxi_cluster_cache_disable_without_axi();
624
625 phys_reset = (phys_reset_t)(unsigned long)__pa_symbol(cpu_reset);
626 phys_reset(__pa_symbol(sunxi_mc_smp_resume), false);
627 BUG();
628}
629
630static int __init sunxi_mc_smp_lookback(void)
631{
632 int ret;
633
634 /*
635 * We're going to soft-restart the current CPU through the
636 * low-level MCPM code by leveraging the suspend/resume
637 * infrastructure. Let's play it safe by using cpu_pm_enter()
638 * in case the CPU init code path resets the VFP or similar.
639 */
640 sunxi_mc_smp_first_comer = true;
641 local_irq_disable();
642 local_fiq_disable();
643 ret = cpu_pm_enter();
644 if (!ret) {
645 ret = cpu_suspend(0, nocache_trampoline);
646 cpu_pm_exit();
647 }
648 local_fiq_enable();
649 local_irq_enable();
650 sunxi_mc_smp_first_comer = false;
651
652 return ret;
653}
654
655static int __init sunxi_mc_smp_init(void)
656{
657 struct device_node *cpucfg_node, *node;
658 struct resource res;
659 int ret;
660
661 if (!of_machine_is_compatible("allwinner,sun9i-a80"))
662 return -ENODEV;
663
664 if (!sunxi_mc_smp_cpu_table_init())
665 return -EINVAL;
666
667 if (!cci_probed()) {
668 pr_err("%s: CCI-400 not available\n", __func__);
669 return -ENODEV;
670 }
671
672 node = of_find_compatible_node(NULL, NULL, "allwinner,sun9i-a80-prcm");
673 if (!node) {
674 pr_err("%s: PRCM not available\n", __func__);
675 return -ENODEV;
676 }
677
678 /*
679 * Unfortunately we can not request the I/O region for the PRCM.
680 * It is shared with the PRCM clock.
681 */
682 prcm_base = of_iomap(node, 0);
683 of_node_put(node);
684 if (!prcm_base) {
685 pr_err("%s: failed to map PRCM registers\n", __func__);
686 return -ENOMEM;
687 }
688
689 cpucfg_node = of_find_compatible_node(NULL, NULL,
690 "allwinner,sun9i-a80-cpucfg");
691 if (!cpucfg_node) {
692 ret = -ENODEV;
693 pr_err("%s: CPUCFG not available\n", __func__);
694 goto err_unmap_prcm;
695 }
696
697 cpucfg_base = of_io_request_and_map(cpucfg_node, 0, "sunxi-mc-smp");
698 if (IS_ERR(cpucfg_base)) {
699 ret = PTR_ERR(cpucfg_base);
700 pr_err("%s: failed to map CPUCFG registers: %d\n",
701 __func__, ret);
702 goto err_put_cpucfg_node;
703 }
704
705 /* Configure CCI-400 for boot cluster */
706 ret = sunxi_mc_smp_lookback();
707 if (ret) {
708 pr_err("%s: failed to configure boot cluster: %d\n",
709 __func__, ret);
710 goto err_unmap_release_cpucfg;
711 }
712
713 /* We don't need the CPUCFG device node anymore */
714 of_node_put(cpucfg_node);
715
716 /* Set the hardware entry point address */
717 writel(__pa_symbol(sunxi_mc_smp_secondary_startup),
718 prcm_base + PRCM_CPU_SOFT_ENTRY_REG);
719
720 /* Actually enable multi cluster SMP */
721 smp_set_ops(&sunxi_mc_smp_smp_ops);
722
723 pr_info("sunxi multi cluster SMP support installed\n");
724
725 return 0;
726
727err_unmap_release_cpucfg:
728 iounmap(cpucfg_base);
729 of_address_to_resource(cpucfg_node, 0, &res);
730 release_mem_region(res.start, resource_size(&res));
731err_put_cpucfg_node:
732 of_node_put(cpucfg_node);
733err_unmap_prcm:
734 iounmap(prcm_base);
735 return ret;
736}
737
738early_initcall(sunxi_mc_smp_init);