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