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 +#include +#include + + __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 #include #include +#include #include #include #include @@ -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 +#include #include +#include #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 + * + * 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 +#include + +#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 #include #include -#include #include #include #include @@ -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 #include #include +#include #include #include #include @@ -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,16 +59,18 @@ 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. 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 #include #include +#include #include #include #include @@ -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; - /* 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. + int k; + u32 pstr; + + /* + * 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 };