Commit a62580e58065dc00430b16ced6e7a00837b8323f

Authored by Marc Zyngier
Committed by Arnd Bergmann
1 parent 5ac21a943e

ARM: SoC: convert shmobile SMP to SMP operations

Convert shmobile SMP platforms to use struct smp_operations to provide
their SMP and CPU hotplug operations.

Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Nicolas Pitre <nico@linaro.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Showing 15 changed files with 165 additions and 146 deletions Side-by-side Diff

arch/arm/mach-shmobile/board-ag5evm.c
... ... @@ -650,6 +650,7 @@
650 650 }
651 651  
652 652 MACHINE_START(AG5EVM, "ag5evm")
  653 + .smp = smp_ops(sh73a0_smp_ops),
653 654 .map_io = sh73a0_map_io,
654 655 .init_early = sh73a0_add_early_devices,
655 656 .nr_irqs = NR_IRQS_LEGACY,
arch/arm/mach-shmobile/board-kota2.c
... ... @@ -545,6 +545,7 @@
545 545 }
546 546  
547 547 MACHINE_START(KOTA2, "kota2")
  548 + .smp = smp_ops(sh73a0_smp_ops),
548 549 .map_io = sh73a0_map_io,
549 550 .init_early = sh73a0_add_early_devices,
550 551 .nr_irqs = NR_IRQS_LEGACY,
arch/arm/mach-shmobile/board-kzm9d.c
... ... @@ -84,6 +84,7 @@
84 84 };
85 85  
86 86 DT_MACHINE_START(KZM9D_DT, "kzm9d")
  87 + .smp = smp_ops(emev2_smp_ops),
87 88 .map_io = emev2_map_io,
88 89 .init_early = emev2_add_early_devices,
89 90 .nr_irqs = NR_IRQS_LEGACY,
arch/arm/mach-shmobile/board-kzm9g.c
... ... @@ -769,6 +769,7 @@
769 769 };
770 770  
771 771 DT_MACHINE_START(KZM9G_DT, "kzm9g")
  772 + .smp = smp_ops(sh73a0_smp_ops),
772 773 .map_io = sh73a0_map_io,
773 774 .init_early = sh73a0_add_early_devices,
774 775 .nr_irqs = NR_IRQS_LEGACY,
arch/arm/mach-shmobile/board-marzen.c
... ... @@ -102,6 +102,7 @@
102 102 }
103 103  
104 104 MACHINE_START(MARZEN, "marzen")
  105 + .smp = smp_ops(r8a7779_smp_ops),
105 106 .map_io = r8a7779_map_io,
106 107 .init_early = r8a7779_add_early_devices,
107 108 .nr_irqs = NR_IRQS_LEGACY,
arch/arm/mach-shmobile/hotplug.c
... ... @@ -14,31 +14,17 @@
14 14 #include <linux/smp.h>
15 15 #include <linux/cpumask.h>
16 16 #include <linux/delay.h>
  17 +#include <linux/of.h>
17 18 #include <mach/common.h>
  19 +#include <mach/r8a7779.h>
  20 +#include <mach/emev2.h>
18 21 #include <asm/cacheflush.h>
  22 +#include <asm/mach-types.h>
19 23  
20 24 static cpumask_t dead_cpus;
21 25  
22   -int platform_cpu_kill(unsigned int cpu)
  26 +void shmobile_cpu_die(unsigned int cpu)
23 27 {
24   - int k;
25   -
26   - /* this function is running on another CPU than the offline target,
27   - * here we need wait for shutdown code in platform_cpu_die() to
28   - * finish before asking SoC-specific code to power off the CPU core.
29   - */
30   - for (k = 0; k < 1000; k++) {
31   - if (cpumask_test_cpu(cpu, &dead_cpus))
32   - return shmobile_platform_cpu_kill(cpu);
33   -
34   - mdelay(1);
35   - }
36   -
37   - return 0;
38   -}
39   -
40   -void platform_cpu_die(unsigned int cpu)
41   -{
42 28 /* hardware shutdown code running on the CPU that is being offlined */
43 29 flush_cache_all();
44 30 dsb();
... ... @@ -60,7 +46,7 @@
60 46 }
61 47 }
62 48  
63   -int platform_cpu_disable(unsigned int cpu)
  49 +int shmobile_cpu_disable(unsigned int cpu)
