1 From e99fb6d01cddf38cffc11655aba4a96a981d604e Mon Sep 17 00:00:00 2001
2 From: Kapil Hali <kapilh@broadcom.com>
3 Date: Wed, 25 Nov 2015 13:25:55 -0500
4 Subject: [PATCH 133/134] ARM: BCM: Add SMP support for Broadcom NSP
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.
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
16 Signed-off-by: Kapil Hali <kapilh@broadcom.com>
18 arch/arm/mach-bcm/Kconfig | 2 +
19 arch/arm/mach-bcm/Makefile | 8 +-
20 arch/arm/mach-bcm/kona_smp.c | 228 ----------------------------------
21 arch/arm/mach-bcm/platsmp.c | 290 +++++++++++++++++++++++++++++++++++++++++++
22 4 files changed, 298 insertions(+), 230 deletions(-)
23 delete mode 100644 arch/arm/mach-bcm/kona_smp.c
24 create mode 100644 arch/arm/mach-bcm/platsmp.c
26 --- a/arch/arm/mach-bcm/Makefile
27 +++ b/arch/arm/mach-bcm/Makefile
28 @@ -23,7 +23,7 @@ obj-$(CONFIG_ARCH_BCM_281XX) += board_bc
29 obj-$(CONFIG_ARCH_BCM_21664) += board_bcm21664.o
31 # BCM281XX and BCM21664 SMP support
32 -obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += kona_smp.o
33 +obj-$(CONFIG_ARCH_BCM_MOBILE_SMP) += platsmp.o
35 # BCM281XX and BCM21664 L2 cache control
36 obj-$(CONFIG_ARCH_BCM_MOBILE_L2_CACHE) += kona_l2_cache.o
37 --- a/arch/arm/mach-bcm/kona_smp.c
41 - * Copyright (C) 2014-2015 Broadcom Corporation
42 - * Copyright 2014 Linaro Limited
44 - * This program is free software; you can redistribute it and/or
45 - * modify it under the terms of the GNU General Public License as
46 - * published by the Free Software Foundation version 2.
48 - * This program is distributed "as is" WITHOUT ANY WARRANTY of any
49 - * kind, whether express or implied; without even the implied warranty
50 - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 - * GNU General Public License for more details.
54 -#include <linux/init.h>
55 -#include <linux/errno.h>
56 -#include <linux/io.h>
57 -#include <linux/of.h>
58 -#include <linux/sched.h>
61 -#include <asm/smp_plat.h>
62 -#include <asm/smp_scu.h>
64 -/* Size of mapped Cortex A9 SCU address space */
65 -#define CORTEX_A9_SCU_SIZE 0x58
67 -#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */
68 -#define BOOT_ADDR_CPUID_MASK 0x3
70 -/* Name of device node property defining secondary boot register location */
71 -#define OF_SECONDARY_BOOT "secondary-boot-reg"
72 -#define MPIDR_CPUID_BITMASK 0x3
74 -/* I/O address of register used to coordinate secondary core startup */
75 -static u32 secondary_boot_addr;
78 - * Enable the Cortex A9 Snoop Control Unit
80 - * By the time this is called we already know there are multiple
81 - * cores present. We assume we're running on a Cortex A9 processor,
82 - * so any trouble getting the base address register or getting the
83 - * SCU base is a problem.
85 - * Return 0 if successful or an error code otherwise.
87 -static int __init scu_a9_enable(void)
89 - unsigned long config_base;
90 - void __iomem *scu_base;
92 - if (!scu_a9_has_base()) {
93 - pr_err("no configuration base address register!\n");
97 - /* Config base address register value is zero for uniprocessor */
98 - config_base = scu_a9_get_base();
100 - pr_err("hardware reports only one core\n");
104 - scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
106 - pr_err("failed to remap config base (%lu/%u) for SCU\n",
107 - config_base, CORTEX_A9_SCU_SIZE);
111 - scu_enable(scu_base);
113 - iounmap(scu_base); /* That's the last we'll need of this */
118 -static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
120 - static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
121 - struct device_node *cpus_node = NULL;
122 - struct device_node *cpu_node = NULL;
126 - * This function is only called via smp_ops->smp_prepare_cpu().
127 - * That only happens if a "/cpus" device tree node exists
128 - * and has an "enable-method" property that selects the SMP
129 - * operations defined herein.
131 - cpus_node = of_find_node_by_path("/cpus");
135 - for_each_child_of_node(cpus_node, cpu_node) {
138 - if (of_node_cmp(cpu_node->type, "cpu"))
141 - if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
142 - pr_debug("%s: missing reg property\n",
143 - cpu_node->full_name);
149 - * "secondary-boot-reg" property should be defined only
150 - * for secondary cpu
152 - if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
154 - * Our secondary enable method requires a
155 - * "secondary-boot-reg" property to specify a register
156 - * address used to request the ROM code boot a secondary
157 - * core. If we have any trouble getting this we fall
158 - * back to uniprocessor mode.
160 - if (of_property_read_u32(cpu_node,
162 - &secondary_boot_addr)) {
163 - pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
172 - * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
173 - * returned, the SoC reported a uniprocessor configuration.
174 - * We bail on any other error.
176 - ret = scu_a9_enable();
178 - of_node_put(cpu_node);
179 - of_node_put(cpus_node);
182 - /* Update the CPU present map to reflect uniprocessor mode */
183 - pr_warn("disabling SMP\n");
184 - init_cpu_present(&only_cpu_0);
189 - * The ROM code has the secondary cores looping, waiting for an event.
190 - * When an event occurs each core examines the bottom two bits of the
191 - * secondary boot register. When a core finds those bits contain its
192 - * own core id, it performs initialization, including computing its boot
193 - * address by clearing the boot register value's bottom two bits. The
194 - * core signals that it is beginning its execution by writing its boot
195 - * address back to the secondary boot register, and finally jumps to
198 - * So to start a core executing we need to:
199 - * - Encode the (hardware) CPU id with the bottom bits of the secondary
201 - * - Write that value into the secondary boot register.
202 - * - Generate an event to wake up the secondary CPU(s).
203 - * - Wait for the secondary boot register to be re-written, which
204 - * indicates the secondary core has started.
206 -static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
208 - void __iomem *boot_reg;
209 - phys_addr_t boot_func;
213 - bool timeout = false;
215 - cpu_id = cpu_logical_map(cpu);
216 - if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
217 - pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
221 - if (!secondary_boot_addr) {
222 - pr_err("required secondary boot register not specified\n");
226 - boot_reg = ioremap_nocache(
227 - (phys_addr_t)secondary_boot_addr, sizeof(u32));
229 - pr_err("unable to map boot register for cpu %u\n", cpu_id);
234 - * Secondary cores will start in secondary_startup(),
235 - * defined in "arch/arm/kernel/head.S"
237 - boot_func = virt_to_phys(secondary_startup);
238 - BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
239 - BUG_ON(boot_func > (phys_addr_t)U32_MAX);
241 - /* The core to start is encoded in the low bits */
242 - boot_val = (u32)boot_func | cpu_id;
243 - writel_relaxed(boot_val, boot_reg);
247 - /* The low bits will be cleared once the core has started */
248 - start_clock = local_clock();
249 - while (!timeout && readl_relaxed(boot_reg) == boot_val)
250 - timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
257 - pr_err("timeout waiting for cpu %u to start\n", cpu_id);
262 -static struct smp_operations bcm_smp_ops __initdata = {
263 - .smp_prepare_cpus = bcm_smp_prepare_cpus,
264 - .smp_boot_secondary = kona_boot_secondary,
266 -CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
269 +++ b/arch/arm/mach-bcm/platsmp.c
272 + * Copyright (C) 2014-2015 Broadcom Corporation
273 + * Copyright 2014 Linaro Limited
275 + * This program is free software; you can redistribute it and/or
276 + * modify it under the terms of the GNU General Public License as
277 + * published by the Free Software Foundation version 2.
279 + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
280 + * kind, whether express or implied; without even the implied warranty
281 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
282 + * GNU General Public License for more details.
285 +#include <linux/cpumask.h>
286 +#include <linux/delay.h>
287 +#include <linux/errno.h>
288 +#include <linux/init.h>
289 +#include <linux/io.h>
290 +#include <linux/jiffies.h>
291 +#include <linux/of.h>
292 +#include <linux/sched.h>
293 +#include <linux/smp.h>
295 +#include <asm/cacheflush.h>
296 +#include <asm/smp.h>
297 +#include <asm/smp_plat.h>
298 +#include <asm/smp_scu.h>
300 +/* Size of mapped Cortex A9 SCU address space */
301 +#define CORTEX_A9_SCU_SIZE 0x58
303 +#define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */
304 +#define BOOT_ADDR_CPUID_MASK 0x3
306 +/* Name of device node property defining secondary boot register location */
307 +#define OF_SECONDARY_BOOT "secondary-boot-reg"
308 +#define MPIDR_CPUID_BITMASK 0x3
310 +/* I/O address of register used to coordinate secondary core startup */
311 +static u32 secondary_boot_addr;
314 + * Enable the Cortex A9 Snoop Control Unit
316 + * By the time this is called we already know there are multiple
317 + * cores present. We assume we're running on a Cortex A9 processor,
318 + * so any trouble getting the base address register or getting the
319 + * SCU base is a problem.
321 + * Return 0 if successful or an error code otherwise.
323 +static int __init scu_a9_enable(void)
325 + unsigned long config_base;
326 + void __iomem *scu_base;
328 + if (!scu_a9_has_base()) {
329 + pr_err("no configuration base address register!\n");
333 + /* Config base address register value is zero for uniprocessor */
334 + config_base = scu_a9_get_base();
335 + if (!config_base) {
336 + pr_err("hardware reports only one core\n");
340 + scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
342 + pr_err("failed to remap config base (%lu/%u) for SCU\n",
343 + config_base, CORTEX_A9_SCU_SIZE);
347 + scu_enable(scu_base);
349 + iounmap(scu_base); /* That's the last we'll need of this */
354 +static int nsp_write_lut(void)
356 + void __iomem *sku_rom_lut;
357 + phys_addr_t secondary_startup_phy;
359 + if (!secondary_boot_addr) {
360 + pr_warn("required secondary boot register not specified\n");
364 + sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr,
365 + sizeof(secondary_boot_addr));
366 + if (!sku_rom_lut) {
367 + pr_warn("unable to ioremap SKU-ROM LUT register\n");
371 + secondary_startup_phy = virt_to_phys(secondary_startup);
372 + BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX);
374 + writel_relaxed(secondary_startup_phy, sku_rom_lut);
376 + /* Ensure the write is visible to the secondary core */
379 + iounmap(sku_rom_lut);
384 +static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
386 + static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
387 + struct device_node *cpus_node = NULL;
388 + struct device_node *cpu_node = NULL;
392 + * This function is only called via smp_ops->smp_prepare_cpu().
393 + * That only happens if a "/cpus" device tree node exists
394 + * and has an "enable-method" property that selects the SMP
395 + * operations defined herein.
397 + cpus_node = of_find_node_by_path("/cpus");
401 + for_each_child_of_node(cpus_node, cpu_node) {
404 + if (of_node_cmp(cpu_node->type, "cpu"))
407 + if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
408 + pr_debug("%s: missing reg property\n",
409 + cpu_node->full_name);
415 + * "secondary-boot-reg" property should be defined only
416 + * for secondary cpu
418 + if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
420 + * Our secondary enable method requires a
421 + * "secondary-boot-reg" property to specify a register
422 + * address used to request the ROM code boot a secondary
423 + * core. If we have any trouble getting this we fall
424 + * back to uniprocessor mode.
426 + if (of_property_read_u32(cpu_node,
428 + &secondary_boot_addr)) {
429 + pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
438 + * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
439 + * returned, the SoC reported a uniprocessor configuration.
440 + * We bail on any other error.
442 + ret = scu_a9_enable();
444 + of_node_put(cpu_node);
445 + of_node_put(cpus_node);
448 + /* Update the CPU present map to reflect uniprocessor mode */
449 + pr_warn("disabling SMP\n");
450 + init_cpu_present(&only_cpu_0);
455 + * The ROM code has the secondary cores looping, waiting for an event.
456 + * When an event occurs each core examines the bottom two bits of the
457 + * secondary boot register. When a core finds those bits contain its
458 + * own core id, it performs initialization, including computing its boot
459 + * address by clearing the boot register value's bottom two bits. The
460 + * core signals that it is beginning its execution by writing its boot
461 + * address back to the secondary boot register, and finally jumps to
464 + * So to start a core executing we need to:
465 + * - Encode the (hardware) CPU id with the bottom bits of the secondary
467 + * - Write that value into the secondary boot register.
468 + * - Generate an event to wake up the secondary CPU(s).
469 + * - Wait for the secondary boot register to be re-written, which
470 + * indicates the secondary core has started.
472 +static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
474 + void __iomem *boot_reg;
475 + phys_addr_t boot_func;
479 + bool timeout = false;
481 + cpu_id = cpu_logical_map(cpu);
482 + if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
483 + pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
487 + if (!secondary_boot_addr) {
488 + pr_err("required secondary boot register not specified\n");
492 + boot_reg = ioremap_nocache(
493 + (phys_addr_t)secondary_boot_addr, sizeof(u32));
495 + pr_err("unable to map boot register for cpu %u\n", cpu_id);
500 + * Secondary cores will start in secondary_startup(),
501 + * defined in "arch/arm/kernel/head.S"
503 + boot_func = virt_to_phys(secondary_startup);
504 + BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
505 + BUG_ON(boot_func > (phys_addr_t)U32_MAX);
507 + /* The core to start is encoded in the low bits */
508 + boot_val = (u32)boot_func | cpu_id;
509 + writel_relaxed(boot_val, boot_reg);
513 + /* The low bits will be cleared once the core has started */
514 + start_clock = local_clock();
515 + while (!timeout && readl_relaxed(boot_reg) == boot_val)
516 + timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
523 + pr_err("timeout waiting for cpu %u to start\n", cpu_id);
528 +static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
533 + * After wake up, secondary core branches to the startup
534 + * address programmed at SKU ROM LUT location.
536 + ret = nsp_write_lut();
538 + pr_err("unable to write startup addr to SKU ROM LUT\n");
542 + /* Send a CPU wakeup interrupt to the secondary core */
543 + arch_send_wakeup_ipi_mask(cpumask_of(cpu));
549 +static struct smp_operations bcm_smp_ops __initdata = {
550 + .smp_prepare_cpus = bcm_smp_prepare_cpus,
551 + .smp_boot_secondary = kona_boot_secondary,
553 +CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
556 +struct smp_operations nsp_smp_ops __initdata = {
557 + .smp_prepare_cpus = bcm_smp_prepare_cpus,
558 + .smp_boot_secondary = nsp_boot_secondary,
560 +CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops);