aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-shmobile/Makefile1
-rw-r--r--arch/arm/mach-shmobile/board-ape6evm-reference.c2
-rw-r--r--arch/arm/mach-shmobile/board-ape6evm.c2
-rw-r--r--arch/arm/mach-shmobile/board-lager-reference.c3
-rw-r--r--arch/arm/mach-shmobile/board-lager.c3
-rw-r--r--arch/arm/mach-shmobile/headsmp.S3
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h12
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a73a4.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/r8a7790.h3
-rw-r--r--arch/arm/mach-shmobile/platsmp-apmu.c195
-rw-r--r--arch/arm/mach-shmobile/platsmp-scu.c30
-rw-r--r--arch/arm/mach-shmobile/platsmp.c22
-rw-r--r--arch/arm/mach-shmobile/setup-r8a73a4.c4
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7790.c26
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c6
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c4
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7790.c67
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c14
18 files changed, 331 insertions, 68 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 228193cc9a38..d30ec1a427ec 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -36,6 +36,7 @@ endif
36smp-y := platsmp.o headsmp.o 36smp-y := platsmp.o headsmp.o
37smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o 37smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o
38smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o 38smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o
39smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o platsmp-apmu.o
39smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o 40smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o
40 41
41# IRQ objects 42# IRQ objects
diff --git a/arch/arm/mach-shmobile/board-ape6evm-reference.c b/arch/arm/mach-shmobile/board-ape6evm-reference.c
index a23fa714f7ac..3276afcf3cc9 100644
--- a/arch/arm/mach-shmobile/board-ape6evm-reference.c
+++ b/arch/arm/mach-shmobile/board-ape6evm-reference.c
@@ -57,7 +57,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
57}; 57};
58 58
59DT_MACHINE_START(APE6EVM_DT, "ape6evm") 59DT_MACHINE_START(APE6EVM_DT, "ape6evm")
60 .init_early = r8a73a4_init_delay, 60 .init_early = r8a73a4_init_early,
61 .init_machine = ape6evm_add_standard_devices, 61 .init_machine = ape6evm_add_standard_devices,
62 .dt_compat = ape6evm_boards_compat_dt, 62 .dt_compat = ape6evm_boards_compat_dt,
63MACHINE_END 63MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ape6evm.c b/arch/arm/mach-shmobile/board-ape6evm.c
index 24b87eea9da3..d36e23f5d8b7 100644
--- a/arch/arm/mach-shmobile/board-ape6evm.c
+++ b/arch/arm/mach-shmobile/board-ape6evm.c
@@ -240,7 +240,7 @@ static const char *ape6evm_boards_compat_dt[] __initdata = {
240}; 240};
241 241
242DT_MACHINE_START(APE6EVM_DT, "ape6evm") 242DT_MACHINE_START(APE6EVM_DT, "ape6evm")
243 .init_early = r8a73a4_init_delay, 243 .init_early = r8a73a4_init_early,
244 .init_machine = ape6evm_add_standard_devices, 244 .init_machine = ape6evm_add_standard_devices,
245 .dt_compat = ape6evm_boards_compat_dt, 245 .dt_compat = ape6evm_boards_compat_dt,
246MACHINE_END 246MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c
index 9c316a1b2e32..d39a91b3ba48 100644
--- a/arch/arm/mach-shmobile/board-lager-reference.c
+++ b/arch/arm/mach-shmobile/board-lager-reference.c
@@ -38,7 +38,8 @@ static const char *lager_boards_compat_dt[] __initdata = {
38}; 38};
39 39
40DT_MACHINE_START(LAGER_DT, "lager") 40DT_MACHINE_START(LAGER_DT, "lager")
41 .init_early = r8a7790_init_delay, 41 .smp = smp_ops(r8a7790_smp_ops),
42 .init_early = r8a7790_init_early,
42 .init_machine = lager_add_standard_devices, 43 .init_machine = lager_add_standard_devices,
43 .init_time = r8a7790_timer_init, 44 .init_time = r8a7790_timer_init,
44 .dt_compat = lager_boards_compat_dt, 45 .dt_compat = lager_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index ffb6f0ac7606..ef3baaa79e6d 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -161,7 +161,8 @@ static const char *lager_boards_compat_dt[] __initdata = {
161}; 161};
162 162
163DT_MACHINE_START(LAGER_DT, "lager") 163DT_MACHINE_START(LAGER_DT, "lager")
164 .init_early = r8a7790_init_delay, 164 .smp = smp_ops(r8a7790_smp_ops),
165 .init_early = r8a7790_init_early,
165 .init_time = r8a7790_timer_init, 166 .init_time = r8a7790_timer_init,
166 .init_machine = lager_add_standard_devices, 167 .init_machine = lager_add_standard_devices,
167 .dt_compat = lager_boards_compat_dt, 168 .dt_compat = lager_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/headsmp.S b/arch/arm/mach-shmobile/headsmp.S
index f93751caf5cb..e5be5c88644b 100644
--- a/arch/arm/mach-shmobile/headsmp.S
+++ b/arch/arm/mach-shmobile/headsmp.S
@@ -40,6 +40,9 @@ shmobile_boot_fn:
40 .globl shmobile_boot_arg 40 .globl shmobile_boot_arg
41shmobile_boot_arg: 41shmobile_boot_arg:
422: .space 4 422: .space 4
43 .globl shmobile_boot_size
44shmobile_boot_size:
45 .long . - shmobile_boot_vector
43 46
44/* 47/*
45 * Per-CPU SMP boot function/argument selection code based on MPIDR 48 * Per-CPU SMP boot function/argument selection code based on MPIDR
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 7b938681e756..e31980590eb4 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -9,16 +9,23 @@ extern void shmobile_setup_console(void);
9extern void shmobile_boot_vector(void); 9extern void shmobile_boot_vector(void);
10extern unsigned long shmobile_boot_fn; 10extern unsigned long shmobile_boot_fn;
11extern unsigned long shmobile_boot_arg; 11extern unsigned long shmobile_boot_arg;
12extern unsigned long shmobile_boot_size;
12extern void shmobile_smp_boot(void); 13extern void shmobile_smp_boot(void);
13extern void shmobile_smp_sleep(void); 14extern void shmobile_smp_sleep(void);
14extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn, 15extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn,
15 unsigned long arg); 16 unsigned long arg);
17extern int shmobile_smp_cpu_disable(unsigned int cpu);
18extern void shmobile_invalidate_start(void);
16extern void shmobile_boot_scu(void); 19extern void shmobile_boot_scu(void);
17extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); 20extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus);
18extern int shmobile_smp_scu_boot_secondary(unsigned int cpu,
19 struct task_struct *idle);
20extern void shmobile_smp_scu_cpu_die(unsigned int cpu); 21extern void shmobile_smp_scu_cpu_die(unsigned int cpu);
21extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); 22extern int shmobile_smp_scu_cpu_kill(unsigned int cpu);
23extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus);
24extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu,
25 struct task_struct *idle);
26extern void shmobile_smp_apmu_cpu_die(unsigned int cpu);
27extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu);
28extern void shmobile_invalidate_start(void);
22struct clk; 29struct clk;
23extern int shmobile_clk_init(void); 30extern int shmobile_clk_init(void);
24extern void shmobile_handle_irq_intc(struct pt_regs *); 31extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -39,7 +46,6 @@ static inline int shmobile_cpuidle_init(void) { return 0; }
39#endif 46#endif
40 47
41extern void __iomem *shmobile_scu_base; 48extern void __iomem *shmobile_scu_base;
42extern void shmobile_smp_init_cpus(unsigned int ncores);
43 49
44static inline void __init shmobile_init_late(void) 50static inline void __init shmobile_init_late(void)
45{ 51{
diff --git a/arch/arm/mach-shmobile/include/mach/r8a73a4.h b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
index f3a9b702da56..5214338a6a47 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a73a4.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a73a4.h
@@ -5,6 +5,6 @@ void r8a73a4_add_standard_devices(void);
5void r8a73a4_add_dt_devices(void); 5void r8a73a4_add_dt_devices(void);
6void r8a73a4_clock_init(void); 6void r8a73a4_clock_init(void);
7void r8a73a4_pinmux_init(void); 7void r8a73a4_pinmux_init(void);
8void r8a73a4_init_delay(void); 8void r8a73a4_init_early(void);
9 9
10#endif /* __ASM_R8A73A4_H__ */ 10#endif /* __ASM_R8A73A4_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h
index 788d55952091..79e731c83e50 100644
--- a/arch/arm/mach-shmobile/include/mach/r8a7790.h
+++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h
@@ -5,8 +5,9 @@ void r8a7790_add_standard_devices(void);
5void r8a7790_add_dt_devices(void); 5void r8a7790_add_dt_devices(void);
6void r8a7790_clock_init(void); 6void r8a7790_clock_init(void);
7void r8a7790_pinmux_init(void); 7void r8a7790_pinmux_init(void);
8void r8a7790_init_delay(void); 8void r8a7790_init_early(void);
9void r8a7790_timer_init(void); 9void r8a7790_timer_init(void);
10extern struct smp_operations r8a7790_smp_ops;
10 11
11#define MD(nr) BIT(nr) 12#define MD(nr) BIT(nr)
12u32 r8a7790_read_mode_pins(void); 13u32 r8a7790_read_mode_pins(void);
diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c
new file mode 100644
index 000000000000..1da5a72d9642
--- /dev/null
+++ b/arch/arm/mach-shmobile/platsmp-apmu.c
@@ -0,0 +1,195 @@
1/*
2 * SMP support for SoCs with APMU
3 *
4 * Copyright (C) 2013 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/delay.h>
11#include <linux/init.h>
12#include <linux/io.h>
13#include <linux/ioport.h>
14#include <linux/of_address.h>
15#include <linux/smp.h>
16#include <asm/cacheflush.h>
17#include <asm/cp15.h>
18#include <asm/smp_plat.h>
19#include <mach/common.h>
20
21static struct {
22 void __iomem *iomem;
23 int bit;
24} apmu_cpus[CONFIG_NR_CPUS];
25
26#define WUPCR_OFFS 0x10
27#define PSTR_OFFS 0x40
28#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n)))
29
30static int apmu_power_on(void __iomem *p, int bit)
31{
32 /* request power on */
33 writel_relaxed(BIT(bit), p + WUPCR_OFFS);
34
35 /* wait for APMU to finish */
36 while (readl_relaxed(p + WUPCR_OFFS) != 0)
37 ;
38
39 return 0;
40}
41
42static int apmu_power_off(void __iomem *p, int bit)
43{
44 /* request Core Standby for next WFI */
45 writel_relaxed(3, p + CPUNCR_OFFS(bit));
46 return 0;
47}
48
49static int apmu_power_off_poll(void __iomem *p, int bit)
50{
51 int k;
52
53 for (k = 0; k < 1000; k++) {
54 if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3)
55 return 1;
56
57 mdelay(1);
58 }
59
60 return 0;
61}
62
63static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu))
64{
65 void __iomem *p = apmu_cpus[cpu].iomem;
66
67 return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL;
68}
69
70static void apmu_init_cpu(struct resource *res, int cpu, int bit)
71{
72 if (apmu_cpus[cpu].iomem)
73 return;
74
75 apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res));
76 apmu_cpus[cpu].bit = bit;
77
78 pr_debug("apmu ioremap %d %d 0x%08x 0x%08x\n", cpu, bit,
79 res->start, resource_size(res));
80}
81
82static struct {
83 struct resource iomem;
84 int cpus[4];
85} apmu_config[] = {
86 {
87 .iomem = DEFINE_RES_MEM(0xe6152000, 0x88),
88 .cpus = { 0, 1, 2, 3 },
89 },
90 {
91 .iomem = DEFINE_RES_MEM(0xe6151000, 0x88),
92 .cpus = { 0x100, 0x101, 0x102, 0x103 },
93 }
94};
95
96static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit))
97{
98 u32 id;
99 int k;
100 int bit, index;
101 bool is_allowed;
102
103 for (k = 0; k < ARRAY_SIZE(apmu_config); k++) {
104 /* only enable the cluster that includes the boot CPU */
105 is_allowed = false;
106 for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
107 id = apmu_config[k].cpus[bit];
108 if (id >= 0) {
109 if (id == cpu_logical_map(0))
110 is_allowed = true;
111 }
112 }
113 if (!is_allowed)
114 continue;
115
116 for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) {
117 id = apmu_config[k].cpus[bit];
118 if (id >= 0) {
119 index = get_logical_index(id);
120 if (index >= 0)
121 fn(&apmu_config[k].iomem, index, bit);
122 }
123 }
124 }
125}
126
127void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus)
128{
129 /* install boot code shared by all CPUs */
130 shmobile_boot_fn = virt_to_phys(shmobile_smp_boot);
131 shmobile_boot_arg = MPIDR_HWID_BITMASK;
132
133 /* perform per-cpu setup */
134 apmu_parse_cfg(apmu_init_cpu);
135}
136
137int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle)
138{
139 /* For this particular CPU register boot vector */
140 shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0);
141
142 return apmu_wrap(cpu, apmu_power_on);
143}
144
145#ifdef CONFIG_HOTPLUG_CPU
146/* nicked from arch/arm/mach-exynos/hotplug.c */
147static inline void cpu_enter_lowpower_a15(void)
148{
149 unsigned int v;
150
151 asm volatile(
152 " mrc p15, 0, %0, c1, c0, 0\n"
153 " bic %0, %0, %1\n"
154 " mcr p15, 0, %0, c1, c0, 0\n"
155 : "=&r" (v)
156 : "Ir" (CR_C)
157 : "cc");
158
159 flush_cache_louis();
160
161 asm volatile(
162 /*
163 * Turn off coherency
164 */
165 " mrc p15, 0, %0, c1, c0, 1\n"
166 " bic %0, %0, %1\n"
167 " mcr p15, 0, %0, c1, c0, 1\n"
168 : "=&r" (v)
169 : "Ir" (0x40)
170 : "cc");
171
172 isb();
173 dsb();
174}
175
176void shmobile_smp_apmu_cpu_die(unsigned int cpu)
177{
178 /* For this particular CPU deregister boot vector */
179 shmobile_smp_hook(cpu, 0, 0);
180
181 /* Select next sleep mode using the APMU */
182 apmu_wrap(cpu, apmu_power_off);
183
184 /* Do ARM specific CPU shutdown */
185 cpu_enter_lowpower_a15();
186
187 /* jump to shared mach-shmobile sleep / reset code */
188 shmobile_smp_sleep();
189}
190
191int shmobile_smp_apmu_cpu_kill(unsigned int cpu)
192{
193 return apmu_wrap(cpu, apmu_power_off_poll);
194}
195#endif
diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c
index c96f50160be6..673ad6e80869 100644
--- a/arch/arm/mach-shmobile/platsmp-scu.c
+++ b/arch/arm/mach-shmobile/platsmp-scu.c
@@ -7,6 +7,7 @@
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10#include <linux/cpu.h>
10#include <linux/delay.h> 11#include <linux/delay.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/io.h> 13#include <linux/io.h>
@@ -16,6 +17,26 @@
16#include <asm/smp_scu.h> 17#include <asm/smp_scu.h>
17#include <mach/common.h> 18#include <mach/common.h>
18 19
20static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb,
21 unsigned long action, void *hcpu)
22{
23 unsigned int cpu = (long)hcpu;
24
25 switch (action) {
26 case CPU_UP_PREPARE:
27 /* For this particular CPU register SCU SMP boot vector */
28 shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
29 (unsigned long)shmobile_scu_base);
30 break;
31 };
32
33 return NOTIFY_OK;
34}
35
36static struct notifier_block shmobile_smp_scu_notifier = {
37 .notifier_call = shmobile_smp_scu_notifier_call,
38};
39
19void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus) 40void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
20{ 41{
21 /* install boot code shared by all CPUs */ 42 /* install boot code shared by all CPUs */
@@ -25,14 +46,9 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus)
25 /* enable SCU and cache coherency on booting CPU */ 46 /* enable SCU and cache coherency on booting CPU */
26 scu_enable(shmobile_scu_base); 47 scu_enable(shmobile_scu_base);
27 scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL); 48 scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
28}
29 49
30int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle) 50 /* Use CPU notifier for reset vector control */
31{ 51 register_cpu_notifier(&shmobile_smp_scu_notifier);
32 /* For this particular CPU register SCU boot vector */
33 shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu),
34 (unsigned long)shmobile_scu_base);
35 return 0;
36} 52}
37 53
38#ifdef CONFIG_HOTPLUG_CPU 54#ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index d4ae616bcedb..9ebc246b8d7d 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -11,25 +11,10 @@
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/smp.h>
15#include <asm/cacheflush.h> 14#include <asm/cacheflush.h>
16#include <asm/smp_plat.h> 15#include <asm/smp_plat.h>
17#include <mach/common.h> 16#include <mach/common.h>
18 17
19void __init shmobile_smp_init_cpus(unsigned int ncores)
20{
21 unsigned int i;
22
23 if (ncores > nr_cpu_ids) {
24 pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
25 ncores, nr_cpu_ids);
26 ncores = nr_cpu_ids;
27 }
28
29 for (i = 0; i < ncores; i++)
30 set_cpu_possible(i, true);
31}
32
33extern unsigned long shmobile_smp_fn[]; 18extern unsigned long shmobile_smp_fn[];
34extern unsigned long shmobile_smp_arg[]; 19extern unsigned long shmobile_smp_arg[];
35extern unsigned long shmobile_smp_mpidr[]; 20extern unsigned long shmobile_smp_mpidr[];
@@ -44,3 +29,10 @@ void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg)
44 shmobile_smp_arg[cpu] = arg; 29 shmobile_smp_arg[cpu] = arg;
45 flush_cache_all(); 30 flush_cache_all();
46} 31}
32
33#ifdef CONFIG_HOTPLUG_CPU
34int shmobile_smp_cpu_disable(unsigned int cpu)
35{
36 return 0; /* Hotplug of any CPU is supported */
37}
38#endif
diff --git a/arch/arm/mach-shmobile/setup-r8a73a4.c b/arch/arm/mach-shmobile/setup-r8a73a4.c
index 89491700afb7..53a896275cae 100644
--- a/arch/arm/mach-shmobile/setup-r8a73a4.c
+++ b/arch/arm/mach-shmobile/setup-r8a73a4.c
@@ -207,7 +207,7 @@ void __init r8a73a4_add_standard_devices(void)
207 r8a73a4_register_thermal(); 207 r8a73a4_register_thermal();
208} 208}
209 209
210void __init r8a73a4_init_delay(void) 210void __init r8a73a4_init_early(void)
211{ 211{
212#ifndef CONFIG_ARM_ARCH_TIMER 212#ifndef CONFIG_ARM_ARCH_TIMER
213 shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */ 213 shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */
@@ -222,7 +222,7 @@ static const char *r8a73a4_boards_compat_dt[] __initdata = {
222}; 222};
223 223
224DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)") 224DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)")
225 .init_early = r8a73a4_init_delay, 225 .init_early = r8a73a4_init_early,
226 .dt_compat = r8a73a4_boards_compat_dt, 226 .dt_compat = r8a73a4_boards_compat_dt,
227MACHINE_END 227MACHINE_END
228#endif /* CONFIG_USE_OF */ 228#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c
index d0f5c9f9349a..c7e24eff9ba2 100644
--- a/arch/arm/mach-shmobile/setup-r8a7790.c
+++ b/arch/arm/mach-shmobile/setup-r8a7790.c
@@ -31,17 +31,18 @@
31#include <mach/r8a7790.h> 31#include <mach/r8a7790.h>
32#include <asm/mach/arch.h> 32#include <asm/mach/arch.h>
33 33
34static struct resource pfc_resources[] __initdata = { 34static const struct resource pfc_resources[] __initconst = {
35 DEFINE_RES_MEM(0xe6060000, 0x250), 35 DEFINE_RES_MEM(0xe6060000, 0x250),
36}; 36};
37 37
38#define R8A7790_GPIO(idx) \ 38#define R8A7790_GPIO(idx) \
39static struct resource r8a7790_gpio##idx##_resources[] __initdata = { \ 39static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \
40 DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \ 40 DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \
41 DEFINE_RES_IRQ(gic_spi(4 + (idx))), \ 41 DEFINE_RES_IRQ(gic_spi(4 + (idx))), \
42}; \ 42}; \
43 \ 43 \
44static struct gpio_rcar_config r8a7790_gpio##idx##_platform_data __initdata = { \ 44static const struct gpio_rcar_config \
45r8a7790_gpio##idx##_platform_data __initconst = { \
45 .gpio_base = 32 * (idx), \ 46 .gpio_base = 32 * (idx), \
46 .irq_base = 0, \ 47 .irq_base = 0, \
47 .number_of_pins = 32, \ 48 .number_of_pins = 32, \
@@ -112,7 +113,7 @@ void __init r8a7790_pinmux_init(void)
112enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1, 113enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1,
113 HSCIF0, HSCIF1 }; 114 HSCIF0, HSCIF1 };
114 115
115static struct plat_sci_port scif[] __initdata = { 116static const struct plat_sci_port scif[] __initconst = {
116 SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */ 117 SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */
117 SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */ 118 SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */
118 SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */ 119 SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */
@@ -131,11 +132,11 @@ static inline void r8a7790_register_scif(int idx)
131 sizeof(struct plat_sci_port)); 132 sizeof(struct plat_sci_port));
132} 133}
133 134
134static struct renesas_irqc_config irqc0_data __initdata = { 135static const struct renesas_irqc_config irqc0_data __initconst = {
135 .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ 136 .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
136}; 137};
137 138
138static struct resource irqc0_resources[] __initdata = { 139static const struct resource irqc0_resources[] __initconst = {
139 DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */ 140 DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */
140 DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */ 141 DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */
141 DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */ 142 DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */
@@ -150,7 +151,7 @@ static struct resource irqc0_resources[] __initdata = {
150 &irqc##idx##_data, \ 151 &irqc##idx##_data, \
151 sizeof(struct renesas_irqc_config)) 152 sizeof(struct renesas_irqc_config))
152 153
153static struct resource thermal_resources[] __initdata = { 154static const struct resource thermal_resources[] __initconst = {
154 DEFINE_RES_MEM(0xe61f0000, 0x14), 155 DEFINE_RES_MEM(0xe61f0000, 0x14),
155 DEFINE_RES_MEM(0xe61f0100, 0x38), 156 DEFINE_RES_MEM(0xe61f0100, 0x38),
156 DEFINE_RES_IRQ(gic_spi(69)), 157 DEFINE_RES_IRQ(gic_spi(69)),
@@ -161,13 +162,13 @@ static struct resource thermal_resources[] __initdata = {
161 thermal_resources, \ 162 thermal_resources, \
162 ARRAY_SIZE(thermal_resources)) 163 ARRAY_SIZE(thermal_resources))
163 164
164static struct sh_timer_config cmt00_platform_data __initdata = { 165static const struct sh_timer_config cmt00_platform_data __initconst = {
165 .name = "CMT00", 166 .name = "CMT00",
166 .timer_bit = 0, 167 .timer_bit = 0,
167 .clockevent_rating = 80, 168 .clockevent_rating = 80,
168}; 169};
169 170
170static struct resource cmt00_resources[] __initdata = { 171static const struct resource cmt00_resources[] __initconst = {
171 DEFINE_RES_MEM(0xffca0510, 0x0c), 172 DEFINE_RES_MEM(0xffca0510, 0x0c),
172 DEFINE_RES_MEM(0xffca0500, 0x04), 173 DEFINE_RES_MEM(0xffca0500, 0x04),
173 DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */ 174 DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */
@@ -267,7 +268,7 @@ void __init r8a7790_timer_init(void)
267 clocksource_of_init(); 268 clocksource_of_init();
268} 269}
269 270
270void __init r8a7790_init_delay(void) 271void __init r8a7790_init_early(void)
271{ 272{
272#ifndef CONFIG_ARM_ARCH_TIMER 273#ifndef CONFIG_ARM_ARCH_TIMER
273 shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */ 274 shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */
@@ -276,13 +277,14 @@ void __init r8a7790_init_delay(void)
276 277
277#ifdef CONFIG_USE_OF 278#ifdef CONFIG_USE_OF
278 279
279static const char *r8a7790_boards_compat_dt[] __initdata = { 280static const char * const r8a7790_boards_compat_dt[] __initconst = {
280 "renesas,r8a7790", 281 "renesas,r8a7790",
281 NULL, 282 NULL,
282}; 283};
283 284
284DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)") 285DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)")
285 .init_early = r8a7790_init_delay, 286 .smp = smp_ops(r8a7790_smp_ops),
287 .init_early = r8a7790_init_early,
286 .init_time = r8a7790_timer_init, 288 .init_time = r8a7790_timer_init,
287 .dt_compat = r8a7790_boards_compat_dt, 289 .dt_compat = r8a7790_boards_compat_dt,
288MACHINE_END 290MACHINE_END
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 522de5ebb55f..f2ca92308f75 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -34,12 +34,6 @@
34 34
35static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) 35static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
36{ 36{
37 int ret;
38
39 ret = shmobile_smp_scu_boot_secondary(cpu, idle);
40 if (ret)
41 return ret;
42
43 arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu))); 37 arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
44 return 0; 38 return 0;
45} 39}
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 0f05e9fb722f..627c1f0d9478 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -87,10 +87,6 @@ static int r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
87 unsigned int lcpu = cpu_logical_map(cpu); 87 unsigned int lcpu = cpu_logical_map(cpu);
88 int ret; 88 int ret;
89 89
90 ret = shmobile_smp_scu_boot_secondary(cpu, idle);
91 if (ret)
92 return ret;
93
94 if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu)) 90 if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu))
95 ch = r8a7779_ch_cpu[lcpu]; 91 ch = r8a7779_ch_cpu[lcpu];
96 92
diff --git a/arch/arm/mach-shmobile/smp-r8a7790.c b/arch/arm/mach-shmobile/smp-r8a7790.c
new file mode 100644
index 000000000000..015e2753de1f
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-r8a7790.c
@@ -0,0 +1,67 @@
1/*
2 * SMP support for r8a7790
3 *
4 * Copyright (C) 2012-2013 Renesas Solutions Corp.
5 * Copyright (C) 2012 Takashi Yoshii <takashi.yoshii.ze@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/smp.h>
19#include <linux/io.h>
20#include <asm/smp_plat.h>
21#include <mach/common.h>
22
23#define RST 0xe6160000
24#define CA15BAR 0x0020
25#define CA7BAR 0x0030
26#define CA15RESCNT 0x0040
27#define CA7RESCNT 0x0044
28#define MERAM 0xe8080000
29
30static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus)
31{
32 void __iomem *p;
33 u32 bar;
34
35 /* let APMU code install data related to shmobile_boot_vector */
36 shmobile_smp_apmu_prepare_cpus(max_cpus);
37
38 /* MERAM for jump stub, because BAR requires 256KB aligned address */
39 p = ioremap_nocache(MERAM, shmobile_boot_size);
40 memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size);
41 iounmap(p);
42
43 /* setup reset vectors */
44 p = ioremap_nocache(RST, 0x63);
45 bar = (MERAM >> 8) & 0xfffffc00;
46 writel_relaxed(bar, p + CA15BAR);
47 writel_relaxed(bar, p + CA7BAR);
48 writel_relaxed(bar | 0x10, p + CA15BAR);
49 writel_relaxed(bar | 0x10, p + CA7BAR);
50
51 /* enable clocks to all CPUs */
52 writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000,
53 p + CA15RESCNT);
54 writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000,
55 p + CA7RESCNT);
56 iounmap(p);
57}
58
59struct smp_operations r8a7790_smp_ops __initdata = {
60 .smp_prepare_cpus = r8a7790_smp_prepare_cpus,
61 .smp_boot_secondary = shmobile_smp_apmu_boot_secondary,
62#ifdef CONFIG_HOTPLUG_CPU
63 .cpu_disable = shmobile_smp_cpu_disable,
64 .cpu_die = shmobile_smp_apmu_cpu_die,
65 .cpu_kill = shmobile_smp_apmu_cpu_kill,
66#endif
67};
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 0baa24443793..13ba36a6831f 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -46,11 +46,6 @@ void __init sh73a0_register_twd(void)
46static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) 46static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
47{ 47{
48 unsigned int lcpu = cpu_logical_map(cpu); 48 unsigned int lcpu = cpu_logical_map(cpu);
49 int ret;
50
51 ret = shmobile_smp_scu_boot_secondary(cpu, idle);
52 if (ret)
53 return ret;
54 49
55 if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3) 50 if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3)
56 __raw_writel(1 << lcpu, WUPCR); /* wake up */ 51 __raw_writel(1 << lcpu, WUPCR); /* wake up */
@@ -71,18 +66,11 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
71 shmobile_smp_scu_prepare_cpus(max_cpus); 66 shmobile_smp_scu_prepare_cpus(max_cpus);
72} 67}
73 68
74#ifdef CONFIG_HOTPLUG_CPU
75static int sh73a0_cpu_disable(unsigned int cpu)
76{
77 return 0; /* CPU0 and CPU1 supported */
78}
79#endif /* CONFIG_HOTPLUG_CPU */
80
81struct smp_operations sh73a0_smp_ops __initdata = { 69struct smp_operations sh73a0_smp_ops __initdata = {
82 .smp_prepare_cpus = sh73a0_smp_prepare_cpus, 70 .smp_prepare_cpus = sh73a0_smp_prepare_cpus,
83 .smp_boot_secondary = sh73a0_boot_secondary, 71 .smp_boot_secondary = sh73a0_boot_secondary,
84#ifdef CONFIG_HOTPLUG_CPU 72#ifdef CONFIG_HOTPLUG_CPU
85 .cpu_disable = sh73a0_cpu_disable, 73 .cpu_disable = shmobile_smp_cpu_disable,
86 .cpu_die = shmobile_smp_scu_cpu_die, 74 .cpu_die = shmobile_smp_scu_cpu_die,
87 .cpu_kill = shmobile_smp_scu_cpu_kill, 75 .cpu_kill = shmobile_smp_scu_cpu_kill,
88#endif 76#endif