From 0750a54592a2daff70771a1c170f9859d5901d3d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:26:48 +0900 Subject: [PATCH 01/17] ARM: shmobile: Rename to r8a73a4_init_early() Rename r8a73a4_init_delay() into r8a73a4_init_early() to make the function name show that more than just delay setup may happen in the future. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-ape6evm-reference.c | 2 +- arch/arm/mach-shmobile/board-ape6evm.c | 2 +- arch/arm/mach-shmobile/include/mach/r8a73a4.h | 2 +- arch/arm/mach-shmobile/setup-r8a73a4.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) 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 = { }; DT_MACHINE_START(APE6EVM_DT, "ape6evm") - .init_early = r8a73a4_init_delay, + .init_early = r8a73a4_init_early, .init_machine = ape6evm_add_standard_devices, .dt_compat = ape6evm_boards_compat_dt, MACHINE_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 = { }; DT_MACHINE_START(APE6EVM_DT, "ape6evm") - .init_early = r8a73a4_init_delay, + .init_early = r8a73a4_init_early, .init_machine = ape6evm_add_standard_devices, .dt_compat = ape6evm_boards_compat_dt, MACHINE_END 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); void r8a73a4_add_dt_devices(void); void r8a73a4_clock_init(void); void r8a73a4_pinmux_init(void); -void r8a73a4_init_delay(void); +void r8a73a4_init_early(void); #endif /* __ASM_R8A73A4_H__ */ 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) r8a73a4_register_thermal(); } -void __init r8a73a4_init_delay(void) +void __init r8a73a4_init_early(void) { #ifndef CONFIG_ARM_ARCH_TIMER shmobile_setup_delay(1500, 2, 4); /* Cortex-A15 @ 1500MHz */ @@ -222,7 +222,7 @@ static const char *r8a73a4_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(R8A73A4_DT, "Generic R8A73A4 (Flattened Device Tree)") - .init_early = r8a73a4_init_delay, + .init_early = r8a73a4_init_early, .dt_compat = r8a73a4_boards_compat_dt, MACHINE_END #endif /* CONFIG_USE_OF */ From 0efd7faa6c611dab4ab8105473d2ffde7918cb69 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:27:01 +0900 Subject: [PATCH 02/17] ARM: shmobile: Rename to r8a7790_init_early() Rename r8a7790_init_delay() into r8a7790_init_early() to make the function name show that more than just delay setup may happen in the future. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/board-lager-reference.c | 2 +- arch/arm/mach-shmobile/board-lager.c | 2 +- arch/arm/mach-shmobile/include/mach/r8a7790.h | 2 +- arch/arm/mach-shmobile/setup-r8a7790.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c index 9c316a1b2e32..2856f51ff8a6 100644 --- a/arch/arm/mach-shmobile/board-lager-reference.c +++ b/arch/arm/mach-shmobile/board-lager-reference.c @@ -38,7 +38,7 @@ static const char *lager_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(LAGER_DT, "lager") - .init_early = r8a7790_init_delay, + .init_early = r8a7790_init_early, .init_machine = lager_add_standard_devices, .init_time = r8a7790_timer_init, .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..4047fac811c0 100644 --- a/arch/arm/mach-shmobile/board-lager.c +++ b/arch/arm/mach-shmobile/board-lager.c @@ -161,7 +161,7 @@ static const char *lager_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(LAGER_DT, "lager") - .init_early = r8a7790_init_delay, + .init_early = r8a7790_init_early, .init_time = r8a7790_timer_init, .init_machine = lager_add_standard_devices, .dt_compat = lager_boards_compat_dt, diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 788d55952091..177a8372abb7 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h @@ -5,7 +5,7 @@ void r8a7790_add_standard_devices(void); void r8a7790_add_dt_devices(void); void r8a7790_clock_init(void); void r8a7790_pinmux_init(void); -void r8a7790_init_delay(void); +void r8a7790_init_early(void); void r8a7790_timer_init(void); #define MD(nr) BIT(nr) diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index d0f5c9f9349a..a42d1f6f1f81 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -267,7 +267,7 @@ void __init r8a7790_timer_init(void) clocksource_of_init(); } -void __init r8a7790_init_delay(void) +void __init r8a7790_init_early(void) { #ifndef CONFIG_ARM_ARCH_TIMER shmobile_setup_delay(1300, 2, 4); /* Cortex-A15 @ 1300MHz */ @@ -282,7 +282,7 @@ static const char *r8a7790_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)") - .init_early = r8a7790_init_delay, + .init_early = r8a7790_init_early, .init_time = r8a7790_timer_init, .dt_compat = r8a7790_boards_compat_dt, MACHINE_END From cde214a890f81797a5eee94fffc89c1de21ed991 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Thu, 8 Aug 2013 00:34:53 +0200 Subject: [PATCH 03/17] ARM: shmobile: r8a7790: Constify platform data and resources Platform data and resources for core devices are kmemdup()ed when the corresponding devices are registered and can thus be declared as const. Do so. Signed-off-by: Laurent Pinchart Acked-by: Kuninori Morimoto Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/setup-r8a7790.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index a42d1f6f1f81..e0d29a265c2d 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -31,17 +31,18 @@ #include #include -static struct resource pfc_resources[] __initdata = { +static const struct resource pfc_resources[] __initconst = { DEFINE_RES_MEM(0xe6060000, 0x250), }; #define R8A7790_GPIO(idx) \ -static struct resource r8a7790_gpio##idx##_resources[] __initdata = { \ +static const struct resource r8a7790_gpio##idx##_resources[] __initconst = { \ DEFINE_RES_MEM(0xe6050000 + 0x1000 * (idx), 0x50), \ DEFINE_RES_IRQ(gic_spi(4 + (idx))), \ }; \ \ -static struct gpio_rcar_config r8a7790_gpio##idx##_platform_data __initdata = { \ +static const struct gpio_rcar_config \ +r8a7790_gpio##idx##_platform_data __initconst = { \ .gpio_base = 32 * (idx), \ .irq_base = 0, \ .number_of_pins = 32, \ @@ -112,7 +113,7 @@ void __init r8a7790_pinmux_init(void) enum { SCIFA0, SCIFA1, SCIFB0, SCIFB1, SCIFB2, SCIFA2, SCIF0, SCIF1, HSCIF0, HSCIF1 }; -static struct plat_sci_port scif[] __initdata = { +static const struct plat_sci_port scif[] __initconst = { SCIFA_DATA(SCIFA0, 0xe6c40000, gic_spi(144)), /* SCIFA0 */ SCIFA_DATA(SCIFA1, 0xe6c50000, gic_spi(145)), /* SCIFA1 */ SCIFB_DATA(SCIFB0, 0xe6c20000, gic_spi(148)), /* SCIFB0 */ @@ -131,11 +132,11 @@ static inline void r8a7790_register_scif(int idx) sizeof(struct plat_sci_port)); } -static struct renesas_irqc_config irqc0_data __initdata = { +static const struct renesas_irqc_config irqc0_data __initconst = { .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */ }; -static struct resource irqc0_resources[] __initdata = { +static const struct resource irqc0_resources[] __initconst = { DEFINE_RES_MEM(0xe61c0000, 0x200), /* IRQC Event Detector Block_0 */ DEFINE_RES_IRQ(gic_spi(0)), /* IRQ0 */ DEFINE_RES_IRQ(gic_spi(1)), /* IRQ1 */ @@ -150,7 +151,7 @@ static struct resource irqc0_resources[] __initdata = { &irqc##idx##_data, \ sizeof(struct renesas_irqc_config)) -static struct resource thermal_resources[] __initdata = { +static const struct resource thermal_resources[] __initconst = { DEFINE_RES_MEM(0xe61f0000, 0x14), DEFINE_RES_MEM(0xe61f0100, 0x38), DEFINE_RES_IRQ(gic_spi(69)), @@ -161,13 +162,13 @@ static struct resource thermal_resources[] __initdata = { thermal_resources, \ ARRAY_SIZE(thermal_resources)) -static struct sh_timer_config cmt00_platform_data __initdata = { +static const struct sh_timer_config cmt00_platform_data __initconst = { .name = "CMT00", .timer_bit = 0, .clockevent_rating = 80, }; -static struct resource cmt00_resources[] __initdata = { +static const struct resource cmt00_resources[] __initconst = { DEFINE_RES_MEM(0xffca0510, 0x0c), DEFINE_RES_MEM(0xffca0500, 0x04), DEFINE_RES_IRQ(gic_spi(142)), /* CMT0_0 */ @@ -276,7 +277,7 @@ void __init r8a7790_init_early(void) #ifdef CONFIG_USE_OF -static const char *r8a7790_boards_compat_dt[] __initdata = { +static const char * const r8a7790_boards_compat_dt[] __initconst = { "renesas,r8a7790", NULL, }; From 5c4dfcd663b6e96cc20f02dc2c7c315749ea1bc1 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:13:30 +0900 Subject: [PATCH 04/17] ARM: shmobile: Introduce shmobile_smp_cpu_disable() Introduce the shared CPU Hotplug function shmobile_smp_cpu_disable() for mach-shmobile. It is useful for the case when all CPUs may be hotplugged, including CPU 0. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/include/mach/common.h | 1 + arch/arm/mach-shmobile/platsmp.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 7b938681e756..1ed155eb3e92 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -13,6 +13,7 @@ extern void shmobile_smp_boot(void); extern void shmobile_smp_sleep(void); extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg); +extern int shmobile_smp_cpu_disable(unsigned int cpu); extern void shmobile_boot_scu(void); extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index d4ae616bcedb..3741562156ed 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -44,3 +44,10 @@ void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg) shmobile_smp_arg[cpu] = arg; flush_cache_all(); } + +#ifdef CONFIG_HOTPLUG_CPU +int shmobile_smp_cpu_disable(unsigned int cpu) +{ + return 0; /* Hotplug of any CPU is supported */ +} +#endif From a3b142a1a08af543473ae726e5d96a969c5b02b5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:13:39 +0900 Subject: [PATCH 05/17] ARM: shmobile: Use shmobile_smp_cpu_disable() on sh73a0 Use shmobile_smp_cpu_disable() on sh73a0 since it allows CPU Hotplug of any CPU. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/smp-sh73a0.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 0baa24443793..9a30a3fc7e7d 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -71,18 +71,11 @@ static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus) shmobile_smp_scu_prepare_cpus(max_cpus); } -#ifdef CONFIG_HOTPLUG_CPU -static int sh73a0_cpu_disable(unsigned int cpu) -{ - return 0; /* CPU0 and CPU1 supported */ -} -#endif /* CONFIG_HOTPLUG_CPU */ - struct smp_operations sh73a0_smp_ops __initdata = { .smp_prepare_cpus = sh73a0_smp_prepare_cpus, .smp_boot_secondary = sh73a0_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU - .cpu_disable = sh73a0_cpu_disable, + .cpu_disable = shmobile_smp_cpu_disable, .cpu_die = shmobile_smp_scu_cpu_die, .cpu_kill = shmobile_smp_scu_cpu_kill, #endif From c4e1e64d2b6a921a57629ede635f81f5d2882543 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:13:49 +0900 Subject: [PATCH 06/17] ARM: shmobile: Remove unused shmobile_smp_init_cpus() Remove shmobile_smp_init_cpus() since all SMP platforms in mach-shmobile now rely on DT for CPU core description instead of for instance determining number of cores from the SCU. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/include/mach/common.h | 1 - arch/arm/mach-shmobile/platsmp.c | 15 --------------- 2 files changed, 16 deletions(-) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 1ed155eb3e92..26eaff1429bf 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -40,7 +40,6 @@ static inline int shmobile_cpuidle_init(void) { return 0; } #endif extern void __iomem *shmobile_scu_base; -extern void shmobile_smp_init_cpus(unsigned int ncores); static inline void __init shmobile_init_late(void) { diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 3741562156ed..9ebc246b8d7d 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -11,25 +11,10 @@ * published by the Free Software Foundation. */ #include -#include #include #include #include -void __init shmobile_smp_init_cpus(unsigned int ncores) -{ - unsigned int i; - - if (ncores > nr_cpu_ids) { - pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", - ncores, nr_cpu_ids); - ncores = nr_cpu_ids; - } - - for (i = 0; i < ncores; i++) - set_cpu_possible(i, true); -} - extern unsigned long shmobile_smp_fn[]; extern unsigned long shmobile_smp_arg[]; extern unsigned long shmobile_smp_mpidr[]; From 87a08ca0f7f99b3136c763377c547a89cf6d0996 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:13:58 +0900 Subject: [PATCH 07/17] ARM: shmobile: Expose shmobile_invalidate_start() Expose shmobile_invalidate_start() in common.h for mach-shmobile. This function will be used for boot of secondary processors on future non-SCU SMP platforms. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/include/mach/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 26eaff1429bf..a9df8f3bfda7 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -14,6 +14,7 @@ extern void shmobile_smp_sleep(void); extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn, unsigned long arg); extern int shmobile_smp_cpu_disable(unsigned int cpu); +extern void shmobile_invalidate_start(void); extern void shmobile_boot_scu(void); extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, From a84a5ab73f77a5dd4f09f0af33f09d8d751d0cc7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Aug 2013 07:14:07 +0900 Subject: [PATCH 08/17] ARM: shmobile: Introduce shmobile_boot_size Introduce shmobile_boot_size that can be used by future SMP code to determine the size of the boot code that needs to be copied to internal SRAM. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/headsmp.S | 3 +++ arch/arm/mach-shmobile/include/mach/common.h | 1 + 2 files changed, 4 insertions(+) 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: .globl shmobile_boot_arg shmobile_boot_arg: 2: .space 4 + .globl shmobile_boot_size +shmobile_boot_size: + .long . - shmobile_boot_vector /* * 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 a9df8f3bfda7..cfe397716fd1 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -9,6 +9,7 @@ extern void shmobile_setup_console(void); extern void shmobile_boot_vector(void); extern unsigned long shmobile_boot_fn; extern unsigned long shmobile_boot_arg; +extern unsigned long shmobile_boot_size; extern void shmobile_smp_boot(void); extern void shmobile_smp_sleep(void); extern void shmobile_smp_hook(unsigned int cpu, unsigned long fn, From a112de8c7ae231f396e28160e84d0eab3a79dffc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 29 Aug 2013 08:21:58 +0900 Subject: [PATCH 09/17] ARM: shmobile: Shared APMU SMP support code without DT Introduce shared APMU SMP code for mach-shmobile. Both SMP boot up and CPU Hotplug is supported. This version does not use DT but if needed this will be added as an incremental feature patch. The code is designed around CONFIG_NR_CPUS and should in theory support any number of APMUs, however due to the current DT-less static design only a single APMU is supported. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/include/mach/common.h | 6 + arch/arm/mach-shmobile/platsmp-apmu.c | 178 +++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 arch/arm/mach-shmobile/platsmp-apmu.c diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index cfe397716fd1..3460bb13c988 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -22,6 +22,12 @@ extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle); extern void shmobile_smp_scu_cpu_die(unsigned int cpu); extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); +extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus); +extern int shmobile_smp_apmu_boot_secondary(unsigned int cpu, + struct task_struct *idle); +extern void shmobile_smp_apmu_cpu_die(unsigned int cpu); +extern int shmobile_smp_apmu_cpu_kill(unsigned int cpu); +extern void shmobile_invalidate_start(void); struct clk; extern int shmobile_clk_init(void); extern void shmobile_handle_irq_intc(struct pt_regs *); diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c new file mode 100644 index 000000000000..34dc40dacb79 --- /dev/null +++ b/arch/arm/mach-shmobile/platsmp-apmu.c @@ -0,0 +1,178 @@ +/* + * SMP support for SoCs with APMU + * + * Copyright (C) 2013 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct { + void __iomem *iomem; + int bit; +} apmu_cpus[CONFIG_NR_CPUS]; + +#define WUPCR_OFFS 0x10 +#define PSTR_OFFS 0x40 +#define CPUNCR_OFFS(n) (0x100 + (0x10 * (n))) + +static int apmu_power_on(void __iomem *p, int bit) +{ + /* request power on */ + writel_relaxed(BIT(bit), p + WUPCR_OFFS); + + /* wait for APMU to finish */ + while (readl_relaxed(p + WUPCR_OFFS) != 0) + ; + + return 0; +} + +static int apmu_power_off(void __iomem *p, int bit) +{ + /* request Core Standby for next WFI */ + writel_relaxed(3, p + CPUNCR_OFFS(bit)); + return 0; +} + +static int apmu_power_off_poll(void __iomem *p, int bit) +{ + int k; + + for (k = 0; k < 1000; k++) { + if (((readl_relaxed(p + PSTR_OFFS) >> (bit * 4)) & 0x03) == 3) + return 1; + + mdelay(1); + } + + return 0; +} + +static int apmu_wrap(int cpu, int (*fn)(void __iomem *p, int cpu)) +{ + void __iomem *p = apmu_cpus[cpu].iomem; + + return p ? fn(p, apmu_cpus[cpu].bit) : -EINVAL; +} + +static void apmu_init_cpu(struct resource *res, int cpu, int bit) +{ + if (apmu_cpus[cpu].iomem) + return; + + apmu_cpus[cpu].iomem = ioremap_nocache(res->start, resource_size(res)); + apmu_cpus[cpu].bit = bit; + + pr_debug("apmu ioremap %d %d 0x%08x 0x%08x\n", cpu, bit, + res->start, resource_size(res)); +} + +static struct { + struct resource iomem; + int cpus[4]; +} apmu_config[] = { + { + .iomem = DEFINE_RES_MEM(0xe6152000, 0x88), + .cpus = { 0, 1, 2, 3 }, + } +}; + +static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit)) +{ + u32 id; + int k; + int bit, index; + + for (k = 0; k < ARRAY_SIZE(apmu_config); k++) { + for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) { + id = apmu_config[k].cpus[bit]; + if (id >= 0) { + index = get_logical_index(id); + if (index >= 0) + fn(&apmu_config[k].iomem, index, bit); + } + } + } +} + +void __init shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus) +{ + /* install boot code shared by all CPUs */ + shmobile_boot_fn = virt_to_phys(shmobile_smp_boot); + shmobile_boot_arg = MPIDR_HWID_BITMASK; + + /* perform per-cpu setup */ + apmu_parse_cfg(apmu_init_cpu); +} + +int shmobile_smp_apmu_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + /* For this particular CPU register boot vector */ + shmobile_smp_hook(cpu, virt_to_phys(shmobile_invalidate_start), 0); + + return apmu_wrap(cpu, apmu_power_on); +} + +#ifdef CONFIG_HOTPLUG_CPU +/* nicked from arch/arm/mach-exynos/hotplug.c */ +static inline void cpu_enter_lowpower_a15(void) +{ + unsigned int v; + + asm volatile( + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "Ir" (CR_C) + : "cc"); + + flush_cache_louis(); + + asm volatile( + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (0x40) + : "cc"); + + isb(); + dsb(); +} + +void shmobile_smp_apmu_cpu_die(unsigned int cpu) +{ + /* For this particular CPU deregister boot vector */ + shmobile_smp_hook(cpu, 0, 0); + + /* Select next sleep mode using the APMU */ + apmu_wrap(cpu, apmu_power_off); + + /* Do ARM specific CPU shutdown */ + cpu_enter_lowpower_a15(); + + /* jump to shared mach-shmobile sleep / reset code */ + shmobile_smp_sleep(); +} + +int shmobile_smp_apmu_cpu_kill(unsigned int cpu) +{ + return apmu_wrap(cpu, apmu_power_off_poll); +} +#endif From ad09cb83811b228eb6f98230d307bb837e6a758f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 29 Aug 2013 08:22:07 +0900 Subject: [PATCH 10/17] ARM: shmobile: Add r8a7790 SMP support using APMU code Add r8a7790 SMP support using the shared APMU code. To enable SMP the r8a7790 specific DTS needs to be updated to include CPU cores, and this is happening in a separate patch. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/Makefile | 1 + .../arm/mach-shmobile/board-lager-reference.c | 1 + arch/arm/mach-shmobile/board-lager.c | 1 + arch/arm/mach-shmobile/include/mach/r8a7790.h | 1 + arch/arm/mach-shmobile/setup-r8a7790.c | 1 + arch/arm/mach-shmobile/smp-r8a7790.c | 67 +++++++++++++++++++ 6 files changed, 72 insertions(+) create mode 100644 arch/arm/mach-shmobile/smp-r8a7790.c diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 2705bfa8c113..381fc97ef0f5 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile @@ -34,6 +34,7 @@ endif smp-y := platsmp.o headsmp.o smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o platsmp-scu.o smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o platsmp-scu.o +smp-$(CONFIG_ARCH_R8A7790) += smp-r8a7790.o platsmp-apmu.o smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o platsmp-scu.o # IRQ objects diff --git a/arch/arm/mach-shmobile/board-lager-reference.c b/arch/arm/mach-shmobile/board-lager-reference.c index 2856f51ff8a6..d39a91b3ba48 100644 --- a/arch/arm/mach-shmobile/board-lager-reference.c +++ b/arch/arm/mach-shmobile/board-lager-reference.c @@ -38,6 +38,7 @@ static const char *lager_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(LAGER_DT, "lager") + .smp = smp_ops(r8a7790_smp_ops), .init_early = r8a7790_init_early, .init_machine = lager_add_standard_devices, .init_time = r8a7790_timer_init, diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c index 4047fac811c0..ef3baaa79e6d 100644 --- a/arch/arm/mach-shmobile/board-lager.c +++ b/arch/arm/mach-shmobile/board-lager.c @@ -161,6 +161,7 @@ static const char *lager_boards_compat_dt[] __initdata = { }; DT_MACHINE_START(LAGER_DT, "lager") + .smp = smp_ops(r8a7790_smp_ops), .init_early = r8a7790_init_early, .init_time = r8a7790_timer_init, .init_machine = lager_add_standard_devices, diff --git a/arch/arm/mach-shmobile/include/mach/r8a7790.h b/arch/arm/mach-shmobile/include/mach/r8a7790.h index 177a8372abb7..79e731c83e50 100644 --- a/arch/arm/mach-shmobile/include/mach/r8a7790.h +++ b/arch/arm/mach-shmobile/include/mach/r8a7790.h @@ -7,6 +7,7 @@ void r8a7790_clock_init(void); void r8a7790_pinmux_init(void); void r8a7790_init_early(void); void r8a7790_timer_init(void); +extern struct smp_operations r8a7790_smp_ops; #define MD(nr) BIT(nr) u32 r8a7790_read_mode_pins(void); diff --git a/arch/arm/mach-shmobile/setup-r8a7790.c b/arch/arm/mach-shmobile/setup-r8a7790.c index e0d29a265c2d..c7e24eff9ba2 100644 --- a/arch/arm/mach-shmobile/setup-r8a7790.c +++ b/arch/arm/mach-shmobile/setup-r8a7790.c @@ -283,6 +283,7 @@ static const char * const r8a7790_boards_compat_dt[] __initconst = { }; DT_MACHINE_START(R8A7790_DT, "Generic R8A7790 (Flattened Device Tree)") + .smp = smp_ops(r8a7790_smp_ops), .init_early = r8a7790_init_early, .init_time = r8a7790_timer_init, .dt_compat = r8a7790_boards_compat_dt, 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 @@ +/* + * SMP support for r8a7790 + * + * Copyright (C) 2012-2013 Renesas Solutions Corp. + * Copyright (C) 2012 Takashi Yoshii + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#include +#include +#include +#include +#include +#include + +#define RST 0xe6160000 +#define CA15BAR 0x0020 +#define CA7BAR 0x0030 +#define CA15RESCNT 0x0040 +#define CA7RESCNT 0x0044 +#define MERAM 0xe8080000 + +static void __init r8a7790_smp_prepare_cpus(unsigned int max_cpus) +{ + void __iomem *p; + u32 bar; + + /* let APMU code install data related to shmobile_boot_vector */ + shmobile_smp_apmu_prepare_cpus(max_cpus); + + /* MERAM for jump stub, because BAR requires 256KB aligned address */ + p = ioremap_nocache(MERAM, shmobile_boot_size); + memcpy_toio(p, shmobile_boot_vector, shmobile_boot_size); + iounmap(p); + + /* setup reset vectors */ + p = ioremap_nocache(RST, 0x63); + bar = (MERAM >> 8) & 0xfffffc00; + writel_relaxed(bar, p + CA15BAR); + writel_relaxed(bar, p + CA7BAR); + writel_relaxed(bar | 0x10, p + CA15BAR); + writel_relaxed(bar | 0x10, p + CA7BAR); + + /* enable clocks to all CPUs */ + writel_relaxed((readl_relaxed(p + CA15RESCNT) & ~0x0f) | 0xa5a50000, + p + CA15RESCNT); + writel_relaxed((readl_relaxed(p + CA7RESCNT) & ~0x0f) | 0x5a5a0000, + p + CA7RESCNT); + iounmap(p); +} + +struct smp_operations r8a7790_smp_ops __initdata = { + .smp_prepare_cpus = r8a7790_smp_prepare_cpus, + .smp_boot_secondary = shmobile_smp_apmu_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_disable = shmobile_smp_cpu_disable, + .cpu_die = shmobile_smp_apmu_cpu_die, + .cpu_kill = shmobile_smp_apmu_cpu_kill, +#endif +}; From 916d6121b5947f162979595cc1c0396192a9aa86 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 14 Sep 2013 22:46:25 +0900 Subject: [PATCH 11/17] ARM: shmobile: Add CPU notifier based SCU boot vector code Add CPU notifiers for the shared mach-shmobile SCU code to allow removal of the shared SCU boot_secondary code. Regarding notifiers, at CPU_UP_PREPARE time the SMP boot vector is initialized so secondary CPU cores can boot. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/platsmp-scu.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c index c96f50160be6..49ae8dfc625d 100644 --- a/arch/arm/mach-shmobile/platsmp-scu.c +++ b/arch/arm/mach-shmobile/platsmp-scu.c @@ -7,6 +7,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -16,6 +17,26 @@ #include #include +static int shmobile_smp_scu_notifier_call(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + unsigned int cpu = (long)hcpu; + + switch (action) { + case CPU_UP_PREPARE: + /* For this particular CPU register SCU SMP boot vector */ + shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu), + (unsigned long)shmobile_scu_base); + break; + }; + + return NOTIFY_OK; +} + +static struct notifier_block shmobile_smp_scu_notifier = { + .notifier_call = shmobile_smp_scu_notifier_call, +}; + void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus) { /* install boot code shared by all CPUs */ @@ -25,6 +46,9 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus) /* enable SCU and cache coherency on booting CPU */ scu_enable(shmobile_scu_base); scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL); + + /* Use CPU notifier for reset vector control */ + register_cpu_notifier(&shmobile_smp_scu_notifier); } int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle) From 344bc8b0c85a63cd2d946376a391e74f4ea0ae46 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 14 Sep 2013 22:46:34 +0900 Subject: [PATCH 12/17] ARM: shmobile: Let sh73a0 rely on SCU CPU notifier Now when CPU notifiers are used for SCU boot vector setup shmobile_smp_scu_boot_secondary() is no longer needed. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/smp-sh73a0.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 9a30a3fc7e7d..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) static int sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned int lcpu = cpu_logical_map(cpu); - int ret; - - ret = shmobile_smp_scu_boot_secondary(cpu, idle); - if (ret) - return ret; if (((__raw_readl(PSTR) >> (4 * lcpu)) & 3) == 3) __raw_writel(1 << lcpu, WUPCR); /* wake up */ From 344c62f7a65f9124d5262e34dab66d581081a3a7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 14 Sep 2013 22:46:43 +0900 Subject: [PATCH 13/17] ARM: shmobile: Let EMEV2 rely on SCU CPU notifier Now when CPU notifiers are used for SCU boot vector setup shmobile_smp_scu_boot_secondary() is no longer needed. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/smp-emev2.c | 6 ------ 1 file changed, 6 deletions(-) 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 @@ static int emev2_boot_secondary(unsigned int cpu, struct task_struct *idle) { - int ret; - - ret = shmobile_smp_scu_boot_secondary(cpu, idle); - if (ret) - return ret; - arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu))); return 0; } From deb4928ea39c5eeef1c9f4562b5cee71f06a31ad Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 14 Sep 2013 22:46:52 +0900 Subject: [PATCH 14/17] ARM: shmobile: Let r8a7779 rely on SCU CPU notifier Now when CPU notifiers are used for SCU boot vector setup shmobile_smp_scu_boot_secondary() is no longer needed. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/smp-r8a7779.c | 4 ---- 1 file changed, 4 deletions(-) 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) unsigned int lcpu = cpu_logical_map(cpu); int ret; - ret = shmobile_smp_scu_boot_secondary(cpu, idle); - if (ret) - return ret; - if (lcpu < ARRAY_SIZE(r8a7779_ch_cpu)) ch = r8a7779_ch_cpu[lcpu]; From e4550216ef8245b1c9892239a2121a7b15ac2e91 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sat, 14 Sep 2013 22:47:02 +0900 Subject: [PATCH 15/17] ARM: shmobile: Remove shmobile_smp_scu_boot_secondary() Remove shmobile_smp_scu_boot_secondary() since it is no longer used. CPU boot vector setup is instead handled by CPU notifiers. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/include/mach/common.h | 2 -- arch/arm/mach-shmobile/platsmp-scu.c | 8 -------- 2 files changed, 10 deletions(-) diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index 3460bb13c988..e31980590eb4 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h @@ -18,8 +18,6 @@ extern int shmobile_smp_cpu_disable(unsigned int cpu); extern void shmobile_invalidate_start(void); extern void shmobile_boot_scu(void); extern void shmobile_smp_scu_prepare_cpus(unsigned int max_cpus); -extern int shmobile_smp_scu_boot_secondary(unsigned int cpu, - struct task_struct *idle); extern void shmobile_smp_scu_cpu_die(unsigned int cpu); extern int shmobile_smp_scu_cpu_kill(unsigned int cpu); extern void shmobile_smp_apmu_prepare_cpus(unsigned int max_cpus); diff --git a/arch/arm/mach-shmobile/platsmp-scu.c b/arch/arm/mach-shmobile/platsmp-scu.c index 49ae8dfc625d..673ad6e80869 100644 --- a/arch/arm/mach-shmobile/platsmp-scu.c +++ b/arch/arm/mach-shmobile/platsmp-scu.c @@ -51,14 +51,6 @@ void __init shmobile_smp_scu_prepare_cpus(unsigned int max_cpus) register_cpu_notifier(&shmobile_smp_scu_notifier); } -int shmobile_smp_scu_boot_secondary(unsigned int cpu, struct task_struct *idle) -{ - /* For this particular CPU register SCU boot vector */ - shmobile_smp_hook(cpu, virt_to_phys(shmobile_boot_scu), - (unsigned long)shmobile_scu_base); - return 0; -} - #ifdef CONFIG_HOTPLUG_CPU void shmobile_smp_scu_cpu_die(unsigned int cpu) { From ee490bcc4f2d456c40df93236cf6a1bce2d5ddd0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sun, 15 Sep 2013 00:29:07 +0900 Subject: [PATCH 16/17] ARM: shmobile: Extend APMU code to allow single cluster only Extend the APMU code with a check to only allow boot of CPU cores that sit in the same cluster as CPU0. This makes it possible for people to use the r8a790 CA7 boot mode with CA7-cores only. The default CA15 boot mode will enable CA15 cores only. This is an intentional software limitation to cope with lacking scheduler support. By removing this patch it is possible to run all 8 cores in parallel, but this is not recommended without out of tree scheduler modfications or custom user space code to control the CPU affinitiy. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/platsmp-apmu.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c index 34dc40dacb79..caaaa35b589f 100644 --- a/arch/arm/mach-shmobile/platsmp-apmu.c +++ b/arch/arm/mach-shmobile/platsmp-apmu.c @@ -94,8 +94,21 @@ static void apmu_parse_cfg(void (*fn)(struct resource *res, int cpu, int bit)) u32 id; int k; int bit, index; + bool is_allowed; for (k = 0; k < ARRAY_SIZE(apmu_config); k++) { + /* only enable the cluster that includes the boot CPU */ + is_allowed = false; + for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) { + id = apmu_config[k].cpus[bit]; + if (id >= 0) { + if (id == cpu_logical_map(0)) + is_allowed = true; + } + } + if (!is_allowed) + continue; + for (bit = 0; bit < ARRAY_SIZE(apmu_config[k].cpus); bit++) { id = apmu_config[k].cpus[bit]; if (id >= 0) { From 43651b15de94d6a5e188ea032311e9661ec708d2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sun, 15 Sep 2013 00:29:16 +0900 Subject: [PATCH 17/17] ARM: shmobile: Include CA7 cores in APMU table Add information to the shared APMU code regarding the APMU instance used to control the CA7 cores. This can be used on r8a7790 and r8a73a4, but should most likely be converted to DT in the future. Signed-off-by: Magnus Damm Signed-off-by: Simon Horman --- arch/arm/mach-shmobile/platsmp-apmu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-shmobile/platsmp-apmu.c b/arch/arm/mach-shmobile/platsmp-apmu.c index caaaa35b589f..1da5a72d9642 100644 --- a/arch/arm/mach-shmobile/platsmp-apmu.c +++ b/arch/arm/mach-shmobile/platsmp-apmu.c @@ -86,6 +86,10 @@ static struct { { .iomem = DEFINE_RES_MEM(0xe6152000, 0x88), .cpus = { 0, 1, 2, 3 }, + }, + { + .iomem = DEFINE_RES_MEM(0xe6151000, 0x88), + .cpus = { 0x100, 0x101, 0x102, 0x103 }, } };