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