ARM: BCM: Clean up SMP support for Broadcom Kona
authorKapil Hali <kapilh@broadcom.com>
Tue, 1 Dec 2015 16:24:06 +0000 (11:24 -0500)
committerFlorian Fainelli <f.fainelli@gmail.com>
Mon, 7 Dec 2015 20:30:17 +0000 (12:30 -0800)
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 <kapilh@broadcom.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
arch/arm/boot/dts/bcm11351.dtsi
arch/arm/boot/dts/bcm21664.dtsi
arch/arm/mach-bcm/kona_smp.c

index 2ddaa51..3dc7a8c 100644 (file)
@@ -31,7 +31,6 @@
                #address-cells = <1>;
                #size-cells = <0>;
                enable-method = "brcm,bcm11351-cpu-method";
-               secondary-boot-reg = <0x3500417c>;
 
                cpu0: cpu@0 {
                        device_type = "cpu";
@@ -42,6 +41,7 @@
                cpu1: cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
+                       secondary-boot-reg = <0x3500417c>;
                        reg = <1>;
                };
        };
index 2016b72..3f525be 100644 (file)
@@ -31,7 +31,6 @@
                #address-cells = <1>;
                #size-cells = <0>;
                enable-method = "brcm,bcm11351-cpu-method";
-               secondary-boot-reg = <0x35004178>;
 
                cpu0: cpu@0 {
                        device_type = "cpu";
@@ -42,6 +41,7 @@
                cpu1: cpu@1 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a9";
+                       secondary-boot-reg = <0x35004178>;
                        reg = <1>;
                };
        };
index 66a0465..15af781 100644 (file)
@@ -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
 
 /* 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);