bcm53xx: backport BCM5301X earlycon and USB VCC patches
[openwrt.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_bc
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);