[PATCH v6 2/5] ARM: BCM: Clean up SMP support for Broadcom Kona
From: Kapil Hali <hidden>
Date: 2015-12-05 11:53:57
Also in:
linux-devicetree, lkml
Subsystem:
arm port, broadcom bcm281xx/bcm11xxx/bcm216xx arm architecture, open firmware and flattened device tree bindings, the rest · Maintainers:
Russell King, Florian Fainelli, Ray Jui, Scott Branden, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Torvalds
These changes cleans up SMP implementaion for Broadcom's Kona SoC which are required for handling SMP for iProc family of SoCs at a single place for BCM NSP and BCM Kona. Signed-off-by: Kapil Hali <redacted> --- .../bindings/arm/bcm/brcm,bcm11351-cpu-method.txt | 12 ++-- arch/arm/boot/dts/bcm11351.dtsi | 4 +- arch/arm/boot/dts/bcm21664.dtsi | 4 +- arch/arm/mach-bcm/kona_smp.c | 82 ++++++++++++++-------- 4 files changed, 64 insertions(+), 38 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt
index 8240c02..3c5fe4b 100644
--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm11351-cpu-method.txt@@ -1,17 +1,17 @@ Broadcom Kona Family CPU Enable Method -------------------------------------- This binding defines the enable method used for starting secondary -CPUs in the following Broadcom SoCs: +CPU in the following Broadcom SoCs: BCM11130, BCM11140, BCM11351, BCM28145, BCM28155, BCM21664 The enable method is specified by defining the following required -properties in the "cpus" device tree node: +properties in the corresponding secondary "cpu" device tree node: - enable-method = "brcm,bcm11351-cpu-method"; - secondary-boot-reg = <...>; The secondary-boot-reg property is a u32 value that specifies the -physical address of the register used to request the ROM holding pen -code release a secondary CPU. The value written to the register is +physical address of the register used to request the ROM code +release a secondary CPU. The value written to the register is formed by encoding the target CPU id into the low bits of the physical start address it should jump to.
@@ -19,8 +19,6 @@ Example: cpus { #address-cells = <1>; #size-cells = <0>; - enable-method = "brcm,bcm11351-cpu-method"; - secondary-boot-reg = <0x3500417c>; cpu0: cpu at 0 { device_type = "cpu";
@@ -31,6 +29,8 @@ Example: cpu1: cpu at 1 { device_type = "cpu"; compatible = "arm,cortex-a9"; + enable-method = "brcm,bcm11351-cpu-method"; + secondary-boot-reg = <0x3500417c>; reg = <1>; }; };
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
index 2ddaa51..18045c3 100644
--- a/arch/arm/boot/dts/bcm11351.dtsi
+++ b/arch/arm/boot/dts/bcm11351.dtsi@@ -30,8 +30,6 @@ cpus { #address-cells = <1>; #size-cells = <0>; - enable-method = "brcm,bcm11351-cpu-method"; - secondary-boot-reg = <0x3500417c>; cpu0: cpu at 0 { device_type = "cpu";
@@ -42,6 +40,8 @@ cpu1: cpu at 1 { device_type = "cpu"; compatible = "arm,cortex-a9"; + enable-method = "brcm,bcm11351-cpu-method"; + secondary-boot-reg = <0x3500417c>; reg = <1>; }; };
diff --git a/arch/arm/boot/dts/bcm21664.dtsi b/arch/arm/boot/dts/bcm21664.dtsi
index 2016b72..6dde95f 100644
--- a/arch/arm/boot/dts/bcm21664.dtsi
+++ b/arch/arm/boot/dts/bcm21664.dtsi@@ -30,8 +30,6 @@ cpus { #address-cells = <1>; #size-cells = <0>; - enable-method = "brcm,bcm11351-cpu-method"; - secondary-boot-reg = <0x35004178>; cpu0: cpu at 0 { device_type = "cpu";
@@ -42,6 +40,8 @@ cpu1: cpu at 1 { device_type = "cpu"; compatible = "arm,cortex-a9"; + enable-method = "brcm,bcm11351-cpu-method"; + secondary-boot-reg = <0x35004178>; reg = <1>; }; };
diff --git a/arch/arm/mach-bcm/kona_smp.c b/arch/arm/mach-bcm/kona_smp.c
index 66a0465..15af781 100644
--- a/arch/arm/mach-bcm/kona_smp.c
+++ b/arch/arm/mach-bcm/kona_smp.c@@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Broadcom Corporation + * Copyright (C) 2014-2015 Broadcom Corporation * Copyright 2014 Linaro Limited * * This program is free software; you can redistribute it and/or
@@ -30,9 +30,10 @@ /* Name of device node property defining secondary boot register location */ #define OF_SECONDARY_BOOT "secondary-boot-reg" +#define MPIDR_CPUID_BITMASK 0x3 /* I/O address of register used to coordinate secondary core startup */ -static u32 secondary_boot; +static u32 secondary_boot_addr; /* * Enable the Cortex A9 Snoop Control Unit
@@ -78,44 +79,68 @@ static int __init scu_a9_enable(void) static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) { static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; - struct device_node *node; + struct device_node *cpus_node = NULL; + struct device_node *cpu_node = NULL; int ret; - BUG_ON(secondary_boot); /* We're called only once */ - /* * This function is only called via smp_ops->smp_prepare_cpu(). * That only happens if a "/cpus" device tree node exists * and has an "enable-method" property that selects the SMP * operations defined herein. */ - node = of_find_node_by_path("/cpus"); - BUG_ON(!node); - - /* - * Our secondary enable method requires a "secondary-boot-reg" - * property to specify a register address used to request the - * ROM code boot a secondary code. If we have any trouble - * getting this we fall back to uniprocessor mode. - */ - if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) { - pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n", - node->name); - ret = -ENOENT; /* Arrange to disable SMP */ - goto out; + cpus_node = of_find_node_by_path("/cpus"); + if (!cpus_node) + return; + + for_each_child_of_node(cpus_node, cpu_node) { + u32 cpuid; + + if (of_node_cmp(cpu_node->type, "cpu")) + continue; + + if (of_property_read_u32(cpu_node, "reg", &cpuid)) { + pr_debug("%s: missing reg property\n", + cpu_node->full_name); + ret = -ENOENT; + goto out; + } + + /* + * "secondary-boot-reg" property should be defined only + * for secondary cpu + */ + if ((cpuid & MPIDR_CPUID_BITMASK) == 1) { + /* + * Our secondary enable method requires a + * "secondary-boot-reg" property to specify a register + * address used to request the ROM code boot a secondary + * core. If we have any trouble getting this we fall + * back to uniprocessor mode. + */ + if (of_property_read_u32(cpu_node, + OF_SECONDARY_BOOT, + &secondary_boot_addr)) { + pr_warn("%s: no" OF_SECONDARY_BOOT "property\n", + cpu_node->name); + ret = -ENOENT; + goto out; + } + } } /* - * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is + * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is * returned, the SoC reported a uniprocessor configuration. * We bail on any other error. */ ret = scu_a9_enable(); out: - of_node_put(node); + of_node_put(cpu_node); + of_node_put(cpus_node); + if (ret) { /* Update the CPU present map to reflect uniprocessor mode */ - BUG_ON(ret != -ENOENT); pr_warn("disabling SMP\n"); init_cpu_present(&only_cpu_0); }
@@ -139,7 +164,7 @@ out: * - Wait for the secondary boot register to be re-written, which * indicates the secondary core has started. */ -static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) +static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) { void __iomem *boot_reg; phys_addr_t boot_func;
@@ -154,15 +179,16 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) return -EINVAL; } - if (!secondary_boot) { + if (!secondary_boot_addr) { pr_err("required secondary boot register not specified\n"); return -EINVAL; } - boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32)); + boot_reg = ioremap_nocache( + (phys_addr_t)secondary_boot_addr, sizeof(u32)); if (!boot_reg) { pr_err("unable to map boot register for cpu %u\n", cpu_id); - return -ENOSYS; + return -ENOMEM; } /*
@@ -191,12 +217,12 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) pr_err("timeout waiting for cpu %u to start\n", cpu_id); - return -ENOSYS; + return -ENXIO; } static struct smp_operations bcm_smp_ops __initdata = { .smp_prepare_cpus = bcm_smp_prepare_cpus, - .smp_boot_secondary = bcm_boot_secondary, + .smp_boot_secondary = kona_boot_secondary, }; CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", &bcm_smp_ops);
--
2.1.0