aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-bcm
diff options
context:
space:
mode:
authorKapil Hali <kapilh@broadcom.com>2015-12-01 11:24:06 -0500
committerFlorian Fainelli <f.fainelli@gmail.com>2015-12-07 15:30:17 -0500
commit84320e1a635fcf90cff4185f029ce9e31bf1d4a7 (patch)
treea42fd368793397dbee9c1c4201ea5429fdecb99b /arch/arm/mach-bcm
parentf4ce7effe2253a325f8ba182903cbdf0d8698593 (diff)
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: Kapil Hali <kapilh@broadcom.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Diffstat (limited to 'arch/arm/mach-bcm')
-rw-r--r--arch/arm/mach-bcm/kona_smp.c82
1 files changed, 54 insertions, 28 deletions
diff --git a/arch/arm/mach-bcm/kona_smp.c b/arch/arm/mach-bcm/kona_smp.c
index 66a0465528a5..15af781228a5 100644
--- a/arch/arm/mach-bcm/kona_smp.c
+++ b/arch/arm/mach-bcm/kona_smp.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2014 Broadcom Corporation 2 * Copyright (C) 2014-2015 Broadcom Corporation
3 * Copyright 2014 Linaro Limited 3 * Copyright 2014 Linaro Limited
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
@@ -30,9 +30,10 @@
30 30
31/* Name of device node property defining secondary boot register location */ 31/* Name of device node property defining secondary boot register location */
32#define OF_SECONDARY_BOOT "secondary-boot-reg" 32#define OF_SECONDARY_BOOT "secondary-boot-reg"
33#define MPIDR_CPUID_BITMASK 0x3
33 34
34/* I/O address of register used to coordinate secondary core startup */ 35/* I/O address of register used to coordinate secondary core startup */
35static u32 secondary_boot; 36static u32 secondary_boot_addr;
36 37
37/* 38/*
38 * Enable the Cortex A9 Snoop Control Unit 39 * Enable the Cortex A9 Snoop Control Unit
@@ -78,44 +79,68 @@ static int __init scu_a9_enable(void)
78static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) 79static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
79{ 80{
80 static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; 81 static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
81 struct device_node *node; 82 struct device_node *cpus_node = NULL;
83 struct device_node *cpu_node = NULL;
82 int ret; 84 int ret;
83 85
84 BUG_ON(secondary_boot); /* We're called only once */
85
86 /* 86 /*
87 * This function is only called via smp_ops->smp_prepare_cpu(). 87 * This function is only called via smp_ops->smp_prepare_cpu().
88 * That only happens if a "/cpus" device tree node exists 88 * That only happens if a "/cpus" device tree node exists
89 * and has an "enable-method" property that selects the SMP 89 * and has an "enable-method" property that selects the SMP
90 * operations defined herein. 90 * operations defined herein.
91 */ 91 */
92 node = of_find_node_by_path("/cpus"); 92 cpus_node = of_find_node_by_path("/cpus");
93 BUG_ON(!node); 93 if (!cpus_node)
94 94 return;
95 /* 95
96 * Our secondary enable method requires a "secondary-boot-reg" 96 for_each_child_of_node(cpus_node, cpu_node) {
97 * property to specify a register address used to request the 97 u32 cpuid;
98 * ROM code boot a secondary code. If we have any trouble 98
99 * getting this we fall back to uniprocessor mode. 99 if (of_node_cmp(cpu_node->type, "cpu"))
100 */ 100 continue;
101 if (of_property_read_u32(node, OF_SECONDARY_BOOT, &secondary_boot)) { 101
102 pr_err("%s: missing/invalid " OF_SECONDARY_BOOT " property\n", 102 if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
103 node->name); 103 pr_debug("%s: missing reg property\n",
104 ret = -ENOENT; /* Arrange to disable SMP */ 104 cpu_node->full_name);
105 goto out; 105 ret = -ENOENT;
106 goto out;
107 }
108
109 /*
110 * "secondary-boot-reg" property should be defined only
111 * for secondary cpu
112 */
113 if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
114 /*
115 * Our secondary enable method requires a
116 * "secondary-boot-reg" property to specify a register
117 * address used to request the ROM code boot a secondary
118 * core. If we have any trouble getting this we fall
119 * back to uniprocessor mode.
120 */
121 if (of_property_read_u32(cpu_node,
122 OF_SECONDARY_BOOT,
123 &secondary_boot_addr)) {
124 pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
125 cpu_node->name);
126 ret = -ENOENT;
127 goto out;
128 }
129 }
106 } 130 }
107 131
108 /* 132 /*
109 * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is 133 * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
110 * returned, the SoC reported a uniprocessor configuration. 134 * returned, the SoC reported a uniprocessor configuration.
111 * We bail on any other error. 135 * We bail on any other error.
112 */ 136 */
113 ret = scu_a9_enable(); 137 ret = scu_a9_enable();
114out: 138out:
115 of_node_put(node); 139 of_node_put(cpu_node);
140 of_node_put(cpus_node);
141
116 if (ret) { 142 if (ret) {
117 /* Update the CPU present map to reflect uniprocessor mode */ 143 /* Update the CPU present map to reflect uniprocessor mode */
118 BUG_ON(ret != -ENOENT);
119 pr_warn("disabling SMP\n"); 144 pr_warn("disabling SMP\n");
120 init_cpu_present(&only_cpu_0); 145 init_cpu_present(&only_cpu_0);
121 } 146 }
@@ -139,7 +164,7 @@ out:
139 * - Wait for the secondary boot register to be re-written, which 164 * - Wait for the secondary boot register to be re-written, which
140 * indicates the secondary core has started. 165 * indicates the secondary core has started.
141 */ 166 */
142static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle) 167static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
143{ 168{
144 void __iomem *boot_reg; 169 void __iomem *boot_reg;
145 phys_addr_t boot_func; 170 phys_addr_t boot_func;
@@ -154,15 +179,16 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
154 return -EINVAL; 179 return -EINVAL;
155 } 180 }
156 181
157 if (!secondary_boot) { 182 if (!secondary_boot_addr) {
158 pr_err("required secondary boot register not specified\n"); 183 pr_err("required secondary boot register not specified\n");
159 return -EINVAL; 184 return -EINVAL;
160 } 185 }
161 186
162 boot_reg = ioremap_nocache((phys_addr_t)secondary_boot, sizeof(u32)); 187 boot_reg = ioremap_nocache(
188 (phys_addr_t)secondary_boot_addr, sizeof(u32));
163 if (!boot_reg) { 189 if (!boot_reg) {
164 pr_err("unable to map boot register for cpu %u\n", cpu_id); 190 pr_err("unable to map boot register for cpu %u\n", cpu_id);
165 return -ENOSYS; 191 return -ENOMEM;
166 } 192 }
167 193
168 /* 194 /*
@@ -191,12 +217,12 @@ static int bcm_boot_secondary(unsigned int cpu, struct task_struct *idle)
191 217
192 pr_err("timeout waiting for cpu %u to start\n", cpu_id); 218 pr_err("timeout waiting for cpu %u to start\n", cpu_id);
193 219
194 return -ENOSYS; 220 return -ENXIO;
195} 221}
196 222
197static struct smp_operations bcm_smp_ops __initdata = { 223static struct smp_operations bcm_smp_ops __initdata = {
198 .smp_prepare_cpus = bcm_smp_prepare_cpus, 224 .smp_prepare_cpus = bcm_smp_prepare_cpus,
199 .smp_boot_secondary = bcm_boot_secondary, 225 .smp_boot_secondary = kona_boot_secondary,
200}; 226};
201CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", 227CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
202 &bcm_smp_ops); 228 &bcm_smp_ops);