aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/cpu/sh4
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/sh4')
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c43
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4.c12
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c130
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh4-202.c164
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c187
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c140
6 files changed, 548 insertions, 128 deletions
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index a33429463e9..21421e34e7d 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -21,10 +21,10 @@
static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 };
static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 };
-static void emi_clk_recalc(struct clk *clk)
+static unsigned long emi_clk_recalc(struct clk *clk)
{
int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007;
- clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+ return clk->parent->rate / frqcr3_divisors[idx];
}
static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
@@ -46,14 +46,14 @@ static struct clk_ops sh4202_emi_clk_ops = {
static struct clk sh4202_emi_clk = {
.name = "emi_clk",
- .flags = CLK_ALWAYS_ENABLED,
+ .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_emi_clk_ops,
};
-static void femi_clk_recalc(struct clk *clk)
+static unsigned long femi_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007;
- clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+ return clk->parent->rate / frqcr3_divisors[idx];
}
static struct clk_ops sh4202_femi_clk_ops = {
@@ -62,7 +62,7 @@ static struct clk_ops sh4202_femi_clk_ops = {
static struct clk sh4202_femi_clk = {
.name = "femi_clk",
- .flags = CLK_ALWAYS_ENABLED,
+ .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_femi_clk_ops,
};
@@ -90,10 +90,10 @@ static void shoc_clk_init(struct clk *clk)
WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */
}
-static void shoc_clk_recalc(struct clk *clk)
+static unsigned long shoc_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007;
- clk->rate = clk->parent->rate / frqcr3_divisors[idx];
+ return clk->parent->rate / frqcr3_divisors[idx];
}
static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
@@ -140,7 +140,7 @@ static struct clk_ops sh4202_shoc_clk_ops = {
static struct clk sh4202_shoc_clk = {
.name = "shoc_clk",
- .flags = CLK_ALWAYS_ENABLED,
+ .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_shoc_clk_ops,
};
@@ -150,31 +150,22 @@ static struct clk *sh4202_onchip_clocks[] = {
&sh4202_shoc_clk,
};
-static int __init sh4202_clk_init(void)
+int __init arch_clk_init(void)
{
- struct clk *clk = clk_get(NULL, "master_clk");
- int i;
+ struct clk *clk;
+ int i, ret = 0;
+
+ cpg_clk_init();
+ clk = clk_get(NULL, "master_clk");
for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
struct clk *clkp = sh4202_onchip_clocks[i];
clkp->parent = clk;
- clk_register(clkp);
- clk_enable(clkp);
+ ret |= clk_register(clkp);
}
- /*
- * Now that we have the rest of the clocks registered, we need to
- * force the parent clock to propagate so that these clocks will
- * automatically figure out their rate. We cheat by handing the
- * parent clock its current rate and forcing child propagation.
- */
- clk_set_rate(clk, clk_get_rate(clk));
-
clk_put(clk);
- return 0;
+ return ret;
}
-
-arch_initcall(sh4202_clk_init);
-
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c
index dca9f87a12d..73294d9cd04 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c
@@ -35,30 +35,30 @@ static struct clk_ops sh4_master_clk_ops = {
.init = master_clk_init,
};
-static void module_clk_recalc(struct clk *clk)
+static unsigned long module_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inw(FRQCR) & 0x0007);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ return clk->parent->rate / pfc_divisors[idx];
}
static struct clk_ops sh4_module_clk_ops = {
.recalc = module_clk_recalc,
};
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007;
- clk->rate = clk->parent->rate / bfc_divisors[idx];
+ return clk->parent->rate / bfc_divisors[idx];
}
static struct clk_ops sh4_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
{
int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007;
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ return clk->parent->rate / ifc_divisors[idx];
}
static struct clk_ops sh4_cpu_clk_ops = {
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 91e3677ae09..6c78d0a9c85 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -60,12 +60,18 @@ int __init detect_cpu_and_cache_system(void)
if ((cvr & 0x10000000) == 0)
boot_cpu_data.flags |= CPU_HAS_DSP;
- boot_cpu_data.flags |= CPU_HAS_LLSC;
+ boot_cpu_data.flags |= CPU_HAS_LLSC | CPU_HAS_PERF_COUNTER;
boot_cpu_data.cut_major = pvr & 0x7f;
+
+ boot_cpu_data.icache.ways = 4;
+ boot_cpu_data.dcache.ways = 4;
+ } else {
+ /* And some SH-4 defaults.. */
+ boot_cpu_data.flags |= CPU_HAS_PTEA;
}
/* FPU detection works for everyone */
- if ((cvr & 0x20000000) == 1)
+ if ((cvr & 0x20000000))
boot_cpu_data.flags |= CPU_HAS_FPU;
/* Mask off the upper chip ID */
@@ -78,25 +84,20 @@ int __init detect_cpu_and_cache_system(void)
switch (pvr) {
case 0x205:
boot_cpu_data.type = CPU_SH7750;
- boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
- CPU_HAS_PERF_COUNTER;
+ boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG |
+ CPU_HAS_PERF_COUNTER;
break;
case 0x206:
boot_cpu_data.type = CPU_SH7750S;
- boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
- CPU_HAS_PERF_COUNTER;
+ boot_cpu_data.flags |= CPU_HAS_P2_FLUSH_BUG |
+ CPU_HAS_PERF_COUNTER;
break;
case 0x1100:
boot_cpu_data.type = CPU_SH7751;
- boot_cpu_data.flags |= CPU_HAS_FPU;
break;
case 0x2001:
case 0x2004:
boot_cpu_data.type = CPU_SH7770;
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
-
- boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
break;
case 0x2006:
case 0x200A:
@@ -107,45 +108,26 @@ int __init detect_cpu_and_cache_system(void)
else
boot_cpu_data.type = CPU_SH7780;
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
-
- boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
- CPU_HAS_LLSC;
break;
case 0x3000:
case 0x3003:
case 0x3009:
boot_cpu_data.type = CPU_SH7343;
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
- boot_cpu_data.flags |= CPU_HAS_LLSC;
break;
case 0x3004:
case 0x3007:
boot_cpu_data.type = CPU_SH7785;
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
- boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
- CPU_HAS_LLSC;
break;
case 0x4004:
boot_cpu_data.type = CPU_SH7786;
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
- boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
- CPU_HAS_LLSC | CPU_HAS_PTEAEX;
+ boot_cpu_data.flags |= CPU_HAS_PTEAEX | CPU_HAS_L2_CACHE;
break;
case 0x3008:
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
- boot_cpu_data.flags |= CPU_HAS_LLSC;
-
switch (prr) {
case 0x50:
case 0x51:
boot_cpu_data.type = CPU_SH7723;
- boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_L2_CACHE;
+ boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
break;
case 0x70:
boot_cpu_data.type = CPU_SH7366;
@@ -156,13 +138,13 @@ int __init detect_cpu_and_cache_system(void)
break;
}
break;
+ case 0x300b:
+ boot_cpu_data.type = CPU_SH7724;
+ boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
+ break;
case 0x4000: /* 1st cut */
case 0x4001: /* 2nd cut */
boot_cpu_data.type = CPU_SHX3;
- boot_cpu_data.icache.ways = 4;
- boot_cpu_data.dcache.ways = 4;
- boot_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
- CPU_HAS_LLSC;
break;
case 0x700:
boot_cpu_data.type = CPU_SH4_501;
@@ -173,7 +155,6 @@ int __init detect_cpu_and_cache_system(void)
boot_cpu_data.type = CPU_SH4_202;
boot_cpu_data.icache.ways = 2;
boot_cpu_data.dcache.ways = 2;
- boot_cpu_data.flags |= CPU_HAS_FPU;
break;
case 0x500 ... 0x501:
switch (prr) {
@@ -191,18 +172,12 @@ int __init detect_cpu_and_cache_system(void)
boot_cpu_data.icache.ways = 2;
boot_cpu_data.dcache.ways = 2;
- boot_cpu_data.flags |= CPU_HAS_FPU;
-
break;
default:
boot_cpu_data.type = CPU_SH_NONE;
break;
}
-#ifdef CONFIG_CPU_HAS_PTEA
- boot_cpu_data.flags |= CPU_HAS_PTEA;
-#endif
-
/*
* On anything that's not a direct-mapped cache, look to the CVR
* for I/D-cache specifics.
@@ -222,43 +197,48 @@ int __init detect_cpu_and_cache_system(void)
}
/*
- * Setup the L2 cache desc
- *
* SH-4A's have an optional PIPT L2.
*/
if (boot_cpu_data.flags & CPU_HAS_L2_CACHE) {
- /* Bug if we can't decode the L2 info */
- BUG_ON(!(cvr & 0xf));
-
- /* Silicon and specifications have clearly never met.. */
- cvr ^= 0xf;
-
/*
- * Size calculation is much more sensible
- * than it is for the L1.
- *
- * Sizes are 128KB, 258KB, 512KB, and 1MB.
+ * Verify that it really has something hooked up, this
+ * is the safety net for CPUs that have optional L2
+ * support yet do not implement it.
*/
- size = (cvr & 0xf) << 17;
-
- BUG_ON(!size);
-
- boot_cpu_data.scache.way_incr = (1 << 16);
- boot_cpu_data.scache.entry_shift = 5;
- boot_cpu_data.scache.ways = 4;
- boot_cpu_data.scache.linesz = L1_CACHE_BYTES;
-
- boot_cpu_data.scache.entry_mask =
- (boot_cpu_data.scache.way_incr -
- boot_cpu_data.scache.linesz);
-
- boot_cpu_data.scache.sets = size /
- (boot_cpu_data.scache.linesz *
- boot_cpu_data.scache.ways);
-
- boot_cpu_data.scache.way_size =
- (boot_cpu_data.scache.sets *
- boot_cpu_data.scache.linesz);
+ if ((cvr & 0xf) == 0)
+ boot_cpu_data.flags &= ~CPU_HAS_L2_CACHE;
+ else {
+ /*
+ * Silicon and specifications have clearly never
+ * met..
+ */
+ cvr ^= 0xf;
+
+ /*
+ * Size calculation is much more sensible
+ * than it is for the L1.
+ *
+ * Sizes are 128KB, 258KB, 512KB, and 1MB.
+ */
+ size = (cvr & 0xf) << 17;
+
+ boot_cpu_data.scache.way_incr = (1 << 16);
+ boot_cpu_data.scache.entry_shift = 5;
+ boot_cpu_data.scache.ways = 4;
+ boot_cpu_data.scache.linesz = L1_CACHE_BYTES;
+
+ boot_cpu_data.scache.entry_mask =
+ (boot_cpu_data.scache.way_incr -
+ boot_cpu_data.scache.linesz);
+
+ boot_cpu_data.scache.sets = size /
+ (boot_cpu_data.scache.linesz *
+ boot_cpu_data.scache.ways);
+
+ boot_cpu_data.scache.way_size =
+ (boot_cpu_data.scache.sets *
+ boot_cpu_data.scache.linesz);
+ }
}
return 0;
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
index 7371abf64f8..6d088d12359 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
@@ -2,6 +2,7 @@
* SH4-202 Setup
*
* Copyright (C) 2006 Paul Mundt
+ * Copyright (C) 2009 Magnus Damm
*
* 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
@@ -11,6 +12,8 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
static struct plat_sci_port sci_platform_data[] = {
{
@@ -31,8 +34,103 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "peripheral_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "peripheral_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
static struct platform_device *sh4202_devices[] __initdata = {
&sci_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
};
static int __init sh4202_devices_setup(void)
@@ -42,7 +140,71 @@ static int __init sh4202_devices_setup(void)
}
__initcall(sh4202_devices_setup);
+static struct platform_device *sh4202_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh4202_early_devices,
+ ARRAY_SIZE(sh4202_early_devices));
+}
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
+ HUDI, TMU0, TMU1, TMU2, RTC, SCIF, WDT,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(HUDI, 0x600),
+ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
+ INTC_VECT(SCIF, 0x700), INTC_VECT(SCIF, 0x720),
+ INTC_VECT(SCIF, 0x740), INTC_VECT(SCIF, 0x760),
+ INTC_VECT(WDT, 0x560),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
+ { 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, 0, 0, 0 } },
+ { 0xffd0000c, 0, 16, 4, /* IPRC */ { 0, 0, SCIF, HUDI } },
+ { 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh4-202", vectors, NULL,
+ NULL, prio_registers, NULL);
+
+static struct intc_vect vectors_irlm[] __initdata = {
+ INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0),
+ INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irlm, "sh4-202_irlm", vectors_irlm, NULL,
+ NULL, prio_registers, NULL);
+
void __init plat_irq_setup(void)
{
- /* do nothing - all IRL interrupts are handled by the board code */
+ register_intc_controller(&intc_desc);
+}
+
+#define INTC_ICR 0xffd00000UL
+#define INTC_ICR_IRLM (1<<7)
+
+void __init plat_irq_setup_pins(int mode)
+{
+ switch (mode) {
+ case IRQ_MODE_IRQ: /* individual interrupt mode for IRL3-0 */
+ ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+ register_intc_controller(&intc_desc_irlm);
+ break;
+ default:
+ BUG();
+ }
}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index a1c80d909cd..851672d15cf 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/io.h>
+#include <linux/sh_timer.h>
#include <linux/serial_sci.h>
static struct resource rtc_resources[] = {
@@ -60,9 +61,177 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "peripheral_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "peripheral_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+/* SH7750R, SH7751 and SH7751R all have two extra timer channels */
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+
+static struct sh_timer_config tmu3_platform_data = {
+ .name = "TMU3",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "peripheral_clk",
+};
+
+static struct resource tmu3_resources[] = {
+ [0] = {
+ .name = "TMU3",
+ .start = 0xfe100008,
+ .end = 0xfe100013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 72,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu3_device = {
+ .name = "sh_tmu",
+ .id = 3,
+ .dev = {
+ .platform_data = &tmu3_platform_data,
+ },
+ .resource = tmu3_resources,
+ .num_resources = ARRAY_SIZE(tmu3_resources),
+};
+
+static struct sh_timer_config tmu4_platform_data = {
+ .name = "TMU4",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "peripheral_clk",
+};
+
+static struct resource tmu4_resources[] = {
+ [0] = {
+ .name = "TMU4",
+ .start = 0xfe100014,
+ .end = 0xfe10001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 76,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu4_device = {
+ .name = "sh_tmu",
+ .id = 4,
+ .dev = {
+ .platform_data = &tmu4_platform_data,
+ },
+ .resource = tmu4_resources,
+ .num_resources = ARRAY_SIZE(tmu4_resources),
+};
+
+#endif
+
static struct platform_device *sh7750_devices[] __initdata = {
&rtc_device,
&sci_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+ &tmu3_device,
+ &tmu4_device,
+#endif
};
static int __init sh7750_devices_setup(void)
@@ -72,6 +241,24 @@ static int __init sh7750_devices_setup(void)
}
__initcall(sh7750_devices_setup);
+static struct platform_device *sh7750_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+ &tmu3_device,
+ &tmu4_device,
+#endif
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7750_early_devices,
+ ARRAY_SIZE(sh7750_early_devices));
+}
+
enum {
UNUSED = 0,
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index d9bdc931ac0..5b822519bd9 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -10,6 +10,7 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/sh_timer.h>
#include <linux/serial_sci.h>
#include <linux/io.h>
@@ -18,10 +19,7 @@ enum {
/* interrupt sources */
IRL0, IRL1, IRL2, IRL3,
- HUDI, GPIOI,
- DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
- DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
- DMAC_DMAE,
+ HUDI, GPIOI, DMAC,
IRQ4, IRQ5, IRQ6, IRQ7,
HCAN20, HCAN21,
SSI0, SSI1,
@@ -36,21 +34,20 @@ enum {
HSPI,
MMCIF0, MMCIF1, MMCIF2, MMCIF3,
MFI, ADC, CMT,
- TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
- WDT,
- REF_RCMI, REF_ROVI,
+ TMU0, TMU1, TMU2,
+ WDT, REF,
/* interrupt groups */
- DMAC, DMABRG, SCIF0, SCIF1, SCIF2, SIM, MMCIF, TMU2, REF,
+ DMABRG, SCIF0, SCIF1, SCIF2, SIM, MMCIF,
};
static struct intc_vect vectors[] __initdata = {
INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
- INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
- INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
- INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0),
- INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0),
- INTC_VECT(DMAC_DMAE, 0x6c0),
+ INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+ INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+ INTC_VECT(DMAC, 0x780), INTC_VECT(DMAC, 0x7a0),
+ INTC_VECT(DMAC, 0x7c0), INTC_VECT(DMAC, 0x7e0),
+ INTC_VECT(DMAC, 0x6c0),
INTC_VECT(IRQ4, 0x800), INTC_VECT(IRQ5, 0x820),
INTC_VECT(IRQ6, 0x840), INTC_VECT(IRQ6, 0x860),
INTC_VECT(HCAN20, 0x900), INTC_VECT(HCAN21, 0x920),
@@ -74,23 +71,18 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(MFI, 0xe80), /* 0xf80 according to data sheet */
INTC_VECT(ADC, 0xf80), INTC_VECT(CMT, 0xfa0),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
INTC_VECT(WDT, 0x560),
- INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
+ INTC_VECT(REF, 0x580), INTC_VECT(REF, 0x5a0),
};
static struct intc_group groups[] __initdata = {
- INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
- DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
- DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
INTC_GROUP(DMABRG, DMABRG0, DMABRG1, DMABRG2),
INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEI),
INTC_GROUP(MMCIF, MMCIF0, MMCIF1, MMCIF2, MMCIF3),
- INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
- INTC_GROUP(REF, REF_RCMI, REF_ROVI),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -168,8 +160,104 @@ static struct platform_device sci_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .name = "TMU0",
+ .channel_offset = 0x04,
+ .timer_bit = 0,
+ .clk = "peripheral_clk",
+ .clockevent_rating = 200,
+};
+
+static struct resource tmu0_resources[] = {
+ [0] = {
+ .name = "TMU0",
+ .start = 0xffd80008,
+ .end = 0xffd80013,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 16,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh_tmu",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
+static struct sh_timer_config tmu1_platform_data = {
+ .name = "TMU1",
+ .channel_offset = 0x10,
+ .timer_bit = 1,
+ .clk = "peripheral_clk",
+ .clocksource_rating = 200,
+};
+
+static struct resource tmu1_resources[] = {
+ [0] = {
+ .name = "TMU1",
+ .start = 0xffd80014,
+ .end = 0xffd8001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 17,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu1_device = {
+ .name = "sh_tmu",
+ .id = 1,
+ .dev = {
+ .platform_data = &tmu1_platform_data,
+ },
+ .resource = tmu1_resources,
+ .num_resources = ARRAY_SIZE(tmu1_resources),
+};
+
+static struct sh_timer_config tmu2_platform_data = {
+ .name = "TMU2",
+ .channel_offset = 0x1c,
+ .timer_bit = 2,
+ .clk = "peripheral_clk",
+};
+
+static struct resource tmu2_resources[] = {
+ [0] = {
+ .name = "TMU2",
+ .start = 0xffd80020,
+ .end = 0xffd8002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 18,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device tmu2_device = {
+ .name = "sh_tmu",
+ .id = 2,
+ .dev = {
+ .platform_data = &tmu2_platform_data,
+ },
+ .resource = tmu2_resources,
+ .num_resources = ARRAY_SIZE(tmu2_resources),
+};
+
+
static struct platform_device *sh7760_devices[] __initdata = {
&sci_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
};
static int __init sh7760_devices_setup(void)
@@ -179,6 +267,18 @@ static int __init sh7760_devices_setup(void)
}
__initcall(sh7760_devices_setup);
+static struct platform_device *sh7760_early_devices[] __initdata = {
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7760_early_devices,
+ ARRAY_SIZE(sh7760_early_devices));
+}
+
#define INTC_ICR 0xffd00000UL
#define INTC_ICR_IRLM (1 << 7)