Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Copyright (C) 2014-2015 Broadcom Corporation
4 : : * Copyright 2014 Linaro Limited
5 : : */
6 : :
7 : : #include <linux/cpumask.h>
8 : : #include <linux/delay.h>
9 : : #include <linux/errno.h>
10 : : #include <linux/init.h>
11 : : #include <linux/io.h>
12 : : #include <linux/irqchip/irq-bcm2836.h>
13 : : #include <linux/jiffies.h>
14 : : #include <linux/of.h>
15 : : #include <linux/of_address.h>
16 : : #include <linux/sched.h>
17 : : #include <linux/sched/clock.h>
18 : : #include <linux/smp.h>
19 : :
20 : : #include <asm/cacheflush.h>
21 : : #include <asm/smp.h>
22 : : #include <asm/smp_plat.h>
23 : : #include <asm/smp_scu.h>
24 : :
25 : : /* Size of mapped Cortex A9 SCU address space */
26 : : #define CORTEX_A9_SCU_SIZE 0x58
27 : :
28 : : #define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */
29 : : #define BOOT_ADDR_CPUID_MASK 0x3
30 : :
31 : : /* Name of device node property defining secondary boot register location */
32 : : #define OF_SECONDARY_BOOT "secondary-boot-reg"
33 : : #define MPIDR_CPUID_BITMASK 0x3
34 : :
35 : : /*
36 : : * Enable the Cortex A9 Snoop Control Unit
37 : : *
38 : : * By the time this is called we already know there are multiple
39 : : * cores present. We assume we're running on a Cortex A9 processor,
40 : : * so any trouble getting the base address register or getting the
41 : : * SCU base is a problem.
42 : : *
43 : : * Return 0 if successful or an error code otherwise.
44 : : */
45 : 0 : static int __init scu_a9_enable(void)
46 : : {
47 : : unsigned long config_base;
48 : : void __iomem *scu_base;
49 : :
50 [ # # ]: 0 : if (!scu_a9_has_base()) {
51 : 0 : pr_err("no configuration base address register!\n");
52 : 0 : return -ENXIO;
53 : : }
54 : :
55 : : /* Config base address register value is zero for uniprocessor */
56 : : config_base = scu_a9_get_base();
57 [ # # ]: 0 : if (!config_base) {
58 : 0 : pr_err("hardware reports only one core\n");
59 : 0 : return -ENOENT;
60 : : }
61 : :
62 : 0 : scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE);
63 [ # # ]: 0 : if (!scu_base) {
64 : 0 : pr_err("failed to remap config base (%lu/%u) for SCU\n",
65 : : config_base, CORTEX_A9_SCU_SIZE);
66 : 0 : return -ENOMEM;
67 : : }
68 : :
69 : : scu_enable(scu_base);
70 : :
71 : 0 : iounmap(scu_base); /* That's the last we'll need of this */
72 : :
73 : 0 : return 0;
74 : : }
75 : :
76 : 0 : static u32 secondary_boot_addr_for(unsigned int cpu)
77 : : {
78 : 0 : u32 secondary_boot_addr = 0;
79 : 0 : struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
80 : :
81 [ # # ]: 0 : if (!cpu_node) {
82 : 0 : pr_err("Failed to find device tree node for CPU%u\n", cpu);
83 : 0 : return 0;
84 : : }
85 : :
86 [ # # ]: 0 : if (of_property_read_u32(cpu_node,
87 : : OF_SECONDARY_BOOT,
88 : : &secondary_boot_addr))
89 : 0 : pr_err("required secondary boot register not specified for CPU%u\n",
90 : : cpu);
91 : :
92 : 0 : of_node_put(cpu_node);
93 : :
94 : 0 : return secondary_boot_addr;
95 : : }
96 : :
97 : 0 : static int nsp_write_lut(unsigned int cpu)
98 : : {
99 : : void __iomem *sku_rom_lut;
100 : : phys_addr_t secondary_startup_phy;
101 : 0 : const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
102 : :
103 [ # # ]: 0 : if (!secondary_boot_addr)
104 : : return -EINVAL;
105 : :
106 : 0 : sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr,
107 : : sizeof(phys_addr_t));
108 [ # # ]: 0 : if (!sku_rom_lut) {
109 : 0 : pr_warn("unable to ioremap SKU-ROM LUT register for cpu %u\n", cpu);
110 : 0 : return -ENOMEM;
111 : : }
112 : :
113 : 0 : secondary_startup_phy = __pa_symbol(secondary_startup);
114 : : BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX);
115 : :
116 : : writel_relaxed(secondary_startup_phy, sku_rom_lut);
117 : :
118 : : /* Ensure the write is visible to the secondary core */
119 : 0 : smp_wmb();
120 : :
121 : 0 : iounmap(sku_rom_lut);
122 : :
123 : 0 : return 0;
124 : : }
125 : :
126 : 0 : static void __init bcm_smp_prepare_cpus(unsigned int max_cpus)
127 : : {
128 : 0 : const cpumask_t only_cpu_0 = { CPU_BITS_CPU0 };
129 : :
130 : : /* Enable the SCU on Cortex A9 based SoCs */
131 [ # # ]: 0 : if (scu_a9_enable()) {
132 : : /* Update the CPU present map to reflect uniprocessor mode */
133 : 0 : pr_warn("failed to enable A9 SCU - disabling SMP\n");
134 : 0 : init_cpu_present(&only_cpu_0);
135 : : }
136 : 0 : }
137 : :
138 : : /*
139 : : * The ROM code has the secondary cores looping, waiting for an event.
140 : : * When an event occurs each core examines the bottom two bits of the
141 : : * secondary boot register. When a core finds those bits contain its
142 : : * own core id, it performs initialization, including computing its boot
143 : : * address by clearing the boot register value's bottom two bits. The
144 : : * core signals that it is beginning its execution by writing its boot
145 : : * address back to the secondary boot register, and finally jumps to
146 : : * that address.
147 : : *
148 : : * So to start a core executing we need to:
149 : : * - Encode the (hardware) CPU id with the bottom bits of the secondary
150 : : * start address.
151 : : * - Write that value into the secondary boot register.
152 : : * - Generate an event to wake up the secondary CPU(s).
153 : : * - Wait for the secondary boot register to be re-written, which
154 : : * indicates the secondary core has started.
155 : : */
156 : 0 : static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
157 : : {
158 : : void __iomem *boot_reg;
159 : : phys_addr_t boot_func;
160 : : u64 start_clock;
161 : : u32 cpu_id;
162 : : u32 boot_val;
163 : : bool timeout = false;
164 : 0 : const u32 secondary_boot_addr = secondary_boot_addr_for(cpu);
165 : :
166 : 0 : cpu_id = cpu_logical_map(cpu);
167 [ # # ]: 0 : if (cpu_id & ~BOOT_ADDR_CPUID_MASK) {
168 : 0 : pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK);
169 : 0 : return -EINVAL;
170 : : }
171 : :
172 [ # # ]: 0 : if (!secondary_boot_addr)
173 : : return -EINVAL;
174 : :
175 : 0 : boot_reg = ioremap_nocache((phys_addr_t)secondary_boot_addr,
176 : : sizeof(phys_addr_t));
177 [ # # ]: 0 : if (!boot_reg) {
178 : 0 : pr_err("unable to map boot register for cpu %u\n", cpu_id);
179 : 0 : return -ENOMEM;
180 : : }
181 : :
182 : : /*
183 : : * Secondary cores will start in secondary_startup(),
184 : : * defined in "arch/arm/kernel/head.S"
185 : : */
186 : 0 : boot_func = __pa_symbol(secondary_startup);
187 [ # # ]: 0 : BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK);
188 : : BUG_ON(boot_func > (phys_addr_t)U32_MAX);
189 : :
190 : : /* The core to start is encoded in the low bits */
191 : 0 : boot_val = (u32)boot_func | cpu_id;
192 : : writel_relaxed(boot_val, boot_reg);
193 : :
194 : 0 : sev();
195 : :
196 : : /* The low bits will be cleared once the core has started */
197 : : start_clock = local_clock();
198 [ # # # # ]: 0 : while (!timeout && readl_relaxed(boot_reg) == boot_val)
199 : 0 : timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS;
200 : :
201 : 0 : iounmap(boot_reg);
202 : :
203 [ # # ]: 0 : if (!timeout)
204 : : return 0;
205 : :
206 : 0 : pr_err("timeout waiting for cpu %u to start\n", cpu_id);
207 : :
208 : 0 : return -ENXIO;
209 : : }
210 : :
211 : : /* Cluster Dormant Control command to bring CPU into a running state */
212 : : #define CDC_CMD 6
213 : : #define CDC_CMD_OFFSET 0
214 : : #define CDC_CMD_REG(cpu) (CDC_CMD_OFFSET + 4*(cpu))
215 : :
216 : : /*
217 : : * BCM23550 has a Cluster Dormant Control block that keeps the core in
218 : : * idle state. A command needs to be sent to the block to bring the CPU
219 : : * into running state.
220 : : */
221 : 0 : static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle)
222 : : {
223 : : void __iomem *cdc_base;
224 : : struct device_node *dn;
225 : : char *name;
226 : : int ret;
227 : :
228 : : /* Make sure a CDC node exists before booting the
229 : : * secondary core.
230 : : */
231 : : name = "brcm,bcm23550-cdc";
232 : 0 : dn = of_find_compatible_node(NULL, NULL, name);
233 [ # # ]: 0 : if (!dn) {
234 : 0 : pr_err("unable to find cdc node\n");
235 : 0 : return -ENODEV;
236 : : }
237 : :
238 : 0 : cdc_base = of_iomap(dn, 0);
239 : 0 : of_node_put(dn);
240 : :
241 [ # # ]: 0 : if (!cdc_base) {
242 : 0 : pr_err("unable to remap cdc base register\n");
243 : 0 : return -ENOMEM;
244 : : }
245 : :
246 : : /* Boot the secondary core */
247 : 0 : ret = kona_boot_secondary(cpu, idle);
248 [ # # ]: 0 : if (ret)
249 : : goto out;
250 : :
251 : : /* Bring this CPU to RUN state so that nIRQ nFIQ
252 : : * signals are unblocked.
253 : : */
254 : 0 : writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu));
255 : :
256 : : out:
257 : 0 : iounmap(cdc_base);
258 : :
259 : 0 : return ret;
260 : : }
261 : :
262 : 0 : static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
263 : : {
264 : : int ret;
265 : :
266 : : /*
267 : : * After wake up, secondary core branches to the startup
268 : : * address programmed at SKU ROM LUT location.
269 : : */
270 : 0 : ret = nsp_write_lut(cpu);
271 [ # # ]: 0 : if (ret) {
272 : 0 : pr_err("unable to write startup addr to SKU ROM LUT\n");
273 : 0 : goto out;
274 : : }
275 : :
276 : : /* Send a CPU wakeup interrupt to the secondary core */
277 : 0 : arch_send_wakeup_ipi_mask(cpumask_of(cpu));
278 : :
279 : : out:
280 : 0 : return ret;
281 : : }
282 : :
283 : 1212 : static int bcm2836_boot_secondary(unsigned int cpu, struct task_struct *idle)
284 : : {
285 : : void __iomem *intc_base;
286 : : struct device_node *dn;
287 : : char *name;
288 : :
289 : : name = "brcm,bcm2836-l1-intc";
290 : 1212 : dn = of_find_compatible_node(NULL, NULL, name);
291 [ - + ]: 1212 : if (!dn) {
292 : 0 : pr_err("unable to find intc node\n");
293 : 0 : return -ENODEV;
294 : : }
295 : :
296 : 1212 : intc_base = of_iomap(dn, 0);
297 : 1212 : of_node_put(dn);
298 : :
299 [ - + ]: 1212 : if (!intc_base) {
300 : 0 : pr_err("unable to remap intc base register\n");
301 : 0 : return -ENOMEM;
302 : : }
303 : :
304 : 2424 : writel(virt_to_phys(secondary_startup),
305 : : intc_base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
306 : :
307 : 1212 : dsb(sy);
308 : 1212 : sev();
309 : :
310 : 1212 : iounmap(intc_base);
311 : :
312 : 1212 : return 0;
313 : : }
314 : :
315 : : static const struct smp_operations kona_smp_ops __initconst = {
316 : : .smp_prepare_cpus = bcm_smp_prepare_cpus,
317 : : .smp_boot_secondary = kona_boot_secondary,
318 : : };
319 : : CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
320 : : &kona_smp_ops);
321 : :
322 : : static const struct smp_operations bcm23550_smp_ops __initconst = {
323 : : .smp_boot_secondary = bcm23550_boot_secondary,
324 : : };
325 : : CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550",
326 : : &bcm23550_smp_ops);
327 : :
328 : : static const struct smp_operations nsp_smp_ops __initconst = {
329 : : .smp_prepare_cpus = bcm_smp_prepare_cpus,
330 : : .smp_boot_secondary = nsp_boot_secondary,
331 : : };
332 : : CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops);
333 : :
334 : : const struct smp_operations bcm2836_smp_ops __initconst = {
335 : : .smp_boot_secondary = bcm2836_boot_secondary,
336 : : };
337 : : CPU_METHOD_OF_DECLARE(bcm_smp_bcm2836, "brcm,bcm2836-smp", &bcm2836_smp_ops);
|