64 50 {
65 51 cpumask_clear_cpu(cpu, &dead_cpus);
66 52 /*
... ... @@ -68,5 +54,10 @@
68 54 * e.g. clock tick interrupts)
69 55 */
70 56 return cpu == 0 ? -EPERM : 0;
  57 +}
  58 +
  59 +int shmobile_cpu_is_dead(unsigned int cpu)
  60 +{
  61 + return cpumask_test_cpu(cpu, &dead_cpus);
71 62 }
arch/arm/mach-shmobile/include/mach/common.h
... ... @@ -4,11 +4,10 @@
4 4 extern void shmobile_earlytimer_init(void);
5 5 extern struct sys_timer shmobile_timer;
6 6 extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
7   - unsigned int mult, unsigned int div);
  7 + unsigned int mult, unsigned int div);
8 8 struct twd_local_timer;
9 9 extern void shmobile_setup_console(void);
10 10 extern void shmobile_secondary_vector(void);
11   -extern int shmobile_platform_cpu_kill(unsigned int cpu);
12 11 struct clk;
13 12 extern int shmobile_clk_init(void);
14 13 extern void shmobile_handle_irq_intc(struct pt_regs *);
... ... @@ -58,11 +57,6 @@
58 57 extern struct clk sh73a0_extcki_clk;
59 58 extern struct clk sh73a0_extalr_clk;
60 59  
61   -extern unsigned int sh73a0_get_core_count(void);
62   -extern void sh73a0_secondary_init(unsigned int cpu);
63   -extern int sh73a0_boot_secondary(unsigned int cpu);
64   -extern void sh73a0_smp_prepare_cpus(void);
65   -
66 60 extern void r8a7740_init_irq(void);
67 61 extern void r8a7740_map_io(void);
68 62 extern void r8a7740_add_early_devices(void);
... ... @@ -79,11 +73,6 @@
79 73 extern void r8a7779_pm_init(void);
80 74 extern void r8a7740_meram_workaround(void);
81 75  
82   -extern unsigned int r8a7779_get_core_count(void);
83   -extern int r8a7779_platform_cpu_kill(unsigned int cpu);
84   -extern void r8a7779_secondary_init(unsigned int cpu);
85   -extern int r8a7779_boot_secondary(unsigned int cpu);
86   -extern void r8a7779_smp_prepare_cpus(void);
87 76 extern void r8a7779_register_twd(void);
88 77  
89 78 extern void shmobile_init_late(void);
... ... @@ -99,6 +88,17 @@
99 88 #else
100 89 static inline int shmobile_cpuidle_init(void) { return 0; }
101 90 #endif
  91 +
  92 +extern void shmobile_cpu_die(unsigned int cpu);
  93 +extern int shmobile_cpu_disable(unsigned int cpu);
  94 +
  95 +#ifdef CONFIG_HOTPLUG_CPU
  96 +extern int shmobile_cpu_is_dead(unsigned int cpu);
  97 +#else
  98 +static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
  99 +#endif
  100 +
  101 +extern void shmobile_smp_init_cpus(unsigned int ncores);
102 102  
103 103 #endif /* __ARCH_MACH_COMMON_H */
arch/arm/mach-shmobile/include/mach/emev2.h
... ... @@ -7,14 +7,11 @@
7 7 extern void emev2_add_standard_devices(void);
8 8 extern void emev2_clock_init(void);
9 9 extern void emev2_set_boot_vector(unsigned long value);
10   -extern unsigned int emev2_get_core_count(void);
11   -extern int emev2_platform_cpu_kill(unsigned int cpu);
12   -extern void emev2_secondary_init(unsigned int cpu);
13   -extern int emev2_boot_secondary(unsigned int cpu);
14   -extern void emev2_smp_prepare_cpus(void);
15 10  
16 11 #define EMEV2_GPIO_BASE 200
17 12 #define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
  13 +
  14 +extern struct smp_operations emev2_smp_ops;
18 15  
19 16 #endif /* __ASM_EMEV2_H__ */
arch/arm/mach-shmobile/include/mach/r8a7779.h
... ... @@ -360,5 +360,7 @@
360 360 #define r8a7779_add_device_to_domain(pd, pdev) do { } while (0)
361 361 #endif /* CONFIG_PM */
362 362  
  363 +extern struct smp_operations r8a7779_smp_ops;
  364 +
363 365 #endif /* __ASM_R8A7779_H__ */
arch/arm/mach-shmobile/include/mach/sh73a0.h
... ... @@ -557,5 +557,7 @@
557 557 #define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
558 558 #define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
559 559  
  560 +extern struct smp_operations sh73a0_smp_ops;
  561 +
