aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-bcm
diff options
context:
space:
mode:
authorChris Brand <chris.brand@broadcom.com>2016-04-28 13:59:59 -0400
committerFlorian Fainelli <f.fainelli@gmail.com>2016-05-31 13:56:08 -0400
commit6585cb5a1341cbc5dfcf99a9b4ebda338b03657e (patch)
tree451d80b572f6feaeef5b0a0f8cd6cfe1b7fa2e21 /arch/arm/mach-bcm
parentf302b57ab0e5ff91a2e90cd1d2b84a27d8d95824 (diff)
ARM: BCM: modify Broadcom CPU enable method
Commit 84320e1a635fcf90cff4185f029ce9e31bf1d4a7 ("ARM: BCM: Clean up SMP support for Broadcom Kona") moved the "secondary-boot-reg" property from the "cpus" node to the individual "cpu" nodes but negelected to actually support multiple "secondary-boot-reg" properties. This patchset rectifies that omission. Note that the behaviour is changed slightly in that the "secondary-boot-reg" property is now read in smp_boot_secondary() rather than smp_prepare_cpus(). This means that any omissions will now only be reported when and if the cpu in question is being brought up. It also means that an omission for one cpu will not force uniprocessor mode. Signed-off-by: Chris Brand <chris.brand@broadcom.com> Reviewed-and-Tested-by: Jon Mason <jon.mason@broadcom.com> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Diffstat (limited to 'arch/arm/mach-bcm')
-rw-r--r--arch/arm/mach-bcm/platsmp.c116
1 files changed, 37 insertions, 79 deletions
diff --git a/arch/arm/mach-bcm/platsmp.c b/arch/arm/mach-bcm/platsmp.c
index cfae9c71fb74..5e53cf2fc052 100644
--- a/arch/arm/mach-bcm/platsmp.c
+++ b/arch/arm/mach-bcm/platsmp.c
@@ -37,9 +37,6 @@
37#define OF_SECONDARY_BOOT "secondary-boot-reg" 37#define OF_SECONDARY_BOOT "secondary-boot-reg"
38#define MPIDR_CPUID_BITMASK 0x3 38#define MPIDR_CPUID_BITMASK 0x3
39 39
40/* I/O address of register used to coordinate secondary core startup */
41static u32 secondary_boot_addr;
42
43/* 40/*
44 * Enable the Cortex A9 Snoop Control Unit 41 * Enable the Cortex A9 Snoop Control Unit
45 * 42 *
@@ -81,20 +78,40 @@ static int __init scu_a9_enable(void)
81 return 0; 78 return 0;
82} 79}
83 80
84static int nsp_write_lut(void) 81static u32 secondary_boot_addr_for(unsigned int cpu)
82{
83 u32 secondary_boot_addr = 0;
84 struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
85
86 if (!cpu_node) {
87 pr_err("Failed to find device tree node for CPU%u\n", cpu);
88 return 0;
89 }
90
91 if (of_property_read_u32(cpu_node,
92 OF_SECONDARY_BOOT,
93 &secondary_boot_addr))
94 pr_err("required secondary boot register not specified for CPU%u\n",
95 cpu);
96
97 of_node_put(cpu_node);
98
99 return secondary_boot_addr;
100}
101
102static int nsp_write_lut(unsigned int cpu)
85{ 103{
86 void __iomem *sku_rom_lut; 104 void __iomem *sku_rom_lut;
87 phys_addr_t secondary_startup_phy; 105 phys_addr_t secondary_startup_phy;
106 const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
88 107
89 if (!secondary_boot_addr) { 108 if (!secondary_boot_addr)
90 pr_warn("required secondary boot register not specified\n");
91 return -EINVAL; 109 return -EINVAL;
92 }
93 110
94 sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, 111 sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr,
95 sizeof(secondary_boot_addr)); 112 sizeof(phys_addr_t));
96 if (!sku_rom_lut) { 113 if (!sku_rom_lut) {
97 pr_warn("unable to ioremap SKU-ROM LUT register\n"); 114 pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu);
98 return -ENOMEM; 115 return -ENOMEM;
99 } 116 }
100 117
@@ -113,70 +130,12 @@ static int nsp_write_lut(void)
113 130
114static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) 131static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
115{ 132{
116 static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; 133 const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
117 struct device_node *cpus_node = NULL;
118 struct device_node *cpu_node = NULL;
119 int ret;
120
121 /*
122 * This function is only called via smp_ops->smp_prepare_cpu().
123 * That only happens if a "/cpus" device tree node exists
124 * and has an "enable-method" property that selects the SMP
125 * operations defined herein.
126 */
127 cpus_node = of_find_node_by_path("/cpus");
128 if (!cpus_node)
129 return;
130
131 for_each_child_of_node(cpus_node, cpu_node) {
132 u32 cpuid;
133
134 if (of_node_cmp(cpu_node->type, "cpu"))
135 continue;
136
137 if (of_property_read_u32(cpu_node, "reg", &cpuid)) {
138 pr_debug("%s: missing reg property\n",
139 cpu_node->full_name);
140 ret = -ENOENT;
141 goto out;
142 }
143
144 /*
145 * "secondary-boot-reg" property should be defined only
146 * for secondary cpu
147 */
148 if ((cpuid & MPIDR_CPUID_BITMASK) == 1) {
149 /*
150 * Our secondary enable method requires a
151 * "secondary-boot-reg" property to specify a register
152 * address used to request the ROM code boot a secondary
153 * core. If we have any trouble getting this we fall
154 * back to uniprocessor mode.
155 */
156 if (of_property_read_u32(cpu_node,
157 OF_SECONDARY_BOOT,
158 &secondary_boot_addr)) {
159 pr_warn("%s: no" OF_SECONDARY_BOOT "property\n",
160 cpu_node->name);
161 ret = -ENOENT;
162 goto out;
163 }
164 }
165 }
166
167 /*
168 * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is
169 * returned, the SoC reported a uniprocessor configuration.
170 * We bail on any other error.
171 */
172 ret = scu_a9_enable();
173out:
174 of_node_put(cpu_node);
175 of_node_put(cpus_node);
176 134
177 if (ret) { 135 /* Enable the SCU on Cortex A9 based SoCs */
136 if (scu_a9_enable()) {
178 /* Update the CPU present map to reflect uniprocessor mode */ 137 /* Update the CPU present map to reflect uniprocessor mode */
179 pr_warn("disabling SMP\n"); 138 pr_warn("failed to enable A9 SCU - disabling SMP\n");
180 init_cpu_present(&only_cpu_0); 139 init_cpu_present(&only_cpu_0);
181 } 140 }
182} 141}
@@ -207,6 +166,7 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
207 u32 cpu_id; 166 u32 cpu_id;
208 u32 boot_val; 167 u32 boot_val;
209 bool timeout = false; 168 bool timeout = false;
169 const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
210 170
211 cpu_id = cpu_logical_map(cpu); 171 cpu_id = cpu_logical_map(cpu);
212 if (cpu_id & ~BOOT_ADDR_CPUID_MASK) { 172 if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
@@ -214,13 +174,11 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
214 return -EINVAL; 174 return -EINVAL;
215 } 175 }
216 176
217 if (!secondary_boot_addr) { 177 if (!secondary_boot_addr)
218 pr_err("required secondary boot register not specified\n");
219 return -EINVAL; 178 return -EINVAL;
220 }
221 179
222 boot_reg = ioremap_nocache( 180 boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr,
223 (phys_addr_t)secondary_boot_addr, sizeof(u32)); 181 sizeof(phys_addr_t));
224 if (!boot_reg) { 182 if (!boot_reg) {
225 pr_err("unable to map boot register for cpu %u\n", cpu_id); 183 pr_err("unable to map boot register for cpu %u\n", cpu_id);
226 return -ENOMEM; 184 return -ENOMEM;
@@ -263,7 +221,7 @@ static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
263 * After wake up, secondary core branches to the startup 221 * After wake up, secondary core branches to the startup
264 * address programmed at SKU ROM LUT location. 222 * address programmed at SKU ROM LUT location.
265 */ 223 */
266 ret = nsp_write_lut(); 224 ret = nsp_write_lut(cpu);
267 if (ret) { 225 if (ret) {
268 pr_err("unable to write startup addr to SKU ROM LUT\n"); 226 pr_err("unable to write startup addr to SKU ROM LUT\n");
269 goto out; 227 goto out;
@@ -276,12 +234,12 @@ out:
276 return ret; 234 return ret;
277} 235}
278 236
279static const struct smp_operations bcm_smp_ops __initconst = { 237static const struct smp_operations kona_smp_ops __initconst = {
280 .smp_prepare_cpus = bcm_smp_prepare_cpus, 238 .smp_prepare_cpus = bcm_smp_prepare_cpus,
281 .smp_boot_secondary = kona_boot_secondary, 239 .smp_boot_secondary = kona_boot_secondary,
282}; 240};
283CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", 241CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
284 &bcm_smp_ops); 242 &kona_smp_ops);
285 243
286static const struct smp_operations nsp_smp_ops __initconst = { 244static const struct smp_operations nsp_smp_ops __initconst = {
287 .smp_prepare_cpus = bcm_smp_prepare_cpus, 245 .smp_prepare_cpus = bcm_smp_prepare_cpus,