Commit | Line | Data |
---|---|---|
7bffa14c BH |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2018 Nuvoton Technology corporation. | |
3 | // Copyright 2018 Google, Inc. | |
4 | ||
5 | #define pr_fmt(fmt) "nuvoton,npcm7xx-smp: " fmt | |
6 | ||
7 | #include <linux/delay.h> | |
8 | #include <linux/device.h> | |
9 | #include <linux/smp.h> | |
10 | #include <linux/io.h> | |
11 | #include <linux/of.h> | |
12 | #include <linux/of_device.h> | |
13 | #include <linux/of_platform.h> | |
14 | #include <linux/of_address.h> | |
15 | #include <asm/cacheflush.h> | |
16 | #include <asm/smp.h> | |
17 | #include <asm/smp_plat.h> | |
18 | #include <asm/smp_scu.h> | |
19 | ||
20 | #define NPCM7XX_SCRPAD_REG 0x13c | |
21 | ||
22 | extern void npcm7xx_secondary_startup(void); | |
23 | ||
24 | static int npcm7xx_smp_boot_secondary(unsigned int cpu, | |
25 | struct task_struct *idle) | |
26 | { | |
27 | struct device_node *gcr_np; | |
28 | void __iomem *gcr_base; | |
29 | int ret = 0; | |
30 | ||
31 | gcr_np = of_find_compatible_node(NULL, NULL, "nuvoton,npcm750-gcr"); | |
32 | if (!gcr_np) { | |
33 | pr_err("no gcr device node\n"); | |
34 | ret = -ENODEV; | |
35 | goto out; | |
36 | } | |
37 | gcr_base = of_iomap(gcr_np, 0); | |
38 | if (!gcr_base) { | |
39 | pr_err("could not iomap gcr"); | |
40 | ret = -ENOMEM; | |
41 | goto out; | |
42 | } | |
43 | ||
44 | /* give boot ROM kernel start address. */ | |
45 | iowrite32(__pa_symbol(npcm7xx_secondary_startup), gcr_base + | |
46 | NPCM7XX_SCRPAD_REG); | |
47 | /* make sure the previous write is seen by all observers. */ | |
48 | dsb_sev(); | |
49 | ||
50 | iounmap(gcr_base); | |
51 | out: | |
52 | return ret; | |
53 | } | |
54 | ||
55 | static void __init npcm7xx_smp_prepare_cpus(unsigned int max_cpus) | |
56 | { | |
57 | struct device_node *scu_np; | |
58 | void __iomem *scu_base; | |
59 | ||
60 | scu_np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu"); | |
61 | if (!scu_np) { | |
62 | pr_err("no scu device node\n"); | |
63 | return; | |
64 | } | |
65 | scu_base = of_iomap(scu_np, 0); | |
66 | if (!scu_base) { | |
67 | pr_err("could not iomap scu"); | |
68 | return; | |
69 | } | |
70 | ||
71 | scu_enable(scu_base); | |
72 | ||
73 | iounmap(scu_base); | |
74 | } | |
75 | ||
76 | static struct smp_operations npcm7xx_smp_ops __initdata = { | |
77 | .smp_prepare_cpus = npcm7xx_smp_prepare_cpus, | |
78 | .smp_boot_secondary = npcm7xx_smp_boot_secondary, | |
79 | }; | |
80 | ||
81 | CPU_METHOD_OF_DECLARE(npcm7xx_smp, "nuvoton,npcm750-smp", &npcm7xx_smp_ops); |