560 562 #endif /* __ASM_SH73A0_H__ */
arch/arm/mach-shmobile/platsmp.c
... ... @@ -11,100 +11,11 @@
11 11 * published by the Free Software Foundation.
12 12 */
13 13 #include <linux/init.h>
14   -#include <linux/errno.h>
15   -#include <linux/delay.h>
16   -#include <linux/device.h>
17 14 #include <linux/smp.h>
18   -#include <linux/io.h>
19   -#include <linux/of.h>
20 15 #include <asm/hardware/gic.h>
21   -#include <asm/mach-types.h>
22   -#include <mach/common.h>
23   -#include <mach/emev2.h>
24 16  
25   -#ifdef CONFIG_ARCH_SH73A0
26   -#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \
27   - of_machine_is_compatible("renesas,sh73a0"))
28   -#else
29   -#define is_sh73a0() (0)
30   -#endif
31   -
32   -#define is_r8a7779() machine_is_marzen()
33   -
34   -#ifdef CONFIG_ARCH_EMEV2
35   -#define is_emev2() of_machine_is_compatible("renesas,emev2")
36   -#else
37   -#define is_emev2() (0)
38   -#endif
39   -
40   -static unsigned int __init shmobile_smp_get_core_count(void)
  17 +void __init shmobile_smp_init_cpus(unsigned int ncores)
41 18 {
42   - if (is_sh73a0())
43   - return sh73a0_get_core_count();
44   -
45   - if (is_r8a7779())
46   - return r8a7779_get_core_count();
47   -
48   - if (is_emev2())
49   - return emev2_get_core_count();
50   -
51   - return 1;
52   -}
53   -
54   -static void __init shmobile_smp_prepare_cpus(void)
55   -{
56   - if (is_sh73a0())
57   - sh73a0_smp_prepare_cpus();
58   -
59   - if (is_r8a7779())
60   - r8a7779_smp_prepare_cpus();
61   -
62   - if (is_emev2())
63   - emev2_smp_prepare_cpus();
64   -}
65   -
66   -int shmobile_platform_cpu_kill(unsigned int cpu)
67   -{
68   - if (is_r8a7779())
69   - return r8a7779_platform_cpu_kill(cpu);
70   -
71   - if (is_emev2())
72   - return emev2_platform_cpu_kill(cpu);
73   -
74   - return 1;
75   -}
76   -
77   -void __cpuinit platform_secondary_init(unsigned int cpu)
78   -{
79   - trace_hardirqs_off();
80   -
81   - if (is_sh73a0())
82   - sh73a0_secondary_init(cpu);
83   -
84   - if (is_r8a7779())
85   - r8a7779_secondary_init(cpu);
86   -
87   - if (is_emev2())
88   - emev2_secondary_init(cpu);
89   -}
90   -
91   -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
92   -{
93   - if (is_sh73a0())
94   - return sh73a0_boot_secondary(cpu);
95   -
96   - if (is_r8a7779())
97   - return r8a7779_boot_secondary(cpu);
98   -
99   - if (is_emev2())
100   - return emev2_boot_secondary(cpu);
101   -
102   - return -ENOSYS;
103   -}
104   -
105   -void __init smp_init_cpus(void)
106   -{
107   - unsigned int ncores = shmobile_smp_get_core_count();
108 19 unsigned int i;
109 20  
110 21 if (ncores > nr_cpu_ids) {
... ... @@ -117,10 +28,5 @@
117 28 set_cpu_possible(i, true);
118 29  
119 30 set_smp_cross_call(gic_raise_softirq);
120   -}
121   -
122   -void __init platform_smp_prepare_cpus(unsigned int max_cpus)
123   -{
124   - shmobile_smp_prepare_cpus();
125 31 }
arch/arm/mach-shmobile/setup-emev2.c
... ... @@ -440,6 +440,7 @@
440 440 }
441 441  
442 442 DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
  443 + .smp = smp_ops(emev2_smp_ops),
443 444 .init_early = emev2_init_delay,
444 445 .nr_irqs = NR_IRQS_LEGACY,
445 446 .init_irq = emev2_init_irq_dt,
arch/arm/mach-shmobile/smp-emev2.c
... ... @@ -50,7 +50,7 @@
50 50  
51 51 }
52 52  
53   -unsigned int __init emev2_get_core_count(void)
  53 +static unsigned int __init emev2_get_core_count(void)
