|
19 | 19 | #include <linux/io.h>
|
20 | 20 | #include <linux/jiffies.h>
|
21 | 21 | #include <linux/of.h>
|
| 22 | +#include <linux/of_address.h> |
22 | 23 | #include <linux/sched.h>
|
23 | 24 | #include <linux/smp.h>
|
24 | 25 |
|
@@ -255,6 +256,57 @@ static int kona_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
255 | 256 | return -ENXIO;
|
256 | 257 | }
|
257 | 258 |
|
| 259 | +/* Cluster Dormant Control command to bring CPU into a running state */ |
| 260 | +#define CDC_CMD 6 |
| 261 | +#define CDC_CMD_OFFSET 0 |
| 262 | +#define CDC_CMD_REG(cpu) (CDC_CMD_OFFSET + 4*(cpu)) |
| 263 | + |
| 264 | +/* |
| 265 | + * BCM23550 has a Cluster Dormant Control block that keeps the core in |
| 266 | + * idle state. A command needs to be sent to the block to bring the CPU |
| 267 | + * into running state. |
| 268 | + */ |
| 269 | +static int bcm23550_boot_secondary(unsigned int cpu, struct task_struct *idle) |
| 270 | +{ |
| 271 | + void __iomem *cdc_base; |
| 272 | + struct device_node *dn; |
| 273 | + char *name; |
| 274 | + int ret; |
| 275 | + |
| 276 | + /* Make sure a CDC node exists before booting the |
| 277 | + * secondary core. |
| 278 | + */ |
| 279 | + name = "brcm,bcm23550-cdc"; |
| 280 | + dn = of_find_compatible_node(NULL, NULL, name); |
| 281 | + if (!dn) { |
| 282 | + pr_err("unable to find cdc node\n"); |
| 283 | + return -ENODEV; |
| 284 | + } |
| 285 | + |
| 286 | + cdc_base = of_iomap(dn, 0); |
| 287 | + of_node_put(dn); |
| 288 | + |
| 289 | + if (!cdc_base) { |
| 290 | + pr_err("unable to remap cdc base register\n"); |
| 291 | + return -ENOMEM; |
| 292 | + } |
| 293 | + |
| 294 | + /* Boot the secondary core */ |
| 295 | + ret = kona_boot_secondary(cpu, idle); |
| 296 | + if (ret) |
| 297 | + goto out; |
| 298 | + |
| 299 | + /* Bring this CPU to RUN state so that nIRQ nFIQ |
| 300 | + * signals are unblocked. |
| 301 | + */ |
| 302 | + writel_relaxed(CDC_CMD, cdc_base + CDC_CMD_REG(cpu)); |
| 303 | + |
| 304 | +out: |
| 305 | + iounmap(cdc_base); |
| 306 | + |
| 307 | + return ret; |
| 308 | +} |
| 309 | + |
258 | 310 | static int nsp_boot_secondary(unsigned int cpu, struct task_struct *idle)
|
259 | 311 | {
|
260 | 312 | int ret;
|
@@ -283,6 +335,12 @@ static const struct smp_operations bcm_smp_ops __initconst = {
|
283 | 335 | CPU_METHOD_OF_DECLARE(bcm_smp_bcm281xx, "brcm,bcm11351-cpu-method",
|
284 | 336 | &bcm_smp_ops);
|
285 | 337 |
|
| 338 | +static const struct smp_operations bcm23550_smp_ops __initconst = { |
| 339 | + .smp_boot_secondary = bcm23550_boot_secondary, |
| 340 | +}; |
| 341 | +CPU_METHOD_OF_DECLARE(bcm_smp_bcm23550, "brcm,bcm23550", |
| 342 | + &bcm23550_smp_ops); |
| 343 | + |
286 | 344 | static const struct smp_operations nsp_smp_ops __initconst = {
|
287 | 345 | .smp_prepare_cpus = bcm_smp_prepare_cpus,
|
288 | 346 | .smp_boot_secondary = nsp_boot_secondary,
|
|
0 commit comments