Commit | Line | Data |
---|---|---|
9a5a110e | 1 | /* |
84320e1a | 2 | * Copyright (C) 2014-2015 Broadcom Corporation |
9a5a110e AE |
3 | * Copyright 2014 Linaro Limited |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License as | |
7 | * published by the Free Software Foundation version 2. | |
8 | * | |
9 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | |
10 | * kind, whether express or implied; without even the implied warranty | |
11 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | */ | |
14 | ||
97890821 KH |
15 | #include <linux/cpumask.h> |
16 | #include <linux/delay.h> | |
9a5a110e | 17 | #include <linux/errno.h> |
97890821 | 18 | #include <linux/init.h> |
9a5a110e | 19 | #include <linux/io.h> |
97890821 | 20 | #include <linux/jiffies.h> |
9a5a110e AE |
21 | #include <linux/of.h> |
22 | #include <linux/sched.h> | |
97890821 | 23 | #include <linux/smp.h> |
9a5a110e | 24 | |
97890821 | 25 | #include <asm/cacheflush.h> |
9a5a110e AE |
26 | #include <asm/smp.h> |
27 | #include <asm/smp_plat.h> | |
28 | #include <asm/smp_scu.h> | |
29 | ||
30 | /* Size of mapped Cortex A9 SCU address space */ | |
31 | #define CORTEX_A9_SCU_SIZE 0x58 | |
32 | ||
33 | #define SECONDARY_TIMEOUT_NS NSEC_PER_MSEC /* 1 msec (in nanoseconds) */ | |
34 | #define BOOT_ADDR_CPUID_MASK 0x3 | |
35 | ||
36 | /* Name of device node property defining secondary boot register location */ | |
37 | #define OF_SECONDARY_BOOT "secondary-boot-reg" | |
84320e1a | 38 | #define MPIDR_CPUID_BITMASK 0x3 |
9a5a110e AE |
39 | |
40 | /* I/O address of register used to coordinate secondary core startup */ | |
84320e1a | 41 | static u32 secondary_boot_addr; |
9a5a110e AE |
42 | |
43 | /* | |
44 | * Enable the Cortex A9 Snoop Control Unit | |
45 | * | |
46 | * By the time this is called we already know there are multiple | |
47 | * cores present. We assume we're running on a Cortex A9 processor, | |
48 | * so any trouble getting the base address register or getting the | |
49 | * SCU base is a problem. | |
50 | * | |
51 | * Return 0 if successful or an error code otherwise. | |
52 | */ | |
53 | static int __init scu_a9_enable(void) | |
54 | { | |
55 | unsigned long config_base; | |
56 | void __iomem *scu_base; | |
57 | ||
58 | if (!scu_a9_has_base()) { | |
59 | pr_err("no configuration base address register!\n"); | |
60 | return -ENXIO; | |
61 | } | |
62 | ||
63 | /* Config base address register value is zero for uniprocessor */ | |
64 | config_base = scu_a9_get_base(); | |
65 | if (!config_base) { | |
66 | pr_err("hardware reports only one core\n"); | |
67 | return -ENOENT; | |
68 | } | |
69 | ||
70 | scu_base = ioremap((phys_addr_t)config_base, CORTEX_A9_SCU_SIZE); | |
71 | if (!scu_base) { | |
72 | pr_err("failed to remap config base (%lu/%u) for SCU\n", | |
73 | config_base, CORTEX_A9_SCU_SIZE); | |
74 | return -ENOMEM; | |
75 | } | |
76 | ||
77 | scu_enable(scu_base); | |
78 | ||
79 | iounmap(scu_base); /* That's the last we'll need of this */ | |
80 | ||
81 | return 0; | |
82 | } | |
83 | ||
97890821 KH |
84 | static int nsp_write_lut(void) |
85 | { | |
86 | void __iomem *sku_rom_lut; | |
87 | phys_addr_t secondary_startup_phy; | |
88 | ||
89 | if (!secondary_boot_addr) { | |
90 | pr_warn("required secondary boot register not specified\n"); | |
91 | return -EINVAL; | |
92 | } | |
93 | ||
94 | sku_rom_lut = ioremap_nocache((phys_addr_t)secondary_boot_addr, | |
95 | sizeof(secondary_boot_addr)); | |
96 | if (!sku_rom_lut) { | |
97 | pr_warn("unable to ioremap SKU-ROM LUT register\n"); | |
98 | return -ENOMEM; | |
99 | } | |
100 | ||
101 | secondary_startup_phy = virt_to_phys(secondary_startup); | |
102 | BUG_ON(secondary_startup_phy > (phys_addr_t)U32_MAX); | |
103 | ||
104 | writel_relaxed(secondary_startup_phy, sku_rom_lut); | |
105 | ||
106 | /* Ensure the write is visible to the secondary core */ | |
107 | smp_wmb(); | |
108 | ||
109 | iounmap(sku_rom_lut); | |
110 | ||
111 | return 0; | |
112 | } | |
113 | ||
9a5a110e AE |
114 | static void __init bcm_smp_prepare_cpus(unsigned int max_cpus) |
115 | { | |
116 | static cpumask_t only_cpu_0 = { CPU_BITS_CPU0 }; | |
84320e1a KH |
117 | struct device_node *cpus_node = NULL; |
118 | struct device_node *cpu_node = NULL; | |
9a5a110e AE |
119 | int ret; |
120 | ||
9a5a110e AE |
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 | */ | |
84320e1a KH |
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 | } | |
9a5a110e AE |
165 | } |
166 | ||
167 | /* | |
84320e1a | 168 | * Enable the SCU on Cortex A9 based SoCs. If -ENOENT is |
9a5a110e AE |
169 | * returned, the SoC reported a uniprocessor configuration. |
170 | * We bail on any other error. | |
171 | */ | |
172 | ret = scu_a9_enable(); | |
173 | out: | |
84320e1a KH |
174 | of_node_put(cpu_node); |
175 | of_node_put(cpus_node); | |
176 | ||
9a5a110e AE |
177 | if (ret) { |
178 | /* Update the CPU present map to reflect uniprocessor mode */ | |
9a5a110e AE |
179 | pr_warn("disabling SMP\n"); |
180 | init_cpu_present(&only_cpu_0); | |
181 | } | |
182 | } | |
183 | ||
184 | /* | |
185 | * The ROM code has the secondary cores looping, waiting for an event. | |
186 | * When an event occurs each core examines the bottom two bits of the | |
187 | * secondary boot register. When a core finds those bits contain its | |
188 | * own core id, it performs initialization, including computing its boot | |
189 | * address by clearing the boot register value's bottom two bits. The | |
190 | * core signals that it is beginning its execution by writing its boot | |
191 | * address back to the secondary boot register, and finally jumps to | |
192 | * that address. | |
193 | * | |
194 | * So to start a core executing we need to: | |
195 | * - Encode the (hardware) CPU id with the bottom bits of the secondary | |
196 | * start address. | |
197 | * - Write that value into the secondary boot register. | |
198 | * - Generate an event to wake up the secondary CPU(s). | |
199 | * - Wait for the secondary boot register to be re-written, which | |
200 | * indicates the secondary core has started. | |
201 | */ | |
84320e1a | 202 | static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle) |
9a5a110e AE |
203 | { |
204 | void __iomem *boot_reg; | |
205 | phys_addr_t boot_func; | |
206 | u64 start_clock; | |
207 | u32 cpu_id; | |
208 | u32 boot_val; | |
209 | bool timeout = false; | |
210 | ||
211 | cpu_id = cpu_logical_map(cpu); | |
212 | if (cpu_id & ~BOOT_ADDR_CPUID_MASK) { | |
213 | pr_err("bad cpu id (%u > %u)\n", cpu_id, BOOT_ADDR_CPUID_MASK); | |
214 | return -EINVAL; | |
215 | } | |
216 | ||
84320e1a | 217 | if (!secondary_boot_addr) { |
9a5a110e AE |
218 | pr_err("required secondary boot register not specified\n"); |
219 | return -EINVAL; | |
220 | } | |
221 | ||
84320e1a KH |
222 | boot_reg = ioremap_nocache( |
223 | (phys_addr_t)secondary_boot_addr, sizeof(u32)); | |
9a5a110e AE |
224 | if (!boot_reg) { |
225 | pr_err("unable to map boot register for cpu %u\n", cpu_id); | |
84320e1a | 226 | return -ENOMEM; |
9a5a110e AE |
227 | } |
228 | ||
229 | /* | |
230 | * Secondary cores will start in secondary_startup(), | |
231 | * defined in "arch/arm/kernel/head.S" | |
232 | */ | |
233 | boot_func = virt_to_phys(secondary_startup); | |
234 | BUG_ON(boot_func & BOOT_ADDR_CPUID_MASK); | |
235 | BUG_ON(boot_func > (phys_addr_t)U32_MAX); | |
236 | ||
237 | /* The core to start is encoded in the low bits */ | |
238 | boot_val = (u32)boot_func | cpu_id; | |
239 | writel_relaxed(boot_val, boot_reg); | |
240 | ||
241 | sev(); | |
242 | ||
243 | /* The low bits will be cleared once the core has started */ | |
244 | start_clock = local_clock(); | |
245 | while (!timeout && readl_relaxed(boot_reg) == boot_val) | |
246 | timeout = local_clock() - start_clock > SECONDARY_TIMEOUT_NS; | |
247 | ||
248 | iounmap(boot_reg); | |
249 | ||
250 | if (!timeout) | |
251 | return 0; | |
252 | ||
253 | pr_err("timeout waiting for cpu %u to start\n", cpu_id); | |
254 | ||
84320e1a | 255 | return -ENXIO; |
9a5a110e AE |
256 | } |
257 | ||
97890821 KH |
258 | static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle) |
259 | { | |
260 | int ret; | |
261 | ||
262 | /* | |
263 | * After wake up, secondary core branches to the startup | |
264 | * address programmed at SKU ROM LUT location. | |
265 | */ | |
266 | ret = nsp_write_lut(); | |
267 | if (ret) { | |
268 | pr_err("unable to write startup addr to SKU ROM LUT\n"); | |
269 | goto out; | |
270 | } | |
271 | ||
272 | /* Send a CPU wakeup interrupt to the secondary core */ | |
273 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | |
274 | ||
275 | out: | |
276 | return ret; | |
277 | } | |
278 | ||
75305275 | 279 | static const struct smp_operations bcm_smp_ops __initconst = { |
9a5a110e | 280 | .smp_prepare_cpus = bcm_smp_prepare_cpus, |
84320e1a | 281 | .smp_boot_secondary = kona_boot_secondary, |
9a5a110e AE |
282 | }; |
283 | CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method", | |
284 | &bcm_smp_ops); | |
97890821 KH |
285 | |
286 | struct smp_operations nsp_smp_ops __initdata = { | |
287 | .smp_prepare_cpus = bcm_smp_prepare_cpus, | |
288 | .smp_boot_secondary = nsp_boot_secondary, | |
289 | }; | |
290 | CPU_METHOD_OF_DECLARE(bcm_smp_nsp, "brcm,bcm-nsp-smp", &nsp_smp_ops); |