54 54 {
55 55 if (!scu_base) {
56 56 scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
57 57  
58 58  
59 59  
... ... @@ -62,17 +62,35 @@
62 62 return scu_base ? scu_get_core_count(scu_base) : 1;
63 63 }
64 64  
65   -int emev2_platform_cpu_kill(unsigned int cpu)
  65 +static int emev2_platform_cpu_kill(unsigned int cpu)
66 66 {
67 67 return 0; /* not supported yet */
68 68 }
69 69  
70   -void __cpuinit emev2_secondary_init(unsigned int cpu)
  70 +static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
71 71 {
  72 + int k;
  73 +
  74 + /* this function is running on another CPU than the offline target,
  75 + * here we need wait for shutdown code in platform_cpu_die() to
  76 + * finish before asking SoC-specific code to power off the CPU core.
  77 + */
  78 + for (k = 0; k < 1000; k++) {
  79 + if (shmobile_cpu_is_dead(cpu))
  80 + return emev2_platform_cpu_kill(cpu);
  81 + mdelay(1);
  82 + }
  83 +
  84 + return 0;
  85 +}
  86 +
  87 +
  88 +static void __cpuinit emev2_secondary_init(unsigned int cpu)
  89 +{
72 90 gic_secondary_init(0);
73 91 }
74 92  
75   -int __cpuinit emev2_boot_secondary(unsigned int cpu)
  93 +static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
76 94 {
77 95 cpu = cpu_logical_map(cpu);
78 96  
... ... @@ -86,7 +104,7 @@
86 104 return 0;
87 105 }
88 106  
89   -void __init emev2_smp_prepare_cpus(void)
  107 +static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
90 108 {
91 109 int cpu = cpu_logical_map(0);
92 110  
... ... @@ -95,4 +113,23 @@
95 113 /* enable cache coherency on CPU0 */
96 114 modify_scu_cpu_psr(0, 3 << (cpu * 8));
97 115 }
  116 +
  117 +static void __init emev2_smp_init_cpus(void)
  118 +{
  119 + unsigned int ncores = emev2_get_core_count();
  120 +
  121 + shmobile_smp_init_cpus(ncores);
  122 +}
  123 +
  124 +struct smp_operations emev2_smp_ops __initdata = {
  125 + .smp_init_cpus = emev2_smp_init_cpus,
  126 + .smp_prepare_cpus = emev2_smp_prepare_cpus,
  127 + .smp_secondary_init = emev2_secondary_init,
  128 + .smp_boot_secondary = emev2_boot_secondary,
  129 +#ifdef CONFIG_HOTPLUG_CPU
  130 + .cpu_kill = emev2_cpu_kill,
  131 + .cpu_die = shmobile_cpu_die,
  132 + .cpu_disable = shmobile_cpu_disable,
  133 +#endif
  134 +};
arch/arm/mach-shmobile/smp-r8a7779.c
... ... @@ -87,14 +87,14 @@
87 87 __raw_writel(tmp, scu_base + 8);
88 88 }
89 89  
90   -unsigned int __init r8a7779_get_core_count(void)
  90 +static unsigned int __init r8a7779_get_core_count(void)
91 91 {
92 92 void __iomem *scu_base = scu_base_addr();
93 93  
94 94 return scu_get_core_count(scu_base);
95 95 }
96 96  
97   -int r8a7779_platform_cpu_kill(unsigned int cpu)
  97 +static int r8a7779_platform_cpu_kill(unsigned int cpu)
98 98 {
99 99 struct r8a7779_pm_ch *ch = NULL;
100 100 int ret = -EIO;
101 101  
102 102  
... ... @@ -113,12 +113,31 @@
113 113 return ret ? ret : 1;
114 114 }
115 115  
116   -void __cpuinit r8a7779_secondary_init(unsigned int cpu)
  116 +static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
117 117 {
  118 + int k;
  119 +
  120 + /* this function is running on another CPU than the offline target,
  121 + * here we need wait for shutdown code in platform_cpu_die() to
  122 + * finish before asking SoC-specific code to power off the CPU core.
  123 + */
  124 + for (k = 0; k < 1000; k++) {
  125 + if (shmobile_cpu_is_dead(cpu))
  126 + return r8a7779_platform_cpu_kill(cpu);
  127 +
  128 + mdelay(1);
  129 + }
  130 +
  131 + return 0;
  132 +}
  133 +
  134 +
  135 +static void __cpuinit r8a7779_secondary_init(unsigned int cpu)
  136 +{
118 137 gic_secondary_init(0);
119 138 }
120 139  
121   -int __cpuinit r8a7779_boot_secondary(unsigned int cpu)
  140 +static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
122 141 {
123 142 struct r8a7779_pm_ch *ch = NULL;
124 143 int ret = -EIO;
... ... @@ -137,7 +156,7 @@
137 156 return ret;
138 157 }
139 158  
140   -void __init r8a7779_smp_prepare_cpus(void)
  159 +static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
