Commit 84320e1a authored by Kapil Hali's avatar Kapil Hali Committed by Florian Fainelli

ARM: BCM: Clean up SMP support for Broadcom Kona

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: default avatarKapil Hali <kapilh@broadcom.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
parent f4ce7eff
...@@ -31,7 +31,6 @@ cpus { ...@@ -31,7 +31,6 @@ cpus {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
enable-method = "brcm,bcm11351-cpu-method"; enable-method = "brcm,bcm11351-cpu-method";
secondary-boot-reg = <0x3500417c>;
cpu0: cpu@0 { cpu0: cpu@0 {
device_type = "cpu"; device_type = "cpu";
...@@ -42,6 +41,7 @@ cpu0: cpu@0 { ...@@ -42,6 +41,7 @@ cpu0: cpu@0 {
cpu1: cpu@1 { cpu1: cpu@1 {
device_type = "cpu"; device_type = "cpu";
compatible = "arm,cortex-a9"; compatible = "arm,cortex-a9";
secondary-boot-reg = <0x3500417c>;
reg = <1>; reg = <1>;
}; };
}; };
......
...@@ -31,7 +31,6 @@ cpus { ...@@ -31,7 +31,6 @@ cpus {
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
enable-method = "brcm,bcm11351-cpu-method"; enable-method = "brcm,bcm11351-cpu-method";
secondary-boot-reg = <0x35004178>;
cpu0: cpu@0 { cpu0: cpu@0 {
device_type = "cpu"; device_type = "cpu";
...@@ -42,6 +41,7 @@ cpu0: cpu@0 { ...@@ -42,6 +41,7 @@ cpu0: cpu@0 {
cpu1: cpu@1 { cpu1: cpu@1 {
device_type = "cpu"; device_type = "cpu";
compatible = "arm,cortex-a9"; compatible = "arm,cortex-a9";
secondary-boot-reg = <0x35004178>;
reg = <1>; reg = <1>;
}; };
}; };
......
/* /*
* Copyright (C) 2014 Broadcom Corporation * Copyright (C) 2014-2015 Broadcom Corporation
* Copyright 2014 Linaro Limited * Copyright 2014 Linaro Limited
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -30,9 +30,10 @@ ...@@ -30,9 +30,10 @@
/* Name of device node property defining secondary boot register location */ /* Name of device node property defining secondary boot register location */
#define OF_SECONDARY_BOOT "secondary-boot-reg" #define OF_SECONDARY_BOOT "secondary-boot-reg"
#define MPIDR_CPUID_BITMASK 0x3
/* I/O address of register used to coordinate secondary core startup */ /* 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 * Enable the Cortex A9 Snoop Control Unit
...@@ -78,32 +79,55 @@ static int __init scu_a9_enable(void) ...@@ -78,32 +79,55 @@ static int __init scu_a9_enable(void)
static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
{ {
static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; 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; int ret;
BUG_ON(secondary_boot); /* We're called only once */
/* /*
* This function is only called via smp_ops->smp_prepare_cpu(). * This function is only called via smp_ops->smp_prepare_cpu().
* That only happens if a "/cpus" device tree node exists * That only happens if a "/cpus" device tree node exists
* and has an "enable-method" property that selects the SMP * and has an "enable-method" property that selects the SMP
* operations defined herein. * operations defined herein.
*/ */
node = of_find_node_by_path("/cpus"); cpus_node = of_find_node_by_path("/cpus");
BUG_ON(!node); 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;
}
/* /*
* Our secondary enable method requires a "secondary-boot-reg" * "secondary-boot-reg" property should be defined only
* property to specify a register address used to request the * for secondary cpu
* 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)) { if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n", /*
node->name); * Our secondary enable method requires a
ret = -ENOENT; /* Arrange to disable SMP */ * "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; goto out;
} }
}
}
/* /*
* Enable the SCU on Cortex A9 based SoCs. If -ENOENT is * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
...@@ -112,10 +136,11 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) ...@@ -112,10 +136,11 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
*/ */
ret = scu_a9_enable(); ret = scu_a9_enable();
out: out:
of_node_put(node); of_node_put(cpu_node);
of_node_put(cpus_node);
if (ret) { if (ret) {
/* Update the CPU present map to reflect uniprocessor mode */ /* Update the CPU present map to reflect uniprocessor mode */
BUG_ON(ret != -ENOENT);
pr_warn("disabling SMP\n"); pr_warn("disabling SMP\n");
init_cpu_present(&only_cpu_0); init_cpu_present(&only_cpu_0);
} }
...@@ -139,7 +164,7 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) ...@@ -139,7 +164,7 @@ static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
* - Wait for the secondary boot register to be re-written, which * - Wait for the secondary boot register to be re-written, which
* indicates the secondary core has started. * 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; void __iomem *boot_reg;
phys_addr_t boot_func; phys_addr_t boot_func;
...@@ -154,15 +179,16 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) ...@@ -154,15 +179,16 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
return -EINVAL; return -EINVAL;
} }
if (!secondary_boot) { if (!secondary_boot_addr) {
pr_err("required secondary boot register not specified\n"); pr_err("required secondary boot register not specified\n");
return -EINVAL; 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) { if (!boot_reg) {
pr_err("unable to map boot register for cpu %u\n", cpu_id); 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) ...@@ -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); pr_err("timeout waiting for cpu %u to start\n", cpu_id);
return -ENOSYS; return -ENXIO;
} }
static struct smp_operations bcm_smp_ops __initdata = { static struct smp_operations bcm_smp_ops __initdata = {
.smp_prepare_cpus = bcm_smp_prepare_cpus, .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", CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
&bcm_smp_ops); &bcm_smp_ops);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment