summaryrefslogtreecommitdiff
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 20:31:45 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 20:31:45 +0400
commit97b1007a2924aaa9126398623f6755a8c3c6a616 (patch)
treeb65c6edb631256e64bb3c72f083fa1be048de097 /arch/arm/mach-shmobile
parentdfab34aa61a0f8c14a67d7b4c1dae28e57ba592d (diff)
parente0d20b69d3fa74a21ec363989612bddd58b930b8 (diff)
downloadlinux-97b1007a2924aaa9126398623f6755a8c3c6a616.tar.xz
Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates from Olof Johansson: "This branch contains part 1 of the platform updates for 3.10. Among the highlights: - Support for the new Atmel Cortex-A5 based platforms (SAMA5D3) - New support for CSR SiRFatlas6 SoCs - A handful of updates for NVidia T114 (a.k.a. Tegra 4) - A bunch of updates for the shmobile platforms - A handful of updates for davinci - A few updates for Qualcomm MSM - Plus a handful of other patches, defconfig updates, etc." * tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (135 commits) ARM: tegra: pm: fix build error w/o PM_SLEEP ARM: davinci: ensure global variables are declared ARM: davinci: sram.c: fix incorrect type in assignment ARM: davinci: da8xx dt: make file local symbols static ARM: davinci: da8xx: add remoteproc support ARM: socfpga: Upgrade clk driver for socfpga to make use of dts clock entries ARM: socfpga: Add clock entries into device tree ARM: socfpga: Enable soft reset ARM: EXYNOS: replace cpumask by the corresponding macro ARM: EXYNOS: handle properly the return values ARM: EXYNOS: factor out the idle states ARM: OMAP4: Enable fix for Cortex-A9 erratas ARM: OMAP2+: Export SoC information to userspace ARM: OMAP2+: SoC name and revision unification ARM: OMAP2+: Move common part of late init into common function ARM: tegra: pm: remove duplicated include from pm.c ARM: davinci: da850: override mmc DT node device name ARM: davinci: da850: add mmc DT entries mmc: davinci_mmc: add DT support ARM: SAMSUNG: check processor type before cache restoration in resume ...
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Makefile7
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7740.c13
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7779.c8
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c7
-rw-r--r--arch/arm/mach-shmobile/headsmp-scu.S (renamed from arch/arm/mach-shmobile/headsmp-sh73a0.S)15
-rw-r--r--arch/arm/mach-shmobile/hotplug.c68
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h21
-rw-r--r--arch/arm/mach-shmobile/include/mach/irqs.h1
-rw-r--r--arch/arm/mach-shmobile/intc-r8a7779.c27
-rw-r--r--arch/arm/mach-shmobile/intc-sh73a0.c8
-rw-r--r--arch/arm/mach-shmobile/setup-emev2.c4
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7779.c104
-rw-r--r--arch/arm/mach-shmobile/setup-sh73a0.c36
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c86
-rw-r--r--arch/arm/mach-shmobile/smp-r8a7779.c129
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c36
16 files changed, 257 insertions, 313 deletions
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index e1fac57514b9..b646ff4d742a 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -14,10 +14,9 @@ obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o
# SMP objects
smp-y := platsmp.o headsmp.o
-smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o
-smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
-smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
+smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o headsmp-scu.o
+smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o headsmp-scu.o
# IRQ objects
obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 19ce885a3b43..1feb9a2286a8 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -593,29 +593,42 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]),
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]),
+ CLKDEV_DEV_ID("e6c80000.sci", &mstp_clks[MSTP200]),
CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[MSTP201]),
+ CLKDEV_DEV_ID("e6c70000.sci", &mstp_clks[MSTP201]),
CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP202]),
+ CLKDEV_DEV_ID("e6c60000.sci", &mstp_clks[MSTP202]),
CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
+ CLKDEV_DEV_ID("e6c50000.sci", &mstp_clks[MSTP203]),
CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
+ CLKDEV_DEV_ID("e6c40000.sci", &mstp_clks[MSTP204]),
CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]),
+ CLKDEV_DEV_ID("e6c30000.sci", &mstp_clks[MSTP206]),
CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]),
+ CLKDEV_DEV_ID("e6cb0000.sci", &mstp_clks[MSTP207]),
CLKDEV_DEV_ID("sh-dma-engine.3", &mstp_clks[MSTP214]),
CLKDEV_DEV_ID("sh-dma-engine.2", &mstp_clks[MSTP216]),
CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[MSTP217]),
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]),
CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP222]),
+ CLKDEV_DEV_ID("e6cd0000.sci", &mstp_clks[MSTP222]),
CLKDEV_DEV_ID("sh-sci.6", &mstp_clks[MSTP230]),
+ CLKDEV_DEV_ID("e6cc0000.sci", &mstp_clks[MSTP230]),
CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]),
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]),
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]),
CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP320]),
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]),
+ CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]),
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
+ CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]),
CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
+ CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]),
CLKDEV_DEV_ID("sh-eth", &mstp_clks[MSTP309]),
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
+ CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]),
/* ICK */
CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index 1db36537255c..d9edeaf66007 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -87,7 +87,8 @@ static struct clk div4_clks[DIV4_NR] = {
};
enum { MSTP323, MSTP322, MSTP321, MSTP320,
- MSTP101, MSTP100,
+ MSTP115,
+ MSTP103, MSTP101, MSTP100,
MSTP030,
MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
MSTP016, MSTP015, MSTP014,
@@ -99,6 +100,8 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */
[MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */
[MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */
+ [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0), /* SATA */
+ [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR1, 3, 0), /* DU */
[MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 1, 0), /* USB2 */
[MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 0, 0), /* USB0/1 */
[MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */
@@ -156,6 +159,8 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
/* MSTP32 clocks */
+ CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
+ CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
@@ -180,6 +185,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
+ CLKDEV_DEV_ID("rcar-du.0", &mstp_clks[MSTP103]), /* DU */
};
void __init r8a7779_clock_init(void)
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index afa5423a0f93..71843dd39e16 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -265,12 +265,12 @@ enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
static struct clk div4_clks[DIV4_NR] = {
[DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT),
- [DIV4_ZG] = DIV4(FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
+ [DIV4_ZG] = SH_CLK_DIV4(&pll0_clk, FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
[DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
[DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT),
[DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0),
[DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0),
- [DIV4_Z] = DIV4(FRQCRB, 24, 0x97f, 0),
+ [DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0),
[DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0),
[DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0),
[DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0),
@@ -581,10 +581,13 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */
CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+ CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+ CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
+ CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP311]), /* SDHI2 */
CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-scu.S
index bec4c0d9b713..7d113f898e7f 100644
--- a/arch/arm/mach-shmobile/headsmp-sh73a0.S
+++ b/arch/arm/mach-shmobile/headsmp-scu.S
@@ -1,5 +1,5 @@
/*
- * SMP support for SoC sh73a0
+ * Shared SCU setup for mach-shmobile
*
* Copyright (C) 2012 Bastian Hecht
*
@@ -35,11 +35,12 @@
* the physical address as the MMU is still turned off.
*/
.align 12
-ENTRY(sh73a0_secondary_vector)
+ENTRY(shmobile_secondary_vector_scu)
mrc p15, 0, r0, c0, c0, 5 @ read MIPDR
and r0, r0, #3 @ mask out cpu ID
lsl r0, r0, #3 @ we will shift by cpu_id * 8 bits
- mov r1, #0xf0000000 @ SCU base address
+ ldr r1, 2f
+ ldr r1, [r1] @ SCU base address
ldr r2, [r1, #8] @ SCU Power Status Register
mov r3, #3
bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode)
@@ -47,4 +48,10 @@ ENTRY(sh73a0_secondary_vector)
ldr pc, 1f
1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
-ENDPROC(sh73a0_secondary_vector)
+2: .long shmobile_scu_base - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ENDPROC(shmobile_secondary_vector_scu)
+
+ .text
+ .globl shmobile_scu_base
+shmobile_scu_base:
+ .space 4
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
deleted file mode 100644
index a1524e3367b0..000000000000
--- a/arch/arm/mach-shmobile/hotplug.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SMP support for R-Mobile / SH-Mobile
- *
- * Copyright (C) 2010 Magnus Damm
- *
- * Based on realview, Copyright (C) 2002 ARM Ltd, All Rights Reserved
- *
- * 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 <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <linux/cpumask.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <mach/common.h>
-#include <mach/r8a7779.h>
-#include <mach/emev2.h>
-#include <asm/cacheflush.h>
-#include <asm/mach-types.h>
-
-static cpumask_t dead_cpus;
-
-void shmobile_cpu_die(unsigned int cpu)
-{
- /* hardware shutdown code running on the CPU that is being offlined */
- flush_cache_all();
- dsb();
-
- /* notify platform_cpu_kill() that hardware shutdown is finished */
- cpumask_set_cpu(cpu, &dead_cpus);
-
- /* wait for SoC code in platform_cpu_kill() to shut off CPU core
- * power. CPU bring up starts from the reset vector.
- */
- while (1) {
- /*
- * here's the WFI
- */
- asm(".word 0xe320f003\n"
- :
- :
- : "memory", "cc");
- }
-}
-
-int shmobile_cpu_disable(unsigned int cpu)
-{
- cpumask_clear_cpu(cpu, &dead_cpus);
- /*
- * we don't allow CPU 0 to be shutdown (it is still too special
- * e.g. clock tick interrupts)
- */
- return cpu == 0 ? -EPERM : 0;
-}
-
-int shmobile_cpu_disable_any(unsigned int cpu)
-{
- cpumask_clear_cpu(cpu, &dead_cpus);
- return 0;
-}
-
-int shmobile_cpu_is_dead(unsigned int cpu)
-{
- return cpumask_test_cpu(cpu, &dead_cpus);
-}
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index 362f9b2d2c02..62c04c252418 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -8,6 +8,7 @@ extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
struct twd_local_timer;
extern void shmobile_setup_console(void);
extern void shmobile_secondary_vector(void);
+extern void shmobile_secondary_vector_scu(void);
struct clk;
extern int shmobile_clk_init(void);
extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -30,23 +31,23 @@ extern int sh7372_do_idle_sysc(unsigned long sleep_mode);
extern struct clk sh7372_extal1_clk;
extern struct clk sh7372_extal2_clk;
+extern void sh73a0_init_delay(void);
extern void sh73a0_init_irq(void);
extern void sh73a0_init_irq_dt(void);
extern void sh73a0_map_io(void);
extern void sh73a0_earlytimer_init(void);
extern void sh73a0_add_early_devices(void);
-extern void sh73a0_add_early_devices_dt(void);
extern void sh73a0_add_standard_devices(void);
extern void sh73a0_add_standard_devices_dt(void);
extern void sh73a0_clock_init(void);
extern void sh73a0_pinmux_init(void);
extern void sh73a0_pm_init(void);
-extern void sh73a0_secondary_vector(void);
extern struct clk sh73a0_extal1_clk;
extern struct clk sh73a0_extal2_clk;
extern struct clk sh73a0_extcki_clk;
extern struct clk sh73a0_extalr_clk;
+extern void r8a7740_meram_workaround(void);
extern void r8a7740_init_irq(void);
extern void r8a7740_map_io(void);
extern void r8a7740_add_early_devices(void);
@@ -55,16 +56,17 @@ extern void r8a7740_clock_init(u8 md_ck);
extern void r8a7740_pinmux_init(void);
extern void r8a7740_pm_init(void);
+extern void r8a7779_init_delay(void);
extern void r8a7779_init_irq(void);
+extern void r8a7779_init_irq_dt(void);
extern void r8a7779_map_io(void);
extern void r8a7779_earlytimer_init(void);
extern void r8a7779_add_early_devices(void);
extern void r8a7779_add_standard_devices(void);
+extern void r8a7779_add_standard_devices_dt(void);
extern void r8a7779_clock_init(void);
extern void r8a7779_pinmux_init(void);
extern void r8a7779_pm_init(void);
-extern void r8a7740_meram_workaround(void);
-
extern void r8a7779_register_twd(void);
#ifdef CONFIG_SUSPEND
@@ -79,16 +81,7 @@ int shmobile_cpuidle_init(void);
static inline int shmobile_cpuidle_init(void) { return 0; }
#endif
-extern void shmobile_cpu_die(unsigned int cpu);
-extern int shmobile_cpu_disable(unsigned int cpu);
-extern int shmobile_cpu_disable_any(unsigned int cpu);
-
-#ifdef CONFIG_HOTPLUG_CPU
-extern int shmobile_cpu_is_dead(unsigned int cpu);
-#else
-static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
-#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/include/mach/irqs.h b/arch/arm/mach-shmobile/include/mach/irqs.h
index 06a5da3c3050..992ed213cec1 100644
--- a/arch/arm/mach-shmobile/include/mach/irqs.h
+++ b/arch/arm/mach-shmobile/include/mach/irqs.h
@@ -5,6 +5,7 @@
/* GIC */
#define gic_spi(nr) ((nr) + 32)
+#define gic_iid(nr) (nr) /* ICCIAR / interrupt ID */
/* INTCS */
#define INTCS_VECT_BASE 0x3400
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
index 8807c27f71f9..f9cc4bc9c798 100644
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
@@ -24,6 +24,7 @@
#include <linux/io.h>
#include <linux/irqchip/arm-gic.h>
#include <mach/common.h>
+#include <linux/irqchip.h>
#include <mach/intc.h>
#include <mach/r8a7779.h>
#include <asm/mach-types.h>
@@ -43,13 +44,8 @@ static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
return 0; /* always allow wakeup */
}
-void __init r8a7779_init_irq(void)
+static void __init r8a7779_init_irq_common(void)
{
- void __iomem *gic_dist_base = IOMEM(0xf0001000);
- void __iomem *gic_cpu_base = IOMEM(0xf0000100);
-
- /* use GIC to handle interrupts */
- gic_init(0, 29, gic_dist_base, gic_cpu_base);
gic_arch_extn.irq_set_wake = r8a7779_set_wake;
/* route all interrupts to ARM */
@@ -63,3 +59,22 @@ void __init r8a7779_init_irq(void)
__raw_writel(0xbffffffc, INT2SMSKCR3);
__raw_writel(0x003fee3f, INT2SMSKCR4);
}
+
+void __init r8a7779_init_irq(void)
+{
+ void __iomem *gic_dist_base = IOMEM(0xf0001000);
+ void __iomem *gic_cpu_base = IOMEM(0xf0000100);
+
+ /* use GIC to handle interrupts */
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+ r8a7779_init_irq_common();
+}
+
+#ifdef CONFIG_OF
+void __init r8a7779_init_irq_dt(void)
+{
+ irqchip_init();
+ r8a7779_init_irq_common();
+}
+#endif
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 91faba666d46..a81a1d804e2e 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -460,11 +460,3 @@ void __init sh73a0_init_irq(void)
sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
}
-
-#ifdef CONFIG_OF
-void __init sh73a0_init_irq_dt(void)
-{
- irqchip_init();
- gic_arch_extn.irq_set_wake = sh73a0_set_wake;
-}
-#endif
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index 47662a581c0a..e4545c152722 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -404,7 +404,7 @@ void __init emev2_add_standard_devices(void)
ARRAY_SIZE(emev2_late_devices));
}
-void __init emev2_init_delay(void)
+static void __init emev2_init_delay(void)
{
shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
}
@@ -439,7 +439,7 @@ static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
{ }
};
-void __init emev2_add_standard_devices_dt(void)
+static void __init emev2_add_standard_devices_dt(void)
{
of_platform_populate(NULL, of_default_bus_match_table,
emev2_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index c54ff9b29fe5..042df35e71a0 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/input.h>
@@ -28,6 +29,7 @@
#include <linux/serial_sci.h>
#include <linux/sh_intc.h>
#include <linux/sh_timer.h>
+#include <linux/dma-mapping.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/r8a7779.h>
@@ -91,7 +93,7 @@ static struct plat_sci_port scif0_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = SCIx_IRQ_MUXED(gic_spi(88)),
+ .irqs = SCIx_IRQ_MUXED(gic_iid(0x78)),
};
static struct platform_device scif0_device = {
@@ -108,7 +110,7 @@ static struct plat_sci_port scif1_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = SCIx_IRQ_MUXED(gic_spi(89)),
+ .irqs = SCIx_IRQ_MUXED(gic_iid(0x79)),
};
static struct platform_device scif1_device = {
@@ -125,7 +127,7 @@ static struct plat_sci_port scif2_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = SCIx_IRQ_MUXED(gic_spi(90)),
+ .irqs = SCIx_IRQ_MUXED(gic_iid(0x7a)),
};
static struct platform_device scif2_device = {
@@ -142,7 +144,7 @@ static struct plat_sci_port scif3_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = SCIx_IRQ_MUXED(gic_spi(91)),
+ .irqs = SCIx_IRQ_MUXED(gic_iid(0x7b)),
};
static struct platform_device scif3_device = {
@@ -159,7 +161,7 @@ static struct plat_sci_port scif4_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = SCIx_IRQ_MUXED(gic_spi(92)),
+ .irqs = SCIx_IRQ_MUXED(gic_iid(0x7c)),
};
static struct platform_device scif4_device = {
@@ -176,7 +178,7 @@ static struct plat_sci_port scif5_platform_data = {
.scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
.scbrr_algo_id = SCBRR_ALGO_2,
.type = PORT_SCIF,
- .irqs = SCIx_IRQ_MUXED(gic_spi(93)),
+ .irqs = SCIx_IRQ_MUXED(gic_iid(0x7d)),
};
static struct platform_device scif5_device = {
@@ -203,7 +205,7 @@ static struct resource tmu00_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = gic_spi(32),
+ .start = gic_iid(0x40),
.flags = IORESOURCE_IRQ,
},
};
@@ -233,7 +235,7 @@ static struct resource tmu01_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = gic_spi(33),
+ .start = gic_iid(0x41),
.flags = IORESOURCE_IRQ,
},
};
@@ -255,7 +257,7 @@ static struct resource rcar_i2c0_res[] = {
.end = 0xffc70fff,
.flags = IORESOURCE_MEM,
}, {
- .start = gic_spi(79),
+ .start = gic_iid(0x6f),
.flags = IORESOURCE_IRQ,
},
};
@@ -273,7 +275,7 @@ static struct resource rcar_i2c1_res[] = {
.end = 0xffc71fff,
.flags = IORESOURCE_MEM,
}, {
- .start = gic_spi(82),
+ .start = gic_iid(0x72),
.flags = IORESOURCE_IRQ,
},
};
@@ -291,7 +293,7 @@ static struct resource rcar_i2c2_res[] = {
.end = 0xffc72fff,
.flags = IORESOURCE_MEM,
}, {
- .start = gic_spi(80),
+ .start = gic_iid(0x70),
.flags = IORESOURCE_IRQ,
},
};
@@ -309,7 +311,7 @@ static struct resource rcar_i2c3_res[] = {
.end = 0xffc73fff,
.flags = IORESOURCE_MEM,
}, {
- .start = gic_spi(81),
+ .start = gic_iid(0x71),
.flags = IORESOURCE_IRQ,
},
};
@@ -321,7 +323,31 @@ static struct platform_device i2c3_device = {
.num_resources = ARRAY_SIZE(rcar_i2c3_res),
};
-static struct platform_device *r8a7779_early_devices[] __initdata = {
+static struct resource sata_resources[] = {
+ [0] = {
+ .name = "rcar-sata",
+ .start = 0xfc600000,
+ .end = 0xfc601fff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = gic_iid(0x84),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sata_device = {
+ .name = "sata_rcar",
+ .id = -1,
+ .resource = sata_resources,
+ .num_resources = ARRAY_SIZE(sata_resources),
+ .dev = {
+ .dma_mask = &sata_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static struct platform_device *r8a7779_devices_dt[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
@@ -330,13 +356,14 @@ static struct platform_device *r8a7779_early_devices[] __initdata = {
&scif5_device,
&tmu00_device,
&tmu01_device,
+};
+
+static struct platform_device *r8a7779_late_devices[] __initdata = {
&i2c0_device,
&i2c1_device,
&i2c2_device,
&i2c3_device,
-};
-
-static struct platform_device *r8a7779_late_devices[] __initdata = {
+ &sata_device,
};
void __init r8a7779_add_standard_devices(void)
@@ -349,8 +376,8 @@ void __init r8a7779_add_standard_devices(void)
r8a7779_init_pm_domains();
- platform_add_devices(r8a7779_early_devices,
- ARRAY_SIZE(r8a7779_early_devices));
+ platform_add_devices(r8a7779_devices_dt,
+ ARRAY_SIZE(r8a7779_devices_dt));
platform_add_devices(r8a7779_late_devices,
ARRAY_SIZE(r8a7779_late_devices));
}
@@ -367,8 +394,8 @@ void __init r8a7779_earlytimer_init(void)
void __init r8a7779_add_early_devices(void)
{
- early_platform_add_devices(r8a7779_early_devices,
- ARRAY_SIZE(r8a7779_early_devices));
+ early_platform_add_devices(r8a7779_devices_dt,
+ ARRAY_SIZE(r8a7779_devices_dt));
/* Early serial console setup is not included here due to
* memory map collisions. The SCIF serial ports in r8a7779
@@ -386,3 +413,40 @@ void __init r8a7779_add_early_devices(void)
* command line in case of the marzen board.
*/
}
+
+#ifdef CONFIG_USE_OF
+void __init r8a7779_init_delay(void)
+{
+ shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
+}
+
+static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = {
+ {},
+};
+
+void __init r8a7779_add_standard_devices_dt(void)
+{
+ /* clocks are setup late during boot in the case of DT */
+ r8a7779_clock_init();
+
+ platform_add_devices(r8a7779_devices_dt,
+ ARRAY_SIZE(r8a7779_devices_dt));
+ of_platform_populate(NULL, of_default_bus_match_table,
+ r8a7779_auxdata_lookup, NULL);
+}
+
+static const char *r8a7779_compat_dt[] __initdata = {
+ "renesas,r8a7779",
+ NULL,
+};
+
+DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
+ .map_io = r8a7779_map_io,
+ .init_early = r8a7779_init_delay,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = r8a7779_init_irq_dt,
+ .init_machine = r8a7779_add_standard_devices_dt,
+ .init_time = shmobile_timer_init,
+ .dt_compat = r8a7779_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index bdab575f88bc..2257a915746d 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/irqchip.h>
#include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/delay.h>
@@ -810,7 +811,7 @@ static struct platform_device ipmmu_device = {
.num_resources = ARRAY_SIZE(ipmmu_resources),
};
-static struct platform_device *sh73a0_early_devices_dt[] __initdata = {
+static struct platform_device *sh73a0_devices_dt[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
@@ -847,8 +848,8 @@ void __init sh73a0_add_standard_devices(void)
/* Clear software reset bit on SY-DMAC module */
__raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2);
- platform_add_devices(sh73a0_early_devices_dt,
- ARRAY_SIZE(sh73a0_early_devices_dt));
+ platform_add_devices(sh73a0_devices_dt,
+ ARRAY_SIZE(sh73a0_devices_dt));
platform_add_devices(sh73a0_early_devices,
ARRAY_SIZE(sh73a0_early_devices));
platform_add_devices(sh73a0_late_devices,
@@ -867,8 +868,8 @@ void __init sh73a0_earlytimer_init(void)
void __init sh73a0_add_early_devices(void)
{
- early_platform_add_devices(sh73a0_early_devices_dt,
- ARRAY_SIZE(sh73a0_early_devices_dt));
+ early_platform_add_devices(sh73a0_devices_dt,
+ ARRAY_SIZE(sh73a0_devices_dt));
early_platform_add_devices(sh73a0_early_devices,
ARRAY_SIZE(sh73a0_early_devices));
@@ -878,23 +879,9 @@ void __init sh73a0_add_early_devices(void)
#ifdef CONFIG_USE_OF
-/* Please note that the clock initialisation shcheme used in
- * sh73a0_add_early_devices_dt() and sh73a0_add_standard_devices_dt()
- * does not work with SMP as there is a yet to be resolved lock-up in
- * workqueue initialisation.
- *
- * CONFIG_SMP should be disabled when using this code.
- */
-
-void __init sh73a0_add_early_devices_dt(void)
+void __init sh73a0_init_delay(void)
{
shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */
-
- early_platform_add_devices(sh73a0_early_devices_dt,
- ARRAY_SIZE(sh73a0_early_devices_dt));
-
- /* setup early console here as well */
- shmobile_setup_console();
}
static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
@@ -906,8 +893,8 @@ void __init sh73a0_add_standard_devices_dt(void)
/* clocks are setup late during boot in the case of DT */
sh73a0_clock_init();
- platform_add_devices(sh73a0_early_devices_dt,
- ARRAY_SIZE(sh73a0_early_devices_dt));
+ platform_add_devices(sh73a0_devices_dt,
+ ARRAY_SIZE(sh73a0_devices_dt));
of_platform_populate(NULL, of_default_bus_match_table,
sh73a0_auxdata_lookup, NULL);
}
@@ -918,10 +905,11 @@ static const char *sh73a0_boards_compat_dt[] __initdata = {
};
DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
+ .smp = smp_ops(sh73a0_smp_ops),
.map_io = sh73a0_map_io,
- .init_early = sh73a0_add_early_devices_dt,
+ .init_early = sh73a0_init_delay,
.nr_irqs = NR_IRQS_LEGACY,
- .init_irq = sh73a0_init_irq_dt,
+ .init_irq = irqchip_init,
.init_machine = sh73a0_add_standard_devices_dt,
.init_time = shmobile_timer_init,
.dt_compat = sh73a0_boards_compat_dt,
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index 384e27dd3601..e38691b4d0dd 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -27,90 +27,35 @@
#include <mach/emev2.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
-#include <asm/cacheflush.h>
#define EMEV2_SCU_BASE 0x1e000000
-static DEFINE_SPINLOCK(scu_lock);
-static void __iomem *scu_base;
-
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
- unsigned long tmp;
-
- /* we assume this code is running on a different cpu
- * than the one that is changing coherency setting */
- spin_lock(&scu_lock);
- tmp = readl(scu_base + 8);
- tmp &= ~clr;
- tmp |= set;
- writel(tmp, scu_base + 8);
- spin_unlock(&scu_lock);
-
-}
-
-static unsigned int __init emev2_get_core_count(void)
-{
- if (!scu_base) {
- scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
- emev2_clock_init(); /* need ioremapped SMU */
- }
-
- WARN_ON_ONCE(!scu_base);
-
- return scu_base ? scu_get_core_count(scu_base) : 1;
-}
-
-static int emev2_platform_cpu_kill(unsigned int cpu)
-{
- return 0; /* not supported yet */
-}
-
-static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
-{
- int k;
-
- /* this function is running on another CPU than the offline target,
- * here we need wait for shutdown code in platform_cpu_die() to
- * finish before asking SoC-specific code to power off the CPU core.
- */
- for (k = 0; k < 1000; k++) {
- if (shmobile_cpu_is_dead(cpu))
- return emev2_platform_cpu_kill(cpu);
- mdelay(1);
- }
-
- return 0;
-}
-
-
static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
- cpu = cpu_logical_map(cpu);
-
- /* enable cache coherency */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
- /* Tell ROM loader about our vector (in headsmp.S) */
- emev2_set_boot_vector(__pa(shmobile_secondary_vector));
-
- arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
return 0;
}
static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
{
- int cpu = cpu_logical_map(0);
+ scu_enable(shmobile_scu_base);
- scu_enable(scu_base);
+ /* Tell ROM loader about our vector (in headsmp-scu.S) */
+ emev2_set_boot_vector(__pa(shmobile_secondary_vector_scu));
- /* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
+ /* enable cache coherency on booting CPU */
+ scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
}
static void __init emev2_smp_init_cpus(void)
{
- unsigned int ncores = emev2_get_core_count();
+ unsigned int ncores;
+
+ /* setup EMEV2 specific SCU base */
+ shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
+ emev2_clock_init(); /* need ioremapped SMU */
+
+ ncores = shmobile_scu_base ? scu_get_core_count(shmobile_scu_base) : 1;
shmobile_smp_init_cpus(ncores);
}
@@ -119,9 +64,4 @@ struct smp_operations emev2_smp_ops __initdata = {
.smp_init_cpus = emev2_smp_init_cpus,
.smp_prepare_cpus = emev2_smp_prepare_cpus,
.smp_boot_secondary = emev2_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
- .cpu_kill = emev2_cpu_kill,
- .cpu_die = shmobile_cpu_die,
- .cpu_disable = shmobile_cpu_disable,
-#endif
};
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 994906560edd..a853bf182ed5 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -25,11 +25,13 @@
#include <linux/delay.h>
#include <mach/common.h>
#include <mach/r8a7779.h>
+#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#define AVECR IOMEM(0xfe700040)
+#define R8A7779_SCU_BASE 0xf0000000
static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
.chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
@@ -55,44 +57,14 @@ static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = {
[3] = &r8a7779_ch_cpu3,
};
-static void __iomem *scu_base_addr(void)
-{
- return (void __iomem *)0xf0000000;
-}
-
-static DEFINE_SPINLOCK(scu_lock);
-static unsigned long tmp;
-
#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
-
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29);
void __init r8a7779_register_twd(void)
{
twd_local_timer_register(&twd_local_timer);
}
#endif
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
- void __iomem *scu_base = scu_base_addr();
-
- spin_lock(&scu_lock);
- tmp = __raw_readl(scu_base + 8);
- tmp &= ~clr;
- tmp |= set;
- spin_unlock(&scu_lock);
-
- /* disable cache coherency after releasing the lock */
- __raw_writel(tmp, scu_base + 8);
-}
-
-static unsigned int __init r8a7779_get_core_count(void)
-{
- void __iomem *scu_base = scu_base_addr();
-
- return scu_get_core_count(scu_base);
-}
-
static int r8a7779_platform_cpu_kill(unsigned int cpu)
{
struct r8a7779_pm_ch *ch = NULL;
@@ -100,9 +72,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
cpu = cpu_logical_map(cpu);
- /* disable cache coherency */
- modify_scu_cpu_psr(3 << (cpu * 8), 0);
-
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[cpu];
@@ -112,25 +81,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
return ret ? ret : 1;
}
-static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
-{
- int k;
-
- /* this function is running on another CPU than the offline target,
- * here we need wait for shutdown code in platform_cpu_die() to
- * finish before asking SoC-specific code to power off the CPU core.
- */
- for (k = 0; k < 1000; k++) {
- if (shmobile_cpu_is_dead(cpu))
- return r8a7779_platform_cpu_kill(cpu);
-
- mdelay(1);
- }
-
- return 0;
-}
-
-
static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
struct r8a7779_pm_ch *ch = NULL;
@@ -138,9 +88,6 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
cpu = cpu_logical_map(cpu);
- /* enable cache coherency */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
ch = r8a7779_ch_cpu[cpu];
@@ -152,15 +99,13 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
{
- int cpu = cpu_logical_map(0);
+ scu_enable(shmobile_scu_base);
- scu_enable(scu_base_addr());
+ /* Map the reset vector (in headsmp-scu.S) */
+ __raw_writel(__pa(shmobile_secondary_vector_scu), AVECR);
- /* Map the reset vector (in headsmp.S) */
- __raw_writel(__pa(shmobile_secondary_vector), AVECR);
-
- /* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
+ /* enable cache coherency on booting CPU */
+ scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
r8a7779_pm_init();
@@ -172,10 +117,60 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
static void __init r8a7779_smp_init_cpus(void)
{
- unsigned int ncores = r8a7779_get_core_count();
+ /* setup r8a7779 specific SCU base */
+ shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
+
+ shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
+}
- shmobile_smp_init_cpus(ncores);
+#ifdef CONFIG_HOTPLUG_CPU
+static int r8a7779_scu_psr_core_disabled(int cpu)
+{
+ unsigned long mask = 3 << (cpu * 8);
+
+ if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
+ return 1;
+
+ return 0;
+}
+
+static int r8a7779_cpu_kill(unsigned int cpu)
+{
+ int k;
+
+ /* this function is running on another CPU than the offline target,
+ * here we need wait for shutdown code in platform_cpu_die() to
+ * finish before asking SoC-specific code to power off the CPU core.
+ */
+ for (k = 0; k < 1000; k++) {
+ if (r8a7779_scu_psr_core_disabled(cpu))
+ return r8a7779_platform_cpu_kill(cpu);
+
+ mdelay(1);
+ }
+
+ return 0;
+}
+
+static void r8a7779_cpu_die(unsigned int cpu)
+{
+ dsb();
+ flush_cache_all();
+
+ /* disable cache coherency */
+ scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
+
+ /* Endless loop until power off from r8a7779_cpu_kill() */
+ while (1)
+ cpu_do_idle();
+}
+
+static int r8a7779_cpu_disable(unsigned int cpu)
+{
+ /* only CPU1->3 have power domains, do not allow hotplug of CPU0 */
+ return cpu == 0 ? -EPERM : 0;
}
+#endif /* CONFIG_HOTPLUG_CPU */
struct smp_operations r8a7779_smp_ops __initdata = {
.smp_init_cpus = r8a7779_smp_init_cpus,
@@ -183,7 +178,7 @@ struct smp_operations r8a7779_smp_ops __initdata = {
.smp_boot_secondary = r8a7779_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = r8a7779_cpu_kill,
- .cpu_die = shmobile_cpu_die,
- .cpu_disable = shmobile_cpu_disable,
+ .cpu_die = r8a7779_cpu_die,
+ .cpu_disable = r8a7779_cpu_disable,
#endif
};
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index d0f9aca22477..bf79626ee5a4 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -38,26 +38,16 @@
#define PSTR_SHUTDOWN_MODE 3
-static void __iomem *scu_base_addr(void)
-{
- return (void __iomem *)0xf0000000;
-}
+#define SH73A0_SCU_BASE 0xf0000000
#ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29);
void __init sh73a0_register_twd(void)
{
twd_local_timer_register(&twd_local_timer);
}
#endif
-static unsigned int __init sh73a0_get_core_count(void)
-{
- void __iomem *scu_base = scu_base_addr();
-
- return scu_get_core_count(scu_base);
-}
-
static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
cpu = cpu_logical_map(cpu);
@@ -72,21 +62,22 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
{
- scu_enable(scu_base_addr());
+ scu_enable(shmobile_scu_base);
- /* Map the reset vector (in headsmp-sh73a0.S) */
+ /* Map the reset vector (in headsmp-scu.S) */
__raw_writel(0, APARMBAREA); /* 4k */
- __raw_writel(__pa(sh73a0_secondary_vector), SBAR);
+ __raw_writel(__pa(shmobile_secondary_vector_scu), SBAR);
/* enable cache coherency on booting CPU */
- scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
+ scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
}
static void __init sh73a0_smp_init_cpus(void)
{
- unsigned int ncores = sh73a0_get_core_count();
+ /* setup sh73a0 specific SCU base */
+ shmobile_scu_base = IOMEM(SH73A0_SCU_BASE);
- shmobile_smp_init_cpus(ncores);
+ shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
}
#ifdef CONFIG_HOTPLUG_CPU
@@ -122,11 +113,16 @@ static void sh73a0_cpu_die(unsigned int cpu)
flush_cache_all();
/* Set power off mode. This takes the CPU out of the MP cluster */
- scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
+ scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
/* Enter shutdown mode */
cpu_do_idle();
}
+
+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 = {
@@ -136,6 +132,6 @@ struct smp_operations sh73a0_smp_ops __initdata = {
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = sh73a0_cpu_kill,
.cpu_die = sh73a0_cpu_die,
- .cpu_disable = shmobile_cpu_disable_any,
+ .cpu_disable = sh73a0_cpu_disable,
#endif
};