141 160 {
142 161 int cpu = cpu_logical_map(0);
143 162  
... ... @@ -156,4 +175,23 @@
156 175 r8a7779_platform_cpu_kill(2);
157 176 r8a7779_platform_cpu_kill(3);
158 177 }
  178 +
  179 +static void __init r8a7779_smp_init_cpus(void)
  180 +{
  181 + unsigned int ncores = r8a7779_get_core_count();
  182 +
  183 + shmobile_smp_init_cpus(ncores);
  184 +}
  185 +
  186 +struct smp_operations r8a7779_smp_ops __initdata = {
  187 + .smp_init_cpus = r8a7779_smp_init_cpus,
  188 + .smp_prepare_cpus = r8a7779_smp_prepare_cpus,
  189 + .smp_secondary_init = r8a7779_secondary_init,
  190 + .smp_boot_secondary = r8a7779_boot_secondary,
  191 +#ifdef CONFIG_HOTPLUG_CPU
  192 + .cpu_kill = r8a7779_cpu_kill,
  193 + .cpu_die = shmobile_cpu_die,
  194 + .cpu_disable = shmobile_cpu_disable,
  195 +#endif
  196 +};
arch/arm/mach-shmobile/smp-sh73a0.c
... ... @@ -22,8 +22,10 @@
22 22 #include <linux/smp.h>
23 23 #include <linux/spinlock.h>
24 24 #include <linux/io.h>
  25 +#include <linux/delay.h>
25 26 #include <mach/common.h>
26 27 #include <asm/smp_plat.h>
  28 +#include <mach/sh73a0.h>
27 29 #include <asm/smp_scu.h>
28 30 #include <asm/smp_twd.h>
29 31 #include <asm/hardware/gic.h>
30 32  
31 33  
... ... @@ -64,19 +66,19 @@
64 66 __raw_writel(tmp, scu_base + 8);
65 67 }
66 68  
67   -unsigned int __init sh73a0_get_core_count(void)
  69 +static unsigned int __init sh73a0_get_core_count(void)
68 70 {
69 71 void __iomem *scu_base = scu_base_addr();
70 72  
71 73 return scu_get_core_count(scu_base);
72 74 }
73 75  
74   -void __cpuinit sh73a0_secondary_init(unsigned int cpu)
  76 +static void __cpuinit sh73a0_secondary_init(unsigned int cpu)
75 77 {
76 78 gic_secondary_init(0);
77 79 }
78 80  
79   -int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
  81 +static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
80 82 {
81 83 cpu = cpu_logical_map(cpu);
82 84  
... ... @@ -91,7 +93,7 @@
91 93 return 0;
92 94 }
93 95  
94   -void __init sh73a0_smp_prepare_cpus(void)
  96 +static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
95 97 {
96 98 int cpu = cpu_logical_map(0);
97 99  
... ... @@ -104,4 +106,42 @@
104 106 /* enable cache coherency on CPU0 */
105 107 modify_scu_cpu_psr(0, 3 << (cpu * 8));
106 108 }
  109 +
  110 +static void __init sh73a0_smp_init_cpus(void)
  111 +{
  112 + unsigned int ncores = sh73a0_get_core_count();
  113 +
  114 + shmobile_smp_init_cpus(ncores);
  115 +}
  116 +
  117 +static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
  118 +{
  119 + int k;
  120 +
  121 + /* this function is running on another CPU than the offline target,
  122 + * here we need wait for shutdown code in platform_cpu_die() to
  123 + * finish before asking SoC-specific code to power off the CPU core.
  124 + */
  125 + for (k = 0; k < 1000; k++) {
  126 + if (shmobile_cpu_is_dead(cpu))
  127 + return 1;
  128 +
  129 + mdelay(1);
  130 + }
  131 +
  132 + return 0;
  133 +}
  134 +
  135 +
  136 +struct smp_operations sh73a0_smp_ops __initdata = {
  137 + .smp_init_cpus = sh73a0_smp_init_cpus,
  138 + .smp_prepare_cpus = sh73a0_smp_prepare_cpus,
  139 + .smp_secondary_init = sh73a0_secondary_init,
  140 + .smp_boot_secondary = sh73a0_boot_secondary,
  141 +#ifdef CONFIG_HOTPLUG_CPU
  142 + .cpu_kill = sh73a0_cpu_kill,
  143 + .cpu_die = shmobile_cpu_die,
  144 + .cpu_disable = shmobile_cpu_disable,
  145 +#endif
  146 +};