bcm53xx: use backported BCM5301X patches from stblinux soc/next
[openwrt/svn-archive/archive.git] / target / linux / bcm53xx / patches-4.4 / 023-ARM-BCM-Add-SMP-support-for-Broadcom-NSP.patch
1 From 55be958cd27439a58c4d9369d6fe2a1f83efdaa6 Mon Sep 17 00:00:00 2001
2 From: Kapil Hali <kapilh@broadcom.com>
3 Date: Sat, 5 Dec 2015 06:53:43 -0500
4 Subject: [PATCH] ARM: BCM: Add SMP support for Broadcom NSP
5
6 Add SMP support for Broadcom's Northstar Plus SoC
7 cpu enable method. This changes also consolidates
8 iProc family's - BCM NSP and BCM Kona, platform
9 SMP handling in a common file.
10
11 Northstar Plus SoC is based on ARM Cortex-A9
12 revision r3p0 which requires configuration for ARM
13 Errata 764369 for SMP. This change adds the needed
14 configuration option.
15
16 Signed-off-by: Kapil Hali <kapilh@broadcom.com>
17 Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
18 ---
19 arch/arm/mach-bcm/Kconfig | 2 +
20 arch/arm/mach-bcm/Makefile | 8 +-
21 arch/arm/mach-bcm/kona_smp.c | 228 ----------------------------------
22 arch/arm/mach-bcm/platsmp.c | 290 +++++++++++++++++++++++++++++++++++++++++++
23 4 files changed, 298 insertions(+), 230 deletions(-)
24 delete mode 100644 arch/arm/mach-bcm/kona_smp.c
25 create mode 100644 arch/arm/mach-bcm/platsmp.c
26
27 --- a/arch/arm/mach-bcm/Kconfig
28 +++ b/arch/arm/mach-bcm/Kconfig
29 @@ -40,6 +40,8 @@ config ARCH_BCM_NSP
30 select ARCH_BCM_IPROC
31 select ARM_ERRATA_754322
32 select ARM_ERRATA_775420
33 + select ARM_ERRATA_764369 if SMP
34 + select HAVE_SMP
35 help
36 Support for Broadcom Northstar Plus SoC.
37 Broadcom Northstar Plus family of SoCs are used for switching control
38 --- a/arch/arm/mach-bcm/Makefile
39 +++ b/arch/arm/mach-bcm/Makefile
40 @@ -14,7 +14,11 @@
41 obj-$(CONFIG_ARCH_BCM_CYGNUS) += bcm_cygnus.o
42
43 # Northstar Plus
44 -obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o
45 +obj-$(CONFIG_ARCH_BCM_NSP) += bcm_nsp.o
46 +
47 +ifeq ($(CONFIG_ARCH_BCM_NSP),y)
48 +obj-$(CONFIG_SMP) += platsmp.o
49 +endif
50
51 # BCM281XX
52 obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o
53 @@ -23,7 +27,7 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bcm281xx.o
54 obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o
55
56 # BCM281XX and BCM21664 SMP support
57 -obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += kona_smp.o
58 +obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += platsmp.o
59
60 # BCM281XX and BCM21664 L2 cache control
61 obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o
62 --- a/arch/arm/mach-bcm/kona_smp.c
63 +++ /dev/null
64 @@ -1,228 +0,0 @@
65 -/*
66 - * Copyright (C) 2014-2015 Broadcom Corporation
67 - * Copyright 2014 Linaro Limited
68 - *
69 - * This program is free software; you can redistribute it and/or
70 - * modify it under the terms of the GNU General Public License as
71 - * published by the Free Software Foundation version 2.
72 - *
73 - * This program is distributed "as is" WITHOUT ANY WARRANTY of any
74 - * kind, whether express or implied; without even the implied warranty
75 - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
76 - * GNU General Public License for more details.
77 - */
78 -
79 -#include <linux/init.h>
80 -#include <linux/errno.h>
81 -#include <linux/io.h>
82 -#include <linux/of.h>
83 -#include <linux/sched.h>
84 -
85 -#include <asm/smp.h>
86 -#include <asm/smp_plat.h>
87 -#include <asm/smp_scu.h>
88 -
89 -/* Size of mapped Cortex A9 SCU address space */
90 -#define CORTEX_A9_SCU_SIZE 0x58
91 -
92 -#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */
93 -#define BOOT_ADDR_CPUID_MASK 0x3
94 -
95 -/* Name of device node property defining secondary boot register location */
96 -#define OF_SECONDARY_BOOT "secondary-boot-reg"
97 -#define MPIDR_CPUID_BITMASK 0x3
98 -
99 -/* I/O address of register used to coordinate secondary core startup */
100 -static u32 secondary_boot_addr;
101 -
102 -/*
103 - * Enable the Cortex A9 Snoop Control Unit
104 - *
105 - * By the time this is called we already know there are multiple
106 - * cores present. We assume we're running on a Cortex A9 processor,
107 - * so any trouble getting the base address register or getting the
108 - * SCU base is a problem.
109 - *
110 - * Return 0 if successful or an error code otherwise.
111 - */
112 -static int __init scu_a9_enable(void)
113 -{
114 - unsigned long config_base;
115 - void __iomem *scu_base;
116 -
117 - if (!scu_a9_has_base()) {
118 - pr_err("no configuration base address register!\n");
119 - return -ENXIO;
120 - }
121 -
122 - /* Config base address register value is zero for uniprocessor */
123 - config_base = scu_a9_get_base();
124 - if (!config_base) {
125 - pr_err("hardware reports only one core\n");
126 - return -ENOENT;
127 - }
128 -
129 - scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
130 - if (!scu_base) {
131 - pr_err("failed to remap config base (%lu/%u) for SCU\n",
132 - config_base, CORTEX_A9_SCU_SIZE);
133 - return -ENOMEM;
134 - }
135 -
136 - scu_enable(scu_base);
137 -
138 - iounmap(scu_base); /* That's the last we'll need of this */
139 -
140 - return 0;
141 -}
142 -
143 -static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
144 -{
145 - static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
146 - struct device_node *cpus_node = NULL;
147 - struct device_node *cpu_node = NULL;
148 - int ret;
149 -
150 - /*
151 - * This function is only called via smp_ops->smp_prepare_cpu().
152 - * That only happens if a "/cpus" device tree node exists
153 - * and has an "enable-method" property that selects the SMP
154 - * operations defined herein.
155 - */
156 - cpus_node = of_find_node_by_path("/cpus");
157 - if (!cpus_node)
158 - return;
159 -
160 - for_each_child_of_node(cpus_node, cpu_node) {
161 - u32 cpuid;
162 -
163 - if (of_node_cmp(cpu_node->type, "cpu"))
164 - continue;
165 -
166 - if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
167 - pr_debug("%s: missing reg property\n",
168 - cpu_node->full_name);
169 - ret = -ENOENT;
170 - goto out;
171 - }
172 -
173 - /*
174 - * "secondary-boot-reg" property should be defined only
175 - * for secondary cpu
176 - */
177 - if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
178 - /*
179 - * Our secondary enable method requires a
180 - * "secondary-boot-reg" property to specify a register
181 - * address used to request the ROM code boot a secondary
182 - * core. If we have any trouble getting this we fall
183 - * back to uniprocessor mode.
184 - */
185 - if (of_property_read_u32(cpu_node,
186 - OF_SECONDARY_BOOT,
187 - &secondary_boot_addr)) {
188 - pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
189 - cpu_node->name);
190 - ret = -ENOENT;
191 - goto out;
192 - }
193 - }
194 - }
195 -
196 - /*
197 - * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
198 - * returned, the SoC reported a uniprocessor configuration.
199 - * We bail on any other error.
200 - */
201 - ret = scu_a9_enable();
202 -out:
203 - of_node_put(cpu_node);
204 - of_node_put(cpus_node);
205 -
206 - if (ret) {
207 - /* Update the CPU present map to reflect uniprocessor mode */
208 - pr_warn("disabling SMP\n");
209 - init_cpu_present(&only_cpu_0);
210 - }
211 -}
212 -
213 -/*
214 - * The ROM code has the secondary cores looping, waiting for an event.
215 - * When an event occurs each core examines the bottom two bits of the
216 - * secondary boot register. When a core finds those bits contain its
217 - * own core id, it performs initialization, including computing its boot
218 - * address by clearing the boot register value's bottom two bits. The
219 - * core signals that it is beginning its execution by writing its boot
220 - * address back to the secondary boot register, and finally jumps to
221 - * that address.
222 - *
223 - * So to start a core executing we need to:
224 - * - Encode the (hardware) CPU id with the bottom bits of the secondary
225 - * start address.
226 - * - Write that value into the secondary boot register.
227 - * - Generate an event to wake up the secondary CPU(s).
228 - * - Wait for the secondary boot register to be re-written, which
229 - * indicates the secondary core has started.
230 - */
231 -static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
232 -{
233 - void __iomem *boot_reg;
234 - phys_addr_t boot_func;
235 - u64 start_clock;
236 - u32 cpu_id;
237 - u32 boot_val;
238 - bool timeout = false;
239 -
240 - cpu_id = cpu_logical_map(cpu);
241 - if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
242 - pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
243 - return -EINVAL;
244 - }
245 -
246 - if (!secondary_boot_addr) {
247 - pr_err("required secondary boot register not specified\n");
248 - return -EINVAL;
249 - }
250 -
251 - boot_reg = ioremap_nocache(
252 - (phys_addr_t)secondary_boot_addr, sizeof(u32));
253 - if (!boot_reg) {
254 - pr_err("unable to map boot register for cpu %u\n", cpu_id);
255 - return -ENOMEM;
256 - }
257 -
258 - /*
259 - * Secondary cores will start in secondary_startup(),
260 - * defined in "arch/arm/kernel/head.S"
261 - */
262 - boot_func = virt_to_phys(secondary_startup);
263 - BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
264 - BUG_ON(boot_func > (phys_addr_t)U32_MAX);
265 -
266 - /* The core to start is encoded in the low bits */
267 - boot_val = (u32)boot_func | cpu_id;
268 - writel_relaxed(boot_val, boot_reg);
269 -
270 - sev();
271 -
272 - /* The low bits will be cleared once the core has started */
273 - start_clock = local_clock();
274 - while (!timeout && readl_relaxed(boot_reg) == boot_val)
275 - timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
276 -
277 - iounmap(boot_reg);
278 -
279 - if (!timeout)
280 - return 0;
281 -
282 - pr_err("timeout waiting for cpu %u to start\n", cpu_id);
283 -
284 - return -ENXIO;
285 -}
286 -
287 -static struct smp_operations bcm_smp_ops __initdata = {
288 - .smp_prepare_cpus = bcm_smp_prepare_cpus,
289 - .smp_boot_secondary = kona_boot_secondary,
290 -};
291 -CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
292 - &bcm_smp_ops);
293 --- /dev/null
294 +++ b/arch/arm/mach-bcm/platsmp.c
295 @@ -0,0 +1,290 @@
296 +/*
297 + * Copyright (C) 2014-2015 Broadcom Corporation
298 + * Copyright 2014 Linaro Limited
299 + *
300 + * This program is free software; you can redistribute it and/or
301 + * modify it under the terms of the GNU General Public License as
302 + * published by the Free Software Foundation version 2.
303 + *
304 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
305 + * kind, whether express or implied; without even the implied warranty
306 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
307 + * GNU General Public License for more details.
308 + */
309 +
310 +#include <linux/cpumask.h>
311 +#include <linux/delay.h>
312 +#include <linux/errno.h>
313 +#include <linux/init.h>
314 +#include <linux/io.h>
315 +#include <linux/jiffies.h>
316 +#include <linux/of.h>
317 +#include <linux/sched.h>
318 +#include <linux/smp.h>
319 +
320 +#include <asm/cacheflush.h>
321 +#include <asm/smp.h>
322 +#include <asm/smp_plat.h>
323 +#include <asm/smp_scu.h>
324 +
325 +/* Size of mapped Cortex A9 SCU address space */
326 +#define CORTEX_A9_SCU_SIZE 0x58
327 +
328 +#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */
329 +#define BOOT_ADDR_CPUID_MASK 0x3
330 +
331 +/* Name of device node property defining secondary boot register location */
332 +#define OF_SECONDARY_BOOT "secondary-boot-reg"
333 +#define MPIDR_CPUID_BITMASK 0x3
334 +
335 +/* I/O address of register used to coordinate secondary core startup */
336 +static u32 secondary_boot_addr;
337 +
338 +/*
339 + * Enable the Cortex A9 Snoop Control Unit
340 + *
341 + * By the time this is called we already know there are multiple
342 + * cores present. We assume we're running on a Cortex A9 processor,
343 + * so any trouble getting the base address register or getting the
344 + * SCU base is a problem.
345 + *
346 + * Return 0 if successful or an error code otherwise.
347 + */
348 +static int __init scu_a9_enable(void)
349 +{
350 + unsigned long config_base;
351 + void __iomem *scu_base;
352 +
353 + if (!scu_a9_has_base()) {
354 + pr_err("no configuration base address register!\n");
355 + return -ENXIO;
356 + }
357 +
358 + /* Config base address register value is zero for uniprocessor */
359 + config_base = scu_a9_get_base();
360 + if (!config_base) {
361 + pr_err("hardware reports only one core\n");
362 + return -ENOENT;
363 + }
364 +
365 + scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
366 + if (!scu_base) {
367 + pr_err("failed to remap config base (%lu/%u) for SCU\n",
368 + config_base, CORTEX_A9_SCU_SIZE);
369 + return -ENOMEM;
370 + }
371 +
372 + scu_enable(scu_base);
373 +
374 + iounmap(scu_base); /* That's the last we'll need of this */
375 +
376 + return 0;
377 +}
378 +
379 +static int nsp_write_lut(void)
380 +{
381 + void __iomem *sku_rom_lut;
382 + phys_addr_t secondary_startup_phy;
383 +
384 + if (!secondary_boot_addr) {
385 + pr_warn("required secondary boot register not specified\n");
386 + return -EINVAL;
387 + }
388 +
389 + sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr,
390 + sizeof(secondary_boot_addr));
391 + if (!sku_rom_lut) {
392 + pr_warn("unable to ioremap SKU-ROM LUT register\n");
393 + return -ENOMEM;
394 + }
395 +
396 + secondary_startup_phy = virt_to_phys(secondary_startup);
397 + BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX);
398 +
399 + writel_relaxed(secondary_startup_phy, sku_rom_lut);
400 +
401 + /* Ensure the write is visible to the secondary core */
402 + smp_wmb();
403 +
404 + iounmap(sku_rom_lut);
405 +
406 + return 0;
407 +}
408 +
409 +static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
410 +{
411 + static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
412 + struct device_node *cpus_node = NULL;
413 + struct device_node *cpu_node = NULL;
414 + int ret;
415 +
416 + /*
417 + * This function is only called via smp_ops->smp_prepare_cpu().
418 + * That only happens if a "/cpus" device tree node exists
419 + * and has an "enable-method" property that selects the SMP
420 + * operations defined herein.
421 + */
422 + cpus_node = of_find_node_by_path("/cpus");
423 + if (!cpus_node)
424 + return;
425 +
426 + for_each_child_of_node(cpus_node, cpu_node) {
427 + u32 cpuid;
428 +
429 + if (of_node_cmp(cpu_node->type, "cpu"))
430 + continue;
431 +
432 + if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
433 + pr_debug("%s: missing reg property\n",
434 + cpu_node->full_name);
435 + ret = -ENOENT;
436 + goto out;
437 + }
438 +
439 + /*
440 + * "secondary-boot-reg" property should be defined only
441 + * for secondary cpu
442 + */
443 + if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
444 + /*
445 + * Our secondary enable method requires a
446 + * "secondary-boot-reg" property to specify a register
447 + * address used to request the ROM code boot a secondary
448 + * core. If we have any trouble getting this we fall
449 + * back to uniprocessor mode.
450 + */
451 + if (of_property_read_u32(cpu_node,
452 + OF_SECONDARY_BOOT,
453 + &secondary_boot_addr)) {
454 + pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
455 + cpu_node->name);
456 + ret = -ENOENT;
457 + goto out;
458 + }
459 + }
460 + }
461 +
462 + /*
463 + * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
464 + * returned, the SoC reported a uniprocessor configuration.
465 + * We bail on any other error.
466 + */
467 + ret = scu_a9_enable();
468 +out:
469 + of_node_put(cpu_node);
470 + of_node_put(cpus_node);
471 +
472 + if (ret) {
473 + /* Update the CPU present map to reflect uniprocessor mode */
474 + pr_warn("disabling SMP\n");
475 + init_cpu_present(&only_cpu_0);
476 + }
477 +}
478 +
479 +/*
480 + * The ROM code has the secondary cores looping, waiting for an event.
481 + * When an event occurs each core examines the bottom two bits of the
482 + * secondary boot register. When a core finds those bits contain its
483 + * own core id, it performs initialization, including computing its boot
484 + * address by clearing the boot register value's bottom two bits. The
485 + * core signals that it is beginning its execution by writing its boot
486 + * address back to the secondary boot register, and finally jumps to
487 + * that address.
488 + *
489 + * So to start a core executing we need to:
490 + * - Encode the (hardware) CPU id with the bottom bits of the secondary
491 + * start address.
492 + * - Write that value into the secondary boot register.
493 + * - Generate an event to wake up the secondary CPU(s).
494 + * - Wait for the secondary boot register to be re-written, which
495 + * indicates the secondary core has started.
496 + */
497 +static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
498 +{
499 + void __iomem *boot_reg;
500 + phys_addr_t boot_func;
501 + u64 start_clock;
502 + u32 cpu_id;
503 + u32 boot_val;
504 + bool timeout = false;
505 +
506 + cpu_id = cpu_logical_map(cpu);
507 + if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
508 + pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
509 + return -EINVAL;
510 + }
511 +
512 + if (!secondary_boot_addr) {
513 + pr_err("required secondary boot register not specified\n");
514 + return -EINVAL;
515 + }
516 +
517 + boot_reg = ioremap_nocache(
518 + (phys_addr_t)secondary_boot_addr, sizeof(u32));
519 + if (!boot_reg) {
520 + pr_err("unable to map boot register for cpu %u\n", cpu_id);
521 + return -ENOMEM;
522 + }
523 +
524 + /*
525 + * Secondary cores will start in secondary_startup(),
526 + * defined in "arch/arm/kernel/head.S"
527 + */
528 + boot_func = virt_to_phys(secondary_startup);
529 + BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
530 + BUG_ON(boot_func > (phys_addr_t)U32_MAX);
531 +
532 + /* The core to start is encoded in the low bits */
533 + boot_val = (u32)boot_func | cpu_id;
534 + writel_relaxed(boot_val, boot_reg);
535 +
536 + sev();
537 +
538 + /* The low bits will be cleared once the core has started */
539 + start_clock = local_clock();
540 + while (!timeout && readl_relaxed(boot_reg) == boot_val)
541 + timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
542 +
543 + iounmap(boot_reg);
544 +
545 + if (!timeout)
546 + return 0;
547 +
548 + pr_err("timeout waiting for cpu %u to start\n", cpu_id);
549 +
550 + return -ENXIO;
551 +}
552 +
553 +static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
554 +{
555 + int ret;
556 +
557 + /*
558 + * After wake up, secondary core branches to the startup
559 + * address programmed at SKU ROM LUT location.
560 + */
561 + ret = nsp_write_lut();
562 + if (ret) {
563 + pr_err("unable to write startup addr to SKU ROM LUT\n");
564 + goto out;
565 + }
566 +
567 + /* Send a CPU wakeup interrupt to the secondary core */
568 + arch_send_wakeup_ipi_mask(cpumask_of(cpu));
569 +
570 +out:
571 + return ret;
572 +}
573 +
574 +static struct smp_operations bcm_smp_ops __initdata = {
575 + .smp_prepare_cpus = bcm_smp_prepare_cpus,
576 + .smp_boot_secondary = kona_boot_secondary,
577 +};
578 +CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
579 + &bcm_smp_ops);
580 +
581 +struct smp_operations nsp_smp_ops __initdata = {
582 + .smp_prepare_cpus = bcm_smp_prepare_cpus,
583 + .smp_boot_secondary = nsp_boot_secondary,
584 +};
585 +CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops);