aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-shmobile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-shmobile')
-rw-r--r--arch/arm/mach-shmobile/Kconfig11
-rw-r--r--arch/arm/mach-shmobile/Makefile3
-rw-r--r--arch/arm/mach-shmobile/board-kzm9d.c85
-rw-r--r--arch/arm/mach-shmobile/clock-emev2.c249
-rw-r--r--arch/arm/mach-shmobile/clock-r8a7740.c125
-rw-r--r--arch/arm/mach-shmobile/include/mach/emev2.h19
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh7372.h2
-rw-r--r--arch/arm/mach-shmobile/include/mach/sh73a0.h34
-rw-r--r--arch/arm/mach-shmobile/pfc-r8a7740.c39
-rw-r--r--arch/arm/mach-shmobile/platsmp.c18
-rw-r--r--arch/arm/mach-shmobile/setup-emev2.c452
-rw-r--r--arch/arm/mach-shmobile/setup-r8a7740.c12
-rw-r--r--arch/arm/mach-shmobile/setup-sh7372.c10
-rw-r--r--arch/arm/mach-shmobile/smp-emev2.c97
-rw-r--r--arch/arm/mach-shmobile/timer.c3
15 files changed, 1147 insertions, 12 deletions
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 34560cab45d..7dcf08ee979 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -41,6 +41,12 @@ config ARCH_R8A7779
select ARM_GIC
select ARCH_WANT_OPTIONAL_GPIOLIB
+config ARCH_EMEV2
+ bool "Emma Mobile EV2"
+ select CPU_V7
+ select ARM_GIC
+ select ARCH_WANT_OPTIONAL_GPIOLIB
+
comment "SH-Mobile Board Type"
config MACH_G3EVM
@@ -98,6 +104,11 @@ config MACH_MARZEN
depends on ARCH_R8A7779
select ARCH_REQUIRE_GPIOLIB
+config MACH_KZM9D
+ bool "KZM9D board"
+ depends on ARCH_EMEV2
+ select USE_OF
+
comment "SH-Mobile System Configuration"
config CPU_HAS_INTEVT
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index e7c2590b75d..c795335931c 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -12,12 +12,14 @@ obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o
obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o
obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o
obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o
+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_R8A7779) += smp-r8a7779.o
+smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o
# Pinmux setup
pfc-y :=
@@ -49,6 +51,7 @@ obj-$(CONFIG_MACH_MACKEREL) += board-mackerel.o
obj-$(CONFIG_MACH_KOTA2) += board-kota2.o
obj-$(CONFIG_MACH_BONITO) += board-bonito.o
obj-$(CONFIG_MACH_MARZEN) += board-marzen.o
+obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o
# Framework support
obj-$(CONFIG_SMP) += $(smp-y)
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
new file mode 100644
index 00000000000..7bc5e7d39f9
--- /dev/null
+++ b/arch/arm/mach-shmobile/board-kzm9d.c
@@ -0,0 +1,85 @@
+/*
+ * kzm9d board support
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <mach/common.h>
+#include <mach/emev2.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+/* Ether */
+static struct resource smsc911x_resources[] = {
+ [0] = {
+ .start = 0x20000000,
+ .end = 0x2000ffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = EMEV2_GPIO_IRQ(1),
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+ },
+};
+
+static struct smsc911x_platform_config smsc911x_platdata = {
+ .flags = SMSC911X_USE_32BIT,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+};
+
+static struct platform_device smsc91x_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .dev = {
+ .platform_data = &smsc911x_platdata,
+ },
+ .num_resources = ARRAY_SIZE(smsc911x_resources),
+ .resource = smsc911x_resources,
+};
+
+static struct platform_device *kzm9d_devices[] __initdata = {
+ &smsc91x_device,
+};
+
+void __init kzm9d_add_standard_devices(void)
+{
+ emev2_add_standard_devices();
+
+ platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices));
+}
+
+static const char *kzm9d_boards_compat_dt[] __initdata = {
+ "renesas,kzm9d",
+ NULL,
+};
+
+DT_MACHINE_START(KZM9D_DT, "kzm9d")
+ .map_io = emev2_map_io,
+ .init_early = emev2_add_early_devices,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = emev2_init_irq,
+ .handle_irq = gic_handle_irq,
+ .init_machine = kzm9d_add_standard_devices,
+ .timer = &shmobile_timer,
+ .dt_compat = kzm9d_boards_compat_dt,
+MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c
new file mode 100644
index 00000000000..4710f1847bb
--- /dev/null
+++ b/arch/arm/mach-shmobile/clock-emev2.c
@@ -0,0 +1,249 @@
+/*
+ * Emma Mobile EV2 clock framework support
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+#include <linux/clkdev.h>
+#include <mach/common.h>
+
+#define EMEV2_SMU_BASE 0xe0110000
+
+/* EMEV2 SMU registers */
+#define USIAU0_RSTCTRL 0x094
+#define USIBU1_RSTCTRL 0x0ac
+#define USIBU2_RSTCTRL 0x0b0
+#define USIBU3_RSTCTRL 0x0b4
+#define STI_RSTCTRL 0x124
+#define USIAU0GCLKCTRL 0x4a0
+#define USIBU1GCLKCTRL 0x4b8
+#define USIBU2GCLKCTRL 0x4bc
+#define USIBU3GCLKCTRL 0x04c0
+#define STIGCLKCTRL 0x528
+#define USIAU0SCLKDIV 0x61c
+#define USIB2SCLKDIV 0x65c
+#define USIB3SCLKDIV 0x660
+#define STI_CLKSEL 0x688
+#define SMU_GENERAL_REG0 0x7c0
+
+/* not pretty, but hey */
+static void __iomem *smu_base;
+
+static void emev2_smu_write(unsigned long value, int offs)
+{
+ BUG_ON(!smu_base || (offs >= PAGE_SIZE));
+ iowrite32(value, smu_base + offs);
+}
+
+void emev2_set_boot_vector(unsigned long value)
+{
+ emev2_smu_write(value, SMU_GENERAL_REG0);
+}
+
+static struct clk_mapping smu_mapping = {
+ .phys = EMEV2_SMU_BASE,
+ .len = PAGE_SIZE,
+};
+
+/* Fixed 32 KHz root clock from C32K pin */
+static struct clk c32k_clk = {
+ .rate = 32768,
+ .mapping = &smu_mapping,
+};
+
+/* PLL3 multiplies C32K with 7000 */
+static unsigned long pll3_recalc(struct clk *clk)
+{
+ return clk->parent->rate * 7000;
+}
+
+static struct sh_clk_ops pll3_clk_ops = {
+ .recalc = pll3_recalc,
+};
+
+static struct clk pll3_clk = {
+ .ops = &pll3_clk_ops,
+ .parent = &c32k_clk,
+};
+
+static struct clk *main_clks[] = {
+ &c32k_clk,
+ &pll3_clk,
+};
+
+enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3,
+ SCLKDIV_NR };
+
+#define SCLKDIV(_reg, _shift) \
+{ \
+ .parent = &pll3_clk, \
+ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
+ .enable_bit = _shift, \
+}
+
+static struct clk sclkdiv_clks[SCLKDIV_NR] = {
+ [SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0),
+ [SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16),
+ [SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0),
+ [SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0),
+};
+
+enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK,
+ GCLK_STI_SCLK,
+ GCLK_NR };
+
+#define GCLK_SCLK(_parent, _reg) \
+{ \
+ .parent = _parent, \
+ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \
+ .enable_bit = 1, /* SCLK_GCC */ \
+}
+
+static struct clk gclk_clks[GCLK_NR] = {
+ [GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0],
+ USIAU0GCLKCTRL),
+ [GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1],
+ USIBU1GCLKCTRL),
+ [GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2],
+ USIBU2GCLKCTRL),
+ [GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3],
+ USIBU3GCLKCTRL),
+ [GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL),
+};
+
+static int emev2_gclk_enable(struct clk *clk)
+{
+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+ clk->mapped_reg);
+ return 0;
+}
+
+static void emev2_gclk_disable(struct clk *clk)
+{
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+ clk->mapped_reg);
+}
+
+static struct sh_clk_ops emev2_gclk_clk_ops = {
+ .enable = emev2_gclk_enable,
+ .disable = emev2_gclk_disable,
+ .recalc = followparent_recalc,
+};
+
+static int __init emev2_gclk_register(struct clk *clks, int nr)
+{
+ struct clk *clkp;
+ int ret = 0;
+ int k;
+
+ for (k = 0; !ret && (k < nr); k++) {
+ clkp = clks + k;
+ clkp->ops = &emev2_gclk_clk_ops;
+ ret |= clk_register(clkp);
+ }
+
+ return ret;
+}
+
+static unsigned long emev2_sclkdiv_recalc(struct clk *clk)
+{
+ unsigned int sclk_div;
+
+ sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff;
+
+ return clk->parent->rate / (sclk_div + 1);
+}
+
+static struct sh_clk_ops emev2_sclkdiv_clk_ops = {
+ .recalc = emev2_sclkdiv_recalc,
+};
+
+static int __init emev2_sclkdiv_register(struct clk *clks, int nr)
+{
+ struct clk *clkp;
+ int ret = 0;
+ int k;
+
+ for (k = 0; !ret && (k < nr); k++) {
+ clkp = clks + k;
+ clkp->ops = &emev2_sclkdiv_clk_ops;
+ ret |= clk_register(clkp);
+ }
+
+ return ret;
+}
+
+static struct clk_lookup lookups[] = {
+ CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]),
+ CLKDEV_DEV_ID("e1020000.uart", &gclk_clks[GCLK_USIAU0_SCLK]),
+ CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]),
+ CLKDEV_DEV_ID("e1030000.uart", &gclk_clks[GCLK_USIBU1_SCLK]),
+ CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]),
+ CLKDEV_DEV_ID("e1040000.uart", &gclk_clks[GCLK_USIBU2_SCLK]),
+ CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]),
+ CLKDEV_DEV_ID("e1050000.uart", &gclk_clks[GCLK_USIBU3_SCLK]),
+ CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]),
+ CLKDEV_DEV_ID("e0180000.sti", &gclk_clks[GCLK_STI_SCLK]),
+};
+
+void __init emev2_clock_init(void)
+{
+ int k, ret = 0;
+ static int is_setup;
+
+ /* yuck, this is ugly as hell, but the non-smp case of clocks
+ * code is now designed to rely on ioremap() instead of static
+ * entity maps. in the case of smp we need access to the SMU
+ * register earlier than ioremap() is actually working without
+ * any static maps. to enable SMP in ugly but with dynamic
+ * mappings we have to call emev2_clock_init() from different
+ * places depending on UP and SMP...
+ */
+ if (is_setup++)
+ return;
+
+ smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE);
+ BUG_ON(!smu_base);
+
+ /* setup STI timer to run on 37.768 kHz and deassert reset */
+ emev2_smu_write(0, STI_CLKSEL);
+ emev2_smu_write(1, STI_RSTCTRL);
+
+ /* deassert reset for UART0->UART3 */
+ emev2_smu_write(2, USIAU0_RSTCTRL);
+ emev2_smu_write(2, USIBU1_RSTCTRL);
+ emev2_smu_write(2, USIBU2_RSTCTRL);
+ emev2_smu_write(2, USIBU3_RSTCTRL);
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ if (!ret)
+ ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR);
+
+ if (!ret)
+ ret = emev2_gclk_register(gclk_clks, GCLK_NR);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ shmobile_clk_init();
+ else
+ panic("failed to setup emev2 clocks\n");
+}
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index 99c4d743a99..81b54a6af20 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -47,6 +47,7 @@
#define PLLC01CR 0xe6150028
#define SUBCKCR 0xe6150080
+#define USBCKCR 0xe615008c
#define MSTPSR0 0xe6150030
#define MSTPSR1 0xe6150038
@@ -181,6 +182,95 @@ static struct clk pllc1_div2_clk = {
.parent = &pllc1_clk,
};
+/* USB clock */
+static struct clk *usb24s_parents[] = {
+ [0] = &system_clk,
+ [1] = &extal2_clk
+};
+
+static int usb24s_enable(struct clk *clk)
+{
+ __raw_writel(__raw_readl(USBCKCR) & ~(1 << 8), USBCKCR);
+
+ return 0;
+}
+
+static void usb24s_disable(struct clk *clk)
+{
+ __raw_writel(__raw_readl(USBCKCR) | (1 << 8), USBCKCR);
+}
+
+static int usb24s_set_parent(struct clk *clk, struct clk *parent)
+{
+ int i, ret;
+ u32 val;
+
+ if (!clk->parent_table || !clk->parent_num)
+ return -EINVAL;
+
+ /* Search the parent */
+ for (i = 0; i < clk->parent_num; i++)
+ if (clk->parent_table[i] == parent)
+ break;
+
+ if (i == clk->parent_num)
+ return -ENODEV;
+
+ ret = clk_reparent(clk, parent);
+ if (ret < 0)
+ return ret;
+
+ val = __raw_readl(USBCKCR);
+ val &= ~(1 << 7);
+ val |= i << 7;
+ __raw_writel(val, USBCKCR);
+
+ return 0;
+}
+
+static struct sh_clk_ops usb24s_clk_ops = {
+ .recalc = followparent_recalc,
+ .enable = usb24s_enable,
+ .disable = usb24s_disable,
+ .set_parent = usb24s_set_parent,
+};
+
+static struct clk usb24s_clk = {
+ .ops = &usb24s_clk_ops,
+ .parent_table = usb24s_parents,
+ .parent_num = ARRAY_SIZE(usb24s_parents),
+ .parent = &system_clk,
+};
+
+static unsigned long usb24_recalc(struct clk *clk)
+{
+ return clk->parent->rate /
+ ((__raw_readl(USBCKCR) & (1 << 6)) ? 1 : 2);
+};
+
+static int usb24_set_rate(struct clk *clk, unsigned long rate)
+{
+ u32 val;
+
+ /* closer to which ? parent->rate or parent->rate/2 */
+ val = __raw_readl(USBCKCR);
+ val &= ~(1 << 6);
+ val |= (rate > (clk->parent->rate / 4) * 3) << 6;
+ __raw_writel(val, USBCKCR);
+
+ return 0;
+}
+
+static struct sh_clk_ops usb24_clk_ops = {
+ .recalc = usb24_recalc,
+ .set_rate = usb24_set_rate,
+};
+
+static struct clk usb24_clk = {
+ .ops = &usb24_clk_ops,
+ .parent = &usb24s_clk,
+};
+
struct clk *main_clks[] = {
&extalr_clk,
&extal1_clk,
@@ -196,6 +286,8 @@ struct clk *main_clks[] = {
&pllc0_clk,
&pllc1_clk,
&pllc1_div2_clk,
+ &usb24s_clk,
+ &usb24_clk,
};
static void div4_kick(struct clk *clk)
@@ -223,7 +315,7 @@ static struct clk_div4_table div4_table = {
enum {
DIV4_I, DIV4_ZG, DIV4_B, DIV4_M1, DIV4_HP,
- DIV4_HPP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
+ DIV4_HPP, DIV4_USBP, DIV4_S, DIV4_ZB, DIV4_M3, DIV4_CP,
DIV4_NR
};
@@ -234,6 +326,7 @@ struct clk div4_clks[DIV4_NR] = {
[DIV4_M1] = SH_CLK_DIV4(&pllc1_clk, FRQCRA, 4, 0x6fff, CLK_ENABLE_ON_INIT),
[DIV4_HP] = SH_CLK_DIV4(&pllc1_clk, FRQCRB, 4, 0x6fff, 0),
[DIV4_HPP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 20, 0x6fff, 0),
+ [DIV4_USBP] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 16, 0x6fff, 0),
[DIV4_S] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 12, 0x6fff, 0),
[DIV4_ZB] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 8, 0x6fff, 0),
[DIV4_M3] = SH_CLK_DIV4(&pllc1_clk, FRQCRC, 4, 0x6fff, 0),
@@ -257,7 +350,10 @@ enum {
MSTP222,
MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
- MSTP329, MSTP323,
+ MSTP329, MSTP328, MSTP323, MSTP320,
+ MSTP314, MSTP313, MSTP312,
+
+ MSTP416, MSTP415, MSTP407, MSTP406,
MSTP_NR
};
@@ -280,7 +376,17 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP200] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR2, 0, 0), /* SCIFA4 */
[MSTP329] = SH_CLK_MSTP32(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
+ [MSTP328] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 28, 0), /* FSI */
[MSTP323] = SH_CLK_MSTP32(&div6_clks[DIV6_SUB], SMSTPCR3, 23, 0), /* IIC1 */
+ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 20, 0), /* USBF */
+ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 14, 0), /* SDHI0 */
+ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 13, 0), /* SDHI1 */
+ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMC */
+
+ [MSTP416] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 16, 0), /* USBHOST */
+ [MSTP415] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 15, 0), /* SDHI2 */
+ [MSTP407] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 7, 0), /* USB-Func */
+ [MSTP406] = SH_CLK_MSTP32(&div4_clks[DIV4_HP], SMSTPCR4, 6, 0), /* USB Phy */
};
static struct clk_lookup lookups[] = {
@@ -299,6 +405,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("pllc0_clk", &pllc0_clk),
CLKDEV_CON_ID("pllc1_clk", &pllc1_clk),
CLKDEV_CON_ID("pllc1_div2_clk", &pllc1_div2_clk),
+ CLKDEV_CON_ID("usb24s", &usb24s_clk),
/* DIV4 clocks */
CLKDEV_CON_ID("i_clk", &div4_clks[DIV4_I]),
@@ -334,7 +441,21 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-sci.6", &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("sh_mobile_sdhi.1", &mstp_clks[MSTP313]),
+ CLKDEV_DEV_ID("sh_mmcif", &mstp_clks[MSTP312]),
+
+ CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]),
+
+ /* ICK */
+ CLKDEV_ICK_ID("host", "renesas_usbhs", &mstp_clks[MSTP416]),
+ CLKDEV_ICK_ID("func", "renesas_usbhs", &mstp_clks[MSTP407]),
+ CLKDEV_ICK_ID("phy", "renesas_usbhs", &mstp_clks[MSTP406]),
+ CLKDEV_ICK_ID("pci", "renesas_usbhs", &div4_clks[DIV4_USBP]),
+ CLKDEV_ICK_ID("usb24", "renesas_usbhs", &usb24_clk),
};
void __init r8a7740_clock_init(u8 md_ck)
diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h
new file mode 100644
index 00000000000..e6b0c1bf4b7
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/emev2.h
@@ -0,0 +1,19 @@
+#ifndef __ASM_EMEV2_H__
+#define __ASM_EMEV2_H__
+
+extern void emev2_map_io(void);
+extern void emev2_init_irq(void);
+extern void emev2_add_early_devices(void);
+extern void emev2_add_standard_devices(void);
+extern void emev2_clock_init(void);
+extern void emev2_set_boot_vector(unsigned long value);
+extern unsigned int emev2_get_core_count(void);
+extern int emev2_platform_cpu_kill(unsigned int cpu);
+extern void emev2_secondary_init(unsigned int cpu);
+extern int emev2_boot_secondary(unsigned int cpu);
+extern void emev2_smp_prepare_cpus(void);
+
+#define EMEV2_GPIO_BASE 200
+#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n))
+
+#endif /* __ASM_EMEV2_H__ */
diff --git a/arch/arm/mach-shmobile/include/mach/sh7372.h b/arch/arm/mach-shmobile/include/mach/sh7372.h
index 8254ab86f6c..915d0093da0 100644
--- a/arch/arm/mach-shmobile/include/mach/sh7372.h
+++ b/arch/arm/mach-shmobile/include/mach/sh7372.h
@@ -457,6 +457,8 @@ enum {
SHDMA_SLAVE_SDHI1_TX,
SHDMA_SLAVE_SDHI2_RX,
SHDMA_SLAVE_SDHI2_TX,
+ SHDMA_SLAVE_FSIA_RX,
+ SHDMA_SLAVE_FSIA_TX,
SHDMA_SLAVE_MMCIF_RX,
SHDMA_SLAVE_MMCIF_TX,
SHDMA_SLAVE_USB0_TX,
diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h
index cad57578cee..9b3598e4f10 100644
--- a/arch/arm/mach-shmobile/include/mach/sh73a0.h
+++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h
@@ -515,8 +515,36 @@ enum {
SHDMA_SLAVE_MMCIF_RX,
};
-/* PINT interrupts are located at Linux IRQ 800 and up */
-#define SH73A0_PINT0_IRQ(irq) ((irq) + 800)
-#define SH73A0_PINT1_IRQ(irq) ((irq) + 832)
+/*
+ * SH73A0 IRQ LOCATION TABLE
+ *
+ * 416 -----------------------------------------
+ * IRQ0-IRQ15
+ * 431 -----------------------------------------
+ * ...
+ * 448 -----------------------------------------
+ * sh73a0-intcs
+ * sh73a0-intca-irq-pins
+ * 680 -----------------------------------------
+ * ...
+ * 700 -----------------------------------------
+ * sh73a0-pint0
+ * 731 -----------------------------------------
+ * 732 -----------------------------------------
+ * sh73a0-pint1
+ * 739 -----------------------------------------
+ * ...
+ * 800 -----------------------------------------
+ * IRQ16-IRQ31
+ * 815 -----------------------------------------
+ * ...
+ * 928 -----------------------------------------
+ * sh73a0-intca-irq-pins
+ * 943 -----------------------------------------
+ */
+
+/* PINT interrupts are located at Linux IRQ 700 and up */
+#define SH73A0_PINT0_IRQ(irq) ((irq) + 700)
+#define SH73A0_PINT1_IRQ(irq) ((irq) + 732)
#endif /* __ASM_SH73A0_H__ */
diff --git a/arch/arm/mach-shmobile/pfc-r8a7740.c b/arch/arm/mach-shmobile/pfc-r8a7740.c
index a4fff6950b0..670fe1869db 100644
--- a/arch/arm/mach-shmobile/pfc-r8a7740.c
+++ b/arch/arm/mach-shmobile/pfc-r8a7740.c
@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <mach/r8a7740.h>
+#include <mach/irqs.h>
#define CPU_ALL_PORT(fn, pfx, sfx) \
PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx), \
@@ -2527,6 +2528,41 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
{ },
};
+static struct pinmux_irq pinmux_irqs[] = {
+ PINMUX_IRQ(evt2irq(0x0200), PORT2_FN0, PORT13_FN0), /* IRQ0A */
+ PINMUX_IRQ(evt2irq(0x0220), PORT20_FN0), /* IRQ1A */
+ PINMUX_IRQ(evt2irq(0x0240), PORT11_FN0, PORT12_FN0), /* IRQ2A */
+ PINMUX_IRQ(evt2irq(0x0260), PORT10_FN0, PORT14_FN0), /* IRQ3A */
+ PINMUX_IRQ(evt2irq(0x0280), PORT15_FN0, PORT172_FN0), /* IRQ4A */
+ PINMUX_IRQ(evt2irq(0x02A0), PORT0_FN0, PORT1_FN0), /* IRQ5A */
+ PINMUX_IRQ(evt2irq(0x02C0), PORT121_FN0, PORT173_FN0), /* IRQ6A */
+ PINMUX_IRQ(evt2irq(0x02E0), PORT120_FN0, PORT209_FN0), /* IRQ7A */
+ PINMUX_IRQ(evt2irq(0x0300), PORT119_FN0), /* IRQ8A */
+ PINMUX_IRQ(evt2irq(0x0320), PORT118_FN0, PORT210_FN0), /* IRQ9A */
+ PINMUX_IRQ(evt2irq(0x0340), PORT19_FN0), /* IRQ10A */
+ PINMUX_IRQ(evt2irq(0x0360), PORT104_FN0), /* IRQ11A */
+ PINMUX_IRQ(evt2irq(0x0380), PORT42_FN0, PORT97_FN0), /* IRQ12A */
+ PINMUX_IRQ(evt2irq(0x03A0), PORT64_FN0, PORT98_FN0), /* IRQ13A */
+ PINMUX_IRQ(evt2irq(0x03C0), PORT63_FN0, PORT99_FN0), /* IRQ14A */
+ PINMUX_IRQ(evt2irq(0x03E0), PORT62_FN0, PORT100_FN0), /* IRQ15A */
+ PINMUX_IRQ(evt2irq(0x3200), PORT68_FN0, PORT211_FN0), /* IRQ16A */
+ PINMUX_IRQ(evt2irq(0x3220), PORT69_FN0), /* IRQ17A */
+ PINMUX_IRQ(evt2irq(0x3240), PORT70_FN0), /* IRQ18A */
+ PINMUX_IRQ(evt2irq(0x3260), PORT71_FN0), /* IRQ19A */
+ PINMUX_IRQ(evt2irq(0x3280), PORT67_FN0), /* IRQ20A */
+ PINMUX_IRQ(evt2irq(0x32A0), PORT202_FN0), /* IRQ21A */
+ PINMUX_IRQ(evt2irq(0x32C0), PORT95_FN0), /* IRQ22A */
+ PINMUX_IRQ(evt2irq(0x32E0), PORT96_FN0), /* IRQ23A */
+ PINMUX_IRQ(evt2irq(0x3300), PORT180_FN0), /* IRQ24A */
+ PINMUX_IRQ(evt2irq(0x3320), PORT38_FN0), /* IRQ25A */
+ PINMUX_IRQ(evt2irq(0x3340), PORT58_FN0, PORT81_FN0), /* IRQ26A */
+ PINMUX_IRQ(evt2irq(0x3360), PORT57_FN0, PORT168_FN0), /* IRQ27A */
+ PINMUX_IRQ(evt2irq(0x3380), PORT56_FN0, PORT169_FN0), /* IRQ28A */
+ PINMUX_IRQ(evt2irq(0x33A0), PORT50_FN0, PORT170_FN0), /* IRQ29A */
+ PINMUX_IRQ(evt2irq(0x33C0), PORT49_FN0, PORT171_FN0), /* IRQ30A */
+ PINMUX_IRQ(evt2irq(0x33E0), PORT41_FN0, PORT167_FN0), /* IRQ31A */
+};
+
static struct pinmux_info r8a7740_pinmux_info = {
.name = "r8a7740_pfc",
.reserved_id = PINMUX_RESERVED,
@@ -2554,6 +2590,9 @@ static struct pinmux_info r8a7740_pinmux_info = {
.gpio_data = pinmux_data,
.gpio_data_size = ARRAY_SIZE(pinmux_data),
+
+ .gpio_irq = pinmux_irqs,
+ .gpio_irq_size = ARRAY_SIZE(pinmux_irqs),
};
void r8a7740_pinmux_init(void)
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index 45fa3924c6a..7006cdc8b8c 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -16,12 +16,15 @@
#include <linux/device.h>
#include <linux/smp.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <asm/hardware/gic.h>
#include <asm/mach-types.h>
#include <mach/common.h>
+#include <mach/emev2.h>
#define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2())
#define is_r8a7779() machine_is_marzen()
+#define is_emev2() of_machine_is_compatible("renesas,emev2")
static unsigned int __init shmobile_smp_get_core_count(void)
{
@@ -31,6 +34,9 @@ static unsigned int __init shmobile_smp_get_core_count(void)
if (is_r8a7779())
return r8a7779_get_core_count();
+ if (is_emev2())
+ return emev2_get_core_count();
+
return 1;
}
@@ -41,6 +47,9 @@ static void __init shmobile_smp_prepare_cpus(void)
if (is_r8a7779())
r8a7779_smp_prepare_cpus();
+
+ if (is_emev2())
+ emev2_smp_prepare_cpus();
}
int shmobile_platform_cpu_kill(unsigned int cpu)
@@ -48,6 +57,9 @@ int shmobile_platform_cpu_kill(unsigned int cpu)
if (is_r8a7779())
return r8a7779_platform_cpu_kill(cpu);
+ if (is_emev2())
+ return emev2_platform_cpu_kill(cpu);
+
return 1;
}
@@ -60,6 +72,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
if (is_r8a7779())
r8a7779_secondary_init(cpu);
+
+ if (is_emev2())
+ emev2_secondary_init(cpu);
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -70,6 +85,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
if (is_r8a7779())
return r8a7779_boot_secondary(cpu);
+ if (is_emev2())
+ return emev2_boot_secondary(cpu);
+
return -ENOSYS;
}
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
new file mode 100644
index 00000000000..dae9aa68bb0
--- /dev/null
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -0,0 +1,452 @@
+/*
+ * Emma Mobile EV2 processor support
+ *
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/gpio-em.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/emev2.h>
+#include <mach/irqs.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+
+static struct map_desc emev2_io_desc[] __initdata = {
+#ifdef CONFIG_SMP
+ /* 128K entity map for 0xe0100000 (SMU) */
+ {
+ .virtual = 0xe0100000,
+ .pfn = __phys_to_pfn(0xe0100000),
+ .length = SZ_128K,
+ .type = MT_DEVICE
+ },
+ /* 2M mapping for SCU + L2 controller */
+ {
+ .virtual = 0xf0000000,
+ .pfn = __phys_to_pfn(0x1e000000),
+ .length = SZ_2M,
+ .type = MT_DEVICE
+ },
+#endif
+};
+
+void __init emev2_map_io(void)
+{
+ iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc));
+}
+
+/* UART */
+static struct resource uart0_resources[] = {
+ [0] = {
+ .start = 0xe1020000,
+ .end = 0xe1020037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 40,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart0_device = {
+ .name = "serial8250-em",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(uart0_resources),
+ .resource = uart0_resources,
+};
+
+static struct resource uart1_resources[] = {
+ [0] = {
+ .start = 0xe1030000,
+ .end = 0xe1030037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 41,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart1_device = {
+ .name = "serial8250-em",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(uart1_resources),
+ .resource = uart1_resources,
+};
+
+static struct resource uart2_resources[] = {
+ [0] = {
+ .start = 0xe1040000,
+ .end = 0xe1040037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 42,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart2_device = {
+ .name = "serial8250-em",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(uart2_resources),
+ .resource = uart2_resources,
+};
+
+static struct resource uart3_resources[] = {
+ [0] = {
+ .start = 0xe1050000,
+ .end = 0xe1050037,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 43,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device uart3_device = {
+ .name = "serial8250-em",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(uart3_resources),
+ .resource = uart3_resources,
+};
+
+/* STI */
+static struct resource sti_resources[] = {
+ [0] = {
+ .name = "STI",
+ .start = 0xe0180000,
+ .end = 0xe0180053,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 157,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device sti_device = {
+ .name = "em_sti",
+ .id = 0,
+ .resource = sti_resources,
+ .num_resources = ARRAY_SIZE(sti_resources),
+};
+
+
+/* GIO */
+static struct gpio_em_config gio0_config = {
+ .gpio_base = 0,
+ .irq_base = EMEV2_GPIO_IRQ(0),
+ .number_of_pins = 32,
+};
+
+static struct resource gio0_resources[] = {
+ [0] = {
+ .name = "GIO_000",
+ .start = 0xe0050000,
+ .end = 0xe005002b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_000",
+ .start = 0xe0050040,
+ .end = 0xe005005f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 99,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 100,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio0_device = {
+ .name = "em_gio",
+ .id = 0,
+ .resource = gio0_resources,
+ .num_resources = ARRAY_SIZE(gio0_resources),
+ .dev = {
+ .platform_data = &gio0_config,
+ },
+};
+
+static struct gpio_em_config gio1_config = {
+ .gpio_base = 32,
+ .irq_base = EMEV2_GPIO_IRQ(32),
+ .number_of_pins = 32,
+};
+
+static struct resource gio1_resources[] = {
+ [0] = {
+ .name = "GIO_032",
+ .start = 0xe0050080,
+ .end = 0xe00500ab,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_032",
+ .start = 0xe00500c0,
+ .end = 0xe00500df,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 101,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 102,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio1_device = {
+ .name = "em_gio",
+ .id = 1,
+ .resource = gio1_resources,
+ .num_resources = ARRAY_SIZE(gio1_resources),
+ .dev = {
+ .platform_data = &gio1_config,
+ },
+};
+
+static struct gpio_em_config gio2_config = {
+ .gpio_base = 64,
+ .irq_base = EMEV2_GPIO_IRQ(64),
+ .number_of_pins = 32,
+};
+
+static struct resource gio2_resources[] = {
+ [0] = {
+ .name = "GIO_064",
+ .start = 0xe0050100,
+ .end = 0xe005012b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_064",
+ .start = 0xe0050140,
+ .end = 0xe005015f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 103,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 104,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio2_device = {
+ .name = "em_gio",
+ .id = 2,
+ .resource = gio2_resources,
+ .num_resources = ARRAY_SIZE(gio2_resources),
+ .dev = {
+ .platform_data = &gio2_config,
+ },
+};
+
+static struct gpio_em_config gio3_config = {
+ .gpio_base = 96,
+ .irq_base = EMEV2_GPIO_IRQ(96),
+ .number_of_pins = 32,
+};
+
+static struct resource gio3_resources[] = {
+ [0] = {
+ .name = "GIO_096",
+ .start = 0xe0050100,
+ .end = 0xe005012b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_096",
+ .start = 0xe0050140,
+ .end = 0xe005015f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 105,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 106,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio3_device = {
+ .name = "em_gio",
+ .id = 3,
+ .resource = gio3_resources,
+ .num_resources = ARRAY_SIZE(gio3_resources),
+ .dev = {
+ .platform_data = &gio3_config,
+ },
+};
+
+static struct gpio_em_config gio4_config = {
+ .gpio_base = 128,
+ .irq_base = EMEV2_GPIO_IRQ(128),
+ .number_of_pins = 31,
+};
+
+static struct resource gio4_resources[] = {
+ [0] = {
+ .name = "GIO_128",
+ .start = 0xe0050200,
+ .end = 0xe005022b,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "GIO_128",
+ .start = 0xe0050240,
+ .end = 0xe005025f,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .start = 107,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ .start = 108,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device gio4_device = {
+ .name = "em_gio",
+ .id = 4,
+ .resource = gio4_resources,
+ .num_resources = ARRAY_SIZE(gio4_resources),
+ .dev = {
+ .platform_data = &gio4_config,
+ },
+};
+
+static struct platform_device *emev2_early_devices[] __initdata = {
+ &uart0_device,
+ &uart1_device,
+ &uart2_device,
+ &uart3_device,
+};
+
+static struct platform_device *emev2_late_devices[] __initdata = {
+ &sti_device,
+ &gio0_device,
+ &gio1_device,
+ &gio2_device,
+ &gio3_device,
+ &gio4_device,
+};
+
+void __init emev2_add_standard_devices(void)
+{
+ emev2_clock_init();
+
+ platform_add_devices(emev2_early_devices,
+ ARRAY_SIZE(emev2_early_devices));
+
+ platform_add_devices(emev2_late_devices,
+ ARRAY_SIZE(emev2_late_devices));
+}
+
+void __init emev2_init_delay(void)
+{
+ shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
+}
+
+void __init emev2_add_early_devices(void)
+{
+ emev2_init_delay();
+
+ early_platform_add_devices(emev2_early_devices,
+ ARRAY_SIZE(emev2_early_devices));
+
+ /* setup early console here as well */
+ shmobile_setup_console();
+}
+
+void __init emev2_init_irq(void)
+{
+ void __iomem *gic_dist_base;
+ void __iomem *gic_cpu_base;
+
+ /* Static mappings, never released */
+ gic_dist_base = ioremap(0xe0028000, PAGE_SIZE);
+ gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE);
+ BUG_ON(!gic_dist_base || !gic_cpu_base);
+
+ /* Use GIC to handle interrupts */
+ gic_init(0, 29, gic_dist_base, gic_cpu_base);
+}
+
+#ifdef CONFIG_USE_OF
+static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
+ { }
+};
+
+void __init emev2_add_standard_devices_dt(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table,
+ emev2_auxdata_lookup, NULL);
+}
+
+static const struct of_device_id emev2_dt_irq_match[] = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ {},
+};
+
+static const char *emev2_boards_compat_dt[] __initdata = {
+ "renesas,emev2",
+ NULL,
+};
+
+void __init emev2_init_irq_dt(void)
+{
+ of_irq_init(emev2_dt_irq_match);
+}
+
+DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
+ .init_early = emev2_init_delay,
+ .nr_irqs = NR_IRQS_LEGACY,
+ .init_irq = emev2_init_irq_dt,
+ .handle_irq = gic_handle_irq,
+ .init_machine = emev2_add_standard_devices_dt,
+ .timer = &shmobile_timer,
+ .dt_compat = emev2_boards_compat_dt,
+MACHINE_END
+
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 14edb5cffa7..34a1548dbda 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -350,19 +350,19 @@ static void r8a7740_i2c_workaround(struct platform_device *pdev)
i2c_write(reg, ICSTART, i2c_read(reg, ICSTART) | 0x10);
i2c_read(reg, ICSTART); /* dummy read */
- mdelay(100);
+ udelay(10);
i2c_write(reg, ICCR, 0x01);
- i2c_read(reg, ICCR);
i2c_write(reg, ICSTART, 0x00);
- i2c_read(reg, ICSTART);
+
+ udelay(10);
i2c_write(reg, ICCR, 0x10);
- mdelay(100);
+ udelay(10);
i2c_write(reg, ICCR, 0x00);
- mdelay(100);
+ udelay(10);
i2c_write(reg, ICCR, 0x10);
- mdelay(100);
+ udelay(10);
iounmap(reg);
}
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 4c7fece5ef9..6a4bd582c02 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -462,6 +462,16 @@ static const struct sh_dmae_slave_config sh7372_dmae_slaves[] = {
.chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xce,
}, {
+ .slave_id = SHDMA_SLAVE_FSIA_TX,
+ .addr = 0xfe1f0024,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb1,
+ }, {
+ .slave_id = SHDMA_SLAVE_FSIA_RX,
+ .addr = 0xfe1f0020,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb2,
+ }, {
.slave_id = SHDMA_SLAVE_MMCIF_TX,
.addr = 0xe6bd0034,
.chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
new file mode 100644
index 00000000000..6a35c4a31e6
--- /dev/null
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -0,0 +1,97 @@
+/*
+ * SMP support for Emma Mobile EV2
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Magnus Damm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/common.h>
+#include <mach/emev2.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include <asm/hardware/gic.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);
+
+}
+
+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;
+}
+
+int emev2_platform_cpu_kill(unsigned int cpu)
+{
+ return 0; /* not supported yet */
+}
+
+void __cpuinit emev2_secondary_init(unsigned int cpu)
+{
+ gic_secondary_init(0);
+}
+
+int __cpuinit emev2_boot_secondary(unsigned int cpu)
+{
+ 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));
+
+ gic_raise_softirq(cpumask_of(cpu), 1);
+ return 0;
+}
+
+void __init emev2_smp_prepare_cpus(void)
+{
+ int cpu = cpu_logical_map(0);
+
+ scu_enable(scu_base);
+
+ /* enable cache coherency on CPU0 */
+ modify_scu_cpu_psr(0, 3 << (cpu * 8));
+}
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index cba39d86668..a68919727e2 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -36,7 +36,8 @@ void __init shmobile_setup_delay(unsigned int max_cpu_core_mhz,
unsigned int value = (1000000 * mult) / (HZ * div);
- lpj_fine = max_cpu_core_mhz * value;
+ if (!preset_lpj)
+ preset_lpj = max_cpu_core_mhz * value;
}
static void __init shmobile_late_time_init(void)