summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/boot/dts/sh73a0-reference.dtsi24
-rw-r--r--arch/arm/boot/dts/sh73a0.dtsi93
-rw-r--r--arch/arm/mach-shmobile/Makefile3
-rw-r--r--arch/arm/mach-shmobile/board-armadillo800eva.c2
-rw-r--r--arch/arm/mach-shmobile/board-kzm9g.c2
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7740.c6
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c9
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c35
-rw-r--r--arch/arm/mach-shmobile/headsmp-sh73a0.S50
-rw-r--r--arch/arm/mach-shmobile/include/mach/common.h8
-rw-r--r--arch/arm/mach-shmobile/intc-sh73a0.c16
-rw-r--r--arch/arm/mach-shmobile/pm-r8a7740.c22
-rw-r--r--arch/arm/mach-shmobile/pm-sh73a0.c32
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7740.c95
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7779.c18
-rw-r--r--arch/arm/mach-shmobile/setup-sh73a0.c62
-rw-r--r--arch/arm/mach-shmobile/sleep-sh7372.S12
-rw-r--r--arch/arm/mach-shmobile/smp-sh73a0.c66
18 files changed, 485 insertions, 70 deletions
diff --git a/arch/arm/boot/dts/sh73a0-reference.dtsi b/arch/arm/boot/dts/sh73a0-reference.dtsi
new file mode 100644
index 000000000000..d4bb0125b2b2
--- /dev/null
+++ b/arch/arm/boot/dts/sh73a0-reference.dtsi
@@ -0,0 +1,24 @@
+/*
+ * Device Tree Source for the SH73A0 SoC
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "sh73a0.dtsi"
+
+/ {
+ compatible = "renesas,sh73a0";
+
+ mmcif: mmcif@0x10010000 {
+ compatible = "renesas,sh-mmcif";
+ reg = <0xe6bd0000 0x100>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 140 0x4
+ 0 141 0x4>;
+ reg-io-width = <4>;
+ };
+};
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
new file mode 100644
index 000000000000..721f48668f98
--- /dev/null
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -0,0 +1,93 @@
+/*
+ * Device Tree Source for the SH73A0 SoC
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "renesas,sh73a0";
+
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ };
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ };
+ };
+
+ gic: interrupt-controller@f0001000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ interrupt-controller;
+ reg = <0xf0001000 0x1000>,
+ <0xf0000100 0x100>;
+ };
+
+ i2c0: i2c@0xe6820000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xe6820000 0x425>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 167 0x4
+ 0 168 0x4
+ 0 169 0x4
+ 0 170 0x4>;
+ };
+
+ i2c1: i2c@0xe6822000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xe6822000 0x425>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 51 0x4
+ 0 52 0x4
+ 0 53 0x4
+ 0 54 0x4>;
+ };
+
+ i2c2: i2c@0xe6824000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xe6824000 0x425>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 171 0x4
+ 0 172 0x4
+ 0 173 0x4
+ 0 174 0x4>;
+ };
+
+ i2c3: i2c@0xe6826000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xe6826000 0x425>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 183 0x4
+ 0 184 0x4
+ 0 185 0x4
+ 0 186 0x4>;
+ };
+
+ i2c4: i2c@0xe6828000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,rmobile-iic";
+ reg = <0xe6828000 0x425>;
+ interrupt-parent = <&gic>;
+ interrupts = <0 187 0x4
+ 0 188 0x4
+ 0 189 0x4
+ 0 190 0x4>;
+ };
+};
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 0b7147928aa3..700e6623aa86 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -15,7 +15,7 @@ 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
+smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o headsmp-sh73a0.o
smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o
smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
@@ -37,6 +37,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += pm-rmobile.o
obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
obj-$(CONFIG_ARCH_R8A7740) += pm-r8a7740.o
obj-$(CONFIG_ARCH_R8A7779) += pm-r8a7779.o
+obj-$(CONFIG_ARCH_SH73A0) += pm-sh73a0.o
# Board objects
obj-$(CONFIG_MACH_AP4EVB) += board-ap4evb.o
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index e7912447ad50..65731370da81 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -1181,6 +1181,8 @@ static void __init eva_init(void)
rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device);
if (usb)
rmobile_add_device_to_domain("A3SP", usb);
+
+ r8a7740_pm_init();
}
static void __init eva_earlytimer_init(void)
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index ac9428530d7b..363c6edfa3cd 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -772,6 +772,8 @@ static void __init kzm_init(void)
sh73a0_add_standard_devices();
platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
+
+ sh73a0_pm_init();
}
static void kzm9g_restart(char mode, const char *cmd)
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index eac49d59782f..19ce885a3b43 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -581,10 +581,14 @@ static struct clk_lookup lookups[] = {
/* MSTP32 clocks */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]),
- CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP111]),
+ CLKDEV_DEV_ID("sh_tmu.3", &mstp_clks[MSTP111]),
+ CLKDEV_DEV_ID("sh_tmu.4", &mstp_clks[MSTP111]),
+ CLKDEV_DEV_ID("sh_tmu.5", &mstp_clks[MSTP111]),
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]),
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]),
CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP125]),
+ CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]),
+ CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP125]),
CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]),
CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP128]),
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 3ca6757b129a..45d21fe317f4 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -544,6 +544,7 @@ static struct clk_lookup lookups[] = {
/* MSTP32 clocks */
CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
+ CLKDEV_DEV_ID("fff30000.i2c", &mstp_clks[MSTP001]), /* IIC2 */
CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */
CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
@@ -556,6 +557,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
+ CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]), /* IIC0 */
CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */
CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
@@ -577,18 +579,25 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
+ CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]), /* IIC1 */
CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("sh_flctl.0", &mstp_clks[MSTP315]), /* FLCTL */
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+ CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+ CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
+ CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMC */
CLKDEV_DEV_ID("sh-mipi-dsi.1", &mstp_clks[MSTP423]), /* DSITX1 */
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */
+ CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), /* SDHI2 */
CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
+ CLKDEV_DEV_ID("e6d20000.i2c", &mstp_clks[MSTP411]), /* IIC3 */
CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
+ CLKDEV_DEV_ID("e6d30000.i2c", &mstp_clks[MSTP410]), /* IIC4 */
CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */
CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 516ff7f3e434..afa5423a0f93 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -264,17 +264,17 @@ enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags)
static struct clk div4_clks[DIV4_NR] = {
- [DIV4_I] = DIV4(FRQCRA, 20, 0xfff, CLK_ENABLE_ON_INIT),
- [DIV4_ZG] = DIV4(FRQCRA, 16, 0xbff, CLK_ENABLE_ON_INIT),
- [DIV4_M3] = DIV4(FRQCRA, 12, 0xfff, CLK_ENABLE_ON_INIT),
- [DIV4_B] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT),
- [DIV4_M1] = DIV4(FRQCRA, 4, 0xfff, 0),
- [DIV4_M2] = DIV4(FRQCRA, 0, 0xfff, 0),
- [DIV4_Z] = DIV4(FRQCRB, 24, 0xbff, 0),
- [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xfff, 0),
- [DIV4_ZT] = DIV4(FRQCRB, 16, 0xfff, 0),
- [DIV4_ZX] = DIV4(FRQCRB, 12, 0xfff, 0),
- [DIV4_HP] = DIV4(FRQCRB, 4, 0xfff, 0),
+ [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT),
+ [DIV4_ZG] = DIV4(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_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0),
+ [DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0),
+ [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0),
+ [DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0),
};
enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
@@ -525,6 +525,13 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
};
+/* The lookups structure below includes duplicate entries for some clocks
+ * with alternate names.
+ * - The traditional name used when a device is initialised with platform data
+ * - The name used when a device is initialised using device tree
+ * The longer-term aim is to remove these duplicates, and indeed the
+ * lookups table entirely, by describing clocks using device tree.
+ */
static struct clk_lookup lookups[] = {
/* main clocks */
CLKDEV_CON_ID("r_clk", &r_clk),
@@ -545,6 +552,7 @@ static struct clk_lookup lookups[] = {
/* MSTP32 clocks */
CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
+ CLKDEV_DEV_ID("e6824000.i2c", &mstp_clks[MSTP001]), /* I2C2 */
CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */
CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */
CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */
@@ -553,6 +561,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
+ CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
@@ -569,17 +578,21 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
+ 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("sh_mobile_sdhi.1", &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("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 */
CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */
CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
+ CLKDEV_DEV_ID("e6826000.i2c", &mstp_clks[MSTP411]), /* I2C3 */
CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
+ CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */
CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
};
diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
new file mode 100644
index 000000000000..bec4c0d9b713
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
@@ -0,0 +1,50 @@
+/*
+ * SMP support for SoC sh73a0
+ *
+ * Copyright (C) 2012 Bastian Hecht
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+
+ __CPUINIT
+/*
+ * Reset vector for secondary CPUs.
+ *
+ * First we turn on L1 cache coherency for our CPU. Then we jump to
+ * shmobile_invalidate_start that invalidates the cache and hands over control
+ * to the common ARM startup code.
+ * This function will be mapped to address 0 by the SBAR register.
+ * A normal branch is out of range here so we need a long jump. We jump to
+ * the physical address as the MMU is still turned off.
+ */
+ .align 12
+ENTRY(sh73a0_secondary_vector)
+ 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 r2, [r1, #8] @ SCU Power Status Register
+ mov r3, #3
+ bic r2, r2, r3, lsl r0 @ Clear bits of our CPU (Run Mode)
+ str r2, [r1, #8] @ write back
+
+ ldr pc, 1f
+1: .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ENDPROC(sh73a0_secondary_vector)
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index a57439eec11a..64c0622ae7d6 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -23,6 +23,8 @@ extern void sh7372_map_io(void);
extern void sh7372_earlytimer_init(void);
extern void sh7372_add_early_devices(void);
extern void sh7372_add_standard_devices(void);
+extern void sh7372_add_early_devices_dt(void);
+extern void sh7372_add_standard_devices_dt(void);
extern void sh7372_clock_init(void);
extern void sh7372_pinmux_init(void);
extern void sh7372_pm_init(void);
@@ -32,12 +34,17 @@ extern struct clk sh7372_extal1_clk;
extern struct clk sh7372_extal2_clk;
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;
@@ -49,6 +56,7 @@ extern void r8a7740_add_early_devices(void);
extern void r8a7740_add_standard_devices(void);
extern void r8a7740_clock_init(u8 md_ck);
extern void r8a7740_pinmux_init(void);
+extern void r8a7740_pm_init(void);
extern void r8a7779_init_irq(void);
extern void r8a7779_map_io(void);
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index 978369973be4..91faba666d46 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -23,6 +23,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/sh_intc.h>
+#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic.h>
#include <mach/intc.h>
#include <mach/irqs.h>
@@ -315,11 +316,6 @@ static int intca_gic_set_type(struct irq_data *data, unsigned int type)
return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
}
-static int intca_gic_set_wake(struct irq_data *data, unsigned int on)
-{
- return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on);
-}
-
#ifdef CONFIG_SMP
static int intca_gic_set_affinity(struct irq_data *data,
const struct cpumask *cpumask,
@@ -339,7 +335,7 @@ struct irq_chip intca_gic_irq_chip = {
.irq_disable = intca_gic_disable,
.irq_shutdown = intca_gic_disable,
.irq_set_type = intca_gic_set_type,
- .irq_set_wake = intca_gic_set_wake,
+ .irq_set_wake = sh73a0_set_wake,
#ifdef CONFIG_SMP
.irq_set_affinity = intca_gic_set_affinity,
#endif
@@ -464,3 +460,11 @@ 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/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index 21e5316d2d88..40b87aa1d448 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -9,7 +9,9 @@
* for more details.
*/
#include <linux/console.h>
+#include <linux/suspend.h>
#include <mach/pm-rmobile.h>
+#include <mach/common.h>
#ifdef CONFIG_PM
static int r8a7740_pd_a4s_suspend(void)
@@ -58,3 +60,23 @@ void __init r8a7740_init_pm_domains(void)
}
#endif /* CONFIG_PM */
+
+#ifdef CONFIG_SUSPEND
+static int r8a7740_enter_suspend(suspend_state_t suspend_state)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static void r8a7740_suspend_init(void)
+{
+ shmobile_suspend_ops.enter = r8a7740_enter_suspend;
+}
+#else
+static void r8a7740_suspend_init(void) {}
+#endif
+
+void __init r8a7740_pm_init(void)
+{
+ r8a7740_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c
new file mode 100644
index 000000000000..99086e98fbbc
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-sh73a0.c
@@ -0,0 +1,32 @@
+/*
+ * sh73a0 Power management support
+ *
+ * Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/suspend.h>
+#include <mach/common.h>
+
+#ifdef CONFIG_SUSPEND
+static int sh73a0_enter_suspend(suspend_state_t suspend_state)
+{
+ cpu_do_idle();
+ return 0;
+}
+
+static void sh73a0_suspend_init(void)
+{
+ shmobile_suspend_ops.enter = sh73a0_enter_suspend;
+}
+#else
+static void sh73a0_suspend_init(void) {}
+#endif
+
+void __init sh73a0_pm_init(void)
+{
+ sh73a0_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 03c69f9979aa..847567d55487 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -27,7 +27,6 @@
#include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_timer.h>
-#include <linux/dma-mapping.h>
#include <mach/dma-register.h>
#include <mach/r8a7740.h>
#include <mach/pm-rmobile.h>
@@ -262,6 +261,97 @@ static struct platform_device cmt10_device = {
.num_resources = ARRAY_SIZE(cmt10_resources),
};
+/* TMU */
+static struct sh_timer_config tmu00_platform_data = {
+ .name = "TMU00",
+ .channel_offset = 0x4,
+ .timer_bit = 0,
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu00_resources[] = {
+ [0] = {
+ .name = "TMU00",
+ .start = 0xfff80008,
+ .end = 0xfff80014 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0xe80),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu00_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu00_platform_data,
+ },
+ .resource = tmu00_resources,
+ .num_resources = ARRAY_SIZE(tmu00_resources),
+};
+
+static struct sh_timer_config tmu01_platform_data = {
+ .name = "TMU01",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu01_resources[] = {
+ [0] = {
+ .name = "TMU01",
+ .start = 0xfff80014,
+ .end = 0xfff80020 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0xea0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu01_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu01_platform_data,
+ },
+ .resource = tmu01_resources,
+ .num_resources = ARRAY_SIZE(tmu01_resources),
+};
+
+static struct sh_timer_config tmu02_platform_data = {
+ .name = "TMU02",
+ .channel_offset = 0x1C,
+ .timer_bit = 2,
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu02_resources[] = {
+ [0] = {
+ .name = "TMU02",
+ .start = 0xfff80020,
+ .end = 0xfff8002C - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = intcs_evt2irq(0xec0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu02_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu02_platform_data,
+ },
+ .resource = tmu02_resources,
+ .num_resources = ARRAY_SIZE(tmu02_resources),
+};
+
static struct platform_device *r8a7740_early_devices[] __initdata = {
&scif0_device,
&scif1_device,
@@ -273,6 +363,9 @@ static struct platform_device *r8a7740_early_devices[] __initdata = {
&scif7_device,
&scifb_device,
&cmt10_device,
+ &tmu00_device,
+ &tmu01_device,
+ &tmu02_device,
};
/* DMA */
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index a181ced09e45..7e87ab3eb8d3 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -66,8 +66,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 = { gic_spi(88), gic_spi(88),
- gic_spi(88), gic_spi(88) },
+ .irqs = SCIx_IRQ_MUXED(gic_spi(88)),
};
static struct platform_device scif0_device = {
@@ -84,8 +83,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 = { gic_spi(89), gic_spi(89),
- gic_spi(89), gic_spi(89) },
+ .irqs = SCIx_IRQ_MUXED(gic_spi(89)),
};
static struct platform_device scif1_device = {
@@ -102,8 +100,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 = { gic_spi(90), gic_spi(90),
- gic_spi(90), gic_spi(90) },
+ .irqs = SCIx_IRQ_MUXED(gic_spi(90)),
};
static struct platform_device scif2_device = {
@@ -120,8 +117,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 = { gic_spi(91), gic_spi(91),
- gic_spi(91), gic_spi(91) },
+ .irqs = SCIx_IRQ_MUXED(gic_spi(91)),
};
static struct platform_device scif3_device = {
@@ -138,8 +134,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 = { gic_spi(92), gic_spi(92),
- gic_spi(92), gic_spi(92) },
+ .irqs = SCIx_IRQ_MUXED(gic_spi(92)),
};
static struct platform_device scif4_device = {
@@ -156,8 +151,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 = { gic_spi(93), gic_spi(93),
- gic_spi(93), gic_spi(93) },
+ .irqs = SCIx_IRQ_MUXED(gic_spi(93)),
};
static struct platform_device scif5_device = {
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index 8c2d6424f470..f7ecb0bc1bec 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -23,6 +23,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/io.h>
@@ -754,7 +755,7 @@ static struct platform_device pmu_device = {
.resource = pmu_resources,
};
-static struct platform_device *sh73a0_early_devices[] __initdata = {
+static struct platform_device *sh73a0_early_devices_dt[] __initdata = {
&scif0_device,
&scif1_device,
&scif2_device,
@@ -765,6 +766,9 @@ static struct platform_device *sh73a0_early_devices[] __initdata = {
&scif7_device,
&scif8_device,
&cmt10_device,
+};
+
+static struct platform_device *sh73a0_early_devices[] __initdata = {
&tmu00_device,
&tmu01_device,
};
@@ -787,6 +791,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_early_devices,
ARRAY_SIZE(sh73a0_early_devices));
platform_add_devices(sh73a0_late_devices,
@@ -805,9 +811,63 @@ 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_early_devices,
ARRAY_SIZE(sh73a0_early_devices));
/* setup early console here as well */
shmobile_setup_console();
}
+
+#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)
+{
+ 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 = {
+ {},
+};
+
+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));
+ of_platform_populate(NULL, of_default_bus_match_table,
+ sh73a0_auxdata_lookup, NULL);
+}
+
+static const char *sh73a0_boards_compat_dt[] __initdata = {
+ "renesas,sh73a0",
+ NULL,
+};
+
+DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
+ .map_io = sh73a0_map_io,
+ .init_early = sh73a0_add_early_devices_dt,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = sh73a0_init_irq_dt,
+ .init_machine = sh73a0_add_standard_devices_dt,
+ .init_time = shmobile_timer_init,
+ .dt_compat = sh73a0_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S
index 1d564674451d..a9df53b69ab8 100644
--- a/arch/arm/mach-shmobile/sleep-sh7372.S
+++ b/arch/arm/mach-shmobile/sleep-sh7372.S
@@ -59,17 +59,19 @@ sh7372_do_idle_sysc:
mcr p15, 0, r0, c1, c0, 0
isb
+ /*
+ * Clean and invalidate data cache again.
+ */
+ ldr r1, kernel_flush
+ blx r1
+
/* disable L2 cache in the aux control register */
mrc p15, 0, r10, c1, c0, 1
bic r10, r10, #2
mcr p15, 0, r10, c1, c0, 1
+ isb
/*
- * Invalidate data cache again.
- */
- ldr r1, kernel_flush
- blx r1
- /*
* The kernel doesn't interwork: v7_flush_dcache_all in particluar will
* always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
* This sequence switches back to ARM. Note that .align may insert a
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 5c5bcb595350..9812ea3255c9 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/irqchip/arm-gic.h>
#include <mach/common.h>
+#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <mach/sh73a0.h>
#include <asm/smp_scu.h>
@@ -36,14 +37,13 @@
#define SBAR IOMEM(0xe6180020)
#define APARMBAREA IOMEM(0xe6f10020)
+#define PSTR_SHUTDOWN_MODE 3
+
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);
void __init sh73a0_register_twd(void)
@@ -52,20 +52,6 @@ void __init sh73a0_register_twd(void)
}
#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 sh73a0_get_core_count(void)
{
void __iomem *scu_base = scu_base_addr();
@@ -82,9 +68,6 @@ static int __cpuinit sh73a0_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 (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
__raw_writel(1 << cpu, WUPCR); /* wake up */
else
@@ -95,16 +78,14 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
{
- int cpu = cpu_logical_map(0);
-
scu_enable(scu_base_addr());
- /* Map the reset vector (in headsmp.S) */
+ /* Map the reset vector (in headsmp-sh73a0.S) */
__raw_writel(0, APARMBAREA); /* 4k */
- __raw_writel(__pa(shmobile_secondary_vector), SBAR);
+ __raw_writel(__pa(sh73a0_secondary_vector), SBAR);
- /* enable cache coherency on CPU0 */
- modify_scu_cpu_psr(0, 3 << (cpu * 8));
+ /* enable cache coherency on booting CPU */
+ scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
}
static void __init sh73a0_smp_init_cpus(void)
@@ -114,16 +95,20 @@ static void __init sh73a0_smp_init_cpus(void)
shmobile_smp_init_cpus(ncores);
}
-static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static int sh73a0_cpu_kill(unsigned int cpu)
{
+
int k;
+ u32 pstr;
- /* 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.
+ /*
+ * wait until the power status register confirms the shutdown of the
+ * offline target
*/
for (k = 0; k < 1000; k++) {
- if (shmobile_cpu_is_dead(cpu))
+ pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3;
+ if (pstr == PSTR_SHUTDOWN_MODE)
return 1;
mdelay(1);
@@ -132,6 +117,23 @@ static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
return 0;
}
+static void sh73a0_cpu_die(unsigned int cpu)
+{
+ /*
+ * The ARM MPcore does not issue a cache coherency request for the L1
+ * cache when powering off single CPUs. We must take care of this and
+ * further caches.
+ */
+ dsb();
+ 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);
+
+ /* Enter shutdown mode */
+ cpu_do_idle();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
struct smp_operations sh73a0_smp_ops __initdata = {
.smp_init_cpus = sh73a0_smp_init_cpus,
@@ -140,7 +142,7 @@ struct smp_operations sh73a0_smp_ops __initdata = {
.smp_boot_secondary = sh73a0_boot_secondary,
#ifdef CONFIG_HOTPLUG_CPU
.cpu_kill = sh73a0_cpu_kill,
- .cpu_die = shmobile_cpu_die,
+ .cpu_die = sh73a0_cpu_die,
.cpu_disable = shmobile_cpu_disable,
#endif
};