aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu')
-rw-r--r--arch/sh/kernel/cpu/Makefile5
-rw-r--r--arch/sh/kernel/cpu/adc.c12
-rw-r--r--arch/sh/kernel/cpu/clock-cpg.c78
-rw-r--r--arch/sh/kernel/cpu/clock.c340
-rw-r--r--arch/sh/kernel/cpu/fpu.c86
-rw-r--r--arch/sh/kernel/cpu/init.c184
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile2
-rw-r--r--arch/sh/kernel/cpu/irq/imask.c71
-rw-r--r--arch/sh/kernel/cpu/irq/intc-sh5.c95
-rw-r--r--arch/sh/kernel/cpu/irq/intc.c710
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c50
-rw-r--r--arch/sh/kernel/cpu/pfc.c33
-rw-r--r--arch/sh/kernel/cpu/proc.c150
-rw-r--r--arch/sh/kernel/cpu/sh2/clock-sh7619.c52
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S3
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c6
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c172
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile12
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7201.c85
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7203.c52
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7206.c48
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7264.c153
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7269.c184
-rw-r--r--arch/sh/kernel/cpu/sh2a/entry.S3
-rw-r--r--arch/sh/kernel/cpu/sh2a/ex.S1
-rw-r--r--arch/sh/kernel/cpu/sh2a/fpu.c111
-rw-r--r--arch/sh/kernel/cpu/sh2a/opcode_helper.c1
-rw-r--r--arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c30
-rw-r--r--arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c30
-rw-r--r--arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c31
-rw-r--r--arch/sh/kernel/cpu/sh2a/probe.c19
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-mxg.c120
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7201.c428
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7203.c408
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c323
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7264.c570
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7269.c586
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile24
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh3.c32
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7705.c32
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7706.c32
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7709.c43
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7710.c32
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7712.c24
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S483
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S8
-rw-r--r--arch/sh/kernel/cpu/sh3/pinmux-sh7720.c30
-rw-r--r--arch/sh/kernel/cpu/sh3/probe.c30
-rw-r--r--arch/sh/kernel/cpu/sh3/serial-sh770x.c33
-rw-r--r--arch/sh/kernel/cpu/sh3/serial-sh7710.c20
-rw-r--r--arch/sh/kernel/cpu/sh3/serial-sh7720.c37
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh3.c2
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7705.c162
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh770x.c207
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7710.c161
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7720.c205
-rw-r--r--arch/sh/kernel/cpu/sh3/swsusp.S147
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile9
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c79
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4.c32
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c178
-rw-r--r--arch/sh/kernel/cpu/sh4/perf_event.c268
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c174
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh4-202.c124
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c238
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c201
-rw-r--r--arch/sh/kernel/cpu/sh4/softfloat.c102
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c50
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile37
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7343.c289
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7366.c282
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7722.c863
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7723.c313
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7724.c377
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7734.c260
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7757.c155
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7763.c79
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7770.c32
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7780.c77
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7785.c251
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7786.c192
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-shx3.c196
-rw-r--r--arch/sh/kernel/cpu/sh4a/intc-shx3.c34
-rw-r--r--arch/sh/kernel/cpu/sh4a/perf_event.c302
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c20
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c30
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c35
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c35
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c35
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c30
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c35
-rw-r--r--arch/sh/kernel/cpu/sh4a/pinmux-shx3.c29
-rw-r--r--arch/sh/kernel/cpu/sh4a/serial-sh7722.c23
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c244
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c170
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c460
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c360
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c1305
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7734.c629
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7757.c1247
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7763.c304
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7770.c609
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c376
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7785.c473
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7786.c848
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-shx3.c236
-rw-r--r--arch/sh/kernel/cpu/sh4a/smp-shx3.c156
-rw-r--r--arch/sh/kernel/cpu/sh4a/ubc.c133
-rw-r--r--arch/sh/kernel/cpu/sh5/Makefile8
-rw-r--r--arch/sh/kernel/cpu/sh5/clock-sh5.c79
-rw-r--r--arch/sh/kernel/cpu/sh5/entry.S191
-rw-r--r--arch/sh/kernel/cpu/sh5/fpu.c68
-rw-r--r--arch/sh/kernel/cpu/sh5/probe.c6
-rw-r--r--arch/sh/kernel/cpu/sh5/setup-sh5.c123
-rw-r--r--arch/sh/kernel/cpu/sh5/unwind.c63
-rw-r--r--arch/sh/kernel/cpu/shmobile/Makefile7
-rw-r--r--arch/sh/kernel/cpu/shmobile/cpuidle.c101
-rw-r--r--arch/sh/kernel/cpu/shmobile/pm.c156
-rw-r--r--arch/sh/kernel/cpu/shmobile/sleep.S405
-rw-r--r--arch/sh/kernel/cpu/ubc.S59
120 files changed, 16285 insertions, 4985 deletions
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index f471d242774..accc7ca722e 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -11,10 +11,11 @@ obj-$(CONFIG_CPU_SH5) = sh5/
# Special cases for family ancestry.
obj-$(CONFIG_CPU_SH4A) += sh4a/
+obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/
# Common interfaces.
-obj-$(CONFIG_UBC_WAKEUP) += ubc.o
obj-$(CONFIG_SH_ADC) += adc.o
+obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o
-obj-y += irq/ init.o clock.o
+obj-y += irq/ init.o clock.o fpu.o pfc.o proc.o
diff --git a/arch/sh/kernel/cpu/adc.c b/arch/sh/kernel/cpu/adc.c
index da3d6877f93..d307571d54b 100644
--- a/arch/sh/kernel/cpu/adc.c
+++ b/arch/sh/kernel/cpu/adc.c
@@ -18,19 +18,19 @@ int adc_single(unsigned int channel)
off = (channel & 0x03) << 2;
- csr = ctrl_inb(ADCSR);
+ csr = __raw_readb(ADCSR);
csr = channel | ADCSR_ADST | ADCSR_CKS;
- ctrl_outb(csr, ADCSR);
+ __raw_writeb(csr, ADCSR);
do {
- csr = ctrl_inb(ADCSR);
+ csr = __raw_readb(ADCSR);
} while ((csr & ADCSR_ADF) == 0);
csr &= ~(ADCSR_ADF | ADCSR_ADST);
- ctrl_outb(csr, ADCSR);
+ __raw_writeb(csr, ADCSR);
- return (((ctrl_inb(ADDRAH + off) << 8) |
- ctrl_inb(ADDRAL + off)) >> 6);
+ return (((__raw_readb(ADDRAH + off) << 8) |
+ __raw_readb(ADDRAL + off)) >> 6);
}
EXPORT_SYMBOL(adc_single);
diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c
new file mode 100644
index 00000000000..8525a671266
--- /dev/null
+++ b/arch/sh/kernel/cpu/clock-cpg.c
@@ -0,0 +1,78 @@
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+static struct clk master_clk = {
+ .flags = CLK_ENABLE_ON_INIT,
+ .rate = CONFIG_SH_PCLK_FREQ,
+};
+
+static struct clk peripheral_clk = {
+ .parent = &master_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static struct clk bus_clk = {
+ .parent = &master_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static struct clk cpu_clk = {
+ .parent = &master_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+/*
+ * The ordering of these clocks matters, do not change it.
+ */
+static struct clk *onchip_clocks[] = {
+ &master_clk,
+ &peripheral_clk,
+ &bus_clk,
+ &cpu_clk,
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("master_clk", &master_clk),
+ CLKDEV_CON_ID("peripheral_clk", &peripheral_clk),
+ CLKDEV_CON_ID("bus_clk", &bus_clk),
+ CLKDEV_CON_ID("cpu_clk", &cpu_clk),
+};
+
+int __init __deprecated cpg_clk_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
+ struct clk *clk = onchip_clocks[i];
+ arch_init_clk_ops(&clk->ops, i);
+ if (clk->ops)
+ ret |= clk_register(clk);
+ }
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ clk_add_alias("fck", "sh-tmu-sh3.0", "peripheral_clk", NULL);
+ clk_add_alias("fck", "sh-tmu.0", "peripheral_clk", NULL);
+ clk_add_alias("fck", "sh-tmu.1", "peripheral_clk", NULL);
+ clk_add_alias("fck", "sh-tmu.2", "peripheral_clk", NULL);
+ clk_add_alias("fck", "sh-mtu2", "peripheral_clk", NULL);
+ clk_add_alias("fck", "sh-cmt-16.0", "peripheral_clk", NULL);
+ clk_add_alias("fck", "sh-cmt-32.0", "peripheral_clk", NULL);
+ clk_add_alias("sci_ick", NULL, "peripheral_clk", NULL);
+
+ return ret;
+}
+
+/*
+ * Placeholder for compatibility, until the lazy CPUs do this
+ * on their own.
+ */
+int __init __weak arch_clk_init(void)
+{
+ return cpg_clk_init();
+}
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index f5eb56e6bc5..4187cf4fe18 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -1,11 +1,11 @@
/*
* arch/sh/kernel/cpu/clock.c - SuperH clock framework
*
- * Copyright (C) 2005, 2006, 2007 Paul Mundt
+ * Copyright (C) 2005 - 2009 Paul Mundt
*
* This clock framework is derived from the OMAP version by:
*
- * Copyright (C) 2004 - 2005 Nokia Corporation
+ * Copyright (C) 2004 - 2008 Nokia Corporation
* Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
*
* Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
@@ -16,338 +16,36 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/kref.h>
-#include <linux/seq_file.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/proc_fs.h>
+#include <linux/clk.h>
#include <asm/clock.h>
-#include <asm/timer.h>
+#include <asm/machvec.h>
-static LIST_HEAD(clock_list);
-static DEFINE_SPINLOCK(clock_lock);
-static DEFINE_MUTEX(clock_list_sem);
-
-/*
- * Each subtype is expected to define the init routines for these clocks,
- * as each subtype (or processor family) will have these clocks at the
- * very least. These are all provided through the CPG, which even some of
- * the more quirky parts (such as ST40, SH4-202, etc.) still have.
- *
- * The processor-specific code is expected to register any additional
- * clock sources that are of interest.
- */
-static struct clk master_clk = {
- .name = "master_clk",
- .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
- .rate = CONFIG_SH_PCLK_FREQ,
-};
-
-static struct clk module_clk = {
- .name = "module_clk",
- .parent = &master_clk,
- .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-};
-
-static struct clk bus_clk = {
- .name = "bus_clk",
- .parent = &master_clk,
- .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES,
-};
-
-static struct clk cpu_clk = {
- .name = "cpu_clk",
- .parent = &master_clk,
- .flags = CLK_ALWAYS_ENABLED,
-};
-
-/*
- * The ordering of these clocks matters, do not change it.
- */
-static struct clk *onchip_clocks[] = {
- &master_clk,
- &module_clk,
- &bus_clk,
- &cpu_clk,
-};
-
-static void propagate_rate(struct clk *clk)
-{
- struct clk *clkp;
-
- list_for_each_entry(clkp, &clock_list, node) {
- if (likely(clkp->parent != clk))
- continue;
- if (likely(clkp->ops && clkp->ops->recalc))
- clkp->ops->recalc(clkp);
- if (unlikely(clkp->flags & CLK_RATE_PROPAGATES))
- propagate_rate(clkp);
- }
-}
-
-static int __clk_enable(struct clk *clk)
-{
- /*
- * See if this is the first time we're enabling the clock, some
- * clocks that are always enabled still require "special"
- * initialization. This is especially true if the clock mode
- * changes and the clock needs to hunt for the proper set of
- * divisors to use before it can effectively recalc.
- */
- if (unlikely(atomic_read(&clk->kref.refcount) == 1))
- if (clk->ops && clk->ops->init)
- clk->ops->init(clk);
-
- kref_get(&clk->kref);
-
- if (clk->flags & CLK_ALWAYS_ENABLED)
- return 0;
-
- if (likely(clk->ops && clk->ops->enable))
- clk->ops->enable(clk);
-
- return 0;
-}
-
-int clk_enable(struct clk *clk)
+int __init clk_init(void)
{
- unsigned long flags;
int ret;
- spin_lock_irqsave(&clock_lock, flags);
- ret = __clk_enable(clk);
- spin_unlock_irqrestore(&clock_lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(clk_enable);
-
-static void clk_kref_release(struct kref *kref)
-{
- /* Nothing to do */
-}
-
-static void __clk_disable(struct clk *clk)
-{
- int count = kref_put(&clk->kref, clk_kref_release);
-
- if (clk->flags & CLK_ALWAYS_ENABLED)
- return;
-
- if (!count) { /* count reaches zero, disable the clock */
- if (likely(clk->ops && clk->ops->disable))
- clk->ops->disable(clk);
- }
-}
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clock_lock, flags);
- __clk_disable(clk);
- spin_unlock_irqrestore(&clock_lock, flags);
-}
-EXPORT_SYMBOL_GPL(clk_disable);
-
-int clk_register(struct clk *clk)
-{
- mutex_lock(&clock_list_sem);
-
- list_add(&clk->node, &clock_list);
- kref_init(&clk->kref);
-
- mutex_unlock(&clock_list_sem);
-
- if (clk->flags & CLK_ALWAYS_ENABLED) {
- pr_debug( "Clock '%s' is ALWAYS_ENABLED\n", clk->name);
- if (clk->ops && clk->ops->init)
- clk->ops->init(clk);
- if (clk->ops && clk->ops->enable)
- clk->ops->enable(clk);
- pr_debug( "Enabled.");
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
- mutex_lock(&clock_list_sem);
- list_del(&clk->node);
- mutex_unlock(&clock_list_sem);
-}
-EXPORT_SYMBOL_GPL(clk_unregister);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
- return clk_set_rate_ex(clk, rate, 0);
-}
-EXPORT_SYMBOL_GPL(clk_set_rate);
-
-int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
-{
- int ret = -EOPNOTSUPP;
-
- if (likely(clk->ops && clk->ops->set_rate)) {
- unsigned long flags;
-
- spin_lock_irqsave(&clock_lock, flags);
- ret = clk->ops->set_rate(clk, rate, algo_id);
- spin_unlock_irqrestore(&clock_lock, flags);
+ ret = arch_clk_init();
+ if (unlikely(ret)) {
+ pr_err("%s: CPU clock registration failed.\n", __func__);
+ return ret;
}
- if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
- propagate_rate(clk);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_rate_ex);
-
-void clk_recalc_rate(struct clk *clk)
-{
- if (likely(clk->ops && clk->ops->recalc)) {
- unsigned long flags;
-
- spin_lock_irqsave(&clock_lock, flags);
- clk->ops->recalc(clk);
- spin_unlock_irqrestore(&clock_lock, flags);
- }
-
- if (unlikely(clk->flags & CLK_RATE_PROPAGATES))
- propagate_rate(clk);
-}
-EXPORT_SYMBOL_GPL(clk_recalc_rate);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
- if (likely(clk->ops && clk->ops->round_rate)) {
- unsigned long flags, rounded;
-
- spin_lock_irqsave(&clock_lock, flags);
- rounded = clk->ops->round_rate(clk, rate);
- spin_unlock_irqrestore(&clock_lock, flags);
-
- return rounded;
- }
-
- return clk_get_rate(clk);
-}
-EXPORT_SYMBOL_GPL(clk_round_rate);
-
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk *clk_get(struct device *dev, const char *id)
-{
- struct clk *p, *clk = ERR_PTR(-ENOENT);
- int idno;
-
- if (dev == NULL || dev->bus != &platform_bus_type)
- idno = -1;
- else
- idno = to_platform_device(dev)->id;
-
- mutex_lock(&clock_list_sem);
- list_for_each_entry(p, &clock_list, node) {
- if (p->id == idno &&
- strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- goto found;
+ if (sh_mv.mv_clk_init) {
+ ret = sh_mv.mv_clk_init();
+ if (unlikely(ret)) {
+ pr_err("%s: machvec clock initialization failed.\n",
+ __func__);
+ return ret;
}
}
- list_for_each_entry(p, &clock_list, node) {
- if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
-
-found:
- mutex_unlock(&clock_list_sem);
-
- return clk;
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
- if (clk && !IS_ERR(clk))
- module_put(clk->owner);
-}
-EXPORT_SYMBOL_GPL(clk_put);
-
-void __init __attribute__ ((weak))
-arch_init_clk_ops(struct clk_ops **ops, int type)
-{
-}
-
-void __init __attribute__ ((weak))
-arch_clk_init(void)
-{
-}
-
-static int show_clocks(char *buf, char **start, off_t off,
- int len, int *eof, void *data)
-{
- struct clk *clk;
- char *p = buf;
-
- list_for_each_entry_reverse(clk, &clock_list, node) {
- unsigned long rate = clk_get_rate(clk);
-
- p += sprintf(p, "%-12s\t: %ld.%02ldMHz\t%s\n", clk->name,
- rate / 1000000, (rate % 1000000) / 10000,
- ((clk->flags & CLK_ALWAYS_ENABLED) ||
- (atomic_read(&clk->kref.refcount) != 1)) ?
- "enabled" : "disabled");
- }
-
- return p - buf;
-}
-
-int __init clk_init(void)
-{
- int i, ret = 0;
-
- BUG_ON(!master_clk.rate);
-
- for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
- struct clk *clk = onchip_clocks[i];
-
- arch_init_clk_ops(&clk->ops, i);
- ret |= clk_register(clk);
- }
-
- arch_clk_init();
-
/* Kick the child clocks.. */
- propagate_rate(&master_clk);
- propagate_rate(&bus_clk);
+ recalculate_root_clocks();
+
+ /* Enable the necessary init clocks */
+ clk_enable_init_clocks();
return ret;
}
-static int __init clk_proc_init(void)
-{
- struct proc_dir_entry *p;
- p = create_proc_read_entry("clocks", S_IRUSR, NULL,
- show_clocks, NULL);
- if (unlikely(!p))
- return -EINVAL;
- return 0;
-}
-subsys_initcall(clk_proc_init);
diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c
new file mode 100644
index 00000000000..4e332244ea7
--- /dev/null
+++ b/arch/sh/kernel/cpu/fpu.c
@@ -0,0 +1,86 @@
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <asm/processor.h>
+#include <asm/fpu.h>
+#include <asm/traps.h>
+
+int init_fpu(struct task_struct *tsk)
+{
+ if (tsk_used_math(tsk)) {
+ if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
+ unlazy_fpu(tsk, task_pt_regs(tsk));
+ return 0;
+ }
+
+ /*
+ * Memory allocation at the first usage of the FPU and other state.
+ */
+ if (!tsk->thread.xstate) {
+ tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep,
+ GFP_KERNEL);
+ if (!tsk->thread.xstate)
+ return -ENOMEM;
+ }
+
+ if (boot_cpu_data.flags & CPU_HAS_FPU) {
+ struct sh_fpu_hard_struct *fp = &tsk->thread.xstate->hardfpu;
+ memset(fp, 0, xstate_size);
+ fp->fpscr = FPSCR_INIT;
+ } else {
+ struct sh_fpu_soft_struct *fp = &tsk->thread.xstate->softfpu;
+ memset(fp, 0, xstate_size);
+ fp->fpscr = FPSCR_INIT;
+ }
+
+ set_stopped_child_used_math(tsk);
+ return 0;
+}
+
+#ifdef CONFIG_SH_FPU
+void __fpu_state_restore(void)
+{
+ struct task_struct *tsk = current;
+
+ restore_fpu(tsk);
+
+ task_thread_info(tsk)->status |= TS_USEDFPU;
+ tsk->thread.fpu_counter++;
+}
+
+void fpu_state_restore(struct pt_regs *regs)
+{
+ struct task_struct *tsk = current;
+
+ if (unlikely(!user_mode(regs))) {
+ printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
+ BUG();
+ return;
+ }
+
+ if (!tsk_used_math(tsk)) {
+ local_irq_enable();
+ /*
+ * does a slab alloc which can sleep
+ */
+ if (init_fpu(tsk)) {
+ /*
+ * ran out of memory!
+ */
+ do_group_exit(SIGKILL);
+ return;
+ }
+ local_irq_disable();
+ }
+
+ grab_fpu(regs);
+
+ __fpu_state_restore();
+}
+
+BUILD_TRAP_HANDLER(fpu_state_restore)
+{
+ TRAP_HANDLER_DECL;
+
+ fpu_state_restore(regs);
+}
+#endif /* CONFIG_SH_FPU */
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index 75fb03d3567..0d7360d549c 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -3,7 +3,7 @@
*
* CPU init code
*
- * Copyright (C) 2002 - 2007 Paul Mundt
+ * Copyright (C) 2002 - 2009 Paul Mundt
* Copyright (C) 2003 Richard Curnow
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -18,28 +18,38 @@
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/page.h>
-#include <asm/system.h>
#include <asm/cacheflush.h>
#include <asm/cache.h>
#include <asm/elf.h>
#include <asm/io.h>
#include <asm/smp.h>
-#ifdef CONFIG_SUPERH32
-#include <asm/ubc.h>
+#include <asm/sh_bios.h>
+#include <asm/setup.h>
+
+#ifdef CONFIG_SH_FPU
+#define cpu_has_fpu 1
+#else
+#define cpu_has_fpu 0
+#endif
+
+#ifdef CONFIG_SH_DSP
+#define cpu_has_dsp 1
+#else
+#define cpu_has_dsp 0
#endif
/*
* Generic wrapper for command line arguments to disable on-chip
* peripherals (nofpu, nodsp, and so forth).
*/
-#define onchip_setup(x) \
-static int x##_disabled __initdata = 0; \
- \
-static int __init x##_setup(char *opts) \
-{ \
- x##_disabled = 1; \
- return 1; \
-} \
+#define onchip_setup(x) \
+static int x##_disabled = !cpu_has_##x; \
+ \
+static int x##_setup(char *opts) \
+{ \
+ x##_disabled = 1; \
+ return 1; \
+} \
__setup("no" __stringify(x), x##_setup);
onchip_setup(fpu);
@@ -49,29 +59,60 @@ onchip_setup(dsp);
#define CPUOPM 0xff2f0000
#define CPUOPM_RABD (1 << 5)
-static void __init speculative_execution_init(void)
+static void speculative_execution_init(void)
{
/* Clear RABD */
- ctrl_outl(ctrl_inl(CPUOPM) & ~CPUOPM_RABD, CPUOPM);
+ __raw_writel(__raw_readl(CPUOPM) & ~CPUOPM_RABD, CPUOPM);
/* Flush the update */
- (void)ctrl_inl(CPUOPM);
+ (void)__raw_readl(CPUOPM);
ctrl_barrier();
}
#else
#define speculative_execution_init() do { } while (0)
#endif
+#ifdef CONFIG_CPU_SH4A
+#define EXPMASK 0xff2f0004
+#define EXPMASK_RTEDS (1 << 0)
+#define EXPMASK_BRDSSLP (1 << 1)
+#define EXPMASK_MMCAW (1 << 4)
+
+static void expmask_init(void)
+{
+ unsigned long expmask = __raw_readl(EXPMASK);
+
+ /*
+ * Future proofing.
+ *
+ * Disable support for slottable sleep instruction, non-nop
+ * instructions in the rte delay slot, and associative writes to
+ * the memory-mapped cache array.
+ */
+ expmask &= ~(EXPMASK_RTEDS | EXPMASK_BRDSSLP | EXPMASK_MMCAW);
+
+ __raw_writel(expmask, EXPMASK);
+ ctrl_barrier();
+}
+#else
+#define expmask_init() do { } while (0)
+#endif
+
+/* 2nd-level cache init */
+void __attribute__ ((weak)) l2_cache_init(void)
+{
+}
+
/*
* Generic first-level cache init
*/
#ifdef CONFIG_SUPERH32
-static void __uses_jump_to_uncached cache_init(void)
+static void cache_init(void)
{
unsigned long ccr, flags;
jump_to_uncached();
- ccr = ctrl_inl(CCR);
+ ccr = __raw_readl(SH_CCR);
/*
* At this point we don't know whether the cache is enabled or not - a
@@ -115,7 +156,7 @@ static void __uses_jump_to_uncached cache_init(void)
for (addr = addrstart;
addr < addrstart + waysize;
addr += current_cpu_data.dcache.linesz)
- ctrl_outl(0, addr);
+ __raw_writel(0, addr);
addrstart += current_cpu_data.dcache.way_incr;
} while (--ways);
@@ -146,7 +187,9 @@ static void __uses_jump_to_uncached cache_init(void)
flags &= ~CCR_CACHE_ENABLE;
#endif
- ctrl_outl(flags, CCR);
+ l2_cache_init();
+
+ __raw_writel(flags, SH_CCR);
back_to_cached();
}
#else
@@ -174,8 +217,20 @@ static void detect_cache_shape(void)
l2_cache_shape = -1; /* No S-cache */
}
+static void fpu_init(void)
+{
+ /* Disable the FPU */
+ if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) {
+ printk("FPU Disabled\n");
+ current_cpu_data.flags &= ~CPU_HAS_FPU;
+ }
+
+ disable_fpu();
+ clear_used_math();
+}
+
#ifdef CONFIG_SH_DSP
-static void __init release_dsp(void)
+static void release_dsp(void)
{
unsigned long sr;
@@ -189,7 +244,7 @@ static void __init release_dsp(void)
);
}
-static void __init dsp_init(void)
+static void dsp_init(void)
{
unsigned long sr;
@@ -211,34 +266,41 @@ static void __init dsp_init(void)
if (sr & SR_DSP)
current_cpu_data.flags |= CPU_HAS_DSP;
+ /* Disable the DSP */
+ if (dsp_disabled && (current_cpu_data.flags & CPU_HAS_DSP)) {
+ printk("DSP Disabled\n");
+ current_cpu_data.flags &= ~CPU_HAS_DSP;
+ }
+
/* Now that we've determined the DSP status, clear the DSP bit. */
release_dsp();
}
+#else
+static inline void dsp_init(void) { }
#endif /* CONFIG_SH_DSP */
/**
- * sh_cpu_init
+ * cpu_init
*
- * This is our initial entry point for each CPU, and is invoked on the boot
- * CPU prior to calling start_kernel(). For SMP, a combination of this and
- * start_secondary() will bring up each processor to a ready state prior
- * to hand forking the idle loop.
+ * This is our initial entry point for each CPU, and is invoked on the
+ * boot CPU prior to calling start_kernel(). For SMP, a combination of
+ * this and start_secondary() will bring up each processor to a ready
+ * state prior to hand forking the idle loop.
*
- * We do all of the basic processor init here, including setting up the
- * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is
- * hit (and subsequently platform_setup()) things like determining the
- * CPU subtype and initial configuration will all be done.
+ * We do all of the basic processor init here, including setting up
+ * the caches, FPU, DSP, etc. By the time start_kernel() is hit (and
+ * subsequently platform_setup()) things like determining the CPU
+ * subtype and initial configuration will all be done.
*
* Each processor family is still responsible for doing its own probing
- * and cache configuration in detect_cpu_and_cache_system().
+ * and cache configuration in cpu_probe().
*/
-
-asmlinkage void __init sh_cpu_init(void)
+asmlinkage void cpu_init(void)
{
current_thread_info()->cpu = hard_smp_processor_id();
/* First, probe the CPU */
- detect_cpu_and_cache_system();
+ cpu_probe();
if (current_cpu_data.type == CPU_SH_NONE)
panic("Unknown CPU");
@@ -269,18 +331,8 @@ asmlinkage void __init sh_cpu_init(void)
detect_cache_shape();
}
- /* Disable the FPU */
- if (fpu_disabled) {
- printk("FPU Disabled\n");
- current_cpu_data.flags &= ~CPU_HAS_FPU;
- disable_fpu();
- }
-
- /* FPU initialization */
- if ((current_cpu_data.flags & CPU_HAS_FPU)) {
- clear_thread_flag(TIF_USEDFPU);
- clear_used_math();
- }
+ fpu_init();
+ dsp_init();
/*
* Initialize the per-CPU ASID cache very early, since the
@@ -288,28 +340,26 @@ asmlinkage void __init sh_cpu_init(void)
*/
current_cpu_data.asid_cache = NO_CONTEXT;
-#ifdef CONFIG_SH_DSP
- /* Probe for DSP */
- dsp_init();
+ current_cpu_data.phys_bits = __in_29bit_mode() ? 29 : 32;
- /* Disable the DSP */
- if (dsp_disabled) {
- printk("DSP Disabled\n");
- current_cpu_data.flags &= ~CPU_HAS_DSP;
- release_dsp();
- }
-#endif
+ speculative_execution_init();
+ expmask_init();
- /*
- * Some brain-damaged loaders decided it would be a good idea to put
- * the UBC to sleep. This causes some issues when it comes to things
- * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So ..
- * we wake it up and hope that all is well.
- */
-#ifdef CONFIG_SUPERH32
- if (raw_smp_processor_id() == 0)
- ubc_wakeup();
-#endif
+ /* Do the rest of the boot processor setup */
+ if (raw_smp_processor_id() == 0) {
+ /* Save off the BIOS VBR, if there is one */
+ sh_bios_vbr_init();
- speculative_execution_init();
+ /*
+ * Setup VBR for boot CPU. Secondary CPUs do this through
+ * start_secondary().
+ */
+ per_cpu_trap_init();
+
+ /*
+ * Boot processor to setup the FP and extended state
+ * context info.
+ */
+ init_thread_xstate();
+ }
}
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index 462a8f6dfee..f0c7025a67d 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -1,8 +1,6 @@
#
# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
#
-obj-y += intc.o
-
obj-$(CONFIG_SUPERH32) += imask.o
obj-$(CONFIG_CPU_SH5) += intc-sh5.o
obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o
diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c
index 301b505c427..e7f1745bd12 100644
--- a/arch/sh/kernel/cpu/irq/imask.c
+++ b/arch/sh/kernel/cpu/irq/imask.c
@@ -18,38 +18,16 @@
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/irq.h>
-#include <asm/system.h>
+#include <linux/bitmap.h>
#include <asm/irq.h>
/* Bitmap of IRQ masked */
-static unsigned long imask_mask = 0x7fff;
-static int interrupt_priority = 0;
-
-static void enable_imask_irq(unsigned int irq);
-static void disable_imask_irq(unsigned int irq);
-static void shutdown_imask_irq(unsigned int irq);
-static void mask_and_ack_imask(unsigned int);
-static void end_imask_irq(unsigned int irq);
-
#define IMASK_PRIORITY 15
-static unsigned int startup_imask_irq(unsigned int irq)
-{
- /* Nothing to do */
- return 0; /* never anything pending */
-}
+static DECLARE_BITMAP(imask_mask, IMASK_PRIORITY);
+static int interrupt_priority;
-static struct hw_interrupt_type imask_irq_type = {
- .typename = "SR.IMASK",
- .startup = startup_imask_irq,
- .shutdown = shutdown_imask_irq,
- .enable = enable_imask_irq,
- .disable = disable_imask_irq,
- .ack = mask_and_ack_imask,
- .end = end_imask_irq
-};
-
-void static inline set_interrupt_registers(int ip)
+static inline void set_interrupt_registers(int ip)
{
unsigned long __dummy;
@@ -72,42 +50,35 @@ void static inline set_interrupt_registers(int ip)
: "t");
}
-static void disable_imask_irq(unsigned int irq)
+static void mask_imask_irq(struct irq_data *data)
{
- clear_bit(irq, &imask_mask);
+ unsigned int irq = data->irq;
+
+ clear_bit(irq, imask_mask);
if (interrupt_priority < IMASK_PRIORITY - irq)
interrupt_priority = IMASK_PRIORITY - irq;
-
set_interrupt_registers(interrupt_priority);
}
-static void enable_imask_irq(unsigned int irq)
+static void unmask_imask_irq(struct irq_data *data)
{
- set_bit(irq, &imask_mask);
- interrupt_priority = IMASK_PRIORITY - ffz(imask_mask);
+ unsigned int irq = data->irq;
+ set_bit(irq, imask_mask);
+ interrupt_priority = IMASK_PRIORITY -
+ find_first_zero_bit(imask_mask, IMASK_PRIORITY);
set_interrupt_registers(interrupt_priority);
}
-static void mask_and_ack_imask(unsigned int irq)
-{
- disable_imask_irq(irq);
-}
-
-static void end_imask_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- enable_imask_irq(irq);
-}
-
-static void shutdown_imask_irq(unsigned int irq)
-{
- /* Nothing to do */
-}
+static struct irq_chip imask_irq_chip = {
+ .name = "SR.IMASK",
+ .irq_mask = mask_imask_irq,
+ .irq_unmask = unmask_imask_irq,
+ .irq_mask_ack = mask_imask_irq,
+};
void make_imask_irq(unsigned int irq)
{
- disable_irq_nosync(irq);
- irq_desc[irq].chip = &imask_irq_type;
- enable_irq(irq);
+ irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq,
+ "level");
}
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c
index 726f0335da7..9e056a3a0c7 100644
--- a/arch/sh/kernel/cpu/irq/intc-sh5.c
+++ b/arch/sh/kernel/cpu/irq/intc-sh5.c
@@ -76,39 +76,11 @@ int intc_evt_to_irq[(0xE20/0x20)+1] = {
};
static unsigned long intc_virt;
-
-static unsigned int startup_intc_irq(unsigned int irq);
-static void shutdown_intc_irq(unsigned int irq);
-static void enable_intc_irq(unsigned int irq);
-static void disable_intc_irq(unsigned int irq);
-static void mask_and_ack_intc(unsigned int);
-static void end_intc_irq(unsigned int irq);
-
-static struct hw_interrupt_type intc_irq_type = {
- .typename = "INTC",
- .startup = startup_intc_irq,
- .shutdown = shutdown_intc_irq,
- .enable = enable_intc_irq,
- .disable = disable_intc_irq,
- .ack = mask_and_ack_intc,
- .end = end_intc_irq
-};
-
static int irlm; /* IRL mode */
-static unsigned int startup_intc_irq(unsigned int irq)
-{
- enable_intc_irq(irq);
- return 0; /* never anything pending */
-}
-
-static void shutdown_intc_irq(unsigned int irq)
-{
- disable_intc_irq(irq);
-}
-
-static void enable_intc_irq(unsigned int irq)
+static void enable_intc_irq(struct irq_data *data)
{
+ unsigned int irq = data->irq;
unsigned long reg;
unsigned long bitmask;
@@ -123,11 +95,12 @@ static void enable_intc_irq(unsigned int irq)
bitmask = 1 << (irq - 32);
}
- ctrl_outl(bitmask, reg);
+ __raw_writel(bitmask, reg);
}
-static void disable_intc_irq(unsigned int irq)
+static void disable_intc_irq(struct irq_data *data)
{
+ unsigned int irq = data->irq;
unsigned long reg;
unsigned long bitmask;
@@ -139,56 +112,22 @@ static void disable_intc_irq(unsigned int irq)
bitmask = 1 << (irq - 32);
}
- ctrl_outl(bitmask, reg);
-}
-
-static void mask_and_ack_intc(unsigned int irq)
-{
- disable_intc_irq(irq);
-}
-
-static void end_intc_irq(unsigned int irq)
-{
- enable_intc_irq(irq);
-}
-
-/* For future use, if we ever support IRLM=0) */
-void make_intc_irq(unsigned int irq)
-{
- disable_irq_nosync(irq);
- irq_desc[irq].chip = &intc_irq_type;
- disable_intc_irq(irq);
+ __raw_writel(bitmask, reg);
}
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-static int IRQ_to_vectorN[NR_INTC_IRQS] = {
- 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */
- -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */
- 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */
- 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */
- 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */
- -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */
-
+static struct irq_chip intc_irq_type = {
+ .name = "INTC",
+ .irq_enable = enable_intc_irq,
+ .irq_disable = disable_intc_irq,
};
-int intc_irq_describe(char* p, int irq)
-{
- if (irq < NR_INTC_IRQS)
- return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20);
- else
- return 0;
-}
-#endif
-
void __init plat_irq_setup(void)
{
unsigned long long __dummy0, __dummy1=~0x00000000100000f0;
unsigned long reg;
int i;
- intc_virt = onchip_remap(INTC_BASE, 1024, "INTC");
+ intc_virt = (unsigned long)ioremap_nocache(INTC_BASE, 1024);
if (!intc_virt) {
panic("Unable to remap INTC\n");
}
@@ -196,15 +135,15 @@ void __init plat_irq_setup(void)
/* Set default: per-line enable/disable, priority driven ack/eoi */
for (i = 0; i < NR_INTC_IRQS; i++)
- irq_desc[i].chip = &intc_irq_type;
+ irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
/* Disable all interrupts and set all priorities to 0 to avoid trouble */
- ctrl_outl(-1, INTC_INTDSB_0);
- ctrl_outl(-1, INTC_INTDSB_1);
+ __raw_writel(-1, INTC_INTDSB_0);
+ __raw_writel(-1, INTC_INTDSB_1);
for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8)
- ctrl_outl( NO_PRIORITY, reg);
+ __raw_writel( NO_PRIORITY, reg);
#ifdef CONFIG_SH_CAYMAN
@@ -229,7 +168,7 @@ void __init plat_irq_setup(void)
reg = INTC_ICR_SET;
i = IRQ_IRL0;
}
- ctrl_outl(INTC_ICR_IRLM, reg);
+ __raw_writel(INTC_ICR_IRLM, reg);
/* Set interrupt priorities according to platform description */
for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) {
@@ -237,7 +176,7 @@ void __init plat_irq_setup(void)
((i % INTC_INTPRI_PPREG) * 4);
if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) {
/* Upon the 7th, set Priority Register */
- ctrl_outl(data, reg);
+ __raw_writel(data, reg);
data = 0;
reg += 8;
}
diff --git a/arch/sh/kernel/cpu/irq/intc.c b/arch/sh/kernel/cpu/irq/intc.c
deleted file mode 100644
index 8c70e201bde..00000000000
--- a/arch/sh/kernel/cpu/irq/intc.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Shared interrupt handling code for IPR and INTC2 types of IRQs.
- *
- * Copyright (C) 2007, 2008 Magnus Damm
- *
- * Based on intc2.c and ipr.c
- *
- * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi
- * Copyright (C) 2000 Kazumoto Kojima
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * Copyright (C) 2005, 2006 Paul Mundt
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/bootmem.h>
-
-#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
- ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
- ((addr_e) << 16) | ((addr_d << 24)))
-
-#define _INTC_SHIFT(h) (h & 0x1f)
-#define _INTC_WIDTH(h) ((h >> 5) & 0xf)
-#define _INTC_FN(h) ((h >> 9) & 0xf)
-#define _INTC_MODE(h) ((h >> 13) & 0x7)
-#define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
-#define _INTC_ADDR_D(h) ((h >> 24) & 0xff)
-
-struct intc_handle_int {
- unsigned int irq;
- unsigned long handle;
-};
-
-struct intc_desc_int {
- unsigned long *reg;
-#ifdef CONFIG_SMP
- unsigned long *smp;
-#endif
- unsigned int nr_reg;
- struct intc_handle_int *prio;
- unsigned int nr_prio;
- struct intc_handle_int *sense;
- unsigned int nr_sense;
- struct irq_chip chip;
-};
-
-#ifdef CONFIG_SMP
-#define IS_SMP(x) x.smp
-#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
-#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
-#else
-#define IS_SMP(x) 0
-#define INTC_REG(d, x, c) (d->reg[(x)])
-#define SMP_NR(d, x) 1
-#endif
-
-static unsigned int intc_prio_level[NR_IRQS]; /* for now */
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
-static unsigned long ack_handle[NR_IRQS];
-#endif
-
-static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
-{
- struct irq_chip *chip = get_irq_chip(irq);
- return (void *)((char *)chip - offsetof(struct intc_desc_int, chip));
-}
-
-static inline unsigned int set_field(unsigned int value,
- unsigned int field_value,
- unsigned int handle)
-{
- unsigned int width = _INTC_WIDTH(handle);
- unsigned int shift = _INTC_SHIFT(handle);
-
- value &= ~(((1 << width) - 1) << shift);
- value |= field_value << shift;
- return value;
-}
-
-static void write_8(unsigned long addr, unsigned long h, unsigned long data)
-{
- ctrl_outb(set_field(0, data, h), addr);
-}
-
-static void write_16(unsigned long addr, unsigned long h, unsigned long data)
-{
- ctrl_outw(set_field(0, data, h), addr);
-}
-
-static void write_32(unsigned long addr, unsigned long h, unsigned long data)
-{
- ctrl_outl(set_field(0, data, h), addr);
-}
-
-static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
-{
- unsigned long flags;
- local_irq_save(flags);
- ctrl_outb(set_field(ctrl_inb(addr), data, h), addr);
- local_irq_restore(flags);
-}
-
-static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
-{
- unsigned long flags;
- local_irq_save(flags);
- ctrl_outw(set_field(ctrl_inw(addr), data, h), addr);
- local_irq_restore(flags);
-}
-
-static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
-{
- unsigned long flags;
- local_irq_save(flags);
- ctrl_outl(set_field(ctrl_inl(addr), data, h), addr);
- local_irq_restore(flags);
-}
-
-enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 };
-
-static void (*intc_reg_fns[])(unsigned long addr,
- unsigned long h,
- unsigned long data) = {
- [REG_FN_WRITE_BASE + 0] = write_8,
- [REG_FN_WRITE_BASE + 1] = write_16,
- [REG_FN_WRITE_BASE + 3] = write_32,
- [REG_FN_MODIFY_BASE + 0] = modify_8,
- [REG_FN_MODIFY_BASE + 1] = modify_16,
- [REG_FN_MODIFY_BASE + 3] = modify_32,
-};
-
-enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
- MODE_MASK_REG, /* Bit(s) set -> interrupt disabled */
- MODE_DUAL_REG, /* Two registers, set bit to enable / disable */
- MODE_PRIO_REG, /* Priority value written to enable interrupt */
- MODE_PCLR_REG, /* Above plus all bits set to disable interrupt */
-};
-
-static void intc_mode_field(unsigned long addr,
- unsigned long handle,
- void (*fn)(unsigned long,
- unsigned long,
- unsigned long),
- unsigned int irq)
-{
- fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
-}
-
-static void intc_mode_zero(unsigned long addr,
- unsigned long handle,
- void (*fn)(unsigned long,
- unsigned long,
- unsigned long),
- unsigned int irq)
-{
- fn(addr, handle, 0);
-}
-
-static void intc_mode_prio(unsigned long addr,
- unsigned long handle,
- void (*fn)(unsigned long,
- unsigned long,
- unsigned long),
- unsigned int irq)
-{
- fn(addr, handle, intc_prio_level[irq]);
-}
-
-static void (*intc_enable_fns[])(unsigned long addr,
- unsigned long handle,
- void (*fn)(unsigned long,
- unsigned long,
- unsigned long),
- unsigned int irq) = {
- [MODE_ENABLE_REG] = intc_mode_field,
- [MODE_MASK_REG] = intc_mode_zero,
- [MODE_DUAL_REG] = intc_mode_field,
- [MODE_PRIO_REG] = intc_mode_prio,
- [MODE_PCLR_REG] = intc_mode_prio,
-};
-
-static void (*intc_disable_fns[])(unsigned long addr,
- unsigned long handle,
- void (*fn)(unsigned long,
- unsigned long,
- unsigned long),
- unsigned int irq) = {
- [MODE_ENABLE_REG] = intc_mode_zero,
- [MODE_MASK_REG] = intc_mode_field,
- [MODE_DUAL_REG] = intc_mode_field,
- [MODE_PRIO_REG] = intc_mode_zero,
- [MODE_PCLR_REG] = intc_mode_field,
-};
-
-static inline void _intc_enable(unsigned int irq, unsigned long handle)
-{
- struct intc_desc_int *d = get_intc_desc(irq);
- unsigned long addr;
- unsigned int cpu;
-
- for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
- addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
- intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
- [_INTC_FN(handle)], irq);
- }
-}
-
-static void intc_enable(unsigned int irq)
-{
- _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
-}
-
-static void intc_disable(unsigned int irq)
-{
- struct intc_desc_int *d = get_intc_desc(irq);
- unsigned long handle = (unsigned long) get_irq_chip_data(irq);
- unsigned long addr;
- unsigned int cpu;
-
- for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
- addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
- intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
- [_INTC_FN(handle)], irq);
- }
-}
-
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
-static void intc_mask_ack(unsigned int irq)
-{
- struct intc_desc_int *d = get_intc_desc(irq);
- unsigned long handle = ack_handle[irq];
- unsigned long addr;
-
- intc_disable(irq);
-
- /* read register and write zero only to the assocaited bit */
-
- if (handle) {
- addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
- switch (_INTC_FN(handle)) {
- case REG_FN_MODIFY_BASE + 0: /* 8bit */
- ctrl_inb(addr);
- ctrl_outb(0xff ^ set_field(0, 1, handle), addr);
- break;
- case REG_FN_MODIFY_BASE + 1: /* 16bit */
- ctrl_inw(addr);
- ctrl_outw(0xffff ^ set_field(0, 1, handle), addr);
- break;
- case REG_FN_MODIFY_BASE + 3: /* 32bit */
- ctrl_inl(addr);
- ctrl_outl(0xffffffff ^ set_field(0, 1, handle), addr);
- break;
- default:
- BUG();
- break;
- }
- }
-}
-#endif
-
-static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
- unsigned int nr_hp,
- unsigned int irq)
-{
- int i;
-
- /* this doesn't scale well, but...
- *
- * this function should only be used for cerain uncommon
- * operations such as intc_set_priority() and intc_set_sense()
- * and in those rare cases performance doesn't matter that much.
- * keeping the memory footprint low is more important.
- *
- * one rather simple way to speed this up and still keep the
- * memory footprint down is to make sure the array is sorted
- * and then perform a bisect to lookup the irq.
- */
-
- for (i = 0; i < nr_hp; i++) {
- if ((hp + i)->irq != irq)
- continue;
-
- return hp + i;
- }
-
- return NULL;
-}
-
-int intc_set_priority(unsigned int irq, unsigned int prio)
-{
- struct intc_desc_int *d = get_intc_desc(irq);
- struct intc_handle_int *ihp;
-
- if (!intc_prio_level[irq] || prio <= 1)
- return -EINVAL;
-
- ihp = intc_find_irq(d->prio, d->nr_prio, irq);
- if (ihp) {
- if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
- return -EINVAL;
-
- intc_prio_level[irq] = prio;
-
- /*
- * only set secondary masking method directly
- * primary masking method is using intc_prio_level[irq]
- * priority level will be set during next enable()
- */
-
- if (_INTC_FN(ihp->handle) != REG_FN_ERR)
- _intc_enable(irq, ihp->handle);
- }
- return 0;
-}
-
-#define VALID(x) (x | 0x80)
-
-static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
- [IRQ_TYPE_EDGE_FALLING] = VALID(0),
- [IRQ_TYPE_EDGE_RISING] = VALID(1),
- [IRQ_TYPE_LEVEL_LOW] = VALID(2),
- /* SH7706, SH7707 and SH7709 do not support high level triggered */
-#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
- !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
- !defined(CONFIG_CPU_SUBTYPE_SH7709)
- [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
-#endif
-};
-
-static int intc_set_sense(unsigned int irq, unsigned int type)
-{
- struct intc_desc_int *d = get_intc_desc(irq);
- unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
- struct intc_handle_int *ihp;
- unsigned long addr;
-
- if (!value)
- return -EINVAL;
-
- ihp = intc_find_irq(d->sense, d->nr_sense, irq);
- if (ihp) {
- addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
- intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
- }
- return 0;
-}
-
-static unsigned int __init intc_get_reg(struct intc_desc_int *d,
- unsigned long address)
-{
- unsigned int k;
-
- for (k = 0; k < d->nr_reg; k++) {
- if (d->reg[k] == address)
- return k;
- }
-
- BUG();
- return 0;
-}
-
-static intc_enum __init intc_grp_id(struct intc_desc *desc,
- intc_enum enum_id)
-{
- struct intc_group *g = desc->groups;
- unsigned int i, j;
-
- for (i = 0; g && enum_id && i < desc->nr_groups; i++) {
- g = desc->groups + i;
-
- for (j = 0; g->enum_ids[j]; j++) {
- if (g->enum_ids[j] != enum_id)
- continue;
-
- return g->enum_id;
- }
- }
-
- return 0;
-}
-
-static unsigned int __init intc_mask_data(struct intc_desc *desc,
- struct intc_desc_int *d,
- intc_enum enum_id, int do_grps)
-{
- struct intc_mask_reg *mr = desc->mask_regs;
- unsigned int i, j, fn, mode;
- unsigned long reg_e, reg_d;
-
- for (i = 0; mr && enum_id && i < desc->nr_mask_regs; i++) {
- mr = desc->mask_regs + i;
-
- for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
- if (mr->enum_ids[j] != enum_id)
- continue;
-
- if (mr->set_reg && mr->clr_reg) {
- fn = REG_FN_WRITE_BASE;
- mode = MODE_DUAL_REG;
- reg_e = mr->clr_reg;
- reg_d = mr->set_reg;
- } else {
- fn = REG_FN_MODIFY_BASE;
- if (mr->set_reg) {
- mode = MODE_ENABLE_REG;
- reg_e = mr->set_reg;
- reg_d = mr->set_reg;
- } else {
- mode = MODE_MASK_REG;
- reg_e = mr->clr_reg;
- reg_d = mr->clr_reg;
- }
- }
-
- fn += (mr->reg_width >> 3) - 1;
- return _INTC_MK(fn, mode,
- intc_get_reg(d, reg_e),
- intc_get_reg(d, reg_d),
- 1,
- (mr->reg_width - 1) - j);
- }
- }
-
- if (do_grps)
- return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
-
- return 0;
-}
-
-static unsigned int __init intc_prio_data(struct intc_desc *desc,
- struct intc_desc_int *d,
- intc_enum enum_id, int do_grps)
-{
- struct intc_prio_reg *pr = desc->prio_regs;
- unsigned int i, j, fn, mode, bit;
- unsigned long reg_e, reg_d;
-
- for (i = 0; pr && enum_id && i < desc->nr_prio_regs; i++) {
- pr = desc->prio_regs + i;
-
- for (j = 0; j < ARRAY_SIZE(pr->enum_ids); j++) {
- if (pr->enum_ids[j] != enum_id)
- continue;
-
- if (pr->set_reg && pr->clr_reg) {
- fn = REG_FN_WRITE_BASE;
- mode = MODE_PCLR_REG;
- reg_e = pr->set_reg;
- reg_d = pr->clr_reg;
- } else {
- fn = REG_FN_MODIFY_BASE;
- mode = MODE_PRIO_REG;
- if (!pr->set_reg)
- BUG();
- reg_e = pr->set_reg;
- reg_d = pr->set_reg;
- }
-
- fn += (pr->reg_width >> 3) - 1;
- bit = pr->reg_width - ((j + 1) * pr->field_width);
-
- BUG_ON(bit < 0);
-
- return _INTC_MK(fn, mode,
- intc_get_reg(d, reg_e),
- intc_get_reg(d, reg_d),
- pr->field_width, bit);
- }
- }
-
- if (do_grps)
- return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);
-
- return 0;
-}
-
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
-static unsigned int __init intc_ack_data(struct intc_desc *desc,
- struct intc_desc_int *d,
- intc_enum enum_id)
-{
- struct intc_mask_reg *mr = desc->ack_regs;
- unsigned int i, j, fn, mode;
- unsigned long reg_e, reg_d;
-
- for (i = 0; mr && enum_id && i < desc->nr_ack_regs; i++) {
- mr = desc->ack_regs + i;
-
- for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
- if (mr->enum_ids[j] != enum_id)
- continue;
-
- fn = REG_FN_MODIFY_BASE;
- mode = MODE_ENABLE_REG;
- reg_e = mr->set_reg;
- reg_d = mr->set_reg;
-
- fn += (mr->reg_width >> 3) - 1;
- return _INTC_MK(fn, mode,
- intc_get_reg(d, reg_e),
- intc_get_reg(d, reg_d),
- 1,
- (mr->reg_width - 1) - j);
- }
- }
-
- return 0;
-}
-#endif
-
-static unsigned int __init intc_sense_data(struct intc_desc *desc,
- struct intc_desc_int *d,
- intc_enum enum_id)
-{
- struct intc_sense_reg *sr = desc->sense_regs;
- unsigned int i, j, fn, bit;
-
- for (i = 0; sr && enum_id && i < desc->nr_sense_regs; i++) {
- sr = desc->sense_regs + i;
-
- for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
- if (sr->enum_ids[j] != enum_id)
- continue;
-
- fn = REG_FN_MODIFY_BASE;
- fn += (sr->reg_width >> 3) - 1;
- bit = sr->reg_width - ((j + 1) * sr->field_width);
-
- BUG_ON(bit < 0);
-
- return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
- 0, sr->field_width, bit);
- }
- }
-
- return 0;
-}
-
-static void __init intc_register_irq(struct intc_desc *desc,
- struct intc_desc_int *d,
- intc_enum enum_id,
- unsigned int irq)
-{
- struct intc_handle_int *hp;
- unsigned int data[2], primary;
-
- /* Prefer single interrupt source bitmap over other combinations:
- * 1. bitmap, single interrupt source
- * 2. priority, single interrupt source
- * 3. bitmap, multiple interrupt sources (groups)
- * 4. priority, multiple interrupt sources (groups)
- */
-
- data[0] = intc_mask_data(desc, d, enum_id, 0);
- data[1] = intc_prio_data(desc, d, enum_id, 0);
-
- primary = 0;
- if (!data[0] && data[1])
- primary = 1;
-
- data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
- data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
-
- if (!data[primary])
- primary ^= 1;
-
- BUG_ON(!data[primary]); /* must have primary masking method */
-
- disable_irq_nosync(irq);
- set_irq_chip_and_handler_name(irq, &d->chip,
- handle_level_irq, "level");
- set_irq_chip_data(irq, (void *)data[primary]);
-
- /* set priority level
- * - this needs to be at least 2 for 5-bit priorities on 7780
- */
- intc_prio_level[irq] = 2;
-
- /* enable secondary masking method if present */
- if (data[!primary])
- _intc_enable(irq, data[!primary]);
-
- /* add irq to d->prio list if priority is available */
- if (data[1]) {
- hp = d->prio + d->nr_prio;
- hp->irq = irq;
- hp->handle = data[1];
-
- if (primary) {
- /*
- * only secondary priority should access registers, so
- * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
- */
-
- hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
- hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
- }
- d->nr_prio++;
- }
-
- /* add irq to d->sense list if sense is available */
- data[0] = intc_sense_data(desc, d, enum_id);
- if (data[0]) {
- (d->sense + d->nr_sense)->irq = irq;
- (d->sense + d->nr_sense)->handle = data[0];
- d->nr_sense++;
- }
-
- /* irq should be disabled by default */
- d->chip.mask(irq);
-
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
- if (desc->ack_regs)
- ack_handle[irq] = intc_ack_data(desc, d, enum_id);
-#endif
-}
-
-static unsigned int __init save_reg(struct intc_desc_int *d,
- unsigned int cnt,
- unsigned long value,
- unsigned int smp)
-{
- if (value) {
- d->reg[cnt] = value;
-#ifdef CONFIG_SMP
- d->smp[cnt] = smp;
-#endif
- return 1;
- }
-
- return 0;
-}
-
-
-void __init register_intc_controller(struct intc_desc *desc)
-{
- unsigned int i, k, smp;
- struct intc_desc_int *d;
-
- d = alloc_bootmem(sizeof(*d));
-
- d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
- d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
- d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
-
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
- d->nr_reg += desc->ack_regs ? desc->nr_ack_regs : 0;
-#endif
- d->reg = alloc_bootmem(d->nr_reg * sizeof(*d->reg));
-#ifdef CONFIG_SMP
- d->smp = alloc_bootmem(d->nr_reg * sizeof(*d->smp));
-#endif
- k = 0;
-
- if (desc->mask_regs) {
- for (i = 0; i < desc->nr_mask_regs; i++) {
- smp = IS_SMP(desc->mask_regs[i]);
- k += save_reg(d, k, desc->mask_regs[i].set_reg, smp);
- k += save_reg(d, k, desc->mask_regs[i].clr_reg, smp);
- }
- }
-
- if (desc->prio_regs) {
- d->prio = alloc_bootmem(desc->nr_vectors * sizeof(*d->prio));
-
- for (i = 0; i < desc->nr_prio_regs; i++) {
- smp = IS_SMP(desc->prio_regs[i]);
- k += save_reg(d, k, desc->prio_regs[i].set_reg, smp);
- k += save_reg(d, k, desc->prio_regs[i].clr_reg, smp);
- }
- }
-
- if (desc->sense_regs) {
- d->sense = alloc_bootmem(desc->nr_vectors * sizeof(*d->sense));
-
- for (i = 0; i < desc->nr_sense_regs; i++) {
- k += save_reg(d, k, desc->sense_regs[i].reg, 0);
- }
- }
-
- d->chip.name = desc->name;
- d->chip.mask = intc_disable;
- d->chip.unmask = intc_enable;
- d->chip.mask_ack = intc_disable;
- d->chip.set_type = intc_set_sense;
-
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
- if (desc->ack_regs) {
- for (i = 0; i < desc->nr_ack_regs; i++)
- k += save_reg(d, k, desc->ack_regs[i].set_reg, 0);
-
- d->chip.mask_ack = intc_mask_ack;
- }
-#endif
-
- BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
-
- for (i = 0; i < desc->nr_vectors; i++) {
- struct intc_vect *vect = desc->vectors + i;
-
- intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
- }
-}
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 56ea7b269b5..5de6dff5c21 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -17,31 +17,34 @@
* for more details.
*/
#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/irq.h>
+#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
+#include <linux/topology.h>
-static inline struct ipr_desc *get_ipr_desc(unsigned int irq)
+static inline struct ipr_desc *get_ipr_desc(struct irq_data *data)
{
- struct irq_chip *chip = get_irq_chip(irq);
- return (void *)((char *)chip - offsetof(struct ipr_desc, chip));
+ struct irq_chip *chip = irq_data_get_irq_chip(data);
+ return container_of(chip, struct ipr_desc, chip);
}
-static void disable_ipr_irq(unsigned int irq)
+static void disable_ipr_irq(struct irq_data *data)
{
- struct ipr_data *p = get_irq_chip_data(irq);
- unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
+ struct ipr_data *p = irq_data_get_irq_chip_data(data);
+ unsigned long addr = get_ipr_desc(data)->ipr_offsets[p->ipr_idx];
/* Set the priority in IPR to 0 */
- ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
+ __raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr);
+ (void)__raw_readw(addr); /* Read back to flush write posting */
}
-static void enable_ipr_irq(unsigned int irq)
+static void enable_ipr_irq(struct irq_data *data)
{
- struct ipr_data *p = get_irq_chip_data(irq);
- unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
+ struct ipr_data *p = irq_data_get_irq_chip_data(data);
+ unsigned long addr = get_ipr_desc(data)->ipr_offsets[p->ipr_idx];
/* Set priority in IPR back to original value */
- ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
+ __raw_writew(__raw_readw(addr) | (p->priority << p->shift), addr);
}
/*
@@ -53,21 +56,28 @@ void register_ipr_controller(struct ipr_desc *desc)
{
int i;
- desc->chip.mask = disable_ipr_irq;
- desc->chip.unmask = enable_ipr_irq;
- desc->chip.mask_ack = disable_ipr_irq;
+ desc->chip.irq_mask = disable_ipr_irq;
+ desc->chip.irq_unmask = enable_ipr_irq;
for (i = 0; i < desc->nr_irqs; i++) {
struct ipr_data *p = desc->ipr_data + i;
+ int res;
BUG_ON(p->ipr_idx >= desc->nr_offsets);
BUG_ON(!desc->ipr_offsets[p->ipr_idx]);
+ res = irq_alloc_desc_at(p->irq, numa_node_id());
+ if (unlikely(res != p->irq && res != -EEXIST)) {
+ printk(KERN_INFO "can not get irq_desc for %d\n",
+ p->irq);
+ continue;
+ }
+
disable_irq_nosync(p->irq);
- set_irq_chip_and_handler_name(p->irq, &desc->chip,
- handle_level_irq, "level");
- set_irq_chip_data(p->irq, p);
- disable_ipr_irq(p->irq);
+ irq_set_chip_and_handler_name(p->irq, &desc->chip,
+ handle_level_irq, "level");
+ irq_set_chip_data(p->irq, p);
+ disable_ipr_irq(irq_get_irq_data(p->irq));
}
}
EXPORT_SYMBOL(register_ipr_controller);
diff --git a/arch/sh/kernel/cpu/pfc.c b/arch/sh/kernel/cpu/pfc.c
new file mode 100644
index 00000000000..d766564ef7c
--- /dev/null
+++ b/arch/sh/kernel/cpu/pfc.c
@@ -0,0 +1,33 @@
+/*
+ * SH Pin Function Control Initialization
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <cpu/pfc.h>
+
+static struct platform_device sh_pfc_device = {
+ .id = -1,
+};
+
+int __init sh_pfc_register(const char *name,
+ struct resource *resource, u32 num_resources)
+{
+ sh_pfc_device.name = name;
+ sh_pfc_device.num_resources = num_resources;
+ sh_pfc_device.resource = resource;
+
+ return platform_device_register(&sh_pfc_device);
+}
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
new file mode 100644
index 00000000000..9e6624c9108
--- /dev/null
+++ b/arch/sh/kernel/cpu/proc.c
@@ -0,0 +1,150 @@
+#include <linux/seq_file.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/processor.h>
+
+static const char *cpu_name[] = {
+ [CPU_SH7201] = "SH7201",
+ [CPU_SH7203] = "SH7203", [CPU_SH7263] = "SH7263",
+ [CPU_SH7264] = "SH7264", [CPU_SH7269] = "SH7269",
+ [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
+ [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
+ [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
+ [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710",
+ [CPU_SH7712] = "SH7712", [CPU_SH7720] = "SH7720",
+ [CPU_SH7721] = "SH7721", [CPU_SH7729] = "SH7729",
+ [CPU_SH7750] = "SH7750", [CPU_SH7750S] = "SH7750S",
+ [CPU_SH7750R] = "SH7750R", [CPU_SH7751] = "SH7751",
+ [CPU_SH7751R] = "SH7751R", [CPU_SH7760] = "SH7760",
+ [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
+ [CPU_SH7763] = "SH7763", [CPU_SH7770] = "SH7770",
+ [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781",
+ [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785",
+ [CPU_SH7786] = "SH7786", [CPU_SH7757] = "SH7757",
+ [CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3",
+ [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103",
+ [CPU_MXG] = "MX-G", [CPU_SH7723] = "SH7723",
+ [CPU_SH7366] = "SH7366", [CPU_SH7724] = "SH7724",
+ [CPU_SH7372] = "SH7372", [CPU_SH7734] = "SH7734",
+ [CPU_SH_NONE] = "Unknown"
+};
+
+const char *get_cpu_subtype(struct sh_cpuinfo *c)
+{
+ return cpu_name[c->type];
+}
+EXPORT_SYMBOL(get_cpu_subtype);
+
+#ifdef CONFIG_PROC_FS
+/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
+static const char *cpu_flags[] = {
+ "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+ "ptea", "llsc", "l2", "op32", "pteaex", NULL
+};
+
+static void show_cpuflags(struct seq_file *m, struct sh_cpuinfo *c)
+{
+ unsigned long i;
+
+ seq_printf(m, "cpu flags\t:");
+
+ if (!c->flags) {
+ seq_printf(m, " %s\n", cpu_flags[0]);
+ return;
+ }
+
+ for (i = 0; cpu_flags[i]; i++)
+ if ((c->flags & (1 << i)))
+ seq_printf(m, " %s", cpu_flags[i+1]);
+
+ seq_printf(m, "\n");
+}
+
+static void show_cacheinfo(struct seq_file *m, const char *type,
+ struct cache_info info)
+{
+ unsigned int cache_size;
+
+ cache_size = info.ways * info.sets * info.linesz;
+
+ seq_printf(m, "%s size\t: %2dKiB (%d-way)\n",
+ type, cache_size >> 10, info.ways);
+}
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ struct sh_cpuinfo *c = v;
+ unsigned int cpu = c - cpu_data;
+
+ if (!cpu_online(cpu))
+ return 0;
+
+ if (cpu == 0)
+ seq_printf(m, "machine\t\t: %s\n", get_system_type());
+ else
+ seq_printf(m, "\n");
+
+ seq_printf(m, "processor\t: %d\n", cpu);
+ seq_printf(m, "cpu family\t: %s\n", init_utsname()->machine);
+ seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype(c));
+ if (c->cut_major == -1)
+ seq_printf(m, "cut\t\t: unknown\n");
+ else if (c->cut_minor == -1)
+ seq_printf(m, "cut\t\t: %d.x\n", c->cut_major);
+ else
+ seq_printf(m, "cut\t\t: %d.%d\n", c->cut_major, c->cut_minor);
+
+ show_cpuflags(m, c);
+
+ seq_printf(m, "cache type\t: ");
+
+ /*
+ * Check for what type of cache we have, we support both the
+ * unified cache on the SH-2 and SH-3, as well as the harvard
+ * style cache on the SH-4.
+ */
+ if (c->icache.flags & SH_CACHE_COMBINED) {
+ seq_printf(m, "unified\n");
+ show_cacheinfo(m, "cache", c->icache);
+ } else {
+ seq_printf(m, "split (harvard)\n");
+ show_cacheinfo(m, "icache", c->icache);
+ show_cacheinfo(m, "dcache", c->dcache);
+ }
+
+ /* Optional secondary cache */
+ if (c->flags & CPU_HAS_L2_CACHE)
+ show_cacheinfo(m, "scache", c->scache);
+
+ seq_printf(m, "address sizes\t: %u bits physical\n", c->phys_bits);
+
+ seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ c->loops_per_jiffy/(500000/HZ),
+ (c->loops_per_jiffy/(5000/HZ)) % 100);
+
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+const struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
+#endif /* CONFIG_PROC_FS */
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
index d2c15791799..e80252ae5bc 100644
--- a/arch/sh/kernel/cpu/sh2/clock-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
@@ -14,68 +14,64 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/io.h>
#include <asm/clock.h>
#include <asm/freq.h>
-#include <asm/io.h>
+#include <asm/processor.h>
static const int pll1rate[] = {1,2};
static const int pfc_divisors[] = {1,2,0,4};
-
-#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
-#define PLL2 (2)
-#else
-#error "Illigal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
static void master_clk_init(struct clk *clk)
{
- clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+ clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
}
-static struct clk_ops sh7619_master_clk_ops = {
+static struct sh_clk_ops sh7619_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(FREQCR) & 0x0007);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7619_module_clk_ops = {
+static struct sh_clk_ops sh7619_module_clk_ops = {
.recalc = module_clk_recalc,
};
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
{
- clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
+ return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 7];
}
-static struct clk_ops sh7619_bus_clk_ops = {
+static struct sh_clk_ops sh7619_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
-static void cpu_clk_recalc(struct clk *clk)
-{
- clk->rate = clk->parent->rate;
-}
-
-static struct clk_ops sh7619_cpu_clk_ops = {
- .recalc = cpu_clk_recalc,
+static struct sh_clk_ops sh7619_cpu_clk_ops = {
+ .recalc = followparent_recalc,
};
-static struct clk_ops *sh7619_clk_ops[] = {
+static struct sh_clk_ops *sh7619_clk_ops[] = {
&sh7619_master_clk_ops,
&sh7619_module_clk_ops,
&sh7619_bus_clk_ops,
&sh7619_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
+ if (test_mode_pin(MODE_PIN2 | MODE_PIN0) ||
+ test_mode_pin(MODE_PIN2 | MODE_PIN1))
+ pll2_mult = 2;
+ else if (test_mode_pin(MODE_PIN0) || test_mode_pin(MODE_PIN1))
+ pll2_mult = 4;
+
+ BUG_ON(!pll2_mult);
+
if (idx < ARRAY_SIZE(sh7619_clk_ops))
*ops = sh7619_clk_ops[idx];
}
-
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index becc54c4569..c8a4331d9b8 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -227,8 +227,9 @@ ENTRY(sh_bios_handler)
mov.l @r15+, r14
add #8,r15
lds.l @r15+, pr
+ mov.l @r15+,r15
rte
- mov.l @r15+,r15
+ nop
.align 2
1: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index 5916d9096b9..6c687ae812e 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -13,7 +13,7 @@
#include <asm/processor.h>
#include <asm/cache.h>
-int __init detect_cpu_and_cache_system(void)
+void cpu_probe(void)
{
#if defined(CONFIG_CPU_SUBTYPE_SH7619)
boot_cpu_data.type = CPU_SH7619;
@@ -29,7 +29,5 @@ int __init detect_cpu_and_cache_system(void)
*/
boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
boot_cpu_data.icache = boot_cpu_data.dcache;
-
- return 0;
+ boot_cpu_data.family = CPU_FAMILY_SH2;
}
-
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
index 56e5878e551..58c19adae90 100644
--- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -2,6 +2,7 @@
* SH7619 Setup
*
* Copyright (C) 2006 Yoshinori Sato
+ * Copyright (C) 2009 Paul Mundt
*
* 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,9 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_eth.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
@@ -18,15 +22,10 @@ enum {
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
WDT, EDMAC, CMT0, CMT1,
- SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
- SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
- SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
+ SCIF0, SCIF1, SCIF2,
HIF_HIFI, HIF_HIFBI,
DMAC0, DMAC1, DMAC2, DMAC3,
SIOF,
-
- /* interrupt groups */
- SCIF0, SCIF1, SCIF2,
};
static struct intc_vect vectors[] __initdata = {
@@ -36,24 +35,18 @@ static struct intc_vect vectors[] __initdata = {
INTC_IRQ(IRQ6, 82), INTC_IRQ(IRQ7, 83),
INTC_IRQ(WDT, 84), INTC_IRQ(EDMAC, 85),
INTC_IRQ(CMT0, 86), INTC_IRQ(CMT1, 87),
- INTC_IRQ(SCIF0_ERI, 88), INTC_IRQ(SCIF0_RXI, 89),
- INTC_IRQ(SCIF0_BRI, 90), INTC_IRQ(SCIF0_TXI, 91),
- INTC_IRQ(SCIF1_ERI, 92), INTC_IRQ(SCIF1_RXI, 93),
- INTC_IRQ(SCIF1_BRI, 94), INTC_IRQ(SCIF1_TXI, 95),
- INTC_IRQ(SCIF2_ERI, 96), INTC_IRQ(SCIF2_RXI, 97),
- INTC_IRQ(SCIF2_BRI, 98), INTC_IRQ(SCIF2_TXI, 99),
+ INTC_IRQ(SCIF0, 88), INTC_IRQ(SCIF0, 89),
+ INTC_IRQ(SCIF0, 90), INTC_IRQ(SCIF0, 91),
+ INTC_IRQ(SCIF1, 92), INTC_IRQ(SCIF1, 93),
+ INTC_IRQ(SCIF1, 94), INTC_IRQ(SCIF1, 95),
+ INTC_IRQ(SCIF2, 96), INTC_IRQ(SCIF2, 97),
+ INTC_IRQ(SCIF2, 98), INTC_IRQ(SCIF2, 99),
INTC_IRQ(HIF_HIFI, 100), INTC_IRQ(HIF_HIFBI, 101),
INTC_IRQ(DMAC0, 104), INTC_IRQ(DMAC1, 105),
INTC_IRQ(DMAC2, 106), INTC_IRQ(DMAC3, 107),
INTC_IRQ(SIOF, 108),
};
-static struct intc_group groups[] __initdata = {
- 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),
-};
-
static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xf8140006, 0, 16, 4, /* IPRA */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
{ 0xf8140008, 0, 16, 4, /* IPRB */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
@@ -64,42 +57,82 @@ static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xf8080008, 0, 16, 4, /* IPRG */ { SIOF } },
};
-static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7619", vectors, NULL,
NULL, prio_registers, NULL);
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xf8400000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 88, 89, 91, 90},
- }, {
- .mapbase = 0xf8410000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 92, 93, 95, 94},
- }, {
- .mapbase = 0xf8420000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 96, 97, 99, 98},
- }, {
- .flags = 0,
- }
-};
-
-static struct platform_device sci_device = {
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xf8400000, 0x100),
+ DEFINE_RES_IRQ(88),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xf8410000, 0x100),
+ DEFINE_RES_IRQ(92),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xf8420000, 0x100),
+ DEFINE_RES_IRQ(96),
+};
+
+static struct platform_device scif2_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif2_platform_data,
},
};
+static struct sh_eth_plat_data eth_platform_data = {
+ .phy = 1,
+ .edmac_endian = EDMAC_LITTLE_ENDIAN,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
static struct resource eth_resources[] = {
[0] = {
.start = 0xfb000000,
- .end = 0xfb0001c8,
+ .end = 0xfb0001c7,
.flags = IORESOURCE_MEM,
},
[1] = {
@@ -110,18 +143,41 @@ static struct resource eth_resources[] = {
};
static struct platform_device eth_device = {
- .name = "sh-eth",
- .id = -1,
+ .name = "sh7619-ether",
+ .id = -1,
.dev = {
- .platform_data = (void *)1,
+ .platform_data = &eth_platform_data,
},
.num_resources = ARRAY_SIZE(eth_resources),
.resource = eth_resources,
};
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0xf84a0070, 0x10),
+ DEFINE_RES_IRQ(86),
+ DEFINE_RES_IRQ(87),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-16",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
static struct platform_device *sh7619_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
&eth_device,
+ &cmt_device,
};
static int __init sh7619_devices_setup(void)
@@ -129,9 +185,27 @@ static int __init sh7619_devices_setup(void)
return platform_add_devices(sh7619_devices,
ARRAY_SIZE(sh7619_devices));
}
-__initcall(sh7619_devices_setup);
+arch_initcall(sh7619_devices_setup);
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7619_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &cmt_device,
+};
+
+#define STBCR3 0xf80a0000
+
+void __init plat_early_device_setup(void)
+{
+ /* enable CMT clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x10, STBCR3);
+
+ early_platform_add_devices(sh7619_early_devices,
+ ARRAY_SIZE(sh7619_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
index 1ab1ecf4c76..990195d9845 100644
--- a/arch/sh/kernel/cpu/sh2a/Makefile
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -8,7 +8,17 @@ common-y += ex.o entry.o
obj-$(CONFIG_SH_FPU) += fpu.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7201) += setup-sh7201.o clock-sh7201.o
obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o
obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7264) += setup-sh7264.o clock-sh7264.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7269) += setup-sh7269.o clock-sh7269.o
obj-$(CONFIG_CPU_SUBTYPE_MXG) += setup-mxg.o clock-sh7206.o
+
+# Pinmux setup
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7203) := pinmux-sh7203.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7264) := pinmux-sh7264.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7269) := pinmux-sh7269.o
+
+obj-$(CONFIG_GPIOLIB) += $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
new file mode 100644
index 00000000000..532a36c7232
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c
@@ -0,0 +1,85 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/clock-sh7201.c
+ *
+ * SH7201 support for the clock framework
+ *
+ * Copyright (C) 2008 Peter Griffin <pgriffin@mpc-data.co.uk>
+ *
+ * Based on clock-sh4.c
+ * Copyright (C) 2005 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static const int pll1rate[]={1,2,3,4,6,8};
+static const int pfc_divisors[]={1,2,3,4,6,8,12};
+#define ifc_divisors pfc_divisors
+
+static unsigned int pll2_mult;
+
+static void master_clk_init(struct clk *clk)
+{
+ clk->rate = 10000000 * pll2_mult *
+ pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+}
+
+static struct sh_clk_ops sh7201_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static unsigned long module_clk_recalc(struct clk *clk)
+{
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct sh_clk_ops sh7201_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static unsigned long bus_clk_recalc(struct clk *clk)
+{
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct sh_clk_ops sh7201_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static unsigned long cpu_clk_recalc(struct clk *clk)
+{
+ int idx = ((__raw_readw(FREQCR) >> 4) & 0x0007);
+ return clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct sh_clk_ops sh7201_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct sh_clk_ops *sh7201_clk_ops[] = {
+ &sh7201_master_clk_ops,
+ &sh7201_module_clk_ops,
+ &sh7201_bus_clk_ops,
+ &sh7201_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
+{
+ if (test_mode_pin(MODE_PIN1 | MODE_PIN0))
+ pll2_mult = 1;
+ else if (test_mode_pin(MODE_PIN1))
+ pll2_mult = 2;
+ else
+ pll2_mult = 4;
+
+ if (idx < ARRAY_SIZE(sh7201_clk_ops))
+ *ops = sh7201_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
index fb781329848..529f719b6e3 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7203.c
@@ -25,65 +25,57 @@ static const int pll1rate[]={8,12,16,0};
static const int pfc_divisors[]={1,2,3,4,6,8,12};
#define ifc_divisors pfc_divisors
-#if (CONFIG_SH_CLK_MD == 0)
-#define PLL2 (1)
-#elif (CONFIG_SH_CLK_MD == 1)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 3)
-#define PLL2 (4)
-#else
-#error "Illegal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
static void master_clk_init(struct clk *clk)
{
- clk->rate *= pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0003] * PLL2 ;
+ clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * pll2_mult;
}
-static struct clk_ops sh7203_master_clk_ops = {
+static struct sh_clk_ops sh7203_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(FREQCR) & 0x0007);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7203_module_clk_ops = {
+static struct sh_clk_ops sh7203_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(FREQCR) & 0x0007);
- clk->rate = clk->parent->rate / pfc_divisors[idx-2];
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx-2];
}
-static struct clk_ops sh7203_bus_clk_ops = {
+static struct sh_clk_ops sh7203_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
-static void cpu_clk_recalc(struct clk *clk)
-{
- clk->rate = clk->parent->rate;
-}
-
-static struct clk_ops sh7203_cpu_clk_ops = {
- .recalc = cpu_clk_recalc,
+static struct sh_clk_ops sh7203_cpu_clk_ops = {
+ .recalc = followparent_recalc,
};
-static struct clk_ops *sh7203_clk_ops[] = {
+static struct sh_clk_ops *sh7203_clk_ops[] = {
&sh7203_master_clk_ops,
&sh7203_module_clk_ops,
&sh7203_bus_clk_ops,
&sh7203_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
+ if (test_mode_pin(MODE_PIN1))
+ pll2_mult = 4;
+ else if (test_mode_pin(MODE_PIN0))
+ pll2_mult = 2;
+ else
+ pll2_mult = 1;
+
if (idx < ARRAY_SIZE(sh7203_clk_ops))
*ops = sh7203_clk_ops[idx];
}
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
index 82d7f991ef6..17778983467 100644
--- a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
@@ -22,64 +22,62 @@ static const int pll1rate[]={1,2,3,4,6,8};
static const int pfc_divisors[]={1,2,3,4,6,8,12};
#define ifc_divisors pfc_divisors
-#if (CONFIG_SH_CLK_MD == 2)
-#define PLL2 (4)
-#elif (CONFIG_SH_CLK_MD == 6)
-#define PLL2 (2)
-#elif (CONFIG_SH_CLK_MD == 7)
-#define PLL2 (1)
-#else
-#error "Illigal Clock Mode!"
-#endif
+static unsigned int pll2_mult;
static void master_clk_init(struct clk *clk)
{
- clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+ clk->rate *= pll2_mult * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
}
-static struct clk_ops sh7206_master_clk_ops = {
+static struct sh_clk_ops sh7206_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(FREQCR) & 0x0007);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7206_module_clk_ops = {
+static struct sh_clk_ops sh7206_module_clk_ops = {
.recalc = module_clk_recalc,
};
-static void bus_clk_recalc(struct clk *clk)
+static unsigned long bus_clk_recalc(struct clk *clk)
{
- clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
+ return clk->parent->rate / pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
}
-static struct clk_ops sh7206_bus_clk_ops = {
+static struct sh_clk_ops sh7206_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(FREQCR) & 0x0007);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ int idx = (__raw_readw(FREQCR) & 0x0007);
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh7206_cpu_clk_ops = {
+static struct sh_clk_ops sh7206_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7206_clk_ops[] = {
+static struct sh_clk_ops *sh7206_clk_ops[] = {
&sh7206_master_clk_ops,
&sh7206_module_clk_ops,
&sh7206_bus_clk_ops,
&sh7206_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
+ if (test_mode_pin(MODE_PIN2 | MODE_PIN1 | MODE_PIN0))
+ pll2_mult = 1;
+ else if (test_mode_pin(MODE_PIN2 | MODE_PIN1))
+ pll2_mult = 2;
+ else if (test_mode_pin(MODE_PIN1))
+ pll2_mult = 4;
+
if (idx < ARRAY_SIZE(sh7206_clk_ops))
*ops = sh7206_clk_ops[idx];
}
-
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7264.c b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
new file mode 100644
index 00000000000..8638fba6cd7
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7264.c
@@ -0,0 +1,153 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/clock-sh7264.c
+ *
+ * SH7264 clock framework support
+ *
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+/* SH7264 registers */
+#define FRQCR 0xfffe0010
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+#define STBCR5 0xfffe0410
+#define STBCR6 0xfffe0414
+#define STBCR7 0xfffe0418
+#define STBCR8 0xfffe041c
+
+static const unsigned int pll1rate[] = {8, 12};
+
+static unsigned int pll1_div;
+
+/* Fixed 32 KHz root clock for RTC */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 18000000,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long rate = clk->parent->rate / pll1_div;
+ return rate * pll1rate[(__raw_readw(FRQCR) >> 8) & 1];
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &pll_clk,
+};
+
+static int div2[] = { 1, 2, 3, 4, 6, 8, 12 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_P,
+ DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+/* The mask field specifies the div2 entries that are valid */
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 4, 0x7, CLK_ENABLE_REG_16BIT
+ | CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCR, 0, 0x78, CLK_ENABLE_REG_16BIT),
+};
+
+enum { MSTP77, MSTP74, MSTP72,
+ MSTP60,
+ MSTP35, MSTP34, MSTP33, MSTP32, MSTP30,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP77] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 7, 0), /* SCIF */
+ [MSTP74] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 4, 0), /* VDC */
+ [MSTP72] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR7, 2, 0), /* CMT */
+ [MSTP60] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR6, 0, 0), /* USB */
+ [MSTP35] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 6, 0), /* MTU2 */
+ [MSTP34] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 4, 0), /* SDHI0 */
+ [MSTP33] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 3, 0), /* SDHI1 */
+ [MSTP32] = SH_CLK_MSTP8(&div4_clks[DIV4_P], STBCR3, 2, 0), /* ADC */
+ [MSTP30] = SH_CLK_MSTP8(&r_clk, STBCR3, 0, 0), /* RTC */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+
+ /* MSTP clocks */
+ CLKDEV_CON_ID("sci_ick", &mstp_clks[MSTP77]),
+ CLKDEV_CON_ID("vdc3", &mstp_clks[MSTP74]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
+ CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
+ CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]),
+ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP34]),
+ CLKDEV_CON_ID("sdhi1", &mstp_clks[MSTP33]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP30]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ if (test_mode_pin(MODE_PIN0)) {
+ if (test_mode_pin(MODE_PIN1))
+ pll1_div = 3;
+ else
+ pll1_div = 4;
+ } else
+ pll1_div = 1;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7269.c b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
new file mode 100644
index 00000000000..f8a5c2abdfb
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7269.c
@@ -0,0 +1,184 @@
+/*
+ * arch/sh/kernel/cpu/sh2a/clock-sh7269.c
+ *
+ * SH7269 clock framework support
+ *
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+/* SH7269 registers */
+#define FRQCR 0xfffe0010
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+#define STBCR5 0xfffe0410
+#define STBCR6 0xfffe0414
+#define STBCR7 0xfffe0418
+
+#define PLL_RATE 20
+
+/* Fixed 32 KHz root clock for RTC */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 13340000,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ return clk->parent->rate * PLL_RATE;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long peripheral0_recalc(struct clk *clk)
+{
+ return clk->parent->rate / 8;
+}
+
+static struct sh_clk_ops peripheral0_clk_ops = {
+ .recalc = peripheral0_recalc,
+};
+
+static struct clk peripheral0_clk = {
+ .ops = &peripheral0_clk_ops,
+ .parent = &pll_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long peripheral1_recalc(struct clk *clk)
+{
+ return clk->parent->rate / 4;
+}
+
+static struct sh_clk_ops peripheral1_clk_ops = {
+ .recalc = peripheral1_recalc,
+};
+
+static struct clk peripheral1_clk = {
+ .ops = &peripheral1_clk_ops,
+ .parent = &pll_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &pll_clk,
+ &peripheral0_clk,
+ &peripheral1_clk,
+};
+
+static int div2[] = { 1, 2, 0, 4 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_B,
+ DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+/* The mask field specifies the div2 entries that are valid */
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 8, 0xB, CLK_ENABLE_REG_16BIT
+ | CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCR, 4, 0xA, CLK_ENABLE_REG_16BIT
+ | CLK_ENABLE_ON_INIT),
+};
+
+enum { MSTP72,
+ MSTP60,
+ MSTP47, MSTP46, MSTP45, MSTP44, MSTP43, MSTP42, MSTP41, MSTP40,
+ MSTP35, MSTP32, MSTP30,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP72] = SH_CLK_MSTP8(&peripheral0_clk, STBCR7, 2, 0), /* CMT */
+ [MSTP60] = SH_CLK_MSTP8(&peripheral1_clk, STBCR6, 0, 0), /* USB */
+ [MSTP47] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 7, 0), /* SCIF0 */
+ [MSTP46] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 6, 0), /* SCIF1 */
+ [MSTP45] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 5, 0), /* SCIF2 */
+ [MSTP44] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 4, 0), /* SCIF3 */
+ [MSTP43] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 3, 0), /* SCIF4 */
+ [MSTP42] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 2, 0), /* SCIF5 */
+ [MSTP41] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 1, 0), /* SCIF6 */
+ [MSTP40] = SH_CLK_MSTP8(&peripheral1_clk, STBCR4, 0, 0), /* SCIF7 */
+ [MSTP35] = SH_CLK_MSTP8(&peripheral0_clk, STBCR3, 5, 0), /* MTU2 */
+ [MSTP32] = SH_CLK_MSTP8(&peripheral1_clk, STBCR3, 2, 0), /* ADC */
+ [MSTP30] = SH_CLK_MSTP8(&r_clk, STBCR3, 0, 0), /* RTC */
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+ CLKDEV_CON_ID("peripheral_clk", &peripheral1_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+
+ /* MSTP clocks */
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP47]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP46]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP45]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP44]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP43]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP42]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.6", &mstp_clks[MSTP41]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.7", &mstp_clks[MSTP40]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[MSTP72]),
+ CLKDEV_CON_ID("usb0", &mstp_clks[MSTP60]),
+ CLKDEV_ICK_ID("fck", "sh-mtu2", &mstp_clks[MSTP35]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[MSTP32]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP30]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh2a/entry.S b/arch/sh/kernel/cpu/sh2a/entry.S
index ab3903eeda5..222742ddc0d 100644
--- a/arch/sh/kernel/cpu/sh2a/entry.S
+++ b/arch/sh/kernel/cpu/sh2a/entry.S
@@ -176,8 +176,9 @@ ENTRY(sh_bios_handler)
movml.l @r15+,r14
add #8,r15
lds.l @r15+, pr
+ mov.l @r15+,r15
rte
- mov.l @r15+,r15
+ nop
.align 2
1: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
diff --git a/arch/sh/kernel/cpu/sh2a/ex.S b/arch/sh/kernel/cpu/sh2a/ex.S
index 3ead9e63965..4568066700c 100644
--- a/arch/sh/kernel/cpu/sh2a/ex.S
+++ b/arch/sh/kernel/cpu/sh2a/ex.S
@@ -66,6 +66,7 @@ vector = 0
.long exception_entry0 + vector * 6
vector = vector + 1
.endr
+vector = 0
.rept 256
.long exception_entry1 + vector * 6
vector = vector + 1
diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c
index 6df2fb98eb3..98bbaa447c9 100644
--- a/arch/sh/kernel/cpu/sh2a/fpu.c
+++ b/arch/sh/kernel/cpu/sh2a/fpu.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/fpu.h>
+#include <asm/traps.h>
/* The PR (precision) bit in the FP Status Register must be clear when
* an frchg instruction is executed, otherwise the instruction is undefined.
@@ -25,14 +26,11 @@
/*
* Save FPU registers onto task structure.
- * Assume called with FPU enabled (SR.FD=0).
*/
-void
-save_fpu(struct task_struct *tsk, struct pt_regs *regs)
+void save_fpu(struct task_struct *tsk)
{
unsigned long dummy;
- clear_tsk_thread_flag(tsk, TIF_USEDFPU);
enable_fpu();
asm volatile("sts.l fpul, @-%0\n\t"
"sts.l fpscr, @-%0\n\t"
@@ -54,17 +52,15 @@ save_fpu(struct task_struct *tsk, struct pt_regs *regs)
"fmov.s fr0, @-%0\n\t"
"lds %3, fpscr\n\t"
: "=r" (dummy)
- : "0" ((char *)(&tsk->thread.fpu.hard.status)),
+ : "0" ((char *)(&tsk->thread.xstate->hardfpu.status)),
"r" (FPSCR_RCHG),
"r" (FPSCR_INIT)
: "memory");
disable_fpu();
- release_fpu(regs);
}
-static void
-restore_fpu(struct task_struct *tsk)
+void restore_fpu(struct task_struct *tsk)
{
unsigned long dummy;
@@ -88,45 +84,12 @@ restore_fpu(struct task_struct *tsk)
"lds.l @%0+, fpscr\n\t"
"lds.l @%0+, fpul\n\t"
: "=r" (dummy)
- : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG)
+ : "0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
: "memory");
disable_fpu();
}
/*
- * Load the FPU with signalling NANS. This bit pattern we're using
- * has the property that no matter wether considered as single or as
- * double precission represents signaling NANS.
- */
-
-static void
-fpu_init(void)
-{
- enable_fpu();
- asm volatile("lds %0, fpul\n\t"
- "fsts fpul, fr0\n\t"
- "fsts fpul, fr1\n\t"
- "fsts fpul, fr2\n\t"
- "fsts fpul, fr3\n\t"
- "fsts fpul, fr4\n\t"
- "fsts fpul, fr5\n\t"
- "fsts fpul, fr6\n\t"
- "fsts fpul, fr7\n\t"
- "fsts fpul, fr8\n\t"
- "fsts fpul, fr9\n\t"
- "fsts fpul, fr10\n\t"
- "fsts fpul, fr11\n\t"
- "fsts fpul, fr12\n\t"
- "fsts fpul, fr13\n\t"
- "fsts fpul, fr14\n\t"
- "fsts fpul, fr15\n\t"
- "lds %2, fpscr\n\t"
- : /* no output */
- : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT));
- disable_fpu();
-}
-
-/*
* Emulate arithmetic ops on denormalized number for some FPU insns.
*/
@@ -493,9 +456,9 @@ ieee_fpe_handler (struct pt_regs *regs)
if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
struct task_struct *tsk = current;
- if ((tsk->thread.fpu.hard.fpscr & FPSCR_FPU_ERROR)) {
+ if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_FPU_ERROR)) {
/* FPU error */
- denormal_to_double (&tsk->thread.fpu.hard,
+ denormal_to_double (&tsk->thread.xstate->hardfpu,
(finsn >> 8) & 0xf);
} else
return 0;
@@ -510,9 +473,9 @@ ieee_fpe_handler (struct pt_regs *regs)
n = (finsn >> 8) & 0xf;
m = (finsn >> 4) & 0xf;
- hx = tsk->thread.fpu.hard.fp_regs[n];
- hy = tsk->thread.fpu.hard.fp_regs[m];
- fpscr = tsk->thread.fpu.hard.fpscr;
+ hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+ hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+ fpscr = tsk->thread.xstate->hardfpu.fpscr;
prec = fpscr & (1 << 19);
if ((fpscr & FPSCR_FPU_ERROR)
@@ -522,15 +485,15 @@ ieee_fpe_handler (struct pt_regs *regs)
/* FPU error because of denormal */
llx = ((long long) hx << 32)
- | tsk->thread.fpu.hard.fp_regs[n+1];
+ | tsk->thread.xstate->hardfpu.fp_regs[n+1];
lly = ((long long) hy << 32)
- | tsk->thread.fpu.hard.fp_regs[m+1];
+ | tsk->thread.xstate->hardfpu.fp_regs[m+1];
if ((hx & 0x7fffffff) >= 0x00100000)
llx = denormal_muld(lly, llx);
else
llx = denormal_muld(llx, lly);
- tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
- tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+ tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
} else if ((fpscr & FPSCR_FPU_ERROR)
&& (!prec && ((hx & 0x7fffffff) < 0x00800000
|| (hy & 0x7fffffff) < 0x00800000))) {
@@ -539,7 +502,7 @@ ieee_fpe_handler (struct pt_regs *regs)
hx = denormal_mulf(hy, hx);
else
hx = denormal_mulf(hx, hy);
- tsk->thread.fpu.hard.fp_regs[n] = hx;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
} else
return 0;
@@ -553,9 +516,9 @@ ieee_fpe_handler (struct pt_regs *regs)
n = (finsn >> 8) & 0xf;
m = (finsn >> 4) & 0xf;
- hx = tsk->thread.fpu.hard.fp_regs[n];
- hy = tsk->thread.fpu.hard.fp_regs[m];
- fpscr = tsk->thread.fpu.hard.fpscr;
+ hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+ hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+ fpscr = tsk->thread.xstate->hardfpu.fpscr;
prec = fpscr & (1 << 19);
if ((fpscr & FPSCR_FPU_ERROR)
@@ -565,15 +528,15 @@ ieee_fpe_handler (struct pt_regs *regs)
/* FPU error because of denormal */
llx = ((long long) hx << 32)
- | tsk->thread.fpu.hard.fp_regs[n+1];
+ | tsk->thread.xstate->hardfpu.fp_regs[n+1];
lly = ((long long) hy << 32)
- | tsk->thread.fpu.hard.fp_regs[m+1];
+ | tsk->thread.xstate->hardfpu.fp_regs[m+1];
if ((finsn & 0xf00f) == 0xf000)
llx = denormal_addd(llx, lly);
else
llx = denormal_addd(llx, lly ^ (1LL << 63));
- tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
- tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+ tsk->thread.xstate->hardfpu.fp_regs[n+1] = llx & 0xffffffff;
} else if ((fpscr & FPSCR_FPU_ERROR)
&& (!prec && ((hx & 0x7fffffff) < 0x00800000
|| (hy & 0x7fffffff) < 0x00800000))) {
@@ -582,7 +545,7 @@ ieee_fpe_handler (struct pt_regs *regs)
hx = denormal_addf(hx, hy);
else
hx = denormal_addf(hx, hy ^ 0x80000000);
- tsk->thread.fpu.hard.fp_regs[n] = hx;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
} else
return 0;
@@ -598,37 +561,15 @@ BUILD_TRAP_HANDLER(fpu_error)
struct task_struct *tsk = current;
TRAP_HANDLER_DECL;
- save_fpu(tsk, regs);
+ __unlazy_fpu(tsk, regs);
if (ieee_fpe_handler(regs)) {
- tsk->thread.fpu.hard.fpscr &=
+ tsk->thread.xstate->hardfpu.fpscr &=
~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
grab_fpu(regs);
restore_fpu(tsk);
- set_tsk_thread_flag(tsk, TIF_USEDFPU);
+ task_thread_info(tsk)->status |= TS_USEDFPU;
return;
}
force_sig(SIGFPE, tsk);
}
-
-BUILD_TRAP_HANDLER(fpu_state_restore)
-{
- struct task_struct *tsk = current;
- TRAP_HANDLER_DECL;
-
- grab_fpu(regs);
- if (!user_mode(regs)) {
- printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
- return;
- }
-
- if (used_math()) {
- /* Using the FPU again. */
- restore_fpu(tsk);
- } else {
- /* First time FPU user. */
- fpu_init();
- set_used_math();
- }
- set_tsk_thread_flag(tsk, TIF_USEDFPU);
-}
diff --git a/arch/sh/kernel/cpu/sh2a/opcode_helper.c b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
index 9704b7926d8..72aa61c81e4 100644
--- a/arch/sh/kernel/cpu/sh2a/opcode_helper.c
+++ b/arch/sh/kernel/cpu/sh2a/opcode_helper.c
@@ -10,7 +10,6 @@
* for more details.
*/
#include <linux/kernel.h>
-#include <asm/system.h>
/*
* Instructions on SH are generally fixed at 16-bits, however, SH-2A
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
new file mode 100644
index 00000000000..eef17dcc3a4
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
@@ -0,0 +1,30 @@
+/*
+ * SH7203 Pinmux
+ *
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7203_pfc_resources[] = {
+ [0] = {
+ .start = 0xfffe3800,
+ .end = 0xfffe3a9f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7203", sh7203_pfc_resources,
+ ARRAY_SIZE(sh7203_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
new file mode 100644
index 00000000000..569decbd6d9
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7264.c
@@ -0,0 +1,30 @@
+/*
+ * SH7264 Pinmux
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7264_pfc_resources[] = {
+ [0] = {
+ .start = 0xfffe3800,
+ .end = 0xfffe393f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7264", sh7264_pfc_resources,
+ ARRAY_SIZE(sh7264_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
new file mode 100644
index 00000000000..4c17fb6970b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/pinmux-sh7269.c
@@ -0,0 +1,31 @@
+/*
+ * SH7269 Pinmux
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7269_pfc_resources[] = {
+ [0] = {
+ .start = 0xfffe3800,
+ .end = 0xfffe391f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7269", sh7269_pfc_resources,
+ ARRAY_SIZE(sh7269_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
index 6e79132f6f3..3f87971082f 100644
--- a/arch/sh/kernel/cpu/sh2a/probe.c
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -13,21 +13,30 @@
#include <asm/processor.h>
#include <asm/cache.h>
-int __init detect_cpu_and_cache_system(void)
+void cpu_probe(void)
{
+ boot_cpu_data.family = CPU_FAMILY_SH2A;
+
/* All SH-2A CPUs have support for 16 and 32-bit opcodes.. */
boot_cpu_data.flags |= CPU_HAS_OP32;
-#if defined(CONFIG_CPU_SUBTYPE_SH7203)
+#if defined(CONFIG_CPU_SUBTYPE_SH7201)
+ boot_cpu_data.type = CPU_SH7201;
+ boot_cpu_data.flags |= CPU_HAS_FPU;
+#elif defined(CONFIG_CPU_SUBTYPE_SH7203)
boot_cpu_data.type = CPU_SH7203;
- /* SH7203 has an FPU.. */
boot_cpu_data.flags |= CPU_HAS_FPU;
#elif defined(CONFIG_CPU_SUBTYPE_SH7263)
boot_cpu_data.type = CPU_SH7263;
boot_cpu_data.flags |= CPU_HAS_FPU;
+#elif defined(CONFIG_CPU_SUBTYPE_SH7264)
+ boot_cpu_data.type = CPU_SH7264;
+ boot_cpu_data.flags |= CPU_HAS_FPU;
+#elif defined(CONFIG_CPU_SUBTYPE_SH7269)
+ boot_cpu_data.type = CPU_SH7269;
+ boot_cpu_data.flags |= CPU_HAS_FPU;
#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
boot_cpu_data.type = CPU_SH7206;
- /* While SH7206 has a DSP.. */
boot_cpu_data.flags |= CPU_HAS_DSP;
#elif defined(CONFIG_CPU_SUBTYPE_MXG)
boot_cpu_data.type = CPU_MXG;
@@ -48,6 +57,4 @@ int __init detect_cpu_and_cache_system(void)
* on the cache info.
*/
boot_cpu_data.icache = boot_cpu_data.dcache;
-
- return 0;
}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
index e611d79fac4..26fcdbd4127 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c
@@ -1,7 +1,7 @@
/*
* Renesas MX-G (R8A03022BG) Setup
*
- * Copyright (C) 2008 Paul Mundt
+ * Copyright (C) 2008, 2009 Paul Mundt
*
* 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 +11,7 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
enum {
UNUSED = 0,
@@ -20,23 +21,15 @@ enum {
IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15,
PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
-
SINT8, SINT7, SINT6, SINT5, SINT4, SINT3, SINT2, SINT1,
- SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
- SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
+ SCIF0, SCIF1,
- MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
- MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F,
- MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U,
- MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
- MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V,
- MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V,
- MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W,
+ MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5,
+ MTU2_TGI3B, MTU2_TGI3C,
/* interrupt groups */
- PINT, SCIF0, SCIF1,
- MTU2_GROUP1, MTU2_GROUP2, MTU2_GROUP3, MTU2_GROUP4, MTU2_GROUP5
+ PINT,
};
static struct intc_vect vectors[] __initdata = {
@@ -59,47 +52,36 @@ static struct intc_vect vectors[] __initdata = {
INTC_IRQ(SINT4, 98), INTC_IRQ(SINT3, 99),
INTC_IRQ(SINT2, 100), INTC_IRQ(SINT1, 101),
- INTC_IRQ(SCIF0_RXI, 220), INTC_IRQ(SCIF0_TXI, 221),
- INTC_IRQ(SCIF0_BRI, 222), INTC_IRQ(SCIF0_ERI, 223),
- INTC_IRQ(SCIF1_RXI, 224), INTC_IRQ(SCIF1_TXI, 225),
- INTC_IRQ(SCIF1_BRI, 226), INTC_IRQ(SCIF1_ERI, 227),
+ INTC_IRQ(SCIF0, 220), INTC_IRQ(SCIF0, 221),
+ INTC_IRQ(SCIF0, 222), INTC_IRQ(SCIF0, 223),
+ INTC_IRQ(SCIF1, 224), INTC_IRQ(SCIF1, 225),
+ INTC_IRQ(SCIF1, 226), INTC_IRQ(SCIF1, 227),
- INTC_IRQ(MTU2_TGI0A, 228), INTC_IRQ(MTU2_TGI0B, 229),
- INTC_IRQ(MTU2_TGI0C, 230), INTC_IRQ(MTU2_TGI0D, 231),
- INTC_IRQ(MTU2_TCI0V, 232), INTC_IRQ(MTU2_TGI0E, 233),
+ INTC_IRQ(MTU2_GROUP1, 228), INTC_IRQ(MTU2_GROUP1, 229),
+ INTC_IRQ(MTU2_GROUP1, 230), INTC_IRQ(MTU2_GROUP1, 231),
+ INTC_IRQ(MTU2_GROUP1, 232), INTC_IRQ(MTU2_GROUP1, 233),
- INTC_IRQ(MTU2_TGI0F, 234), INTC_IRQ(MTU2_TGI1A, 235),
- INTC_IRQ(MTU2_TGI1B, 236), INTC_IRQ(MTU2_TCI1V, 237),
- INTC_IRQ(MTU2_TCI1U, 238), INTC_IRQ(MTU2_TGI2A, 239),
+ INTC_IRQ(MTU2_GROUP2, 234), INTC_IRQ(MTU2_GROUP2, 235),
+ INTC_IRQ(MTU2_GROUP2, 236), INTC_IRQ(MTU2_GROUP2, 237),
+ INTC_IRQ(MTU2_GROUP2, 238), INTC_IRQ(MTU2_GROUP2, 239),
- INTC_IRQ(MTU2_TGI2B, 240), INTC_IRQ(MTU2_TCI2V, 241),
- INTC_IRQ(MTU2_TCI2U, 242), INTC_IRQ(MTU2_TGI3A, 243),
+ INTC_IRQ(MTU2_GROUP3, 240), INTC_IRQ(MTU2_GROUP3, 241),
+ INTC_IRQ(MTU2_GROUP3, 242), INTC_IRQ(MTU2_GROUP3, 243),
INTC_IRQ(MTU2_TGI3B, 244),
INTC_IRQ(MTU2_TGI3C, 245),
- INTC_IRQ(MTU2_TGI3D, 246), INTC_IRQ(MTU2_TCI3V, 247),
- INTC_IRQ(MTU2_TGI4A, 248), INTC_IRQ(MTU2_TGI4B, 249),
- INTC_IRQ(MTU2_TGI4C, 250), INTC_IRQ(MTU2_TGI4D, 251),
+ INTC_IRQ(MTU2_GROUP4, 246), INTC_IRQ(MTU2_GROUP4, 247),
+ INTC_IRQ(MTU2_GROUP4, 248), INTC_IRQ(MTU2_GROUP4, 249),
+ INTC_IRQ(MTU2_GROUP4, 250), INTC_IRQ(MTU2_GROUP4, 251),
- INTC_IRQ(MTU2_TCI4V, 252), INTC_IRQ(MTU2_TGI5U, 253),
- INTC_IRQ(MTU2_TGI5V, 254), INTC_IRQ(MTU2_TGI5W, 255),
+ INTC_IRQ(MTU2_GROUP5, 252), INTC_IRQ(MTU2_GROUP5, 253),
+ INTC_IRQ(MTU2_GROUP5, 254), INTC_IRQ(MTU2_GROUP5, 255),
};
static struct intc_group groups[] __initdata = {
INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
PINT4, PINT5, PINT6, PINT7),
- INTC_GROUP(MTU2_GROUP1, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
- MTU2_TCI0V, MTU2_TGI0E),
- INTC_GROUP(MTU2_GROUP2, MTU2_TGI0F, MTU2_TGI1A, MTU2_TGI1B,
- MTU2_TCI1V, MTU2_TCI1U, MTU2_TGI2A),
- INTC_GROUP(MTU2_GROUP3, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
- MTU2_TGI3A),
- INTC_GROUP(MTU2_GROUP4, MTU2_TGI3D, MTU2_TCI3V, MTU2_TGI4A,
- MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
- INTC_GROUP(MTU2_GROUP5, MTU2_TCI4V, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W),
- INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
- INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
};
static struct intc_prio_reg prio_registers[] __initdata = {
@@ -132,27 +114,44 @@ static struct intc_mask_reg mask_registers[] __initdata = {
static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups,
mask_registers, prio_registers, NULL);
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xff804000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 223, 220, 221, 222 },
- }, {
- .flags = 0,
- }
+static struct resource mtu2_resources[] = {
+ DEFINE_RES_MEM(0xff801000, 0x400),
+ DEFINE_RES_IRQ_NAMED(228, "tgi0a"),
+ DEFINE_RES_IRQ_NAMED(234, "tgi1a"),
+ DEFINE_RES_IRQ_NAMED(240, "tgi2a"),
};
-static struct platform_device sci_device = {
- .name = "sh-sci",
+static struct platform_device mtu2_device = {
+ .name = "sh-mtu2",
.id = -1,
+ .resource = mtu2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_resources),
+};
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xff804000, 0x100),
+ DEFINE_RES_IRQ(220),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif0_platform_data,
},
};
static struct platform_device *mxg_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &mtu2_device,
};
static int __init mxg_devices_setup(void)
@@ -160,9 +159,20 @@ static int __init mxg_devices_setup(void)
return platform_add_devices(mxg_devices,
ARRAY_SIZE(mxg_devices));
}
-__initcall(mxg_devices_setup);
+arch_initcall(mxg_devices_setup);
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *mxg_early_devices[] __initdata = {
+ &scif0_device,
+ &mtu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(mxg_early_devices,
+ ARRAY_SIZE(mxg_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
new file mode 100644
index 00000000000..abc0ce9fb80
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c
@@ -0,0 +1,428 @@
+/*
+ * SH7201 setup
+ *
+ * Copyright (C) 2008 Peter Griffin pgriffin@mpc-data.co.uk
+ * Copyright (C) 2009 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
+
+ ADC_ADI,
+
+ MTU20_ABCD, MTU20_VEF, MTU21_AB, MTU21_VU, MTU22_AB, MTU22_VU,
+ MTU23_ABCD, MTU24_ABCD, MTU25_UVW, MTU2_TCI3V, MTU2_TCI4V,
+
+ RTC, WDT,
+
+ IIC30, IIC31, IIC32,
+
+ DMAC0_DMINT0, DMAC1_DMINT1,
+ DMAC2_DMINT2, DMAC3_DMINT3,
+
+ SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
+
+ DMAC0_DMINTA, DMAC4_DMINT4, DMAC5_DMINT5, DMAC6_DMINT6,
+ DMAC7_DMINT7,
+
+ RCAN0, RCAN1,
+
+ SSI0_SSII, SSI1_SSII,
+
+ TMR0, TMR1,
+
+ /* interrupt groups */
+ PINT,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
+ INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
+ INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
+ INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
+
+ INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
+ INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
+ INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
+ INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
+
+ INTC_IRQ(ADC_ADI, 92),
+
+ INTC_IRQ(MTU20_ABCD, 108), INTC_IRQ(MTU20_ABCD, 109),
+ INTC_IRQ(MTU20_ABCD, 110), INTC_IRQ(MTU20_ABCD, 111),
+
+ INTC_IRQ(MTU20_VEF, 112), INTC_IRQ(MTU20_VEF, 113),
+ INTC_IRQ(MTU20_VEF, 114),
+
+ INTC_IRQ(MTU21_AB, 116), INTC_IRQ(MTU21_AB, 117),
+ INTC_IRQ(MTU21_VU, 120), INTC_IRQ(MTU21_VU, 121),
+
+ INTC_IRQ(MTU22_AB, 124), INTC_IRQ(MTU22_AB, 125),
+ INTC_IRQ(MTU22_VU, 128), INTC_IRQ(MTU22_VU, 129),
+
+ INTC_IRQ(MTU23_ABCD, 132), INTC_IRQ(MTU23_ABCD, 133),
+ INTC_IRQ(MTU23_ABCD, 134), INTC_IRQ(MTU23_ABCD, 135),
+
+ INTC_IRQ(MTU2_TCI3V, 136),
+
+ INTC_IRQ(MTU24_ABCD, 140), INTC_IRQ(MTU24_ABCD, 141),
+ INTC_IRQ(MTU24_ABCD, 142), INTC_IRQ(MTU24_ABCD, 143),
+
+ INTC_IRQ(MTU2_TCI4V, 144),
+
+ INTC_IRQ(MTU25_UVW, 148), INTC_IRQ(MTU25_UVW, 149),
+ INTC_IRQ(MTU25_UVW, 150),
+
+ INTC_IRQ(RTC, 152), INTC_IRQ(RTC, 153),
+ INTC_IRQ(RTC, 154),
+
+ INTC_IRQ(WDT, 156),
+
+ INTC_IRQ(IIC30, 157), INTC_IRQ(IIC30, 158),
+ INTC_IRQ(IIC30, 159), INTC_IRQ(IIC30, 160),
+ INTC_IRQ(IIC30, 161),
+
+ INTC_IRQ(IIC31, 164), INTC_IRQ(IIC31, 165),
+ INTC_IRQ(IIC31, 166), INTC_IRQ(IIC31, 167),
+ INTC_IRQ(IIC31, 168),
+
+ INTC_IRQ(IIC32, 170), INTC_IRQ(IIC32, 171),
+ INTC_IRQ(IIC32, 172), INTC_IRQ(IIC32, 173),
+ INTC_IRQ(IIC32, 174),
+
+ INTC_IRQ(DMAC0_DMINT0, 176), INTC_IRQ(DMAC1_DMINT1, 177),
+ INTC_IRQ(DMAC2_DMINT2, 178), INTC_IRQ(DMAC3_DMINT3, 179),
+
+ INTC_IRQ(SCIF0, 180), INTC_IRQ(SCIF0, 181),
+ INTC_IRQ(SCIF0, 182), INTC_IRQ(SCIF0, 183),
+ INTC_IRQ(SCIF1, 184), INTC_IRQ(SCIF1, 185),
+ INTC_IRQ(SCIF1, 186), INTC_IRQ(SCIF1, 187),
+ INTC_IRQ(SCIF2, 188), INTC_IRQ(SCIF2, 189),
+ INTC_IRQ(SCIF2, 190), INTC_IRQ(SCIF2, 191),
+ INTC_IRQ(SCIF3, 192), INTC_IRQ(SCIF3, 193),
+ INTC_IRQ(SCIF3, 194), INTC_IRQ(SCIF3, 195),
+ INTC_IRQ(SCIF4, 196), INTC_IRQ(SCIF4, 197),
+ INTC_IRQ(SCIF4, 198), INTC_IRQ(SCIF4, 199),
+ INTC_IRQ(SCIF5, 200), INTC_IRQ(SCIF5, 201),
+ INTC_IRQ(SCIF5, 202), INTC_IRQ(SCIF5, 203),
+ INTC_IRQ(SCIF6, 204), INTC_IRQ(SCIF6, 205),
+ INTC_IRQ(SCIF6, 206), INTC_IRQ(SCIF6, 207),
+ INTC_IRQ(SCIF7, 208), INTC_IRQ(SCIF7, 209),
+ INTC_IRQ(SCIF7, 210), INTC_IRQ(SCIF7, 211),
+
+ INTC_IRQ(DMAC0_DMINTA, 212), INTC_IRQ(DMAC4_DMINT4, 216),
+ INTC_IRQ(DMAC5_DMINT5, 217), INTC_IRQ(DMAC6_DMINT6, 218),
+ INTC_IRQ(DMAC7_DMINT7, 219),
+
+ INTC_IRQ(RCAN0, 228), INTC_IRQ(RCAN0, 229),
+ INTC_IRQ(RCAN0, 230),
+ INTC_IRQ(RCAN0, 231), INTC_IRQ(RCAN0, 232),
+
+ INTC_IRQ(RCAN1, 234), INTC_IRQ(RCAN1, 235),
+ INTC_IRQ(RCAN1, 236),
+ INTC_IRQ(RCAN1, 237), INTC_IRQ(RCAN1, 238),
+
+ INTC_IRQ(SSI0_SSII, 244), INTC_IRQ(SSI1_SSII, 245),
+
+ INTC_IRQ(TMR0, 246), INTC_IRQ(TMR0, 247),
+ INTC_IRQ(TMR0, 248),
+
+ INTC_IRQ(TMR1, 252), INTC_IRQ(TMR1, 253),
+ INTC_IRQ(TMR1, 254),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
+ PINT4, PINT5, PINT6, PINT7),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xfffe9418, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
+ { 0xfffe941a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
+ { 0xfffe9420, 0, 16, 4, /* IPR05 */ { PINT, 0, ADC_ADI, 0 } },
+ { 0xfffe9800, 0, 16, 4, /* IPR06 */ { 0, MTU20_ABCD, MTU20_VEF, MTU21_AB } },
+ { 0xfffe9802, 0, 16, 4, /* IPR07 */ { MTU21_VU, MTU22_AB, MTU22_VU, MTU23_ABCD } },
+ { 0xfffe9804, 0, 16, 4, /* IPR08 */ { MTU2_TCI3V, MTU24_ABCD, MTU2_TCI4V, MTU25_UVW } },
+
+ { 0xfffe9806, 0, 16, 4, /* IPR09 */ { RTC, WDT, IIC30, 0 } },
+ { 0xfffe9808, 0, 16, 4, /* IPR10 */ { IIC31, IIC32, DMAC0_DMINT0, DMAC1_DMINT1 } },
+ { 0xfffe980a, 0, 16, 4, /* IPR11 */ { DMAC2_DMINT2, DMAC3_DMINT3, SCIF0, SCIF1 } },
+ { 0xfffe980c, 0, 16, 4, /* IPR12 */ { SCIF2, SCIF3, SCIF4, SCIF5 } },
+ { 0xfffe980e, 0, 16, 4, /* IPR13 */ { SCIF6, SCIF7, DMAC0_DMINTA, DMAC4_DMINT4 } },
+ { 0xfffe9810, 0, 16, 4, /* IPR14 */ { DMAC5_DMINT5, DMAC6_DMINT6, DMAC7_DMINT7, 0 } },
+ { 0xfffe9812, 0, 16, 4, /* IPR15 */ { 0, RCAN0, RCAN1, 0 } },
+ { 0xfffe9814, 0, 16, 4, /* IPR16 */ { SSI0_SSII, SSI1_SSII, TMR0, TMR1 } },
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xfffe9408, 0, 16, /* PINTER */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xfffe8000, 0x100),
+ DEFINE_RES_IRQ(180),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xfffe8800, 0x100),
+ DEFINE_RES_IRQ(184),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xfffe9000, 0x100),
+ DEFINE_RES_IRQ(188),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xfffe9800, 0x100),
+ DEFINE_RES_IRQ(192),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xfffea000, 0x100),
+ DEFINE_RES_IRQ(196),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xfffea800, 0x100),
+ DEFINE_RES_IRQ(200),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct plat_sci_port scif6_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif6_resources[] = {
+ DEFINE_RES_MEM(0xfffeb000, 0x100),
+ DEFINE_RES_IRQ(204),
+};
+
+static struct platform_device scif6_device = {
+ .name = "sh-sci",
+ .id = 6,
+ .resource = scif6_resources,
+ .num_resources = ARRAY_SIZE(scif6_resources),
+ .dev = {
+ .platform_data = &scif6_platform_data,
+ },
+};
+
+static struct plat_sci_port scif7_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif7_resources[] = {
+ DEFINE_RES_MEM(0xfffeb800, 0x100),
+ DEFINE_RES_IRQ(208),
+};
+
+static struct platform_device scif7_device = {
+ .name = "sh-sci",
+ .id = 7,
+ .resource = scif7_resources,
+ .num_resources = ARRAY_SIZE(scif7_resources),
+ .dev = {
+ .platform_data = &scif7_platform_data,
+ },
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xffff0800,
+ .end = 0xffff2000 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = 152,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static struct resource mtu2_resources[] = {
+ DEFINE_RES_MEM(0xfffe4000, 0x400),
+ DEFINE_RES_IRQ_NAMED(108, "tgi0a"),
+ DEFINE_RES_IRQ_NAMED(116, "tgi1a"),
+ DEFINE_RES_IRQ_NAMED(124, "tgi1b"),
+};
+
+static struct platform_device mtu2_device = {
+ .name = "sh-mtu2",
+ .id = -1,
+ .resource = mtu2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_resources),
+};
+
+static struct platform_device *sh7201_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &rtc_device,
+ &mtu2_device,
+};
+
+static int __init sh7201_devices_setup(void)
+{
+ return platform_add_devices(sh7201_devices,
+ ARRAY_SIZE(sh7201_devices));
+}
+arch_initcall(sh7201_devices_setup);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+static struct platform_device *sh7201_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &mtu2_device,
+};
+
+#define STBCR3 0xfffe0408
+
+void __init plat_early_device_setup(void)
+{
+ /* enable MTU2 clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+ early_platform_add_devices(sh7201_early_devices,
+ ARRAY_SIZE(sh7201_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
index e98dc445035..3b4894cba92 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c
@@ -1,7 +1,7 @@
/*
* SH7203 and SH7263 Setup
*
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2009 Paul Mundt
*
* 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 +11,8 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
@@ -18,50 +20,27 @@ enum {
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
- DMAC0_DEI, DMAC0_HEI, DMAC1_DEI, DMAC1_HEI,
- DMAC2_DEI, DMAC2_HEI, DMAC3_DEI, DMAC3_HEI,
- DMAC4_DEI, DMAC4_HEI, DMAC5_DEI, DMAC5_HEI,
- DMAC6_DEI, DMAC6_HEI, DMAC7_DEI, DMAC7_HEI,
+ DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
USB, LCDC, CMT0, CMT1, BSC, WDT,
- MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
- MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F,
- MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U,
- MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
- MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V,
- MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V,
- ADC_ADI,
- IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, IIC30_TEI,
- IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, IIC31_TEI,
- IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, IIC32_TEI,
- IIC33_STPI, IIC33_NAKI, IIC33_RXI, IIC33_TXI, IIC33_TEI,
- SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
- SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
- SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
- SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
- SSU0_SSERI, SSU0_SSRXI, SSU0_SSTXI,
- SSU1_SSERI, SSU1_SSRXI, SSU1_SSTXI,
- SSI0_SSII, SSI1_SSII, SSI2_SSII, SSI3_SSII,
- /* ROM-DEC, SDHI, SRC, and IEB are SH7263 specific */
- ROMDEC_ISY, ROMDEC_IERR, ROMDEC_IARG, ROMDEC_ISEC, ROMDEC_IBUF,
- ROMDEC_IREADY,
+ MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU4_ABCD, MTU2_TCI3V, MTU2_TCI4V,
- FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
+ ADC_ADI,
- SDHI3, SDHI0, SDHI1,
+ IIC30, IIC31, IIC32, IIC33,
+ SCIF0, SCIF1, SCIF2, SCIF3,
- RTC_ARM, RTC_PRD, RTC_CUP,
- RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1, RCAN0_SLE,
- RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1, RCAN1_SLE,
+ SSU0, SSU1,
- SRC_OVF, SRC_ODFI, SRC_IDEI, IEBI,
+ SSI0_SSII, SSI1_SSII, SSI2_SSII, SSI3_SSII,
+
+ /* ROM-DEC, SDHI, SRC, and IEB are SH7263 specific */
+ ROMDEC, FLCTL, SDHI, RTC, RCAN0, RCAN1,
+ SRC, IEBI,
/* interrupt groups */
- PINT, DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
- MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
- MTU3_ABCD, MTU4_ABCD,
- IIC30, IIC31, IIC32, IIC33, SCIF0, SCIF1, SCIF2, SCIF3,
- SSU0, SSU1, ROMDEC, SDHI, FLCTL, RTC, RCAN0, RCAN1, SRC
+ PINT,
};
static struct intc_vect vectors[] __initdata = {
@@ -73,79 +52,80 @@ static struct intc_vect vectors[] __initdata = {
INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
- INTC_IRQ(DMAC0_DEI, 108), INTC_IRQ(DMAC0_HEI, 109),
- INTC_IRQ(DMAC1_DEI, 112), INTC_IRQ(DMAC1_HEI, 113),
- INTC_IRQ(DMAC2_DEI, 116), INTC_IRQ(DMAC2_HEI, 117),
- INTC_IRQ(DMAC3_DEI, 120), INTC_IRQ(DMAC3_HEI, 121),
- INTC_IRQ(DMAC4_DEI, 124), INTC_IRQ(DMAC4_HEI, 125),
- INTC_IRQ(DMAC5_DEI, 128), INTC_IRQ(DMAC5_HEI, 129),
- INTC_IRQ(DMAC6_DEI, 132), INTC_IRQ(DMAC6_HEI, 133),
- INTC_IRQ(DMAC7_DEI, 136), INTC_IRQ(DMAC7_HEI, 137),
+ INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+ INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+ INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+ INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+ INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+ INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+ INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+ INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
INTC_IRQ(USB, 140), INTC_IRQ(LCDC, 141),
INTC_IRQ(CMT0, 142), INTC_IRQ(CMT1, 143),
INTC_IRQ(BSC, 144), INTC_IRQ(WDT, 145),
- INTC_IRQ(MTU2_TGI0A, 146), INTC_IRQ(MTU2_TGI0B, 147),
- INTC_IRQ(MTU2_TGI0C, 148), INTC_IRQ(MTU2_TGI0D, 149),
- INTC_IRQ(MTU2_TCI0V, 150),
- INTC_IRQ(MTU2_TGI0E, 151), INTC_IRQ(MTU2_TGI0F, 152),
- INTC_IRQ(MTU2_TGI1A, 153), INTC_IRQ(MTU2_TGI1B, 154),
- INTC_IRQ(MTU2_TCI1V, 155), INTC_IRQ(MTU2_TCI1U, 156),
- INTC_IRQ(MTU2_TGI2A, 157), INTC_IRQ(MTU2_TGI2B, 158),
- INTC_IRQ(MTU2_TCI2V, 159), INTC_IRQ(MTU2_TCI2U, 160),
- INTC_IRQ(MTU2_TGI3A, 161), INTC_IRQ(MTU2_TGI3B, 162),
- INTC_IRQ(MTU2_TGI3C, 163), INTC_IRQ(MTU2_TGI3D, 164),
+ INTC_IRQ(MTU0_ABCD, 146), INTC_IRQ(MTU0_ABCD, 147),
+ INTC_IRQ(MTU0_ABCD, 148), INTC_IRQ(MTU0_ABCD, 149),
+ INTC_IRQ(MTU0_VEF, 150),
+ INTC_IRQ(MTU0_VEF, 151), INTC_IRQ(MTU0_VEF, 152),
+ INTC_IRQ(MTU1_AB, 153), INTC_IRQ(MTU1_AB, 154),
+ INTC_IRQ(MTU1_VU, 155), INTC_IRQ(MTU1_VU, 156),
+ INTC_IRQ(MTU2_AB, 157), INTC_IRQ(MTU2_AB, 158),
+ INTC_IRQ(MTU2_VU, 159), INTC_IRQ(MTU2_VU, 160),
+ INTC_IRQ(MTU3_ABCD, 161), INTC_IRQ(MTU3_ABCD, 162),
+ INTC_IRQ(MTU3_ABCD, 163), INTC_IRQ(MTU3_ABCD, 164),
INTC_IRQ(MTU2_TCI3V, 165),
- INTC_IRQ(MTU2_TGI4A, 166), INTC_IRQ(MTU2_TGI4B, 167),
- INTC_IRQ(MTU2_TGI4C, 168), INTC_IRQ(MTU2_TGI4D, 169),
+ INTC_IRQ(MTU4_ABCD, 166), INTC_IRQ(MTU4_ABCD, 167),
+ INTC_IRQ(MTU4_ABCD, 168), INTC_IRQ(MTU4_ABCD, 169),
INTC_IRQ(MTU2_TCI4V, 170),
INTC_IRQ(ADC_ADI, 171),
- INTC_IRQ(IIC30_STPI, 172), INTC_IRQ(IIC30_NAKI, 173),
- INTC_IRQ(IIC30_RXI, 174), INTC_IRQ(IIC30_TXI, 175),
- INTC_IRQ(IIC30_TEI, 176),
- INTC_IRQ(IIC31_STPI, 177), INTC_IRQ(IIC31_NAKI, 178),
- INTC_IRQ(IIC31_RXI, 179), INTC_IRQ(IIC31_TXI, 180),
- INTC_IRQ(IIC31_TEI, 181),
- INTC_IRQ(IIC32_STPI, 182), INTC_IRQ(IIC32_NAKI, 183),
- INTC_IRQ(IIC32_RXI, 184), INTC_IRQ(IIC32_TXI, 185),
- INTC_IRQ(IIC32_TEI, 186),
- INTC_IRQ(IIC33_STPI, 187), INTC_IRQ(IIC33_NAKI, 188),
- INTC_IRQ(IIC33_RXI, 189), INTC_IRQ(IIC33_TXI, 190),
- INTC_IRQ(IIC33_TEI, 191),
- INTC_IRQ(SCIF0_BRI, 192), INTC_IRQ(SCIF0_ERI, 193),
- INTC_IRQ(SCIF0_RXI, 194), INTC_IRQ(SCIF0_TXI, 195),
- INTC_IRQ(SCIF1_BRI, 196), INTC_IRQ(SCIF1_ERI, 197),
- INTC_IRQ(SCIF1_RXI, 198), INTC_IRQ(SCIF1_TXI, 199),
- INTC_IRQ(SCIF2_BRI, 200), INTC_IRQ(SCIF2_ERI, 201),
- INTC_IRQ(SCIF2_RXI, 202), INTC_IRQ(SCIF2_TXI, 203),
- INTC_IRQ(SCIF3_BRI, 204), INTC_IRQ(SCIF3_ERI, 205),
- INTC_IRQ(SCIF3_RXI, 206), INTC_IRQ(SCIF3_TXI, 207),
- INTC_IRQ(SSU0_SSERI, 208), INTC_IRQ(SSU0_SSRXI, 209),
- INTC_IRQ(SSU0_SSTXI, 210),
- INTC_IRQ(SSU1_SSERI, 211), INTC_IRQ(SSU1_SSRXI, 212),
- INTC_IRQ(SSU1_SSTXI, 213),
+ INTC_IRQ(IIC30, 172), INTC_IRQ(IIC30, 173),
+ INTC_IRQ(IIC30, 174), INTC_IRQ(IIC30, 175),
+ INTC_IRQ(IIC30, 176),
+ INTC_IRQ(IIC31, 177), INTC_IRQ(IIC31, 178),
+ INTC_IRQ(IIC31, 179), INTC_IRQ(IIC31, 180),
+ INTC_IRQ(IIC31, 181),
+ INTC_IRQ(IIC32, 182), INTC_IRQ(IIC32, 183),
+ INTC_IRQ(IIC32, 184), INTC_IRQ(IIC32, 185),
+ INTC_IRQ(IIC32, 186),
+ INTC_IRQ(IIC33, 187), INTC_IRQ(IIC33, 188),
+ INTC_IRQ(IIC33, 189), INTC_IRQ(IIC33, 190),
+ INTC_IRQ(IIC33, 191),
+ INTC_IRQ(SCIF0, 192), INTC_IRQ(SCIF0, 193),
+ INTC_IRQ(SCIF0, 194), INTC_IRQ(SCIF0, 195),
+ INTC_IRQ(SCIF1, 196), INTC_IRQ(SCIF1, 197),
+ INTC_IRQ(SCIF1, 198), INTC_IRQ(SCIF1, 199),
+ INTC_IRQ(SCIF2, 200), INTC_IRQ(SCIF2, 201),
+ INTC_IRQ(SCIF2, 202), INTC_IRQ(SCIF2, 203),
+ INTC_IRQ(SCIF3, 204), INTC_IRQ(SCIF3, 205),
+ INTC_IRQ(SCIF3, 206), INTC_IRQ(SCIF3, 207),
+ INTC_IRQ(SSU0, 208), INTC_IRQ(SSU0, 209),
+ INTC_IRQ(SSU0, 210),
+ INTC_IRQ(SSU1, 211), INTC_IRQ(SSU1, 212),
+ INTC_IRQ(SSU1, 213),
INTC_IRQ(SSI0_SSII, 214), INTC_IRQ(SSI1_SSII, 215),
INTC_IRQ(SSI2_SSII, 216), INTC_IRQ(SSI3_SSII, 217),
- INTC_IRQ(FLCTL_FLSTEI, 224), INTC_IRQ(FLCTL_FLTENDI, 225),
- INTC_IRQ(FLCTL_FLTREQ0I, 226), INTC_IRQ(FLCTL_FLTREQ1I, 227),
- INTC_IRQ(RTC_ARM, 231), INTC_IRQ(RTC_PRD, 232),
- INTC_IRQ(RTC_CUP, 233),
- INTC_IRQ(RCAN0_ERS, 234), INTC_IRQ(RCAN0_OVR, 235),
- INTC_IRQ(RCAN0_RM0, 236), INTC_IRQ(RCAN0_RM1, 237),
- INTC_IRQ(RCAN0_SLE, 238),
- INTC_IRQ(RCAN1_ERS, 239), INTC_IRQ(RCAN1_OVR, 240),
- INTC_IRQ(RCAN1_RM0, 241), INTC_IRQ(RCAN1_RM1, 242),
- INTC_IRQ(RCAN1_SLE, 243),
+ INTC_IRQ(FLCTL, 224), INTC_IRQ(FLCTL, 225),
+ INTC_IRQ(FLCTL, 226), INTC_IRQ(FLCTL, 227),
+ INTC_IRQ(RTC, 231), INTC_IRQ(RTC, 232),
+ INTC_IRQ(RTC, 233),
+ INTC_IRQ(RCAN0, 234), INTC_IRQ(RCAN0, 235),
+ INTC_IRQ(RCAN0, 236), INTC_IRQ(RCAN0, 237),
+ INTC_IRQ(RCAN0, 238),
+ INTC_IRQ(RCAN1, 239), INTC_IRQ(RCAN1, 240),
+ INTC_IRQ(RCAN1, 241), INTC_IRQ(RCAN1, 242),
+ INTC_IRQ(RCAN1, 243),
/* SH7263-specific trash */
#ifdef CONFIG_CPU_SUBTYPE_SH7263
- INTC_IRQ(ROMDEC_ISY, 218), INTC_IRQ(ROMDEC_IERR, 219),
- INTC_IRQ(ROMDEC_IARG, 220), INTC_IRQ(ROMDEC_ISEC, 221),
- INTC_IRQ(ROMDEC_IBUF, 222), INTC_IRQ(ROMDEC_IREADY, 223),
+ INTC_IRQ(ROMDEC, 218), INTC_IRQ(ROMDEC, 219),
+ INTC_IRQ(ROMDEC, 220), INTC_IRQ(ROMDEC, 221),
+ INTC_IRQ(ROMDEC, 222), INTC_IRQ(ROMDEC, 223),
- INTC_IRQ(SDHI3, 228), INTC_IRQ(SDHI0, 229), INTC_IRQ(SDHI1, 230),
+ INTC_IRQ(SDHI, 228), INTC_IRQ(SDHI, 229),
+ INTC_IRQ(SDHI, 230),
- INTC_IRQ(SRC_OVF, 244), INTC_IRQ(SRC_ODFI, 245),
- INTC_IRQ(SRC_IDEI, 246),
+ INTC_IRQ(SRC, 244), INTC_IRQ(SRC, 245),
+ INTC_IRQ(SRC, 246),
INTC_IRQ(IEBI, 247),
#endif
@@ -154,50 +134,6 @@ static struct intc_vect vectors[] __initdata = {
static struct intc_group groups[] __initdata = {
INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
PINT4, PINT5, PINT6, PINT7),
- INTC_GROUP(DMAC0, DMAC0_DEI, DMAC0_HEI),
- INTC_GROUP(DMAC1, DMAC1_DEI, DMAC1_HEI),
- INTC_GROUP(DMAC2, DMAC2_DEI, DMAC2_HEI),
- INTC_GROUP(DMAC3, DMAC3_DEI, DMAC3_HEI),
- INTC_GROUP(DMAC4, DMAC4_DEI, DMAC4_HEI),
- INTC_GROUP(DMAC5, DMAC5_DEI, DMAC5_HEI),
- INTC_GROUP(DMAC6, DMAC6_DEI, DMAC6_HEI),
- INTC_GROUP(DMAC7, DMAC7_DEI, DMAC7_HEI),
- INTC_GROUP(MTU0_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D),
- INTC_GROUP(MTU0_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F),
- INTC_GROUP(MTU1_AB, MTU2_TGI1A, MTU2_TGI1B),
- INTC_GROUP(MTU1_VU, MTU2_TCI1V, MTU2_TCI1U),
- INTC_GROUP(MTU2_AB, MTU2_TGI2A, MTU2_TGI2B),
- INTC_GROUP(MTU2_VU, MTU2_TCI2V, MTU2_TCI2U),
- INTC_GROUP(MTU3_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D),
- INTC_GROUP(MTU4_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
- INTC_GROUP(IIC30, IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI,
- IIC30_TEI),
- INTC_GROUP(IIC31, IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI,
- IIC31_TEI),
- INTC_GROUP(IIC32, IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI,
- IIC32_TEI),
- INTC_GROUP(IIC33, IIC33_STPI, IIC33_NAKI, IIC33_RXI, IIC33_TXI,
- IIC33_TEI),
- INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
- INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
- INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
- INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
- INTC_GROUP(SSU0, SSU0_SSERI, SSU0_SSRXI, SSU0_SSTXI),
- INTC_GROUP(SSU1, SSU1_SSERI, SSU1_SSRXI, SSU1_SSTXI),
- INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I,
- FLCTL_FLTREQ1I),
- INTC_GROUP(RTC, RTC_ARM, RTC_PRD, RTC_CUP),
- INTC_GROUP(RCAN0, RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1,
- RCAN0_SLE),
- INTC_GROUP(RCAN1, RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1,
- RCAN1_SLE),
-
-#ifdef CONFIG_CPU_SUBTYPE_SH7263
- INTC_GROUP(ROMDEC, ROMDEC_ISY, ROMDEC_IERR, ROMDEC_IARG,
- ROMDEC_ISEC, ROMDEC_IBUF, ROMDEC_IREADY),
- INTC_GROUP(SDHI, SDHI3, SDHI0, SDHI1),
- INTC_GROUP(SRC, SRC_OVF, SRC_ODFI, SRC_IDEI),
-#endif
};
static struct intc_prio_reg prio_registers[] __initdata = {
@@ -237,40 +173,131 @@ static struct intc_mask_reg mask_registers[] __initdata = {
static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups,
mask_registers, prio_registers, NULL);
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xfffe8000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 193, 194, 195, 192 },
- }, {
- .mapbase = 0xfffe8800,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 197, 198, 199, 196 },
- }, {
- .mapbase = 0xfffe9000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 201, 202, 203, 200 },
- }, {
- .mapbase = 0xfffe9800,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 205, 206, 207, 204 },
- }, {
- .flags = 0,
- }
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xfffe8000, 0x100),
+ DEFINE_RES_IRQ(192),
};
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xfffe8800, 0x100),
+ DEFINE_RES_IRQ(196),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xfffe9000, 0x100),
+ DEFINE_RES_IRQ(200),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif2_platform_data,
},
};
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xfffe9800, 0x100),
+ DEFINE_RES_IRQ(204),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0xfffec000, 0x10),
+ DEFINE_RES_IRQ(142),
+ DEFINE_RES_IRQ(143),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-16",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct resource mtu2_resources[] = {
+ DEFINE_RES_MEM(0xfffe4000, 0x400),
+ DEFINE_RES_IRQ_NAMED(146, "tgi0a"),
+ DEFINE_RES_IRQ_NAMED(153, "tgi1a"),
+};
+
+static struct platform_device mtu2_device = {
+ .name = "sh-mtu2",
+ .id = -1,
+ .resource = mtu2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_resources),
+};
+
static struct resource rtc_resources[] = {
[0] = {
.start = 0xffff2000,
@@ -278,17 +305,7 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- /* Period IRQ */
- .start = 232,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- /* Carry IRQ */
- .start = 233,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- /* Alarm IRQ */
+ /* Shared Period/Carry/Alarm IRQ */
.start = 231,
.flags = IORESOURCE_IRQ,
},
@@ -302,7 +319,12 @@ static struct platform_device rtc_device = {
};
static struct platform_device *sh7203_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &cmt_device,
+ &mtu2_device,
&rtc_device,
};
@@ -311,9 +333,33 @@ static int __init sh7203_devices_setup(void)
return platform_add_devices(sh7203_devices,
ARRAY_SIZE(sh7203_devices));
}
-__initcall(sh7203_devices_setup);
+arch_initcall(sh7203_devices_setup);
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7203_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &cmt_device,
+ &mtu2_device,
+};
+
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
+void __init plat_early_device_setup(void)
+{
+ /* enable CMT clock */
+ __raw_writeb(__raw_readb(STBCR4) & ~0x04, STBCR4);
+
+ /* enable MTU2 clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+ early_platform_add_devices(sh7203_early_devices,
+ ARRAY_SIZE(sh7203_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
index e6d4ec445dd..49bc5a34bec 100644
--- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -2,6 +2,7 @@
* SH7206 Setup
*
* Copyright (C) 2006 Yoshinori Sato
+ * Copyright (C) 2009 Paul Mundt
*
* 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>
enum {
UNUSED = 0,
@@ -19,34 +22,23 @@ enum {
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
ADC_ADI0, ADC_ADI1,
- DMAC0_DEI, DMAC0_HEI, DMAC1_DEI, DMAC1_HEI,
- DMAC2_DEI, DMAC2_HEI, DMAC3_DEI, DMAC3_HEI,
- DMAC4_DEI, DMAC4_HEI, DMAC5_DEI, DMAC5_HEI,
- DMAC6_DEI, DMAC6_HEI, DMAC7_DEI, DMAC7_HEI,
+
+ DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+
+ MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU4_ABCD, MTU5, POE2_12, MTU3S_ABCD, MTU4S_ABCD, MTU5S,
+ IIC3,
+
CMT0, CMT1, BSC, WDT,
- MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D,
- MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F,
- MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U,
- MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U,
- MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V,
- MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V,
- MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W,
- POE2_OEI1, POE2_OEI2,
- MTU2S_TGI3A, MTU2S_TGI3B, MTU2S_TGI3C, MTU2S_TGI3D, MTU2S_TCI3V,
- MTU2S_TGI4A, MTU2S_TGI4B, MTU2S_TGI4C, MTU2S_TGI4D, MTU2S_TCI4V,
- MTU2S_TGI5U, MTU2S_TGI5V, MTU2S_TGI5W,
+
+ MTU2_TCI3V, MTU2_TCI4V, MTU2S_TCI3V, MTU2S_TCI4V,
+
POE2_OEI3,
- IIC3_STPI, IIC3_NAKI, IIC3_RXI, IIC3_TXI, IIC3_TEI,
- SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
- SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
- SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
- SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
+
+ SCIF0, SCIF1, SCIF2, SCIF3,
/* interrupt groups */
- PINT, DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
- MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
- MTU3_ABCD, MTU4_ABCD, MTU5, POE2_12, MTU3S_ABCD, MTU4S_ABCD, MTU5S,
- IIC3, SCIF0, SCIF1, SCIF2, SCIF3,
+ PINT,
};
static struct intc_vect vectors[] __initdata = {
@@ -59,86 +51,58 @@ static struct intc_vect vectors[] __initdata = {
INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
INTC_IRQ(ADC_ADI0, 92), INTC_IRQ(ADC_ADI1, 96),
- INTC_IRQ(DMAC0_DEI, 108), INTC_IRQ(DMAC0_HEI, 109),
- INTC_IRQ(DMAC1_DEI, 112), INTC_IRQ(DMAC1_HEI, 113),
- INTC_IRQ(DMAC2_DEI, 116), INTC_IRQ(DMAC2_HEI, 117),
- INTC_IRQ(DMAC3_DEI, 120), INTC_IRQ(DMAC3_HEI, 121),
- INTC_IRQ(DMAC4_DEI, 124), INTC_IRQ(DMAC4_HEI, 125),
- INTC_IRQ(DMAC5_DEI, 128), INTC_IRQ(DMAC5_HEI, 129),
- INTC_IRQ(DMAC6_DEI, 132), INTC_IRQ(DMAC6_HEI, 133),
- INTC_IRQ(DMAC7_DEI, 136), INTC_IRQ(DMAC7_HEI, 137),
+ INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+ INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+ INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+ INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+ INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+ INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+ INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+ INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
INTC_IRQ(CMT0, 140), INTC_IRQ(CMT1, 144),
INTC_IRQ(BSC, 148), INTC_IRQ(WDT, 152),
- INTC_IRQ(MTU2_TGI0A, 156), INTC_IRQ(MTU2_TGI0B, 157),
- INTC_IRQ(MTU2_TGI0C, 158), INTC_IRQ(MTU2_TGI0D, 159),
- INTC_IRQ(MTU2_TCI0V, 160),
- INTC_IRQ(MTU2_TGI0E, 161), INTC_IRQ(MTU2_TGI0F, 162),
- INTC_IRQ(MTU2_TGI1A, 164), INTC_IRQ(MTU2_TGI1B, 165),
- INTC_IRQ(MTU2_TCI1V, 168), INTC_IRQ(MTU2_TCI1U, 169),
- INTC_IRQ(MTU2_TGI2A, 172), INTC_IRQ(MTU2_TGI2B, 173),
- INTC_IRQ(MTU2_TCI2V, 176), INTC_IRQ(MTU2_TCI2U, 177),
- INTC_IRQ(MTU2_TGI3A, 180), INTC_IRQ(MTU2_TGI3B, 181),
- INTC_IRQ(MTU2_TGI3C, 182), INTC_IRQ(MTU2_TGI3D, 183),
+ INTC_IRQ(MTU0_ABCD, 156), INTC_IRQ(MTU0_ABCD, 157),
+ INTC_IRQ(MTU0_ABCD, 158), INTC_IRQ(MTU0_ABCD, 159),
+ INTC_IRQ(MTU0_VEF, 160), INTC_IRQ(MTU0_VEF, 161),
+ INTC_IRQ(MTU0_VEF, 162),
+ INTC_IRQ(MTU1_AB, 164), INTC_IRQ(MTU1_AB, 165),
+ INTC_IRQ(MTU1_VU, 168), INTC_IRQ(MTU1_VU, 169),
+ INTC_IRQ(MTU2_AB, 172), INTC_IRQ(MTU2_AB, 173),
+ INTC_IRQ(MTU2_VU, 176), INTC_IRQ(MTU2_VU, 177),
+ INTC_IRQ(MTU3_ABCD, 180), INTC_IRQ(MTU3_ABCD, 181),
+ INTC_IRQ(MTU3_ABCD, 182), INTC_IRQ(MTU3_ABCD, 183),
INTC_IRQ(MTU2_TCI3V, 184),
- INTC_IRQ(MTU2_TGI4A, 188), INTC_IRQ(MTU2_TGI4B, 189),
- INTC_IRQ(MTU2_TGI4C, 190), INTC_IRQ(MTU2_TGI4D, 191),
+ INTC_IRQ(MTU4_ABCD, 188), INTC_IRQ(MTU4_ABCD, 189),
+ INTC_IRQ(MTU4_ABCD, 190), INTC_IRQ(MTU4_ABCD, 191),
INTC_IRQ(MTU2_TCI4V, 192),
- INTC_IRQ(MTU2_TGI5U, 196), INTC_IRQ(MTU2_TGI5V, 197),
- INTC_IRQ(MTU2_TGI5W, 198),
- INTC_IRQ(POE2_OEI1, 200), INTC_IRQ(POE2_OEI2, 201),
- INTC_IRQ(MTU2S_TGI3A, 204), INTC_IRQ(MTU2S_TGI3B, 205),
- INTC_IRQ(MTU2S_TGI3C, 206), INTC_IRQ(MTU2S_TGI3D, 207),
+ INTC_IRQ(MTU5, 196), INTC_IRQ(MTU5, 197),
+ INTC_IRQ(MTU5, 198),
+ INTC_IRQ(POE2_12, 200), INTC_IRQ(POE2_12, 201),
+ INTC_IRQ(MTU3S_ABCD, 204), INTC_IRQ(MTU3S_ABCD, 205),
+ INTC_IRQ(MTU3S_ABCD, 206), INTC_IRQ(MTU3S_ABCD, 207),
INTC_IRQ(MTU2S_TCI3V, 208),
- INTC_IRQ(MTU2S_TGI4A, 212), INTC_IRQ(MTU2S_TGI4B, 213),
- INTC_IRQ(MTU2S_TGI4C, 214), INTC_IRQ(MTU2S_TGI4D, 215),
+ INTC_IRQ(MTU4S_ABCD, 212), INTC_IRQ(MTU4S_ABCD, 213),
+ INTC_IRQ(MTU4S_ABCD, 214), INTC_IRQ(MTU4S_ABCD, 215),
INTC_IRQ(MTU2S_TCI4V, 216),
- INTC_IRQ(MTU2S_TGI5U, 220), INTC_IRQ(MTU2S_TGI5V, 221),
- INTC_IRQ(MTU2S_TGI5W, 222),
+ INTC_IRQ(MTU5S, 220), INTC_IRQ(MTU5S, 221),
+ INTC_IRQ(MTU5S, 222),
INTC_IRQ(POE2_OEI3, 224),
- INTC_IRQ(IIC3_STPI, 228), INTC_IRQ(IIC3_NAKI, 229),
- INTC_IRQ(IIC3_RXI, 230), INTC_IRQ(IIC3_TXI, 231),
- INTC_IRQ(IIC3_TEI, 232),
- INTC_IRQ(SCIF0_BRI, 240), INTC_IRQ(SCIF0_ERI, 241),
- INTC_IRQ(SCIF0_RXI, 242), INTC_IRQ(SCIF0_TXI, 243),
- INTC_IRQ(SCIF1_BRI, 244), INTC_IRQ(SCIF1_ERI, 245),
- INTC_IRQ(SCIF1_RXI, 246), INTC_IRQ(SCIF1_TXI, 247),
- INTC_IRQ(SCIF2_BRI, 248), INTC_IRQ(SCIF2_ERI, 249),
- INTC_IRQ(SCIF2_RXI, 250), INTC_IRQ(SCIF2_TXI, 251),
- INTC_IRQ(SCIF3_BRI, 252), INTC_IRQ(SCIF3_ERI, 253),
- INTC_IRQ(SCIF3_RXI, 254), INTC_IRQ(SCIF3_TXI, 255),
+ INTC_IRQ(IIC3, 228), INTC_IRQ(IIC3, 229),
+ INTC_IRQ(IIC3, 230), INTC_IRQ(IIC3, 231),
+ INTC_IRQ(IIC3, 232),
+ INTC_IRQ(SCIF0, 240), INTC_IRQ(SCIF0, 241),
+ INTC_IRQ(SCIF0, 242), INTC_IRQ(SCIF0, 243),
+ INTC_IRQ(SCIF1, 244), INTC_IRQ(SCIF1, 245),
+ INTC_IRQ(SCIF1, 246), INTC_IRQ(SCIF1, 247),
+ INTC_IRQ(SCIF2, 248), INTC_IRQ(SCIF2, 249),
+ INTC_IRQ(SCIF2, 250), INTC_IRQ(SCIF2, 251),
+ INTC_IRQ(SCIF3, 252), INTC_IRQ(SCIF3, 253),
+ INTC_IRQ(SCIF3, 254), INTC_IRQ(SCIF3, 255),
};
static struct intc_group groups[] __initdata = {
INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
PINT4, PINT5, PINT6, PINT7),
- INTC_GROUP(DMAC0, DMAC0_DEI, DMAC0_HEI),
- INTC_GROUP(DMAC1, DMAC1_DEI, DMAC1_HEI),
- INTC_GROUP(DMAC2, DMAC2_DEI, DMAC2_HEI),
- INTC_GROUP(DMAC3, DMAC3_DEI, DMAC3_HEI),
- INTC_GROUP(DMAC4, DMAC4_DEI, DMAC4_HEI),
- INTC_GROUP(DMAC5, DMAC5_DEI, DMAC5_HEI),
- INTC_GROUP(DMAC6, DMAC6_DEI, DMAC6_HEI),
- INTC_GROUP(DMAC7, DMAC7_DEI, DMAC7_HEI),
- INTC_GROUP(MTU0_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D),
- INTC_GROUP(MTU0_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F),
- INTC_GROUP(MTU1_AB, MTU2_TGI1A, MTU2_TGI1B),
- INTC_GROUP(MTU1_VU, MTU2_TCI1V, MTU2_TCI1U),
- INTC_GROUP(MTU2_AB, MTU2_TGI2A, MTU2_TGI2B),
- INTC_GROUP(MTU2_VU, MTU2_TCI2V, MTU2_TCI2U),
- INTC_GROUP(MTU3_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D),
- INTC_GROUP(MTU4_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D),
- INTC_GROUP(MTU5, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W),
- INTC_GROUP(POE2_12, POE2_OEI1, POE2_OEI2),
- INTC_GROUP(MTU3S_ABCD, MTU2S_TGI3A, MTU2S_TGI3B,
- MTU2S_TGI3C, MTU2S_TGI3D),
- INTC_GROUP(MTU4S_ABCD, MTU2S_TGI4A, MTU2S_TGI4B,
- MTU2S_TGI4C, MTU2S_TGI4D),
- INTC_GROUP(MTU5S, MTU2S_TGI5U, MTU2S_TGI5V, MTU2S_TGI5W),
- INTC_GROUP(IIC3, IIC3_STPI, IIC3_NAKI, IIC3_RXI, IIC3_TXI, IIC3_TEI),
- INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
- INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
- INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
- INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
};
static struct intc_prio_reg prio_registers[] __initdata = {
@@ -169,42 +133,131 @@ static struct intc_mask_reg mask_registers[] __initdata = {
static DECLARE_INTC_DESC(intc_desc, "sh7206", vectors, groups,
mask_registers, prio_registers, NULL);
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xfffe8000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 241, 242, 243, 240 },
- }, {
- .mapbase = 0xfffe8800,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 245, 246, 247, 244 },
- }, {
- .mapbase = 0xfffe9000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 249, 250, 251, 248 },
- }, {
- .mapbase = 0xfffe9800,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 253, 254, 255, 252 },
- }, {
- .flags = 0,
- }
-};
-
-static struct platform_device sci_device = {
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xfffe8000, 0x100),
+ DEFINE_RES_IRQ(240),
+};
+
+static struct platform_device scif0_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xfffe8800, 0x100),
+ DEFINE_RES_IRQ(244),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xfffe9000, 0x100),
+ DEFINE_RES_IRQ(248),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xfffe9800, 0x100),
+ DEFINE_RES_IRQ(252),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif3_platform_data,
},
};
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0xfffec000, 0x10),
+ DEFINE_RES_IRQ(140),
+ DEFINE_RES_IRQ(144),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-16",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct resource mtu2_resources[] = {
+ DEFINE_RES_MEM(0xfffe4000, 0x400),
+ DEFINE_RES_IRQ_NAMED(156, "tgi0a"),
+ DEFINE_RES_IRQ_NAMED(164, "tgi1a"),
+ DEFINE_RES_IRQ_NAMED(180, "tgi2a"),
+};
+
+static struct platform_device mtu2_device = {
+ .name = "sh-mtu2s",
+ .id = -1,
+ .resource = mtu2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_resources),
+};
+
static struct platform_device *sh7206_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &cmt_device,
+ &mtu2_device,
};
static int __init sh7206_devices_setup(void)
@@ -212,9 +265,33 @@ static int __init sh7206_devices_setup(void)
return platform_add_devices(sh7206_devices,
ARRAY_SIZE(sh7206_devices));
}
-__initcall(sh7206_devices_setup);
+arch_initcall(sh7206_devices_setup);
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
}
+
+static struct platform_device *sh7206_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &cmt_device,
+ &mtu2_device,
+};
+
+#define STBCR3 0xfffe0408
+#define STBCR4 0xfffe040c
+
+void __init plat_early_device_setup(void)
+{
+ /* enable CMT clock */
+ __raw_writeb(__raw_readb(STBCR4) & ~0x04, STBCR4);
+
+ /* enable MTU2 clock */
+ __raw_writeb(__raw_readb(STBCR3) & ~0x20, STBCR3);
+
+ early_platform_add_devices(sh7206_early_devices,
+ ARRAY_SIZE(sh7206_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7264.c b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
new file mode 100644
index 00000000000..60814645556
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7264.c
@@ -0,0 +1,570 @@
+/*
+ * SH7264 Setup
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
+
+ DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+ DMAC8, DMAC9, DMAC10, DMAC11, DMAC12, DMAC13, DMAC14, DMAC15,
+ USB, VDC3, CMT0, CMT1, BSC, WDT,
+ MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU3_TCI3V, MTU4_ABCD, MTU4_TCI4V,
+ PWMT1, PWMT2, ADC_ADI,
+ SSIF0, SSII1, SSII2, SSII3,
+ RSPDIF,
+ IIC30, IIC31, IIC32, IIC33,
+ SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
+ SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
+ SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
+ SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
+ SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI,
+ SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI,
+ SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI,
+ SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI,
+ SIO_FIFO, RSPIC0, RSPIC1,
+ RCAN0, RCAN1, IEBC, CD_ROMD,
+ NFMC, SDHI, RTC,
+ SRCC0, SRCC1, DCOMU, OFFI, IFEI,
+
+ /* interrupt groups */
+ PINT, SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
+ INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
+ INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
+ INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
+
+ INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
+ INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
+ INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
+ INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
+
+ INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+ INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+ INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+ INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+ INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+ INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+ INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+ INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
+ INTC_IRQ(DMAC8, 140), INTC_IRQ(DMAC8, 141),
+ INTC_IRQ(DMAC9, 144), INTC_IRQ(DMAC9, 145),
+ INTC_IRQ(DMAC10, 148), INTC_IRQ(DMAC10, 149),
+ INTC_IRQ(DMAC11, 152), INTC_IRQ(DMAC11, 153),
+ INTC_IRQ(DMAC12, 156), INTC_IRQ(DMAC12, 157),
+ INTC_IRQ(DMAC13, 160), INTC_IRQ(DMAC13, 161),
+ INTC_IRQ(DMAC14, 164), INTC_IRQ(DMAC14, 165),
+ INTC_IRQ(DMAC15, 168), INTC_IRQ(DMAC15, 169),
+
+ INTC_IRQ(USB, 170),
+ INTC_IRQ(VDC3, 171), INTC_IRQ(VDC3, 172),
+ INTC_IRQ(VDC3, 173), INTC_IRQ(VDC3, 174),
+ INTC_IRQ(CMT0, 175), INTC_IRQ(CMT1, 176),
+ INTC_IRQ(BSC, 177), INTC_IRQ(WDT, 178),
+
+ INTC_IRQ(MTU0_ABCD, 179), INTC_IRQ(MTU0_ABCD, 180),
+ INTC_IRQ(MTU0_ABCD, 181), INTC_IRQ(MTU0_ABCD, 182),
+ INTC_IRQ(MTU0_VEF, 183),
+ INTC_IRQ(MTU0_VEF, 184), INTC_IRQ(MTU0_VEF, 185),
+ INTC_IRQ(MTU1_AB, 186), INTC_IRQ(MTU1_AB, 187),
+ INTC_IRQ(MTU1_VU, 188), INTC_IRQ(MTU1_VU, 189),
+ INTC_IRQ(MTU2_AB, 190), INTC_IRQ(MTU2_AB, 191),
+ INTC_IRQ(MTU2_VU, 192), INTC_IRQ(MTU2_VU, 193),
+ INTC_IRQ(MTU3_ABCD, 194), INTC_IRQ(MTU3_ABCD, 195),
+ INTC_IRQ(MTU3_ABCD, 196), INTC_IRQ(MTU3_ABCD, 197),
+ INTC_IRQ(MTU3_TCI3V, 198),
+ INTC_IRQ(MTU4_ABCD, 199), INTC_IRQ(MTU4_ABCD, 200),
+ INTC_IRQ(MTU4_ABCD, 201), INTC_IRQ(MTU4_ABCD, 202),
+ INTC_IRQ(MTU4_TCI4V, 203),
+
+ INTC_IRQ(PWMT1, 204), INTC_IRQ(PWMT2, 205),
+
+ INTC_IRQ(ADC_ADI, 206),
+
+ INTC_IRQ(SSIF0, 207), INTC_IRQ(SSIF0, 208),
+ INTC_IRQ(SSIF0, 209),
+ INTC_IRQ(SSII1, 210), INTC_IRQ(SSII1, 211),
+ INTC_IRQ(SSII2, 212), INTC_IRQ(SSII2, 213),
+ INTC_IRQ(SSII3, 214), INTC_IRQ(SSII3, 215),
+
+ INTC_IRQ(RSPDIF, 216),
+
+ INTC_IRQ(IIC30, 217), INTC_IRQ(IIC30, 218),
+ INTC_IRQ(IIC30, 219), INTC_IRQ(IIC30, 220),
+ INTC_IRQ(IIC30, 221),
+ INTC_IRQ(IIC31, 222), INTC_IRQ(IIC31, 223),
+ INTC_IRQ(IIC31, 224), INTC_IRQ(IIC31, 225),
+ INTC_IRQ(IIC31, 226),
+ INTC_IRQ(IIC32, 227), INTC_IRQ(IIC32, 228),
+ INTC_IRQ(IIC32, 229), INTC_IRQ(IIC32, 230),
+ INTC_IRQ(IIC32, 231),
+
+ INTC_IRQ(SCIF0_BRI, 232), INTC_IRQ(SCIF0_ERI, 233),
+ INTC_IRQ(SCIF0_RXI, 234), INTC_IRQ(SCIF0_TXI, 235),
+ INTC_IRQ(SCIF1_BRI, 236), INTC_IRQ(SCIF1_ERI, 237),
+ INTC_IRQ(SCIF1_RXI, 238), INTC_IRQ(SCIF1_TXI, 239),
+ INTC_IRQ(SCIF2_BRI, 240), INTC_IRQ(SCIF2_ERI, 241),
+ INTC_IRQ(SCIF2_RXI, 242), INTC_IRQ(SCIF2_TXI, 243),
+ INTC_IRQ(SCIF3_BRI, 244), INTC_IRQ(SCIF3_ERI, 245),
+ INTC_IRQ(SCIF3_RXI, 246), INTC_IRQ(SCIF3_TXI, 247),
+ INTC_IRQ(SCIF4_BRI, 248), INTC_IRQ(SCIF4_ERI, 249),
+ INTC_IRQ(SCIF4_RXI, 250), INTC_IRQ(SCIF4_TXI, 251),
+ INTC_IRQ(SCIF5_BRI, 252), INTC_IRQ(SCIF5_ERI, 253),
+ INTC_IRQ(SCIF5_RXI, 254), INTC_IRQ(SCIF5_TXI, 255),
+ INTC_IRQ(SCIF6_BRI, 256), INTC_IRQ(SCIF6_ERI, 257),
+ INTC_IRQ(SCIF6_RXI, 258), INTC_IRQ(SCIF6_TXI, 259),
+ INTC_IRQ(SCIF7_BRI, 260), INTC_IRQ(SCIF7_ERI, 261),
+ INTC_IRQ(SCIF7_RXI, 262), INTC_IRQ(SCIF7_TXI, 263),
+
+ INTC_IRQ(SIO_FIFO, 264),
+
+ INTC_IRQ(RSPIC0, 265), INTC_IRQ(RSPIC0, 266),
+ INTC_IRQ(RSPIC0, 267),
+ INTC_IRQ(RSPIC1, 268), INTC_IRQ(RSPIC1, 269),
+ INTC_IRQ(RSPIC1, 270),
+
+ INTC_IRQ(RCAN0, 271), INTC_IRQ(RCAN0, 272),
+ INTC_IRQ(RCAN0, 273), INTC_IRQ(RCAN0, 274),
+ INTC_IRQ(RCAN0, 275),
+ INTC_IRQ(RCAN1, 276), INTC_IRQ(RCAN1, 277),
+ INTC_IRQ(RCAN1, 278), INTC_IRQ(RCAN1, 279),
+ INTC_IRQ(RCAN1, 280),
+
+ INTC_IRQ(IEBC, 281),
+
+ INTC_IRQ(CD_ROMD, 282), INTC_IRQ(CD_ROMD, 283),
+ INTC_IRQ(CD_ROMD, 284), INTC_IRQ(CD_ROMD, 285),
+ INTC_IRQ(CD_ROMD, 286), INTC_IRQ(CD_ROMD, 287),
+
+ INTC_IRQ(NFMC, 288), INTC_IRQ(NFMC, 289),
+ INTC_IRQ(NFMC, 290), INTC_IRQ(NFMC, 291),
+
+ INTC_IRQ(SDHI, 292), INTC_IRQ(SDHI, 293),
+ INTC_IRQ(SDHI, 294),
+
+ INTC_IRQ(RTC, 296), INTC_IRQ(RTC, 297),
+ INTC_IRQ(RTC, 298),
+
+ INTC_IRQ(SRCC0, 299), INTC_IRQ(SRCC0, 300),
+ INTC_IRQ(SRCC0, 301), INTC_IRQ(SRCC0, 302),
+ INTC_IRQ(SRCC0, 303),
+ INTC_IRQ(SRCC1, 304), INTC_IRQ(SRCC1, 305),
+ INTC_IRQ(SRCC1, 306), INTC_IRQ(SRCC1, 307),
+ INTC_IRQ(SRCC1, 308),
+
+ INTC_IRQ(DCOMU, 310), INTC_IRQ(DCOMU, 311),
+ INTC_IRQ(DCOMU, 312),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
+ PINT4, PINT5, PINT6, PINT7),
+ INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
+ INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
+ INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
+ INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
+ INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI),
+ INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI),
+ INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI),
+ INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xfffe0818, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
+ { 0xfffe081a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
+ { 0xfffe0820, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } },
+ { 0xfffe0c00, 0, 16, 4, /* IPR06 */ { DMAC0, DMAC1, DMAC2, DMAC3 } },
+ { 0xfffe0c02, 0, 16, 4, /* IPR07 */ { DMAC4, DMAC5, DMAC6, DMAC7 } },
+ { 0xfffe0c04, 0, 16, 4, /* IPR08 */ { DMAC8, DMAC9,
+ DMAC10, DMAC11 } },
+ { 0xfffe0c06, 0, 16, 4, /* IPR09 */ { DMAC12, DMAC13,
+ DMAC14, DMAC15 } },
+ { 0xfffe0c08, 0, 16, 4, /* IPR10 */ { USB, VDC3, CMT0, CMT1 } },
+ { 0xfffe0c0a, 0, 16, 4, /* IPR11 */ { BSC, WDT, MTU0_ABCD, MTU0_VEF } },
+ { 0xfffe0c0c, 0, 16, 4, /* IPR12 */ { MTU1_AB, MTU1_VU,
+ MTU2_AB, MTU2_VU } },
+ { 0xfffe0c0e, 0, 16, 4, /* IPR13 */ { MTU3_ABCD, MTU3_TCI3V,
+ MTU4_ABCD, MTU4_TCI4V } },
+ { 0xfffe0c10, 0, 16, 4, /* IPR14 */ { PWMT1, PWMT2, ADC_ADI, 0 } },
+ { 0xfffe0c12, 0, 16, 4, /* IPR15 */ { SSIF0, SSII1, SSII2, SSII3 } },
+ { 0xfffe0c14, 0, 16, 4, /* IPR16 */ { RSPDIF, IIC30, IIC31, IIC32 } },
+ { 0xfffe0c16, 0, 16, 4, /* IPR17 */ { SCIF0, SCIF1, SCIF2, SCIF3 } },
+ { 0xfffe0c18, 0, 16, 4, /* IPR18 */ { SCIF4, SCIF5, SCIF6, SCIF7 } },
+ { 0xfffe0c1a, 0, 16, 4, /* IPR19 */ { SIO_FIFO, 0, RSPIC0, RSPIC1, } },
+ { 0xfffe0c1c, 0, 16, 4, /* IPR20 */ { RCAN0, RCAN1, IEBC, CD_ROMD } },
+ { 0xfffe0c1e, 0, 16, 4, /* IPR21 */ { NFMC, SDHI, RTC, 0 } },
+ { 0xfffe0c20, 0, 16, 4, /* IPR22 */ { SRCC0, SRCC1, 0, DCOMU } },
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xfffe0808, 0, 16, /* PINTER */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7264", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xfffe8000, 0x100),
+ DEFINE_RES_IRQ(233),
+ DEFINE_RES_IRQ(234),
+ DEFINE_RES_IRQ(235),
+ DEFINE_RES_IRQ(232),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xfffe8800, 0x100),
+ DEFINE_RES_IRQ(237),
+ DEFINE_RES_IRQ(238),
+ DEFINE_RES_IRQ(239),
+ DEFINE_RES_IRQ(236),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xfffe9000, 0x100),
+ DEFINE_RES_IRQ(241),
+ DEFINE_RES_IRQ(242),
+ DEFINE_RES_IRQ(243),
+ DEFINE_RES_IRQ(240),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xfffe9800, 0x100),
+ DEFINE_RES_IRQ(245),
+ DEFINE_RES_IRQ(246),
+ DEFINE_RES_IRQ(247),
+ DEFINE_RES_IRQ(244),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xfffea000, 0x100),
+ DEFINE_RES_IRQ(249),
+ DEFINE_RES_IRQ(250),
+ DEFINE_RES_IRQ(251),
+ DEFINE_RES_IRQ(248),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xfffea800, 0x100),
+ DEFINE_RES_IRQ(253),
+ DEFINE_RES_IRQ(254),
+ DEFINE_RES_IRQ(255),
+ DEFINE_RES_IRQ(252),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct plat_sci_port scif6_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif6_resources[] = {
+ DEFINE_RES_MEM(0xfffeb000, 0x100),
+ DEFINE_RES_IRQ(257),
+ DEFINE_RES_IRQ(258),
+ DEFINE_RES_IRQ(259),
+ DEFINE_RES_IRQ(256),
+};
+
+static struct platform_device scif6_device = {
+ .name = "sh-sci",
+ .id = 6,
+ .resource = scif6_resources,
+ .num_resources = ARRAY_SIZE(scif6_resources),
+ .dev = {
+ .platform_data = &scif6_platform_data,
+ },
+};
+
+static struct plat_sci_port scif7_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif7_resources[] = {
+ DEFINE_RES_MEM(0xfffeb800, 0x100),
+ DEFINE_RES_IRQ(261),
+ DEFINE_RES_IRQ(262),
+ DEFINE_RES_IRQ(263),
+ DEFINE_RES_IRQ(260),
+};
+
+static struct platform_device scif7_device = {
+ .name = "sh-sci",
+ .id = 7,
+ .resource = scif7_resources,
+ .num_resources = ARRAY_SIZE(scif7_resources),
+ .dev = {
+ .platform_data = &scif7_platform_data,
+ },
+};
+
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0xfffec000, 0x10),
+ DEFINE_RES_IRQ(175),
+ DEFINE_RES_IRQ(176),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-16",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct resource mtu2_resources[] = {
+ DEFINE_RES_MEM(0xfffe4000, 0x400),
+ DEFINE_RES_IRQ_NAMED(179, "tgi0a"),
+ DEFINE_RES_IRQ_NAMED(186, "tgi1a"),
+};
+
+static struct platform_device mtu2_device = {
+ .name = "sh-mtu2",
+ .id = -1,
+ .resource = mtu2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_resources),
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xfffe6000,
+ .end = 0xfffe6000 + 0x30 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = 296,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* USB Host */
+static void usb_port_power(int port, int power)
+{
+ __raw_writew(0x200 , 0xffffc0c2) ; /* Initialise UACS25 */
+}
+
+static struct r8a66597_platdata r8a66597_data = {
+ .on_chip = 1,
+ .endian = 1,
+ .port_power = usb_port_power,
+};
+
+static struct resource r8a66597_usb_host_resources[] = {
+ [0] = {
+ .start = 0xffffc000,
+ .end = 0xffffc0e4,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 170,
+ .end = 170,
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+ },
+};
+
+static struct platform_device r8a66597_usb_host_device = {
+ .name = "r8a66597_hcd",
+ .id = 0,
+ .dev = {
+ .dma_mask = NULL, /* not use dma */
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &r8a66597_data,
+ },
+ .num_resources = ARRAY_SIZE(r8a66597_usb_host_resources),
+ .resource = r8a66597_usb_host_resources,
+};
+
+static struct platform_device *sh7264_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt_device,
+ &mtu2_device,
+ &rtc_device,
+ &r8a66597_usb_host_device,
+};
+
+static int __init sh7264_devices_setup(void)
+{
+ return platform_add_devices(sh7264_devices,
+ ARRAY_SIZE(sh7264_devices));
+}
+arch_initcall(sh7264_devices_setup);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+static struct platform_device *sh7264_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt_device,
+ &mtu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7264_early_devices,
+ ARRAY_SIZE(sh7264_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7269.c b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
new file mode 100644
index 00000000000..16ce5aa77bd
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7269.c
@@ -0,0 +1,586 @@
+/*
+ * SH7269 Setup
+ *
+ * Copyright (C) 2012 Renesas Electronics Europe Ltd
+ * Copyright (C) 2012 Phil Edworthy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7,
+
+ DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7,
+ DMAC8, DMAC9, DMAC10, DMAC11, DMAC12, DMAC13, DMAC14, DMAC15,
+ USB, VDC4, CMT0, CMT1, BSC, WDT,
+ MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU3_TCI3V, MTU4_ABCD, MTU4_TCI4V,
+ PWMT1, PWMT2, ADC_ADI,
+ SSIF0, SSII1, SSII2, SSII3, SSII4, SSII5,
+ RSPDIF,
+ IIC30, IIC31, IIC32, IIC33,
+ SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
+ SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI,
+ SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
+ SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI,
+ SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI,
+ SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI,
+ SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI,
+ SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI,
+ RCAN0, RCAN1, RCAN2,
+ RSPIC0, RSPIC1,
+ IEBC, CD_ROMD,
+ NFMC,
+ SDHI0, SDHI1,
+ RTC,
+ SRCC0, SRCC1, SRCC2,
+
+ /* interrupt groups */
+ PINT, SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65),
+ INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67),
+ INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69),
+ INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71),
+
+ INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81),
+ INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83),
+ INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85),
+ INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87),
+
+ INTC_IRQ(DMAC0, 108), INTC_IRQ(DMAC0, 109),
+ INTC_IRQ(DMAC1, 112), INTC_IRQ(DMAC1, 113),
+ INTC_IRQ(DMAC2, 116), INTC_IRQ(DMAC2, 117),
+ INTC_IRQ(DMAC3, 120), INTC_IRQ(DMAC3, 121),
+ INTC_IRQ(DMAC4, 124), INTC_IRQ(DMAC4, 125),
+ INTC_IRQ(DMAC5, 128), INTC_IRQ(DMAC5, 129),
+ INTC_IRQ(DMAC6, 132), INTC_IRQ(DMAC6, 133),
+ INTC_IRQ(DMAC7, 136), INTC_IRQ(DMAC7, 137),
+ INTC_IRQ(DMAC8, 140), INTC_IRQ(DMAC8, 141),
+ INTC_IRQ(DMAC9, 144), INTC_IRQ(DMAC9, 145),
+ INTC_IRQ(DMAC10, 148), INTC_IRQ(DMAC10, 149),
+ INTC_IRQ(DMAC11, 152), INTC_IRQ(DMAC11, 153),
+ INTC_IRQ(DMAC12, 156), INTC_IRQ(DMAC12, 157),
+ INTC_IRQ(DMAC13, 160), INTC_IRQ(DMAC13, 161),
+ INTC_IRQ(DMAC14, 164), INTC_IRQ(DMAC14, 165),
+ INTC_IRQ(DMAC15, 168), INTC_IRQ(DMAC15, 169),
+
+ INTC_IRQ(USB, 170),
+
+ INTC_IRQ(VDC4, 171), INTC_IRQ(VDC4, 172),
+ INTC_IRQ(VDC4, 173), INTC_IRQ(VDC4, 174),
+ INTC_IRQ(VDC4, 175), INTC_IRQ(VDC4, 176),
+ INTC_IRQ(VDC4, 177), INTC_IRQ(VDC4, 177),
+
+ INTC_IRQ(CMT0, 188), INTC_IRQ(CMT1, 189),
+
+ INTC_IRQ(BSC, 190), INTC_IRQ(WDT, 191),
+
+ INTC_IRQ(MTU0_ABCD, 192), INTC_IRQ(MTU0_ABCD, 193),
+ INTC_IRQ(MTU0_ABCD, 194), INTC_IRQ(MTU0_ABCD, 195),
+ INTC_IRQ(MTU0_VEF, 196), INTC_IRQ(MTU0_VEF, 197),
+ INTC_IRQ(MTU0_VEF, 198),
+ INTC_IRQ(MTU1_AB, 199), INTC_IRQ(MTU1_AB, 200),
+ INTC_IRQ(MTU1_VU, 201), INTC_IRQ(MTU1_VU, 202),
+ INTC_IRQ(MTU2_AB, 203), INTC_IRQ(MTU2_AB, 204),
+ INTC_IRQ(MTU2_VU, 205), INTC_IRQ(MTU2_VU, 206),
+ INTC_IRQ(MTU3_ABCD, 207), INTC_IRQ(MTU3_ABCD, 208),
+ INTC_IRQ(MTU3_ABCD, 209), INTC_IRQ(MTU3_ABCD, 210),
+ INTC_IRQ(MTU3_TCI3V, 211),
+ INTC_IRQ(MTU4_ABCD, 212), INTC_IRQ(MTU4_ABCD, 213),
+ INTC_IRQ(MTU4_ABCD, 214), INTC_IRQ(MTU4_ABCD, 215),
+ INTC_IRQ(MTU4_TCI4V, 216),
+
+ INTC_IRQ(PWMT1, 217), INTC_IRQ(PWMT2, 218),
+
+ INTC_IRQ(ADC_ADI, 223),
+
+ INTC_IRQ(SSIF0, 224), INTC_IRQ(SSIF0, 225),
+ INTC_IRQ(SSIF0, 226),
+ INTC_IRQ(SSII1, 227), INTC_IRQ(SSII1, 228),
+ INTC_IRQ(SSII2, 229), INTC_IRQ(SSII2, 230),
+ INTC_IRQ(SSII3, 231), INTC_IRQ(SSII3, 232),
+ INTC_IRQ(SSII4, 233), INTC_IRQ(SSII4, 234),
+ INTC_IRQ(SSII5, 235), INTC_IRQ(SSII5, 236),
+
+ INTC_IRQ(RSPDIF, 237),
+
+ INTC_IRQ(IIC30, 238), INTC_IRQ(IIC30, 239),
+ INTC_IRQ(IIC30, 240), INTC_IRQ(IIC30, 241),
+ INTC_IRQ(IIC30, 242),
+ INTC_IRQ(IIC31, 243), INTC_IRQ(IIC31, 244),
+ INTC_IRQ(IIC31, 245), INTC_IRQ(IIC31, 246),
+ INTC_IRQ(IIC31, 247),
+ INTC_IRQ(IIC32, 248), INTC_IRQ(IIC32, 249),
+ INTC_IRQ(IIC32, 250), INTC_IRQ(IIC32, 251),
+ INTC_IRQ(IIC32, 252),
+ INTC_IRQ(IIC33, 253), INTC_IRQ(IIC33, 254),
+ INTC_IRQ(IIC33, 255), INTC_IRQ(IIC33, 256),
+ INTC_IRQ(IIC33, 257),
+
+ INTC_IRQ(SCIF0_BRI, 258), INTC_IRQ(SCIF0_ERI, 259),
+ INTC_IRQ(SCIF0_RXI, 260), INTC_IRQ(SCIF0_TXI, 261),
+ INTC_IRQ(SCIF1_BRI, 262), INTC_IRQ(SCIF1_ERI, 263),
+ INTC_IRQ(SCIF1_RXI, 264), INTC_IRQ(SCIF1_TXI, 265),
+ INTC_IRQ(SCIF2_BRI, 266), INTC_IRQ(SCIF2_ERI, 267),
+ INTC_IRQ(SCIF2_RXI, 268), INTC_IRQ(SCIF2_TXI, 269),
+ INTC_IRQ(SCIF3_BRI, 270), INTC_IRQ(SCIF3_ERI, 271),
+ INTC_IRQ(SCIF3_RXI, 272), INTC_IRQ(SCIF3_TXI, 273),
+ INTC_IRQ(SCIF4_BRI, 274), INTC_IRQ(SCIF4_ERI, 275),
+ INTC_IRQ(SCIF4_RXI, 276), INTC_IRQ(SCIF4_TXI, 277),
+ INTC_IRQ(SCIF5_BRI, 278), INTC_IRQ(SCIF5_ERI, 279),
+ INTC_IRQ(SCIF5_RXI, 280), INTC_IRQ(SCIF5_TXI, 281),
+ INTC_IRQ(SCIF6_BRI, 282), INTC_IRQ(SCIF6_ERI, 283),
+ INTC_IRQ(SCIF6_RXI, 284), INTC_IRQ(SCIF6_TXI, 285),
+ INTC_IRQ(SCIF7_BRI, 286), INTC_IRQ(SCIF7_ERI, 287),
+ INTC_IRQ(SCIF7_RXI, 288), INTC_IRQ(SCIF7_TXI, 289),
+
+ INTC_IRQ(RCAN0, 291), INTC_IRQ(RCAN0, 292),
+ INTC_IRQ(RCAN0, 293), INTC_IRQ(RCAN0, 294),
+ INTC_IRQ(RCAN0, 295),
+ INTC_IRQ(RCAN1, 296), INTC_IRQ(RCAN1, 297),
+ INTC_IRQ(RCAN1, 298), INTC_IRQ(RCAN1, 299),
+ INTC_IRQ(RCAN1, 300),
+ INTC_IRQ(RCAN2, 301), INTC_IRQ(RCAN2, 302),
+ INTC_IRQ(RCAN2, 303), INTC_IRQ(RCAN2, 304),
+ INTC_IRQ(RCAN2, 305),
+
+ INTC_IRQ(RSPIC0, 306), INTC_IRQ(RSPIC0, 307),
+ INTC_IRQ(RSPIC0, 308),
+ INTC_IRQ(RSPIC1, 309), INTC_IRQ(RSPIC1, 310),
+ INTC_IRQ(RSPIC1, 311),
+
+ INTC_IRQ(IEBC, 318),
+
+ INTC_IRQ(CD_ROMD, 319), INTC_IRQ(CD_ROMD, 320),
+ INTC_IRQ(CD_ROMD, 321), INTC_IRQ(CD_ROMD, 322),
+ INTC_IRQ(CD_ROMD, 323), INTC_IRQ(CD_ROMD, 324),
+
+ INTC_IRQ(NFMC, 325), INTC_IRQ(NFMC, 326),
+ INTC_IRQ(NFMC, 327), INTC_IRQ(NFMC, 328),
+
+ INTC_IRQ(SDHI0, 332), INTC_IRQ(SDHI0, 333),
+ INTC_IRQ(SDHI0, 334),
+ INTC_IRQ(SDHI1, 335), INTC_IRQ(SDHI1, 336),
+ INTC_IRQ(SDHI1, 337),
+
+ INTC_IRQ(RTC, 338), INTC_IRQ(RTC, 339),
+ INTC_IRQ(RTC, 340),
+
+ INTC_IRQ(SRCC0, 341), INTC_IRQ(SRCC0, 342),
+ INTC_IRQ(SRCC0, 343), INTC_IRQ(SRCC0, 344),
+ INTC_IRQ(SRCC0, 345),
+ INTC_IRQ(SRCC1, 346), INTC_IRQ(SRCC1, 347),
+ INTC_IRQ(SRCC1, 348), INTC_IRQ(SRCC1, 349),
+ INTC_IRQ(SRCC1, 350),
+ INTC_IRQ(SRCC2, 351), INTC_IRQ(SRCC2, 352),
+ INTC_IRQ(SRCC2, 353), INTC_IRQ(SRCC2, 354),
+ INTC_IRQ(SRCC2, 355),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3,
+ PINT4, PINT5, PINT6, PINT7),
+ INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
+ INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI),
+ INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
+ INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI),
+ INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI),
+ INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI),
+ INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI),
+ INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xfffe0818, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } },
+ { 0xfffe081a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } },
+ { 0xfffe0820, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } },
+ { 0xfffe0c00, 0, 16, 4, /* IPR06 */ { DMAC0, DMAC1, DMAC2, DMAC3 } },
+ { 0xfffe0c02, 0, 16, 4, /* IPR07 */ { DMAC4, DMAC5, DMAC6, DMAC7 } },
+ { 0xfffe0c04, 0, 16, 4, /* IPR08 */ { DMAC8, DMAC9,
+ DMAC10, DMAC11 } },
+ { 0xfffe0c06, 0, 16, 4, /* IPR09 */ { DMAC12, DMAC13,
+ DMAC14, DMAC15 } },
+ { 0xfffe0c08, 0, 16, 4, /* IPR10 */ { USB, VDC4, VDC4, VDC4 } },
+ { 0xfffe0c0a, 0, 16, 4, /* IPR11 */ { 0, 0, 0, 0 } },
+ { 0xfffe0c0c, 0, 16, 4, /* IPR12 */ { CMT0, CMT1, BSC, WDT } },
+ { 0xfffe0c0e, 0, 16, 4, /* IPR13 */ { MTU0_ABCD, MTU0_VEF,
+ MTU1_AB, MTU1_VU } },
+ { 0xfffe0c10, 0, 16, 4, /* IPR14 */ { MTU2_AB, MTU2_VU,
+ MTU3_ABCD, MTU3_TCI3V } },
+ { 0xfffe0c12, 0, 16, 4, /* IPR15 */ { MTU4_ABCD, MTU4_TCI4V,
+ PWMT1, PWMT2 } },
+ { 0xfffe0c14, 0, 16, 4, /* IPR16 */ { 0, 0, 0, 0 } },
+ { 0xfffe0c16, 0, 16, 4, /* IPR17 */ { ADC_ADI, SSIF0, SSII1, SSII2 } },
+ { 0xfffe0c18, 0, 16, 4, /* IPR18 */ { SSII3, SSII4, SSII5, RSPDIF} },
+ { 0xfffe0c1a, 0, 16, 4, /* IPR19 */ { IIC30, IIC31, IIC32, IIC33 } },
+ { 0xfffe0c1c, 0, 16, 4, /* IPR20 */ { SCIF0, SCIF1, SCIF2, SCIF3 } },
+ { 0xfffe0c1e, 0, 16, 4, /* IPR21 */ { SCIF4, SCIF5, SCIF6, SCIF7 } },
+ { 0xfffe0c20, 0, 16, 4, /* IPR22 */ { 0, RCAN0, RCAN1, RCAN2 } },
+ { 0xfffe0c22, 0, 16, 4, /* IPR23 */ { RSPIC0, RSPIC1, 0, 0 } },
+ { 0xfffe0c24, 0, 16, 4, /* IPR24 */ { IEBC, CD_ROMD, NFMC, 0 } },
+ { 0xfffe0c26, 0, 16, 4, /* IPR25 */ { SDHI0, SDHI1, RTC, 0 } },
+ { 0xfffe0c28, 0, 16, 4, /* IPR26 */ { SRCC0, SRCC1, SRCC2, 0 } },
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xfffe0808, 0, 16, /* PINTER */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7269", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xe8007000, 0x100),
+ DEFINE_RES_IRQ(259),
+ DEFINE_RES_IRQ(260),
+ DEFINE_RES_IRQ(261),
+ DEFINE_RES_IRQ(258),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xe8007800, 0x100),
+ DEFINE_RES_IRQ(263),
+ DEFINE_RES_IRQ(264),
+ DEFINE_RES_IRQ(265),
+ DEFINE_RES_IRQ(262),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xe8008000, 0x100),
+ DEFINE_RES_IRQ(267),
+ DEFINE_RES_IRQ(268),
+ DEFINE_RES_IRQ(269),
+ DEFINE_RES_IRQ(266),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xe8008800, 0x100),
+ DEFINE_RES_IRQ(271),
+ DEFINE_RES_IRQ(272),
+ DEFINE_RES_IRQ(273),
+ DEFINE_RES_IRQ(270),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xe8009000, 0x100),
+ DEFINE_RES_IRQ(275),
+ DEFINE_RES_IRQ(276),
+ DEFINE_RES_IRQ(277),
+ DEFINE_RES_IRQ(274),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xe8009800, 0x100),
+ DEFINE_RES_IRQ(279),
+ DEFINE_RES_IRQ(280),
+ DEFINE_RES_IRQ(281),
+ DEFINE_RES_IRQ(278),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct plat_sci_port scif6_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif6_resources[] = {
+ DEFINE_RES_MEM(0xe800a000, 0x100),
+ DEFINE_RES_IRQ(283),
+ DEFINE_RES_IRQ(284),
+ DEFINE_RES_IRQ(285),
+ DEFINE_RES_IRQ(282),
+};
+
+static struct platform_device scif6_device = {
+ .name = "sh-sci",
+ .id = 6,
+ .resource = scif6_resources,
+ .num_resources = ARRAY_SIZE(scif6_resources),
+ .dev = {
+ .platform_data = &scif6_platform_data,
+ },
+};
+
+static struct plat_sci_port scif7_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+ SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif7_resources[] = {
+ DEFINE_RES_MEM(0xe800a800, 0x100),
+ DEFINE_RES_IRQ(287),
+ DEFINE_RES_IRQ(288),
+ DEFINE_RES_IRQ(289),
+ DEFINE_RES_IRQ(286),
+};
+
+static struct platform_device scif7_device = {
+ .name = "sh-sci",
+ .id = 7,
+ .resource = scif7_resources,
+ .num_resources = ARRAY_SIZE(scif7_resources),
+ .dev = {
+ .platform_data = &scif7_platform_data,
+ },
+};
+
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0xfffec000, 0x10),
+ DEFINE_RES_IRQ(188),
+ DEFINE_RES_IRQ(189),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-16",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct resource mtu2_resources[] = {
+ DEFINE_RES_MEM(0xfffe4000, 0x400),
+ DEFINE_RES_IRQ_NAMED(192, "tgi0a"),
+ DEFINE_RES_IRQ_NAMED(203, "tgi1a"),
+};
+
+static struct platform_device mtu2_device = {
+ .name = "sh-mtu2",
+ .id = -1,
+ .resource = mtu2_resources,
+ .num_resources = ARRAY_SIZE(mtu2_resources),
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xfffe6000,
+ .end = 0xfffe6000 + 0x30 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = 338,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* USB Host */
+static struct r8a66597_platdata r8a66597_data = {
+ .on_chip = 1,
+ .endian = 1,
+};
+
+static struct resource r8a66597_usb_host_resources[] = {
+ [0] = {
+ .start = 0xe8010000,
+ .end = 0xe80100e4,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 170,
+ .end = 170,
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+ },
+};
+
+static struct platform_device r8a66597_usb_host_device = {
+ .name = "r8a66597_hcd",
+ .id = 0,
+ .dev = {
+ .dma_mask = NULL, /* not use dma */
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &r8a66597_data,
+ },
+ .num_resources = ARRAY_SIZE(r8a66597_usb_host_resources),
+ .resource = r8a66597_usb_host_resources,
+};
+
+static struct platform_device *sh7269_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt_device,
+ &mtu2_device,
+ &rtc_device,
+ &r8a66597_usb_host_device,
+};
+
+static int __init sh7269_devices_setup(void)
+{
+ return platform_add_devices(sh7269_devices,
+ ARRAY_SIZE(sh7269_devices));
+}
+arch_initcall(sh7269_devices_setup);
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+static struct platform_device *sh7269_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &cmt_device,
+ &mtu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7269_early_devices,
+ ARRAY_SIZE(sh7269_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index 511de55af83..d3634ae7b71 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -4,16 +4,18 @@
obj-y := ex.o probe.o entry.o setup-sh3.o
+obj-$(CONFIG_HIBERNATION) += swsusp.o
+
# CPU subtype setup
-obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7706) += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7707) += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7708) += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh770x.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7710) += setup-sh7710.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7712) += setup-sh7710.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7720) += setup-sh7720.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7721) += setup-sh7720.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7706) += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7707) += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7708) += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7709) += setup-sh770x.o serial-sh770x.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7710) += setup-sh7710.o serial-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7712) += setup-sh7710.o serial-sh7710.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7720) += setup-sh7720.o serial-sh7720.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7721) += setup-sh7720.o serial-sh7720.o
# Primary on-chip clocks (common)
clock-$(CONFIG_CPU_SH3) := clock-sh3.o
@@ -24,4 +26,8 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7710) := clock-sh7710.o
clock-$(CONFIG_CPU_SUBTYPE_SH7720) := clock-sh7710.o
clock-$(CONFIG_CPU_SUBTYPE_SH7712) := clock-sh7712.o
+# Pinmux setup
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7720) := pinmux-sh7720.o
+
obj-y += $(clock-y)
+obj-$(CONFIG_GPIOLIB) += $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c
index c3c945958ba..90faa44ca94 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh3.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c
@@ -28,60 +28,60 @@ static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
static void master_clk_init(struct clk *clk)
{
- int frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
clk->rate *= pfc_divisors[idx];
}
-static struct clk_ops sh3_master_clk_ops = {
+static struct sh_clk_ops sh3_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh3_module_clk_ops = {
+static struct sh_clk_ops sh3_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
- clk->rate = clk->parent->rate / stc_multipliers[idx];
+ return clk->parent->rate / stc_multipliers[idx];
}
-static struct clk_ops sh3_bus_clk_ops = {
+static struct sh_clk_ops sh3_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh3_cpu_clk_ops = {
+static struct sh_clk_ops sh3_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh3_clk_ops[] = {
+static struct sh_clk_ops *sh3_clk_ops[] = {
&sh3_master_clk_ops,
&sh3_module_clk_ops,
&sh3_bus_clk_ops,
&sh3_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh3_clk_ops))
*ops = sh3_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c
index dfdbf3277fd..a8da4a9986b 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c
@@ -32,51 +32,51 @@ static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 };
static void master_clk_init(struct clk *clk)
{
- clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003];
+ clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0003];
}
-static struct clk_ops sh7705_master_clk_ops = {
+static struct sh_clk_ops sh7705_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) & 0x0003;
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ int idx = __raw_readw(FRQCR) & 0x0003;
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7705_module_clk_ops = {
+static struct sh_clk_ops sh7705_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) & 0x0300) >> 8;
- clk->rate = clk->parent->rate / stc_multipliers[idx];
+ int idx = (__raw_readw(FRQCR) & 0x0300) >> 8;
+ return clk->parent->rate / stc_multipliers[idx];
}
-static struct clk_ops sh7705_bus_clk_ops = {
+static struct sh_clk_ops sh7705_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) & 0x0030) >> 4;
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ int idx = (__raw_readw(FRQCR) & 0x0030) >> 4;
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh7705_cpu_clk_ops = {
+static struct sh_clk_ops sh7705_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7705_clk_ops[] = {
+static struct sh_clk_ops *sh7705_clk_ops[] = {
&sh7705_master_clk_ops,
&sh7705_module_clk_ops,
&sh7705_bus_clk_ops,
&sh7705_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7705_clk_ops))
*ops = sh7705_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7706.c b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
index 0cf96f9833b..a4088e5b220 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7706.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
@@ -24,60 +24,60 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
static void master_clk_init(struct clk *clk)
{
- int frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
clk->rate *= pfc_divisors[idx];
}
-static struct clk_ops sh7706_master_clk_ops = {
+static struct sh_clk_ops sh7706_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7706_module_clk_ops = {
+static struct sh_clk_ops sh7706_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
- clk->rate = clk->parent->rate / stc_multipliers[idx];
+ return clk->parent->rate / stc_multipliers[idx];
}
-static struct clk_ops sh7706_bus_clk_ops = {
+static struct sh_clk_ops sh7706_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh7706_cpu_clk_ops = {
+static struct sh_clk_ops sh7706_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7706_clk_ops[] = {
+static struct sh_clk_ops *sh7706_clk_ops[] = {
&sh7706_master_clk_ops,
&sh7706_module_clk_ops,
&sh7706_bus_clk_ops,
&sh7706_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7706_clk_ops))
*ops = sh7706_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
index b791a29fdb6..54a6d4bcc0d 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
@@ -22,74 +22,63 @@ static int stc_multipliers[] = { 1, 2, 4, 8, 3, 6, 1, 1 };
static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
-static void set_bus_parent(struct clk *clk)
-{
- struct clk *bus_clk = clk_get(NULL, "bus_clk");
- clk->parent = bus_clk;
- clk_put(bus_clk);
-}
-
static void master_clk_init(struct clk *clk)
{
- int frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
clk->rate *= pfc_divisors[idx];
}
-static struct clk_ops sh7709_master_clk_ops = {
+static struct sh_clk_ops sh7709_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7709_module_clk_ops = {
-#ifdef CLOCK_MODE_0_1_2_7
- .init = set_bus_parent,
-#endif
+static struct sh_clk_ops sh7709_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = (frqcr & 0x0080) ?
((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1;
- clk->rate = clk->parent->rate * stc_multipliers[idx];
+ return clk->parent->rate * stc_multipliers[idx];
}
-static struct clk_ops sh7709_bus_clk_ops = {
+static struct sh_clk_ops sh7709_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh7709_cpu_clk_ops = {
- .init = set_bus_parent,
+static struct sh_clk_ops sh7709_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7709_clk_ops[] = {
+static struct sh_clk_ops *sh7709_clk_ops[] = {
&sh7709_master_clk_ops,
&sh7709_module_clk_ops,
&sh7709_bus_clk_ops,
&sh7709_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7709_clk_ops))
*ops = sh7709_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7710.c b/arch/sh/kernel/cpu/sh3/clock-sh7710.c
index 4744c50ec44..ce601b2e397 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7710.c
@@ -26,51 +26,51 @@ static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 };
static void master_clk_init(struct clk *clk)
{
- clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007];
+ clk->rate *= md_table[__raw_readw(FRQCR) & 0x0007];
}
-static struct clk_ops sh7710_master_clk_ops = {
+static struct sh_clk_ops sh7710_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 / md_table[idx];
+ int idx = (__raw_readw(FRQCR) & 0x0007);
+ return clk->parent->rate / md_table[idx];
}
-static struct clk_ops sh7710_module_clk_ops = {
+static struct sh_clk_ops sh7710_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) & 0x0700) >> 8;
- clk->rate = clk->parent->rate / md_table[idx];
+ int idx = (__raw_readw(FRQCR) & 0x0700) >> 8;
+ return clk->parent->rate / md_table[idx];
}
-static struct clk_ops sh7710_bus_clk_ops = {
+static struct sh_clk_ops sh7710_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) & 0x0070) >> 4;
- clk->rate = clk->parent->rate / md_table[idx];
+ int idx = (__raw_readw(FRQCR) & 0x0070) >> 4;
+ return clk->parent->rate / md_table[idx];
}
-static struct clk_ops sh7710_cpu_clk_ops = {
+static struct sh_clk_ops sh7710_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7710_clk_ops[] = {
+static struct sh_clk_ops *sh7710_clk_ops[] = {
&sh7710_master_clk_ops,
&sh7710_module_clk_ops,
&sh7710_bus_clk_ops,
&sh7710_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7710_clk_ops))
*ops = sh7710_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7712.c b/arch/sh/kernel/cpu/sh3/clock-sh7712.c
index 54f54df51ef..21438a9a1ae 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7712.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7712.c
@@ -23,47 +23,47 @@ static int divisors[] = { 1, 2, 3, 4, 6 };
static void master_clk_init(struct clk *clk)
{
- int frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = (frqcr & 0x0300) >> 8;
clk->rate *= multipliers[idx];
}
-static struct clk_ops sh7712_master_clk_ops = {
+static struct sh_clk_ops sh7712_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 frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = frqcr & 0x0007;
- clk->rate = clk->parent->rate / divisors[idx];
+ return clk->parent->rate / divisors[idx];
}
-static struct clk_ops sh7712_module_clk_ops = {
+static struct sh_clk_ops sh7712_module_clk_ops = {
.recalc = module_clk_recalc,
};
-static void cpu_clk_recalc(struct clk *clk)
+static unsigned long cpu_clk_recalc(struct clk *clk)
{
- int frqcr = ctrl_inw(FRQCR);
+ int frqcr = __raw_readw(FRQCR);
int idx = (frqcr & 0x0030) >> 4;
- clk->rate = clk->parent->rate / divisors[idx];
+ return clk->parent->rate / divisors[idx];
}
-static struct clk_ops sh7712_cpu_clk_ops = {
+static struct sh_clk_ops sh7712_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7712_clk_ops[] = {
+static struct sh_clk_ops *sh7712_clk_ops[] = {
&sh7712_master_clk_ops,
&sh7712_module_clk_ops,
&sh7712_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7712_clk_ops))
*ops = sh7712_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 3fe482dd05c..262db6ec067 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -2,7 +2,7 @@
* arch/sh/kernel/cpu/sh3/entry.S
*
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2003 - 2006 Paul Mundt
+ * Copyright (C) 2003 - 2012 Paul Mundt
*
* 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
@@ -16,6 +16,8 @@
#include <asm/unistd.h>
#include <cpu/mmu_context.h>
#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/thread_info.h>
! NOTE:
! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -52,10 +54,6 @@
* syscall #
*
*/
-#if defined(CONFIG_KGDB_NMI)
-NMI_VEC = 0x1c0 ! Must catch early for debounce
-#endif
-
/* Offsets to the stack */
OFF_R0 = 0 /* Return value. New ABI also arg4 */
OFF_R1 = 4 /* New ABI: arg5 */
@@ -70,7 +68,6 @@ OFF_PC = (16*4)
OFF_SR = (16*4+8)
OFF_TRA = (16*4+6*4)
-
#define k0 r0
#define k1 r1
#define k2 r2
@@ -112,34 +109,33 @@ OFF_TRA = (16*4+6*4)
#if defined(CONFIG_MMU)
.align 2
ENTRY(tlb_miss_load)
- bra call_dpf
+ bra call_handle_tlbmiss
mov #0, r5
.align 2
ENTRY(tlb_miss_store)
- bra call_dpf
- mov #1, r5
+ bra call_handle_tlbmiss
+ mov #FAULT_CODE_WRITE, r5
.align 2
ENTRY(initial_page_write)
- bra call_dpf
- mov #1, r5
+ bra call_handle_tlbmiss
+ mov #FAULT_CODE_INITIAL, r5
.align 2
ENTRY(tlb_protection_violation_load)
- bra call_dpf
- mov #0, r5
+ bra call_do_page_fault
+ mov #FAULT_CODE_PROT, r5
.align 2
ENTRY(tlb_protection_violation_store)
- bra call_dpf
- mov #1, r5
+ bra call_do_page_fault
+ mov #(FAULT_CODE_PROT | FAULT_CODE_WRITE), r5
-call_dpf:
+call_handle_tlbmiss:
mov.l 1f, r0
mov r5, r8
mov.l @r0, r6
- mov r6, r9
mov.l 2f, r0
sts pr, r10
jsr @r0
@@ -150,16 +146,23 @@ call_dpf:
lds r10, pr
rts
nop
-0: mov.l 3f, r0
- mov r9, r6
+0:
mov r8, r5
+call_do_page_fault:
+ mov.l 1f, r0
+ mov.l @r0, r6
+
+ mov.l 3f, r0
+ mov.l 4f, r1
+ mov r15, r4
jmp @r0
- mov r15, r4
+ lds r1, pr
.align 2
1: .long MMU_TEA
-2: .long __do_page_fault
+2: .long handle_tlbmiss
3: .long do_page_fault
+4: .long ret_from_exception
.align 2
ENTRY(address_error_load)
@@ -187,44 +190,35 @@ call_dae:
#if defined(CONFIG_SH_STANDARD_BIOS)
/* Unwind the stack and jmp to the debug entry */
ENTRY(sh_bios_handler)
- mov.l @r15+, r0
- mov.l @r15+, r1
- mov.l @r15+, r2
- mov.l @r15+, r3
- mov.l @r15+, r4
- mov.l @r15+, r5
- mov.l @r15+, r6
- mov.l @r15+, r7
- stc sr, r8
- mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F
- or r9, r8
- ldc r8, sr ! here, change the register bank
- mov.l @r15+, r8
- mov.l @r15+, r9
- mov.l @r15+, r10
- mov.l @r15+, r11
- mov.l @r15+, r12
- mov.l @r15+, r13
- mov.l @r15+, r14
- mov.l @r15+, k0
- ldc.l @r15+, spc
- lds.l @r15+, pr
- mov.l @r15+, k1
- ldc.l @r15+, gbr
- lds.l @r15+, mach
- lds.l @r15+, macl
- mov k0, r15
+ mov.l 1f, r8
+ bsr restore_regs
+ nop
+
+ lds k2, pr ! restore pr
+ mov k4, r15
!
mov.l 2f, k0
mov.l @k0, k0
jmp @k0
- ldc k1, ssr
+ ldc k3, ssr
.align 2
1: .long 0x300000f0
2: .long gdb_vbr_vector
#endif /* CONFIG_SH_STANDARD_BIOS */
-restore_all:
+! restore_regs()
+! - restore r0, r1, r2, r3, r4, r5, r6, r7 from the stack
+! - switch bank
+! - restore r8, r9, r10, r11, r12, r13, r14, r15 from the stack
+! - restore spc, pr*, ssr, gbr, mach, macl, skip default tra
+! k2 returns original pr
+! k3 returns original sr
+! k4 returns original stack pointer
+! r8 passes SR bitmask, overwritten with restored data on return
+! r9 trashed
+! BL=0 on entry, on exit BL=1 (depending on r8).
+
+ENTRY(restore_regs)
mov.l @r15+, r0
mov.l @r15+, r1
mov.l @r15+, r2
@@ -234,10 +228,9 @@ restore_all:
mov.l @r15+, r6
mov.l @r15+, r7
!
- stc sr, r8
- mov.l 7f, r9
- or r9, r8 ! BL =1, RB=1
- ldc r8, sr ! here, change the register bank
+ stc sr, r9
+ or r8, r9
+ ldc r9, sr
!
mov.l @r15+, r8
mov.l @r15+, r9
@@ -248,53 +241,27 @@ restore_all:
mov.l @r15+, r14
mov.l @r15+, k4 ! original stack pointer
ldc.l @r15+, spc
- lds.l @r15+, pr
+ mov.l @r15+, k2 ! original PR
mov.l @r15+, k3 ! original SR
ldc.l @r15+, gbr
lds.l @r15+, mach
lds.l @r15+, macl
- add #4, r15 ! Skip syscall number
- !
-#ifdef CONFIG_SH_DSP
- mov.l @r15+, k0 ! DSP mode marker
- mov.l 5f, k1
- cmp/eq k0, k1 ! Do we have a DSP stack frame?
- bf skip_restore
-
- stc sr, k0 ! Enable CPU DSP mode
- or k1, k0 ! (within kernel it may be disabled)
- ldc k0, sr
- mov r2, k0 ! Backup r2
-
- ! Restore DSP registers from stack
- mov r15, r2
- movs.l @r2+, a1
- movs.l @r2+, a0g
- movs.l @r2+, a1g
- movs.l @r2+, m0
- movs.l @r2+, m1
- mov r2, r15
-
- lds.l @r15+, a0
- lds.l @r15+, x0
- lds.l @r15+, x1
- lds.l @r15+, y0
- lds.l @r15+, y1
- lds.l @r15+, dsr
- ldc.l @r15+, rs
- ldc.l @r15+, re
- ldc.l @r15+, mod
-
- mov k0, r2 ! Restore r2
-skip_restore:
-#endif
+ rts
+ add #4, r15 ! Skip syscall number
+
+restore_all:
+ mov.l 7f, r8
+ bsr restore_regs
+ nop
+
+ lds k2, pr ! restore pr
!
! Calculate new SR value
mov k3, k2 ! original SR value
- mov #0xf0, k1
+ mov #0xfffffff0, k1
extu.b k1, k1
not k1, k1
- and k1, k2 ! Mask orignal SR value
+ and k1, k2 ! Mask original SR value
!
mov k3, k0 ! Calculate IMASK-bits
shlr2 k0
@@ -307,22 +274,12 @@ skip_restore:
6: or k0, k2 ! Set the IMASK-bits
ldc k2, ssr
!
-#if defined(CONFIG_KGDB_NMI)
- ! Clear in_nmi
- mov.l 6f, k0
- mov #0, k1
- mov.b k1, @k0
-#endif
- mov.l @r15+, k2 ! restore EXPEVT
mov k4, r15
rte
nop
.align 2
5: .long 0x00001000 ! DSP
-#ifdef CONFIG_KGDB_NMI
-6: .long in_nmi
-#endif
7: .long 0x30000000
! common exception handler
@@ -336,81 +293,21 @@ skip_restore:
ENTRY(vbr_base)
.long 0
!
+! 0x100: General exception vector
+!
.balign 256,0,256
general_exception:
- mov.l 1f, k2
- mov.l 2f, k3
-#ifdef CONFIG_CPU_SUBTYPE_SHX3
- mov.l @k2, k2
-
- ! Is EXPEVT larger than 0x800?
- mov #0x8, k0
- shll8 k0
- cmp/hs k0, k2
- bf 0f
-
- ! then add 0x580 (k2 is 0xd80 or 0xda0)
- mov #0x58, k0
- shll2 k0
- shll2 k0
- add k0, k2
-0:
- bra handle_exception
- nop
-#else
- bra handle_exception
- mov.l @k2, k2
-#endif
- .align 2
-1: .long EXPEVT
-2: .long ret_from_exception
-!
-!
-
- .balign 1024,0,1024
-tlb_miss:
- mov.l 1f, k2
- mov.l 4f, k3
- bra handle_exception
- mov.l @k2, k2
-!
- .balign 512,0,512
-interrupt:
- mov.l 2f, k2
- mov.l 3f, k3
-#if defined(CONFIG_KGDB_NMI)
- ! Debounce (filter nested NMI)
- mov.l @k2, k0
- mov.l 5f, k1
- cmp/eq k1, k0
- bf 0f
- mov.l 6f, k1
- tas.b @k1
- bt 0f
- rte
- nop
- .align 2
-5: .long NMI_VEC
-6: .long in_nmi
-0:
-#endif /* defined(CONFIG_KGDB_NMI) */
bra handle_exception
- mov #-1, k2 ! interrupt exception marker
+ sts pr, k3 ! save original pr value in k3
- .align 2
-1: .long EXPEVT
-2: .long INTEVT
-3: .long ret_from_irq
-4: .long ret_from_exception
-
-!
-!
- .align 2
-ENTRY(handle_exception)
- ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
- ! save all registers onto stack.
- !
+! prepare_stack()
+! - roll back gRB
+! - switch to kernel stack
+! k0 returns original sp (after roll back)
+! k1 trashed
+! k2 trashed
+prepare_stack:
#ifdef CONFIG_GUSA
! Check for roll back gRB (User and Kernel)
mov r15, k0
@@ -430,7 +327,7 @@ ENTRY(handle_exception)
2: mov k1, r15 ! SP = r1
1:
#endif
-
+ ! Switch to kernel stack if needed
stc ssr, k0 ! Is it from kernel space?
shll k0 ! Check MD bit (bit30) by shifting it into...
shll k0 ! ...the T bit
@@ -443,65 +340,67 @@ ENTRY(handle_exception)
add current, k1
mov k1, r15 ! change to kernel stack
!
-1: mov.l 2f, k1
- !
-#ifdef CONFIG_SH_DSP
- mov.l r2, @-r15 ! Save r2, we need another reg
- stc sr, k4
- mov.l 1f, r2
- tst r2, k4 ! Check if in DSP mode
- mov.l @r15+, r2 ! Restore r2 now
- bt/s skip_save
- mov #0, k4 ! Set marker for no stack frame
-
- mov r2, k4 ! Backup r2 (in k4) for later
-
- ! Save DSP registers on stack
- stc.l mod, @-r15
- stc.l re, @-r15
- stc.l rs, @-r15
- sts.l dsr, @-r15
- sts.l y1, @-r15
- sts.l y0, @-r15
- sts.l x1, @-r15
- sts.l x0, @-r15
- sts.l a0, @-r15
-
- ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr.
-
- ! FIXME: Make sure that this is still the case with newer toolchains,
- ! as we're not at all interested in supporting ancient toolchains at
- ! this point. -- PFM.
-
- mov r15, r2
- .word 0xf653 ! movs.l a1, @-r2
- .word 0xf6f3 ! movs.l a0g, @-r2
- .word 0xf6d3 ! movs.l a1g, @-r2
- .word 0xf6c3 ! movs.l m0, @-r2
- .word 0xf6e3 ! movs.l m1, @-r2
- mov r2, r15
-
- mov k4, r2 ! Restore r2
- mov.l 1f, k4 ! Force DSP stack frame
-skip_save:
- mov.l k4, @-r15 ! Push DSP mode marker onto stack
-#endif
- ! Save the user registers on the stack.
- mov.l k2, @-r15 ! EXPEVT
+1:
+ rts
+ nop
- mov #-1, k4
- mov.l k4, @-r15 ! set TRA (default: -1)
- !
+!
+! 0x400: Instruction and Data TLB miss exception vector
+!
+ .balign 1024,0,1024
+tlb_miss:
+ sts pr, k3 ! save original pr value in k3
+
+handle_exception:
+ mova exception_data, k0
+
+ ! Setup stack and save DSP context (k0 contains original r15 on return)
+ bsr prepare_stack
+ PREF(k0)
+
+ ! Save registers / Switch to bank 0
+ mov.l 5f, k2 ! vector register address
+ mov.l 1f, k4 ! SR bits to clear in k4
+ bsr save_regs ! needs original pr value in k3
+ mov.l @k2, k2 ! read out vector and keep in k2
+
+handle_exception_special:
+ setup_frame_reg
+
+ ! Setup return address and jump to exception handler
+ mov.l 7f, r9 ! fetch return address
+ stc r2_bank, r0 ! k2 (vector)
+ mov.l 6f, r10
+ shlr2 r0
+ shlr r0
+ mov.l @(r0, r10), r10
+ jmp @r10
+ lds r9, pr ! put return address in pr
+
+ .align L1_CACHE_SHIFT
+
+! save_regs()
+! - save default tra, macl, mach, gbr, ssr, pr* and spc on the stack
+! - save r15*, r14, r13, r12, r11, r10, r9, r8 on the stack
+! - switch bank
+! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
+! k0 contains original stack pointer*
+! k1 trashed
+! k3 passes original pr*
+! k4 passes SR bitmask
+! BL=1 on entry, on exit BL=0.
+
+ENTRY(save_regs)
+ mov #-1, r1
+ mov.l k1, @-r15 ! set TRA (default: -1)
sts.l macl, @-r15
sts.l mach, @-r15
stc.l gbr, @-r15
stc.l ssr, @-r15
- sts.l pr, @-r15
+ mov.l k3, @-r15 ! original pr in k3
stc.l spc, @-r15
- !
- lds k3, pr ! Set the return address to pr
- !
- mov.l k0, @-r15 ! save orignal stack
+
+ mov.l k0, @-r15 ! original stack pointer in k0
mov.l r14, @-r15
mov.l r13, @-r15
mov.l r12, @-r15
@@ -509,13 +408,23 @@ skip_save:
mov.l r10, @-r15
mov.l r9, @-r15
mov.l r8, @-r15
- !
- stc sr, r8 ! Back to normal register bank, and
- or k1, r8 ! Block all interrupts
- mov.l 3f, k1
- and k1, r8 ! ...
- ldc r8, sr ! ...changed here.
- !
+
+ mov.l 0f, k3 ! SR bits to set in k3
+
+ ! fall-through
+
+! save_low_regs()
+! - modify SR for bank switch
+! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack
+! k3 passes bits to set in SR
+! k4 passes bits to clear in SR
+
+ENTRY(save_low_regs)
+ stc sr, r8
+ or k3, r8
+ and k4, r8
+ ldc r8, sr
+
mov.l r7, @-r15
mov.l r6, @-r15
mov.l r5, @-r15
@@ -523,52 +432,82 @@ skip_save:
mov.l r3, @-r15
mov.l r2, @-r15
mov.l r1, @-r15
- mov.l r0, @-r15
+ rts
+ mov.l r0, @-r15
+
+!
+! 0x600: Interrupt / NMI vector
+!
+ .balign 512,0,512
+ENTRY(handle_interrupt)
+ sts pr, k3 ! save original pr value in k3
+ mova exception_data, k0
+
+ ! Setup stack and save DSP context (k0 contains original r15 on return)
+ bsr prepare_stack
+ PREF(k0)
+
+ ! Save registers / Switch to bank 0
+ mov.l 1f, k4 ! SR bits to clear in k4
+ bsr save_regs ! needs original pr value in k3
+ mov #-1, k2 ! default vector kept in k2
+
+ setup_frame_reg
+
+ stc sr, r0 ! get status register
+ shlr2 r0
+ and #0x3c, r0
+ cmp/eq #0x3c, r0
+ bf 9f
+ TRACE_IRQS_OFF
+9:
+
+ ! Setup return address and jump to do_IRQ
+ mov.l 4f, r9 ! fetch return address
+ lds r9, pr ! put return address in pr
+ mov.l 2f, r4
+ mov.l 3f, r9
+ mov.l @r4, r4 ! pass INTEVT vector as arg0
+
+ shlr2 r4
+ shlr r4
+ mov r4, r0 ! save vector->jmp table offset for later
+
+ shlr2 r4 ! vector to IRQ# conversion
+ add #-0x10, r4
+
+ cmp/pz r4 ! is it a valid IRQ?
+ bt 10f
/*
- * This gets a bit tricky.. in the INTEVT case we don't want to use
- * the VBR offset as a destination in the jump call table, since all
- * of the destinations are the same. In this case, (interrupt) sets
- * a marker in r2 (now r2_bank since SR.RB changed), which we check
- * to determine the exception type. For all other exceptions, we
- * forcibly read EXPEVT from memory and fix up the jump address, in
- * the interrupt exception case we jump to do_IRQ() and defer the
- * INTEVT read until there. As a bonus, we can also clean up the SR.RB
- * checks that do_IRQ() was doing..
+ * We got here as a result of taking the INTEVT path for something
+ * that isn't a valid hard IRQ, therefore we bypass the do_IRQ()
+ * path and special case the event dispatch instead. This is the
+ * expected path for the NMI (and any other brilliantly implemented
+ * exception), which effectively wants regular exception dispatch
+ * but is unfortunately reported through INTEVT rather than
+ * EXPEVT. Grr.
*/
- stc r2_bank, r8
- cmp/pz r8
- bf interrupt_exception
- shlr2 r8
- shlr r8
- mov.l 4f, r9
- add r8, r9
- mov.l @r9, r9
+ mov.l 6f, r9
+ mov.l @(r0, r9), r9
jmp @r9
- nop
- rts
- nop
+ mov r15, r8 ! trap handlers take saved regs in r8
- .align 2
-1: .long 0x00001000 ! DSP=1
-2: .long 0x000080f0 ! FD=1, IMASK=15
-3: .long 0xcfffffff ! RB=0, BL=0
-4: .long exception_handling_table
+10:
+ jmp @r9 ! Off to do_IRQ() we go.
+ mov r15, r5 ! pass saved registers as arg1
-interrupt_exception:
- mov.l 1f, r9
- mov.l 2f, r4
- mov.l @r4, r4
- jmp @r9
- mov r15, r5
+ENTRY(exception_none)
rts
nop
- .align 2
-1: .long do_IRQ
+ .align L1_CACHE_SHIFT
+exception_data:
+0: .long 0x000080f0 ! FD=1, IMASK=15
+1: .long 0xcfffffff ! RB=0, BL=0
2: .long INTEVT
-
- .align 2
-ENTRY(exception_none)
- rts
- nop
+3: .long do_IRQ
+4: .long ret_from_irq
+5: .long EXPEVT
+6: .long exception_handling_table
+7: .long ret_from_exception
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index dac42972689..99b4d020179 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -26,7 +26,7 @@
#define fpu_error_trap_handler exception_error
#endif
-#if !defined(CONFIG_KGDB_NMI)
+#if !defined(CONFIG_KGDB)
#define kgdb_handle_exception exception_error
#endif
@@ -48,10 +48,8 @@ ENTRY(exception_handling_table)
.long system_call ! Unconditional Trap /* 160 */
.long exception_error ! reserved_instruction (filled by trap_init) /* 180 */
.long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/
-ENTRY(nmi_slot)
- .long kgdb_handle_exception /* 1C0 */ ! Allow trap to debugger
-ENTRY(user_break_point_trap)
- .long break_point_trap /* 1E0 */
+ .long nmi_trap_handler /* 1C0 */ ! Allow trap to debugger
+ .long breakpoint_trap_handler /* 1E0 */
/*
* Pad the remainder of the table out, exceptions residing in far
diff --git a/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c b/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
new file mode 100644
index 00000000000..26e90a66ebb
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
@@ -0,0 +1,30 @@
+/*
+ * SH7720 Pinmux
+ *
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7720_pfc_resources[] = {
+ [0] = {
+ .start = 0xa4050100,
+ .end = 0xa405016f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7720", sh7720_pfc_resources,
+ ARRAY_SIZE(sh7720_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c
index 10f2a760c5e..426e1e1dced 100644
--- a/arch/sh/kernel/cpu/sh3/probe.c
+++ b/arch/sh/kernel/cpu/sh3/probe.c
@@ -16,7 +16,7 @@
#include <asm/cache.h>
#include <asm/io.h>
-int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
+void cpu_probe(void)
{
unsigned long addr0, addr1, data0, data1, data2, data3;
@@ -30,23 +30,23 @@ int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
addr1 = CACHE_OC_ADDRESS_ARRAY + (1 << 12);
/* First, write back & invalidate */
- data0 = ctrl_inl(addr0);
- ctrl_outl(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0);
- data1 = ctrl_inl(addr1);
- ctrl_outl(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1);
+ data0 = __raw_readl(addr0);
+ __raw_writel(data0&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr0);
+ data1 = __raw_readl(addr1);
+ __raw_writel(data1&~(SH_CACHE_VALID|SH_CACHE_UPDATED), addr1);
/* Next, check if there's shadow or not */
- data0 = ctrl_inl(addr0);
+ data0 = __raw_readl(addr0);
data0 ^= SH_CACHE_VALID;
- ctrl_outl(data0, addr0);
- data1 = ctrl_inl(addr1);
+ __raw_writel(data0, addr0);
+ data1 = __raw_readl(addr1);
data2 = data1 ^ SH_CACHE_VALID;
- ctrl_outl(data2, addr1);
- data3 = ctrl_inl(addr0);
+ __raw_writel(data2, addr1);
+ data3 = __raw_readl(addr0);
/* Lastly, invaliate them. */
- ctrl_outl(data0&~SH_CACHE_VALID, addr0);
- ctrl_outl(data2&~SH_CACHE_VALID, addr1);
+ __raw_writel(data0&~SH_CACHE_VALID, addr0);
+ __raw_writel(data2&~SH_CACHE_VALID, addr1);
back_to_cached();
@@ -94,9 +94,9 @@ int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
boot_cpu_data.dcache.way_incr = (1 << 13);
boot_cpu_data.dcache.entry_mask = 0x1ff0;
boot_cpu_data.dcache.sets = 512;
- ctrl_outl(CCR_CACHE_32KB, CCR3_REG);
+ __raw_writel(CCR_CACHE_32KB, CCR3_REG);
#else
- ctrl_outl(CCR_CACHE_16KB, CCR3_REG);
+ __raw_writel(CCR_CACHE_16KB, CCR3_REG);
#endif
#endif
}
@@ -107,5 +107,5 @@ int __uses_jump_to_uncached detect_cpu_and_cache_system(void)
boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED;
boot_cpu_data.icache = boot_cpu_data.dcache;
- return 0;
+ boot_cpu_data.family = CPU_FAMILY_SH3;
}
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh770x.c b/arch/sh/kernel/cpu/sh3/serial-sh770x.c
new file mode 100644
index 00000000000..4f7242c676b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/serial-sh770x.c
@@ -0,0 +1,33 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+
+#define SCPCR 0xA4000116
+#define SCPDR 0xA4000136
+
+static void sh770x_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+ unsigned short data;
+
+ /* We need to set SCPCR to enable RTS/CTS */
+ data = __raw_readw(SCPCR);
+ /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
+ __raw_writew(data & 0x0fcf, SCPCR);
+
+ if (!(cflag & CRTSCTS)) {
+ /* We need to set SCPCR to enable RTS/CTS */
+ data = __raw_readw(SCPCR);
+ /* Clear out SCP7MD1,0, SCP4MD1,0,
+ Set SCP6MD1,0 = {01} (output) */
+ __raw_writew((data & 0x0fcf) | 0x1000, SCPCR);
+
+ data = __raw_readb(SCPDR);
+ /* Set /RTS2 (bit6) = 0 */
+ __raw_writeb(data & 0xbf, SCPDR);
+ }
+}
+
+struct plat_sci_port_ops sh770x_sci_port_ops = {
+ .init_pins = sh770x_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7710.c b/arch/sh/kernel/cpu/sh3/serial-sh7710.c
new file mode 100644
index 00000000000..42190ef6aeb
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/serial-sh7710.c
@@ -0,0 +1,20 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+
+#define PACR 0xa4050100
+#define PBCR 0xa4050102
+
+static void sh7710_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+ if (port->mapbase == 0xA4400000) {
+ __raw_writew(__raw_readw(PACR) & 0xffc0, PACR);
+ __raw_writew(__raw_readw(PBCR) & 0x0fff, PBCR);
+ } else if (port->mapbase == 0xA4410000)
+ __raw_writew(__raw_readw(PBCR) & 0xf003, PBCR);
+}
+
+struct plat_sci_port_ops sh7710_sci_port_ops = {
+ .init_pins = sh7710_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/serial-sh7720.c b/arch/sh/kernel/cpu/sh3/serial-sh7720.c
new file mode 100644
index 00000000000..c4a0336660d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/serial-sh7720.c
@@ -0,0 +1,37 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <cpu/serial.h>
+#include <cpu/gpio.h>
+
+static void sh7720_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+ unsigned short data;
+
+ if (cflag & CRTSCTS) {
+ /* enable RTS/CTS */
+ if (port->mapbase == 0xa4430000) { /* SCIF0 */
+ /* Clear PTCR bit 9-2; enable all scif pins but sck */
+ data = __raw_readw(PORT_PTCR);
+ __raw_writew((data & 0xfc03), PORT_PTCR);
+ } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
+ /* Clear PVCR bit 9-2 */
+ data = __raw_readw(PORT_PVCR);
+ __raw_writew((data & 0xfc03), PORT_PVCR);
+ }
+ } else {
+ if (port->mapbase == 0xa4430000) { /* SCIF0 */
+ /* Clear PTCR bit 5-2; enable only tx and rx */
+ data = __raw_readw(PORT_PTCR);
+ __raw_writew((data & 0xffc3), PORT_PTCR);
+ } else if (port->mapbase == 0xa4438000) { /* SCIF1 */
+ /* Clear PVCR bit 5-2 */
+ data = __raw_readw(PORT_PVCR);
+ __raw_writew((data & 0xffc3), PORT_PVCR);
+ }
+ }
+}
+
+struct plat_sci_port_ops sh7720_sci_port_ops = {
+ .init_pins = sh7720_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh3.c b/arch/sh/kernel/cpu/sh3/setup-sh3.c
index c9884685785..53be70b9811 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh3.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c
@@ -58,7 +58,7 @@ static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45",
void __init plat_irq_setup_pins(int mode)
{
if (mode == IRQ_MODE_IRQ) {
- ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
+ __raw_writew(__raw_readw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
register_intc_controller(&intc_desc_irq0123);
return;
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index 6468ae86b94..6a72fd14de2 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
@@ -1,7 +1,7 @@
/*
* SH7705 Setup
*
- * Copyright (C) 2006, 2007 Paul Mundt
+ * Copyright (C) 2006 - 2009 Paul Mundt
* Copyright (C) 2007 Nobuhiro Iwamatsu
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -13,7 +13,10 @@
#include <linux/irq.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/rtc.h>
+#include <cpu/serial.h>
enum {
UNUSED = 0,
@@ -21,51 +24,36 @@ enum {
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
PINT07, PINT815,
- DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
- SCIF0_ERI, SCIF0_RXI, SCIF0_TXI,
- SCIF2_ERI, SCIF2_RXI, SCIF2_TXI,
- ADC_ADI,
- USB_USI0, USB_USI1,
+
+ DMAC, SCIF0, SCIF2, ADC_ADI, USB,
+
TPU0, TPU1, TPU2, TPU3,
- TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
- RTC_ATI, RTC_PRI, RTC_CUI,
- WDT,
- REF_RCMI,
+ TMU0, TMU1, TMU2,
- /* interrupt groups */
- RTC, TMU2, DMAC, USB, SCIF2, SCIF0,
+ RTC, WDT, REF_RCMI,
};
static struct intc_vect vectors[] __initdata = {
/* IRQ0->5 are handled in setup-sh3.c */
INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720),
- INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
- INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
- INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
- INTC_VECT(SCIF0_TXI, 0x8e0),
- INTC_VECT(SCIF2_ERI, 0x900), INTC_VECT(SCIF2_RXI, 0x920),
- INTC_VECT(SCIF2_TXI, 0x960),
+ INTC_VECT(DMAC, 0x800), INTC_VECT(DMAC, 0x820),
+ INTC_VECT(DMAC, 0x840), INTC_VECT(DMAC, 0x860),
+ INTC_VECT(SCIF0, 0x880), INTC_VECT(SCIF0, 0x8a0),
+ INTC_VECT(SCIF0, 0x8e0),
+ INTC_VECT(SCIF2, 0x900), INTC_VECT(SCIF2, 0x920),
+ INTC_VECT(SCIF2, 0x960),
INTC_VECT(ADC_ADI, 0x980),
- INTC_VECT(USB_USI0, 0xa20), INTC_VECT(USB_USI1, 0xa40),
+ INTC_VECT(USB, 0xa20), INTC_VECT(USB, 0xa40),
INTC_VECT(TPU0, 0xc00), INTC_VECT(TPU1, 0xc20),
INTC_VECT(TPU2, 0xc80), INTC_VECT(TPU3, 0xca0),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
- INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
- INTC_VECT(RTC_CUI, 0x4c0),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
INTC_VECT(WDT, 0x560),
INTC_VECT(REF_RCMI, 0x580),
};
-static struct intc_group groups[] __initdata = {
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
- INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
- INTC_GROUP(DMAC, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
- INTC_GROUP(USB, USB_USI0, USB_USI1),
- INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI),
- INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI),
-};
-
static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
{ 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF_RCMI, 0, 0 } },
@@ -78,30 +66,53 @@ static struct intc_prio_reg prio_registers[] __initdata = {
};
-static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7705", vectors, NULL,
NULL, prio_registers, NULL);
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xa4410000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 56, 57, 59 },
- }, {
- .mapbase = 0xa4400000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 52, 53, 55 },
- }, {
- .flags = 0,
- }
-};
-
-static struct platform_device sci_device = {
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TIE | SCSCR_RIE | SCSCR_TE |
+ SCSCR_RE | SCSCR_CKE1 | SCSCR_CKE0,
+ .type = PORT_SCIF,
+ .ops = &sh770x_sci_port_ops,
+ .regtype = SCIx_SH7705_SCIF_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xa4410000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
+
+static struct platform_device scif0_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TIE | SCSCR_RIE | SCSCR_TE | SCSCR_RE,
+ .type = PORT_SCIF,
+ .ops = &sh770x_sci_port_ops,
+ .regtype = SCIx_SH7705_SCIF_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xa4400000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
},
};
@@ -112,17 +123,9 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- .start = 20,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = 21,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
- [3] = {
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
};
static struct sh_rtc_platform_info rtc_info = {
@@ -139,8 +142,31 @@ static struct platform_device rtc_device = {
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xfffffe90, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu-sh3",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
static struct platform_device *sh7705_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &tmu0_device,
&rtc_device,
};
@@ -149,7 +175,19 @@ static int __init sh7705_devices_setup(void)
return platform_add_devices(sh7705_devices,
ARRAY_SIZE(sh7705_devices));
}
-__initcall(sh7705_devices_setup);
+arch_initcall(sh7705_devices_setup);
+
+static struct platform_device *sh7705_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7705_early_devices,
+ ARRAY_SIZE(sh7705_early_devices));
+}
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
index 93c55e2ed95..9139d14b9c5 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
@@ -2,6 +2,7 @@
* SH3 Setup code for SH7706, SH7707, SH7708, SH7709
*
* Copyright (C) 2007 Magnus Damm
+ * Copyright (C) 2009 Paul Mundt
*
* Based on setup-sh7709.c
*
@@ -17,6 +18,9 @@
#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <cpu/serial.h>
enum {
UNUSED = 0,
@@ -24,46 +28,37 @@ enum {
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
PINT07, PINT815,
- DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
- SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
- SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
- SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI,
- ADC_ADI,
+ DMAC, SCIF0, SCIF2, SCI, ADC_ADI,
LCDC, PCC0, PCC1,
- TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
- RTC_ATI, RTC_PRI, RTC_CUI,
- WDT,
- REF_RCMI, REF_ROVI,
-
- /* interrupt groups */
- RTC, REF, TMU2, DMAC, SCI, SCIF2, SCIF0,
+ TMU0, TMU1, TMU2,
+ RTC, WDT, REF,
};
static struct intc_vect vectors[] __initdata = {
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
- INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
- INTC_VECT(RTC_CUI, 0x4c0),
- INTC_VECT(SCI_ERI, 0x4e0), INTC_VECT(SCI_RXI, 0x500),
- INTC_VECT(SCI_TXI, 0x520), INTC_VECT(SCI_TEI, 0x540),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
+ INTC_VECT(SCI, 0x4e0), INTC_VECT(SCI, 0x500),
+ INTC_VECT(SCI, 0x520), INTC_VECT(SCI, 0x540),
INTC_VECT(WDT, 0x560),
- INTC_VECT(REF_RCMI, 0x580),
- INTC_VECT(REF_ROVI, 0x5a0),
+ INTC_VECT(REF, 0x580),
+ INTC_VECT(REF, 0x5a0),
#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
defined(CONFIG_CPU_SUBTYPE_SH7707) || \
defined(CONFIG_CPU_SUBTYPE_SH7709)
/* IRQ0->5 are handled in setup-sh3.c */
- INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
- INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
+ INTC_VECT(DMAC, 0x800), INTC_VECT(DMAC, 0x820),
+ INTC_VECT(DMAC, 0x840), INTC_VECT(DMAC, 0x860),
INTC_VECT(ADC_ADI, 0x980),
- INTC_VECT(SCIF2_ERI, 0x900), INTC_VECT(SCIF2_RXI, 0x920),
- INTC_VECT(SCIF2_BRI, 0x940), INTC_VECT(SCIF2_TXI, 0x960),
+ INTC_VECT(SCIF2, 0x900), INTC_VECT(SCIF2, 0x920),
+ INTC_VECT(SCIF2, 0x940), INTC_VECT(SCIF2, 0x960),
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
defined(CONFIG_CPU_SUBTYPE_SH7709)
INTC_VECT(PINT07, 0x700), INTC_VECT(PINT815, 0x720),
- INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
- INTC_VECT(SCIF0_BRI, 0x8c0), INTC_VECT(SCIF0_TXI, 0x8e0),
+ INTC_VECT(SCIF0, 0x880), INTC_VECT(SCIF0, 0x8a0),
+ INTC_VECT(SCIF0, 0x8c0), INTC_VECT(SCIF0, 0x8e0),
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707)
INTC_VECT(LCDC, 0x9a0),
@@ -71,16 +66,6 @@ static struct intc_vect vectors[] __initdata = {
#endif
};
-static struct intc_group groups[] __initdata = {
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
- INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
- INTC_GROUP(REF, REF_RCMI, REF_ROVI),
- INTC_GROUP(DMAC, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
- INTC_GROUP(SCI, SCI_ERI, SCI_RXI, SCI_TXI, SCI_TEI),
- INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
- INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
-};
-
static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
{ 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF, SCI, 0 } },
@@ -101,7 +86,7 @@ static struct intc_prio_reg prio_registers[] __initdata = {
#endif
};
-static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh770x", vectors, NULL,
NULL, prio_registers, NULL);
static struct resource rtc_resources[] = {
@@ -111,15 +96,7 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- .start = 21,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -131,47 +108,115 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xfffffe80,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
- .irqs = { 23, 24, 25, 0 },
+static struct plat_sci_port scif0_platform_data = {
+ .port_reg = 0xa4000136,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE,
+ .type = PORT_SCI,
+ .ops = &sh770x_sci_port_ops,
+ .regshift = 1,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xfffffe80, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x4e0)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
},
+};
#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
defined(CONFIG_CPU_SUBTYPE_SH7707) || \
defined(CONFIG_CPU_SUBTYPE_SH7709)
- {
- .mapbase = 0xa4000150,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 56, 57, 59, 58 },
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE,
+ .type = PORT_SCIF,
+ .ops = &sh770x_sci_port_ops,
+ .regtype = SCIx_SH3_SCIF_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xa4000150, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
},
+};
#endif
#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
defined(CONFIG_CPU_SUBTYPE_SH7709)
- {
- .mapbase = 0xa4000140,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_IRDA,
- .irqs = { 52, 53, 55, 54 },
- },
-#endif
- {
- .flags = 0,
- }
+static struct plat_sci_port scif2_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE,
+ .type = PORT_IRDA,
+ .ops = &sh770x_sci_port_ops,
+ .regshift = 1,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xa4000140, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
};
-static struct platform_device sci_device = {
+static struct platform_device scif2_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif2_platform_data,
},
};
+#endif
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xfffffe90, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu-sh3",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
static struct platform_device *sh770x_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ &scif1_device,
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ &scif2_device,
+#endif
+ &tmu0_device,
&rtc_device,
};
@@ -180,7 +225,27 @@ static int __init sh770x_devices_setup(void)
return platform_add_devices(sh770x_devices,
ARRAY_SIZE(sh770x_devices));
}
-__initcall(sh770x_devices_setup);
+arch_initcall(sh770x_devices_setup);
+
+static struct platform_device *sh770x_early_devices[] __initdata = {
+ &scif0_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ &scif1_device,
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ &scif2_device,
+#endif
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh770x_early_devices,
+ ARRAY_SIZE(sh770x_early_devices));
+}
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 77eee481de4..e9ed300dba5 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
@@ -1,7 +1,7 @@
/*
* SH3 Setup code for SH7710, SH7712
*
- * Copyright (C) 2006, 2007 Paul Mundt
+ * Copyright (C) 2006 - 2009 Paul Mundt
* Copyright (C) 2007 Nobuhiro Iwamatsu
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -13,6 +13,8 @@
#include <linux/irq.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/rtc.h>
enum {
@@ -20,59 +22,40 @@ enum {
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
- DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3,
- SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
- SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
- DMAC_DEI4, DMAC_DEI5,
- IPSEC,
+ DMAC1, SCIF0, SCIF1, DMAC2, IPSEC,
EDMAC0, EDMAC1, EDMAC2,
- SIOF0_ERI, SIOF0_TXI, SIOF0_RXI, SIOF0_CCI,
- SIOF1_ERI, SIOF1_TXI, SIOF1_RXI, SIOF1_CCI,
- TMU0, TMU1, TMU2,
- RTC_ATI, RTC_PRI, RTC_CUI,
- WDT,
- REF,
+ SIOF0, SIOF1,
- /* interrupt groups */
- RTC, DMAC1, SCIF0, SCIF1, DMAC2, SIOF0, SIOF1,
+ TMU0, TMU1, TMU2,
+ RTC, WDT, REF,
};
static struct intc_vect vectors[] __initdata = {
/* IRQ0->5 are handled in setup-sh3.c */
- INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
- INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
- INTC_VECT(SCIF0_ERI, 0x880), INTC_VECT(SCIF0_RXI, 0x8a0),
- INTC_VECT(SCIF0_BRI, 0x8c0), INTC_VECT(SCIF0_TXI, 0x8e0),
- INTC_VECT(SCIF1_ERI, 0x900), INTC_VECT(SCIF1_RXI, 0x920),
- INTC_VECT(SCIF1_BRI, 0x940), INTC_VECT(SCIF1_TXI, 0x960),
- INTC_VECT(DMAC_DEI4, 0xb80), INTC_VECT(DMAC_DEI5, 0xba0),
+ INTC_VECT(DMAC1, 0x800), INTC_VECT(DMAC1, 0x820),
+ INTC_VECT(DMAC1, 0x840), INTC_VECT(DMAC1, 0x860),
+ INTC_VECT(SCIF0, 0x880), INTC_VECT(SCIF0, 0x8a0),
+ INTC_VECT(SCIF0, 0x8c0), INTC_VECT(SCIF0, 0x8e0),
+ INTC_VECT(SCIF1, 0x900), INTC_VECT(SCIF1, 0x920),
+ INTC_VECT(SCIF1, 0x940), INTC_VECT(SCIF1, 0x960),
+ INTC_VECT(DMAC2, 0xb80), INTC_VECT(DMAC2, 0xba0),
#ifdef CONFIG_CPU_SUBTYPE_SH7710
INTC_VECT(IPSEC, 0xbe0),
#endif
INTC_VECT(EDMAC0, 0xc00), INTC_VECT(EDMAC1, 0xc20),
INTC_VECT(EDMAC2, 0xc40),
- INTC_VECT(SIOF0_ERI, 0xe00), INTC_VECT(SIOF0_TXI, 0xe20),
- INTC_VECT(SIOF0_RXI, 0xe40), INTC_VECT(SIOF0_CCI, 0xe60),
- INTC_VECT(SIOF1_ERI, 0xe80), INTC_VECT(SIOF1_TXI, 0xea0),
- INTC_VECT(SIOF1_RXI, 0xec0), INTC_VECT(SIOF1_CCI, 0xee0),
+ INTC_VECT(SIOF0, 0xe00), INTC_VECT(SIOF0, 0xe20),
+ INTC_VECT(SIOF0, 0xe40), INTC_VECT(SIOF0, 0xe60),
+ INTC_VECT(SIOF1, 0xe80), INTC_VECT(SIOF1, 0xea0),
+ INTC_VECT(SIOF1, 0xec0), INTC_VECT(SIOF1, 0xee0),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
INTC_VECT(TMU2, 0x440),
- INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
- INTC_VECT(RTC_CUI, 0x4c0),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
INTC_VECT(WDT, 0x560),
INTC_VECT(REF, 0x580),
};
-static struct intc_group groups[] __initdata = {
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
- INTC_GROUP(DMAC1, DMAC_DEI0, DMAC_DEI1, DMAC_DEI2, DMAC_DEI3),
- INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
- INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
- INTC_GROUP(DMAC2, DMAC_DEI4, DMAC_DEI5),
- INTC_GROUP(SIOF0, SIOF0_ERI, SIOF0_TXI, SIOF0_RXI, SIOF0_CCI),
- INTC_GROUP(SIOF1, SIOF1_ERI, SIOF1_TXI, SIOF1_RXI, SIOF1_CCI),
-};
-
static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xfffffee2, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
{ 0xfffffee4, 0, 16, 4, /* IPRB */ { WDT, REF, 0, 0 } },
@@ -85,7 +68,7 @@ static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xa4080006, 0, 16, 4, /* IPRI */ { 0, 0, SIOF1 } },
};
-static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, NULL,
NULL, prio_registers, NULL);
static struct resource rtc_resources[] = {
@@ -95,17 +78,9 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- .start = 20,
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
- [2] = {
- .start = 21,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
};
static struct sh_rtc_platform_info rtc_info = {
@@ -122,33 +97,75 @@ static struct platform_device rtc_device = {
},
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xa4400000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 52, 53, 55, 54 },
- }, {
- .mapbase = 0xa4410000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 56, 57, 59, 58 },
- }, {
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE | SCSCR_REIE |
+ SCSCR_CKE1 | SCSCR_CKE0,
+ .type = PORT_SCIF,
+};
- .flags = 0,
- }
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xa4400000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
};
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE | SCSCR_REIE |
+ SCSCR_CKE1 | SCSCR_CKE0,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xa4410000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif1_platform_data,
},
};
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xa412fe90, 0x28),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu-sh3",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
static struct platform_device *sh7710_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &tmu0_device,
&rtc_device,
};
@@ -157,7 +174,19 @@ static int __init sh7710_devices_setup(void)
return platform_add_devices(sh7710_devices,
ARRAY_SIZE(sh7710_devices));
}
-__initcall(sh7710_devices_setup);
+arch_initcall(sh7710_devices_setup);
+
+static struct platform_device *sh7710_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7710_early_devices,
+ ARRAY_SIZE(sh7710_early_devices));
+}
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index f807a21b066..84df85a5b80 100644
--- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c
+++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
@@ -1,7 +1,8 @@
/*
- * SH7720 Setup
+ * Setup code for SH7720, SH7721.
*
* Copyright (C) 2007 Markus Brunner, Mark Jonas
+ * Copyright (C) 2009 Paul Mundt
*
* Based on arch/sh/kernel/cpu/sh4/setup-sh7750.c:
*
@@ -17,7 +18,11 @@
#include <linux/serial.h>
#include <linux/io.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
#include <asm/rtc.h>
+#include <cpu/serial.h>
static struct resource rtc_resources[] = {
[0] = {
@@ -26,18 +31,8 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- /* Period IRQ */
- .start = 21,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- /* Carry IRQ */
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- /* Alarm IRQ */
- .start = 20,
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -56,28 +51,49 @@ static struct platform_device rtc_device = {
},
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xa4430000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
- }, {
- .mapbase = 0xa4438000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
- }, {
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE,
+ .type = PORT_SCIF,
+ .ops = &sh7720_sci_port_ops,
+ .regtype = SCIx_SH7705_SCIF_REGTYPE,
+};
- .flags = 0,
- }
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xa4430000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
};
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE,
+ .type = PORT_SCIF,
+ .ops = &sh7720_sci_port_ops,
+ .regtype = SCIx_SH7705_SCIF_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xa4438000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc20)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif1_platform_data,
},
};
@@ -88,19 +104,23 @@ static struct resource usb_ohci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 67,
- .end = 67,
+ .start = evt2irq(0xa60),
+ .end = evt2irq(0xa60),
.flags = IORESOURCE_IRQ,
},
};
static u64 usb_ohci_dma_mask = 0xffffffffUL;
+
+static struct usb_ohci_pdata usb_ohci_pdata;
+
static struct platform_device usb_ohci_device = {
- .name = "sh_ohci",
+ .name = "ohci-platform",
.id = -1,
.dev = {
.dma_mask = &usb_ohci_dma_mask,
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &usb_ohci_pdata,
},
.num_resources = ARRAY_SIZE(usb_ohci_resources),
.resource = usb_ohci_resources,
@@ -115,8 +135,8 @@ static struct resource usbf_resources[] = {
},
[1] = {
.name = "sh_udc",
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ,
},
};
@@ -132,9 +152,52 @@ static struct platform_device usbf_device = {
.resource = usbf_resources,
};
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 0x1f,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0x044a0000, 0x60),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-32",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xa412fe90, 0x28),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+static struct platform_device tmu0_device = {
+ .name = "sh-tmu-sh3",
+ .id = 0,
+ .dev = {
+ .platform_data = &tmu0_platform_data,
+ },
+ .resource = tmu0_resources,
+ .num_resources = ARRAY_SIZE(tmu0_resources),
+};
+
static struct platform_device *sh7720_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &cmt_device,
+ &tmu0_device,
&rtc_device,
- &sci_device,
&usb_ohci_device,
&usbf_device,
};
@@ -144,68 +207,68 @@ static int __init sh7720_devices_setup(void)
return platform_add_devices(sh7720_devices,
ARRAY_SIZE(sh7720_devices));
}
-__initcall(sh7720_devices_setup);
+arch_initcall(sh7720_devices_setup);
+
+static struct platform_device *sh7720_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &cmt_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7720_early_devices,
+ ARRAY_SIZE(sh7720_early_devices));
+}
enum {
UNUSED = 0,
/* interrupt sources */
- TMU0, TMU1, TMU2, RTC_ATI, RTC_PRI, RTC_CUI,
- WDT, REF_RCMI, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND,
+ TMU0, TMU1, TMU2, RTC,
+ WDT, REF_RCMI, SIM,
IRQ0, IRQ1, IRQ2, IRQ3,
USBF_SPD, TMU_SUNI, IRQ5, IRQ4,
- DMAC1_DEI0, DMAC1_DEI1, DMAC1_DEI2, DMAC1_DEI3, LCDC, SSL,
- ADC, DMAC2_DEI4, DMAC2_DEI5, USBFI0, USBFI1, CMT,
+ DMAC1, LCDC, SSL,
+ ADC, DMAC2, USBFI, CMT,
SCIF0, SCIF1,
- PINT07, PINT815, TPU0, TPU1, TPU2, TPU3, IIC,
- SIOF0, SIOF1, MMCI0, MMCI1, MMCI2, MMCI3, PCC,
+ PINT07, PINT815, TPU, IIC,
+ SIOF0, SIOF1, MMC, PCC,
USBHI, AFEIF,
H_UDI,
- /* interrupt groups */
- TMU, RTC, SIM, DMAC1, USBFI, DMAC2, USB, TPU, MMC,
};
static struct intc_vect vectors[] __initdata = {
/* IRQ0->5 are handled in setup-sh3.c */
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2, 0x440), INTC_VECT(RTC_ATI, 0x480),
- INTC_VECT(RTC_PRI, 0x4a0), INTC_VECT(RTC_CUI, 0x4c0),
- INTC_VECT(SIM_ERI, 0x4e0), INTC_VECT(SIM_RXI, 0x500),
- INTC_VECT(SIM_TXI, 0x520), INTC_VECT(SIM_TEND, 0x540),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(RTC, 0x480),
+ INTC_VECT(RTC, 0x4a0), INTC_VECT(RTC, 0x4c0),
+ INTC_VECT(SIM, 0x4e0), INTC_VECT(SIM, 0x500),
+ INTC_VECT(SIM, 0x520), INTC_VECT(SIM, 0x540),
INTC_VECT(WDT, 0x560), INTC_VECT(REF_RCMI, 0x580),
/* H_UDI cannot be masked */ INTC_VECT(TMU_SUNI, 0x6c0),
- INTC_VECT(USBF_SPD, 0x6e0), INTC_VECT(DMAC1_DEI0, 0x800),
- INTC_VECT(DMAC1_DEI1, 0x820), INTC_VECT(DMAC1_DEI2, 0x840),
- INTC_VECT(DMAC1_DEI3, 0x860), INTC_VECT(LCDC, 0x900),
+ INTC_VECT(USBF_SPD, 0x6e0), INTC_VECT(DMAC1, 0x800),
+ INTC_VECT(DMAC1, 0x820), INTC_VECT(DMAC1, 0x840),
+ INTC_VECT(DMAC1, 0x860), INTC_VECT(LCDC, 0x900),
#if defined(CONFIG_CPU_SUBTYPE_SH7720)
INTC_VECT(SSL, 0x980),
#endif
- INTC_VECT(USBFI0, 0xa20), INTC_VECT(USBFI1, 0xa40),
+ INTC_VECT(USBFI, 0xa20), INTC_VECT(USBFI, 0xa40),
INTC_VECT(USBHI, 0xa60),
- INTC_VECT(DMAC2_DEI4, 0xb80), INTC_VECT(DMAC2_DEI5, 0xba0),
+ INTC_VECT(DMAC2, 0xb80), INTC_VECT(DMAC2, 0xba0),
INTC_VECT(ADC, 0xbe0), INTC_VECT(SCIF0, 0xc00),
INTC_VECT(SCIF1, 0xc20), INTC_VECT(PINT07, 0xc80),
INTC_VECT(PINT815, 0xca0), INTC_VECT(SIOF0, 0xd00),
- INTC_VECT(SIOF1, 0xd20), INTC_VECT(TPU0, 0xd80),
- INTC_VECT(TPU1, 0xda0), INTC_VECT(TPU2, 0xdc0),
- INTC_VECT(TPU3, 0xde0), INTC_VECT(IIC, 0xe00),
- INTC_VECT(MMCI0, 0xe80), INTC_VECT(MMCI1, 0xea0),
- INTC_VECT(MMCI2, 0xec0), INTC_VECT(MMCI3, 0xee0),
+ INTC_VECT(SIOF1, 0xd20), INTC_VECT(TPU, 0xd80),
+ INTC_VECT(TPU, 0xda0), INTC_VECT(TPU, 0xdc0),
+ INTC_VECT(TPU, 0xde0), INTC_VECT(IIC, 0xe00),
+ INTC_VECT(MMC, 0xe80), INTC_VECT(MMC, 0xea0),
+ INTC_VECT(MMC, 0xec0), INTC_VECT(MMC, 0xee0),
INTC_VECT(CMT, 0xf00), INTC_VECT(PCC, 0xf60),
INTC_VECT(AFEIF, 0xfe0),
};
-static struct intc_group groups[] __initdata = {
- INTC_GROUP(TMU, TMU0, TMU1, TMU2),
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
- INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND),
- INTC_GROUP(DMAC1, DMAC1_DEI0, DMAC1_DEI1, DMAC1_DEI2, DMAC1_DEI3),
- INTC_GROUP(USBFI, USBFI0, USBFI1),
- INTC_GROUP(DMAC2, DMAC2_DEI4, DMAC2_DEI5),
- INTC_GROUP(TPU, TPU0, TPU1, TPU2, TPU3),
- INTC_GROUP(MMC, MMCI0, MMCI1, MMCI2, MMCI3),
-};
-
static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xA414FEE2UL, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } },
{ 0xA414FEE4UL, 0, 16, 4, /* IPRB */ { WDT, REF_RCMI, SIM, 0 } },
@@ -219,7 +282,7 @@ static struct intc_prio_reg prio_registers[] __initdata = {
{ 0xA4080008UL, 0, 16, 4, /* IPRJ */ { 0, USBHI, 0, AFEIF } },
};
-static DECLARE_INTC_DESC(intc_desc, "sh7720", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7720", vectors, NULL,
NULL, prio_registers, NULL);
void __init plat_irq_setup(void)
diff --git a/arch/sh/kernel/cpu/sh3/swsusp.S b/arch/sh/kernel/cpu/sh3/swsusp.S
new file mode 100644
index 00000000000..01145426a2b
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/swsusp.S
@@ -0,0 +1,147 @@
+/*
+ * arch/sh/kernel/cpu/sh3/swsusp.S
+ *
+ * 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
+ * for more details.
+ */
+#include <linux/sys.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/page.h>
+
+#define k0 r0
+#define k1 r1
+#define k2 r2
+#define k3 r3
+#define k4 r4
+
+! swsusp_arch_resume()
+! - copy restore_pblist pages
+! - restore registers from swsusp_arch_regs_cpu0
+
+ENTRY(swsusp_arch_resume)
+ mov.l 1f, r15
+ mov.l 2f, r4
+ mov.l @r4, r4
+
+swsusp_copy_loop:
+ mov r4, r0
+ cmp/eq #0, r0
+ bt swsusp_restore_regs
+
+ mov.l @(PBE_ADDRESS, r4), r2
+ mov.l @(PBE_ORIG_ADDRESS, r4), r5
+
+ mov #(PAGE_SIZE >> 10), r3
+ shll8 r3
+ shlr2 r3 /* PAGE_SIZE / 16 */
+swsusp_copy_page:
+ dt r3
+ mov.l @r2+,r1 /* 16n+0 */
+ mov.l r1,@r5
+ add #4,r5
+ mov.l @r2+,r1 /* 16n+4 */
+ mov.l r1,@r5
+ add #4,r5
+ mov.l @r2+,r1 /* 16n+8 */
+ mov.l r1,@r5
+ add #4,r5
+ mov.l @r2+,r1 /* 16n+12 */
+ mov.l r1,@r5
+ bf/s swsusp_copy_page
+ add #4,r5
+
+ bra swsusp_copy_loop
+ mov.l @(PBE_NEXT, r4), r4
+
+swsusp_restore_regs:
+ ! BL=0: R7->R0 is bank0
+ mov.l 3f, r8
+ mov.l 4f, r5
+ jsr @r5
+ nop
+
+ ! BL=1: R7->R0 is bank1
+ lds k2, pr
+ ldc k3, ssr
+
+ mov.l @r15+, r0
+ mov.l @r15+, r1
+ mov.l @r15+, r2
+ mov.l @r15+, r3
+ mov.l @r15+, r4
+ mov.l @r15+, r5
+ mov.l @r15+, r6
+ mov.l @r15+, r7
+
+ rte
+ nop
+ ! BL=0: R7->R0 is bank0
+
+ .align 2
+1: .long swsusp_arch_regs_cpu0
+2: .long restore_pblist
+3: .long 0x20000000 ! RB=1
+4: .long restore_regs
+
+! swsusp_arch_suspend()
+! - prepare pc for resume, return from function without swsusp_save on resume
+! - save registers in swsusp_arch_regs_cpu0
+! - call swsusp_save write suspend image
+
+ENTRY(swsusp_arch_suspend)
+ sts pr, r0 ! save pr in r0
+ mov r15, r2 ! save sp in r2
+ mov r8, r5 ! save r8 in r5
+ stc sr, r1
+ ldc r1, ssr ! save sr in ssr
+ mov.l 1f, r1
+ ldc r1, spc ! setup pc value for resuming
+ mov.l 5f, r15 ! use swsusp_arch_regs_cpu0 as stack
+ mov.l 6f, r3
+ add r3, r15 ! save from top of structure
+
+ ! BL=0: R7->R0 is bank0
+ mov.l 2f, r3 ! get new SR value for bank1
+ mov #0, r4
+ mov.l 7f, r1
+ jsr @r1 ! switch to bank1 and save bank1 r7->r0
+ not r4, r4
+
+ ! BL=1: R7->R0 is bank1
+ stc r2_bank, k0 ! fetch old sp from r2_bank0
+ mov.l 3f, k4 ! SR bits to clear in k4
+ mov.l 8f, k1
+ jsr @k1 ! switch to bank0 and save all regs
+ stc r0_bank, k3 ! fetch old pr from r0_bank0
+
+ ! BL=0: R7->R0 is bank0
+ mov r2, r15 ! restore old sp
+ mov r5, r8 ! restore old r8
+ stc ssr, r1
+ ldc r1, sr ! restore old sr
+ lds r0, pr ! restore old pr
+ mov.l 4f, r0
+ jmp @r0
+ nop
+
+swsusp_call_save:
+ mov r2, r15 ! restore old sp
+ mov r5, r8 ! restore old r8
+ lds r0, pr ! restore old pr
+ rts
+ mov #0, r0
+
+ .align 2
+1: .long swsusp_call_save
+2: .long 0x20000000 ! RB=1
+3: .long 0xdfffffff ! RB=0
+4: .long swsusp_save
+5: .long swsusp_arch_regs_cpu0
+6: .long SWSUSP_ARCH_REGS_SIZE
+7: .long save_low_regs
+8: .long save_regs
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index d608557c7a3..3a1dbc70983 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -5,9 +5,15 @@
obj-y := probe.o common.o
common-y += $(addprefix ../sh3/, entry.o ex.o)
+obj-$(CONFIG_HIBERNATION) += $(addprefix ../sh3/, swsusp.o)
obj-$(CONFIG_SH_FPU) += fpu.o softfloat.o
obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
+# Perf events
+perf-$(CONFIG_CPU_SUBTYPE_SH7750) := perf_event.o
+perf-$(CONFIG_CPU_SUBTYPE_SH7750S) := perf_event.o
+perf-$(CONFIG_CPU_SUBTYPE_SH7091) := perf_event.o
+
# CPU subtype setup
obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o
@@ -26,4 +32,5 @@ endif
# Additional clocks by subtype
clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o
-obj-y += $(clock-y)
+obj-y += $(clock-y)
+obj-$(CONFIG_PERF_EVENTS) += $(perf-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index a33429463e9..4b5bab5f875 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -12,19 +12,20 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
#include <asm/clock.h>
#include <asm/freq.h>
-#include <asm/io.h>
#define CPG2_FRQCR3 0xfe0a0018
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];
+ int idx = __raw_readl(CPG2_FRQCR3) & 0x0007;
+ return clk->parent->rate / frqcr3_divisors[idx];
}
static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
@@ -40,29 +41,27 @@ static inline int frqcr3_lookup(struct clk *clk, unsigned long rate)
return 5;
}
-static struct clk_ops sh4202_emi_clk_ops = {
+static struct sh_clk_ops sh4202_emi_clk_ops = {
.recalc = emi_clk_recalc,
};
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];
+ int idx = (__raw_readl(CPG2_FRQCR3) >> 3) & 0x0007;
+ return clk->parent->rate / frqcr3_divisors[idx];
}
-static struct clk_ops sh4202_femi_clk_ops = {
+static struct sh_clk_ops sh4202_femi_clk_ops = {
.recalc = femi_clk_recalc,
};
static struct clk sh4202_femi_clk = {
- .name = "femi_clk",
- .flags = CLK_ALWAYS_ENABLED,
+ .flags = CLK_ENABLE_ON_INIT,
.ops = &sh4202_femi_clk_ops,
};
@@ -82,18 +81,17 @@ static void shoc_clk_init(struct clk *clk)
for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
int divisor = frqcr3_divisors[i];
- if (clk->ops->set_rate(clk, clk->parent->rate /
- divisor, 0) == 0)
+ if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
break;
}
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];
+ int idx = (__raw_readl(CPG2_FRQCR3) >> 6) & 0x0007;
+ return clk->parent->rate / frqcr3_divisors[idx];
}
static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
@@ -111,7 +109,7 @@ static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
return 0;
}
-static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+static int shoc_clk_set_rate(struct clk *clk, unsigned long rate)
{
unsigned long frqcr3;
unsigned int tmp;
@@ -122,25 +120,24 @@ static int shoc_clk_set_rate(struct clk *clk, unsigned long rate, int algo_id)
tmp = frqcr3_lookup(clk, rate);
- frqcr3 = ctrl_inl(CPG2_FRQCR3);
+ frqcr3 = __raw_readl(CPG2_FRQCR3);
frqcr3 &= ~(0x0007 << 6);
frqcr3 |= tmp << 6;
- ctrl_outl(frqcr3, CPG2_FRQCR3);
+ __raw_writel(frqcr3, CPG2_FRQCR3);
clk->rate = clk->parent->rate / frqcr3_divisors[tmp];
return 0;
}
-static struct clk_ops sh4202_shoc_clk_ops = {
+static struct sh_clk_ops sh4202_shoc_clk_ops = {
.init = shoc_clk_init,
.recalc = shoc_clk_recalc,
.set_rate = shoc_clk_set_rate,
};
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 +147,31 @@ static struct clk *sh4202_onchip_clocks[] = {
&sh4202_shoc_clk,
};
-static int __init sh4202_clk_init(void)
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("emi_clk", &sh4202_emi_clk),
+ CLKDEV_CON_ID("femi_clk", &sh4202_femi_clk),
+ CLKDEV_CON_ID("shoc_clk", &sh4202_shoc_clk),
+};
+
+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;
-}
-
-arch_initcall(sh4202_clk_init);
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c
index dca9f87a12d..99e5ec8b483 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c
@@ -28,51 +28,51 @@ static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
static void master_clk_init(struct clk *clk)
{
- clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007];
+ clk->rate *= pfc_divisors[__raw_readw(FRQCR) & 0x0007];
}
-static struct clk_ops sh4_master_clk_ops = {
+static struct sh_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];
+ int idx = (__raw_readw(FRQCR) & 0x0007);
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh4_module_clk_ops = {
+static struct sh_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];
+ int idx = (__raw_readw(FRQCR) >> 3) & 0x0007;
+ return clk->parent->rate / bfc_divisors[idx];
}
-static struct clk_ops sh4_bus_clk_ops = {
+static struct sh_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];
+ int idx = (__raw_readw(FRQCR) >> 6) & 0x0007;
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh4_cpu_clk_ops = {
+static struct sh_clk_ops sh4_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh4_clk_ops[] = {
+static struct sh_clk_ops *sh4_clk_ops[] = {
&sh4_master_clk_ops,
&sh4_module_clk_ops,
&sh4_bus_clk_ops,
&sh4_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh4_clk_ops))
*ops = sh4_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index 2d452f67fb8..69ab4d3c8d4 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -15,8 +15,8 @@
#include <linux/io.h>
#include <cpu/fpu.h>
#include <asm/processor.h>
-#include <asm/system.h>
#include <asm/fpu.h>
+#include <asm/traps.h>
/* The PR (precision) bit in the FP Status Register must be clear when
* an frchg instruction is executed, otherwise the instruction is undefined.
@@ -36,18 +36,16 @@ extern unsigned long int float32_add(unsigned long int a, unsigned long int b);
extern unsigned long long float64_sub(unsigned long long a,
unsigned long long b);
extern unsigned long int float32_sub(unsigned long int a, unsigned long int b);
-
+extern unsigned long int float64_to_float32(unsigned long long a);
static unsigned int fpu_exception_flags;
/*
* Save FPU registers onto task structure.
- * Assume called with FPU enabled (SR.FD=0).
*/
-void save_fpu(struct task_struct *tsk, struct pt_regs *regs)
+void save_fpu(struct task_struct *tsk)
{
unsigned long dummy;
- clear_tsk_thread_flag(tsk, TIF_USEDFPU);
enable_fpu();
asm volatile ("sts.l fpul, @-%0\n\t"
"sts.l fpscr, @-%0\n\t"
@@ -87,15 +85,14 @@ void save_fpu(struct task_struct *tsk, struct pt_regs *regs)
"fmov.s fr1, @-%0\n\t"
"fmov.s fr0, @-%0\n\t"
"lds %3, fpscr\n\t":"=r" (dummy)
- :"0"((char *)(&tsk->thread.fpu.hard.status)),
+ :"0"((char *)(&tsk->thread.xstate->hardfpu.status)),
"r"(FPSCR_RCHG), "r"(FPSCR_INIT)
:"memory");
disable_fpu();
- release_fpu(regs);
}
-static void restore_fpu(struct task_struct *tsk)
+void restore_fpu(struct task_struct *tsk)
{
unsigned long dummy;
@@ -138,62 +135,11 @@ static void restore_fpu(struct task_struct *tsk)
"lds.l @%0+, fpscr\n\t"
"lds.l @%0+, fpul\n\t"
:"=r" (dummy)
- :"0"(&tsk->thread.fpu), "r"(FPSCR_RCHG)
+ :"0" (tsk->thread.xstate), "r" (FPSCR_RCHG)
:"memory");
disable_fpu();
}
-/*
- * Load the FPU with signalling NANS. This bit pattern we're using
- * has the property that no matter wether considered as single or as
- * double precision represents signaling NANS.
- */
-
-static void fpu_init(void)
-{
- enable_fpu();
- asm volatile ( "lds %0, fpul\n\t"
- "lds %1, fpscr\n\t"
- "fsts fpul, fr0\n\t"
- "fsts fpul, fr1\n\t"
- "fsts fpul, fr2\n\t"
- "fsts fpul, fr3\n\t"
- "fsts fpul, fr4\n\t"
- "fsts fpul, fr5\n\t"
- "fsts fpul, fr6\n\t"
- "fsts fpul, fr7\n\t"
- "fsts fpul, fr8\n\t"
- "fsts fpul, fr9\n\t"
- "fsts fpul, fr10\n\t"
- "fsts fpul, fr11\n\t"
- "fsts fpul, fr12\n\t"
- "fsts fpul, fr13\n\t"
- "fsts fpul, fr14\n\t"
- "fsts fpul, fr15\n\t"
- "frchg\n\t"
- "fsts fpul, fr0\n\t"
- "fsts fpul, fr1\n\t"
- "fsts fpul, fr2\n\t"
- "fsts fpul, fr3\n\t"
- "fsts fpul, fr4\n\t"
- "fsts fpul, fr5\n\t"
- "fsts fpul, fr6\n\t"
- "fsts fpul, fr7\n\t"
- "fsts fpul, fr8\n\t"
- "fsts fpul, fr9\n\t"
- "fsts fpul, fr10\n\t"
- "fsts fpul, fr11\n\t"
- "fsts fpul, fr12\n\t"
- "fsts fpul, fr13\n\t"
- "fsts fpul, fr14\n\t"
- "fsts fpul, fr15\n\t"
- "frchg\n\t"
- "lds %2, fpscr\n\t"
- : /* no output */
- :"r" (0), "r"(FPSCR_RCHG), "r"(FPSCR_INIT));
- disable_fpu();
-}
-
/**
* denormal_to_double - Given denormalized float number,
* store double float
@@ -285,10 +231,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
/* fcnvsd */
struct task_struct *tsk = current;
- save_fpu(tsk, regs);
- if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR))
+ if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR))
/* FPU error */
- denormal_to_double(&tsk->thread.fpu.hard,
+ denormal_to_double(&tsk->thread.xstate->hardfpu,
(finsn >> 8) & 0xf);
else
return 0;
@@ -304,9 +249,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
n = (finsn >> 8) & 0xf;
m = (finsn >> 4) & 0xf;
- hx = tsk->thread.fpu.hard.fp_regs[n];
- hy = tsk->thread.fpu.hard.fp_regs[m];
- fpscr = tsk->thread.fpu.hard.fpscr;
+ hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+ hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+ fpscr = tsk->thread.xstate->hardfpu.fpscr;
prec = fpscr & FPSCR_DBL_PRECISION;
if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -316,18 +261,18 @@ static int ieee_fpe_handler(struct pt_regs *regs)
/* FPU error because of denormal (doubles) */
llx = ((long long)hx << 32)
- | tsk->thread.fpu.hard.fp_regs[n + 1];
+ | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
lly = ((long long)hy << 32)
- | tsk->thread.fpu.hard.fp_regs[m + 1];
+ | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
llx = float64_mul(llx, lly);
- tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
- tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+ tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
} else if ((fpscr & FPSCR_CAUSE_ERROR)
&& (!prec && ((hx & 0x7fffffff) < 0x00800000
|| (hy & 0x7fffffff) < 0x00800000))) {
/* FPU error because of denormal (floats) */
hx = float32_mul(hx, hy);
- tsk->thread.fpu.hard.fp_regs[n] = hx;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
} else
return 0;
@@ -342,9 +287,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
n = (finsn >> 8) & 0xf;
m = (finsn >> 4) & 0xf;
- hx = tsk->thread.fpu.hard.fp_regs[n];
- hy = tsk->thread.fpu.hard.fp_regs[m];
- fpscr = tsk->thread.fpu.hard.fpscr;
+ hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+ hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+ fpscr = tsk->thread.xstate->hardfpu.fpscr;
prec = fpscr & FPSCR_DBL_PRECISION;
if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -354,15 +299,15 @@ static int ieee_fpe_handler(struct pt_regs *regs)
/* FPU error because of denormal (doubles) */
llx = ((long long)hx << 32)
- | tsk->thread.fpu.hard.fp_regs[n + 1];
+ | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
lly = ((long long)hy << 32)
- | tsk->thread.fpu.hard.fp_regs[m + 1];
+ | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
if ((finsn & 0xf00f) == 0xf000)
llx = float64_add(llx, lly);
else
llx = float64_sub(llx, lly);
- tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
- tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+ tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
} else if ((fpscr & FPSCR_CAUSE_ERROR)
&& (!prec && ((hx & 0x7fffffff) < 0x00800000
|| (hy & 0x7fffffff) < 0x00800000))) {
@@ -371,7 +316,7 @@ static int ieee_fpe_handler(struct pt_regs *regs)
hx = float32_add(hx, hy);
else
hx = float32_sub(hx, hy);
- tsk->thread.fpu.hard.fp_regs[n] = hx;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
} else
return 0;
@@ -386,9 +331,9 @@ static int ieee_fpe_handler(struct pt_regs *regs)
n = (finsn >> 8) & 0xf;
m = (finsn >> 4) & 0xf;
- hx = tsk->thread.fpu.hard.fp_regs[n];
- hy = tsk->thread.fpu.hard.fp_regs[m];
- fpscr = tsk->thread.fpu.hard.fpscr;
+ hx = tsk->thread.xstate->hardfpu.fp_regs[n];
+ hy = tsk->thread.xstate->hardfpu.fp_regs[m];
+ fpscr = tsk->thread.xstate->hardfpu.fpscr;
prec = fpscr & FPSCR_DBL_PRECISION;
if ((fpscr & FPSCR_CAUSE_ERROR)
@@ -398,20 +343,43 @@ static int ieee_fpe_handler(struct pt_regs *regs)
/* FPU error because of denormal (doubles) */
llx = ((long long)hx << 32)
- | tsk->thread.fpu.hard.fp_regs[n + 1];
+ | tsk->thread.xstate->hardfpu.fp_regs[n + 1];
lly = ((long long)hy << 32)
- | tsk->thread.fpu.hard.fp_regs[m + 1];
+ | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
llx = float64_div(llx, lly);
- tsk->thread.fpu.hard.fp_regs[n] = llx >> 32;
- tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = llx >> 32;
+ tsk->thread.xstate->hardfpu.fp_regs[n + 1] = llx & 0xffffffff;
} else if ((fpscr & FPSCR_CAUSE_ERROR)
&& (!prec && ((hx & 0x7fffffff) < 0x00800000
|| (hy & 0x7fffffff) < 0x00800000))) {
/* FPU error because of denormal (floats) */
hx = float32_div(hx, hy);
- tsk->thread.fpu.hard.fp_regs[n] = hx;
+ tsk->thread.xstate->hardfpu.fp_regs[n] = hx;
+ } else
+ return 0;
+
+ regs->pc = nextpc;
+ return 1;
+ } else if ((finsn & 0xf0bd) == 0xf0bd) {
+ /* fcnvds - double to single precision convert */
+ struct task_struct *tsk = current;
+ int m;
+ unsigned int hx;
+
+ m = (finsn >> 8) & 0x7;
+ hx = tsk->thread.xstate->hardfpu.fp_regs[m];
+
+ if ((tsk->thread.xstate->hardfpu.fpscr & FPSCR_CAUSE_ERROR)
+ && ((hx & 0x7fffffff) < 0x00100000)) {
+ /* subnormal double to float conversion */
+ long long llx;
+
+ llx = ((long long)tsk->thread.xstate->hardfpu.fp_regs[m] << 32)
+ | tsk->thread.xstate->hardfpu.fp_regs[m + 1];
+
+ tsk->thread.xstate->hardfpu.fpul = float64_to_float32(llx);
} else
return 0;
@@ -430,7 +398,7 @@ void float_raise(unsigned int flags)
int float_rounding_mode(void)
{
struct task_struct *tsk = current;
- int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.fpu.hard.fpscr);
+ int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.xstate->hardfpu.fpscr);
return roundingMode;
}
@@ -439,19 +407,19 @@ BUILD_TRAP_HANDLER(fpu_error)
struct task_struct *tsk = current;
TRAP_HANDLER_DECL;
- save_fpu(tsk, regs);
+ __unlazy_fpu(tsk, regs);
fpu_exception_flags = 0;
if (ieee_fpe_handler(regs)) {
- tsk->thread.fpu.hard.fpscr &=
+ tsk->thread.xstate->hardfpu.fpscr &=
~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
- tsk->thread.fpu.hard.fpscr |= fpu_exception_flags;
+ tsk->thread.xstate->hardfpu.fpscr |= fpu_exception_flags;
/* Set the FPSCR flag as well as cause bits - simply
* replicate the cause */
- tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10);
+ tsk->thread.xstate->hardfpu.fpscr |= (fpu_exception_flags >> 10);
grab_fpu(regs);
restore_fpu(tsk);
- set_tsk_thread_flag(tsk, TIF_USEDFPU);
- if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) &
+ task_thread_info(tsk)->status |= TS_USEDFPU;
+ if ((((tsk->thread.xstate->hardfpu.fpscr & FPSCR_ENABLE_MASK) >> 7) &
(fpu_exception_flags >> 2)) == 0) {
return;
}
@@ -459,25 +427,3 @@ BUILD_TRAP_HANDLER(fpu_error)
force_sig(SIGFPE, tsk);
}
-
-BUILD_TRAP_HANDLER(fpu_state_restore)
-{
- struct task_struct *tsk = current;
- TRAP_HANDLER_DECL;
-
- grab_fpu(regs);
- if (!user_mode(regs)) {
- printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
- return;
- }
-
- if (used_math()) {
- /* Using the FPU again. */
- restore_fpu(tsk);
- } else {
- /* First time FPU user. */
- fpu_init();
- set_used_math();
- }
- set_tsk_thread_flag(tsk, TIF_USEDFPU);
-}
diff --git a/arch/sh/kernel/cpu/sh4/perf_event.c b/arch/sh/kernel/cpu/sh4/perf_event.c
new file mode 100644
index 00000000000..fa4f724b295
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4/perf_event.c
@@ -0,0 +1,268 @@
+/*
+ * Performance events support for SH7750-style performance counters
+ *
+ * Copyright (C) 2009 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/perf_event.h>
+#include <asm/processor.h>
+
+#define PM_CR_BASE 0xff000084 /* 16-bit */
+#define PM_CTR_BASE 0xff100004 /* 32-bit */
+
+#define PMCR(n) (PM_CR_BASE + ((n) * 0x04))
+#define PMCTRH(n) (PM_CTR_BASE + 0x00 + ((n) * 0x08))
+#define PMCTRL(n) (PM_CTR_BASE + 0x04 + ((n) * 0x08))
+
+#define PMCR_PMM_MASK 0x0000003f
+
+#define PMCR_CLKF 0x00000100
+#define PMCR_PMCLR 0x00002000
+#define PMCR_PMST 0x00004000
+#define PMCR_PMEN 0x00008000
+
+static struct sh_pmu sh7750_pmu;
+
+/*
+ * There are a number of events supported by each counter (33 in total).
+ * Since we have 2 counters, each counter will take the event code as it
+ * corresponds to the PMCR PMM setting. Each counter can be configured
+ * independently.
+ *
+ * Event Code Description
+ * ---------- -----------
+ *
+ * 0x01 Operand read access
+ * 0x02 Operand write access
+ * 0x03 UTLB miss
+ * 0x04 Operand cache read miss
+ * 0x05 Operand cache write miss
+ * 0x06 Instruction fetch (w/ cache)
+ * 0x07 Instruction TLB miss
+ * 0x08 Instruction cache miss
+ * 0x09 All operand accesses
+ * 0x0a All instruction accesses
+ * 0x0b OC RAM operand access
+ * 0x0d On-chip I/O space access
+ * 0x0e Operand access (r/w)
+ * 0x0f Operand cache miss (r/w)
+ * 0x10 Branch instruction
+ * 0x11 Branch taken
+ * 0x12 BSR/BSRF/JSR
+ * 0x13 Instruction execution
+ * 0x14 Instruction execution in parallel
+ * 0x15 FPU Instruction execution
+ * 0x16 Interrupt
+ * 0x17 NMI
+ * 0x18 trapa instruction execution
+ * 0x19 UBCA match
+ * 0x1a UBCB match
+ * 0x21 Instruction cache fill
+ * 0x22 Operand cache fill
+ * 0x23 Elapsed time
+ * 0x24 Pipeline freeze by I-cache miss
+ * 0x25 Pipeline freeze by D-cache miss
+ * 0x27 Pipeline freeze by branch instruction
+ * 0x28 Pipeline freeze by CPU register
+ * 0x29 Pipeline freeze by FPU
+ */
+
+static const int sh7750_general_events[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = 0x0023,
+ [PERF_COUNT_HW_INSTRUCTIONS] = 0x000a,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0006, /* I-cache */
+ [PERF_COUNT_HW_CACHE_MISSES] = 0x0008, /* I-cache */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0010,
+ [PERF_COUNT_HW_BRANCH_MISSES] = -1,
+ [PERF_COUNT_HW_BUS_CYCLES] = -1,
+};
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+static const int sh7750_cache_events
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0001,
+ [ C(RESULT_MISS) ] = 0x0004,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0002,
+ [ C(RESULT_MISS) ] = 0x0005,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(L1I) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0006,
+ [ C(RESULT_MISS) ] = 0x0008,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(LL) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(DTLB) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0x0003,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(ITLB) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0x0007,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+
+ [ C(BPU) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+};
+
+static int sh7750_event_map(int event)
+{
+ return sh7750_general_events[event];
+}
+
+static u64 sh7750_pmu_read(int idx)
+{
+ return (u64)((u64)(__raw_readl(PMCTRH(idx)) & 0xffff) << 32) |
+ __raw_readl(PMCTRL(idx));
+}
+
+static void sh7750_pmu_disable(struct hw_perf_event *hwc, int idx)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readw(PMCR(idx));
+ tmp &= ~(PMCR_PMM_MASK | PMCR_PMEN);
+ __raw_writew(tmp, PMCR(idx));
+}
+
+static void sh7750_pmu_enable(struct hw_perf_event *hwc, int idx)
+{
+ __raw_writew(__raw_readw(PMCR(idx)) | PMCR_PMCLR, PMCR(idx));
+ __raw_writew(hwc->config | PMCR_PMEN | PMCR_PMST, PMCR(idx));
+}
+
+static void sh7750_pmu_disable_all(void)
+{
+ int i;
+
+ for (i = 0; i < sh7750_pmu.num_events; i++)
+ __raw_writew(__raw_readw(PMCR(i)) & ~PMCR_PMEN, PMCR(i));
+}
+
+static void sh7750_pmu_enable_all(void)
+{
+ int i;
+
+ for (i = 0; i < sh7750_pmu.num_events; i++)
+ __raw_writew(__raw_readw(PMCR(i)) | PMCR_PMEN, PMCR(i));
+}
+
+static struct sh_pmu sh7750_pmu = {
+ .name = "sh7750",
+ .num_events = 2,
+ .event_map = sh7750_event_map,
+ .max_events = ARRAY_SIZE(sh7750_general_events),
+ .raw_event_mask = PMCR_PMM_MASK,
+ .cache_events = &sh7750_cache_events,
+ .read = sh7750_pmu_read,
+ .disable = sh7750_pmu_disable,
+ .enable = sh7750_pmu_enable,
+ .disable_all = sh7750_pmu_disable_all,
+ .enable_all = sh7750_pmu_enable_all,
+};
+
+static int __init sh7750_pmu_init(void)
+{
+ /*
+ * Make sure this CPU actually has perf counters.
+ */
+ if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) {
+ pr_notice("HW perf events unsupported, software events only.\n");
+ return -ENODEV;
+ }
+
+ return register_sh_pmu(&sh7750_pmu);
+}
+early_initcall(sh7750_pmu_init);
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index 2e42572b1b1..a521bcf5069 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -15,7 +15,7 @@
#include <asm/processor.h>
#include <asm/cache.h>
-int __init detect_cpu_and_cache_system(void)
+void cpu_probe(void)
{
unsigned long pvr, prr, cvr;
unsigned long size;
@@ -28,9 +28,9 @@ int __init detect_cpu_and_cache_system(void)
[9] = (1 << 16)
};
- pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff;
- prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
- cvr = (ctrl_inl(CCN_CVR));
+ pvr = (__raw_readl(CCN_PVR) >> 8) & 0xffffff;
+ prr = (__raw_readl(CCN_PRR) >> 4) & 0xff;
+ cvr = (__raw_readl(CCN_CVR));
/*
* Setup some sane SH-4 defaults for the icache
@@ -57,15 +57,26 @@ int __init detect_cpu_and_cache_system(void)
* Setup some generic flags we can probe on SH-4A parts
*/
if (((pvr >> 16) & 0xff) == 0x10) {
- if ((cvr & 0x10000000) == 0)
+ boot_cpu_data.family = CPU_FAMILY_SH4A;
+
+ if ((cvr & 0x10000000) == 0) {
boot_cpu_data.flags |= CPU_HAS_DSP;
+ boot_cpu_data.family = CPU_FAMILY_SH4AL_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 | CPU_HAS_FPU;
+ boot_cpu_data.family = CPU_FAMILY_SH4;
}
- /* FPU detection works for everyone */
- if ((cvr & 0x20000000) == 1)
+ /* FPU detection works for almost everyone */
+ if ((cvr & 0x20000000))
boot_cpu_data.flags |= CPU_HAS_FPU;
/* Mask off the upper chip ID */
@@ -78,25 +89,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,38 +113,27 @@ 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:
+ case 0x4005:
+ boot_cpu_data.type = CPU_SH7786;
+ 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;
@@ -149,16 +144,33 @@ int __init detect_cpu_and_cache_system(void)
break;
}
break;
+ case 0x300b:
+ switch (prr) {
+ case 0x20:
+ boot_cpu_data.type = CPU_SH7724;
+ boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
+ break;
+ case 0x10:
+ case 0x11:
+ boot_cpu_data.type = CPU_SH7757;
+ break;
+ case 0xd0:
+ case 0x40: /* yon-ten-go */
+ boot_cpu_data.type = CPU_SH7372;
+ break;
+ case 0xE0: /* 0x4E0 */
+ boot_cpu_data.type = CPU_SH7734; /* SH7733/SH7734 */
+ break;
+
+ }
+ 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;
+ boot_cpu_data.flags &= ~CPU_HAS_FPU;
boot_cpu_data.icache.ways = 2;
boot_cpu_data.dcache.ways = 2;
break;
@@ -166,7 +178,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) {
@@ -184,23 +195,9 @@ 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_SH_DIRECT_MAPPED
- boot_cpu_data.icache.ways = 1;
- boot_cpu_data.dcache.ways = 1;
-#endif
-
-#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.
@@ -220,44 +217,47 @@ 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, 256KB, 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..e7a7b3cdf68 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,28 +12,58 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <linux/io.h>
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffe80000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
- }, {
- .flags = 0,
- }
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe80000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+ DEFINE_RES_IRQ(evt2irq(0x720)),
+ DEFINE_RES_IRQ(evt2irq(0x760)),
+ DEFINE_RES_IRQ(evt2irq(0x740)),
};
-static struct platform_device sci_device = {
+static struct platform_device scif0_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 platform_device *sh4202_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &tmu0_device,
};
static int __init sh4202_devices_setup(void)
@@ -40,9 +71,72 @@ static int __init sh4202_devices_setup(void)
return platform_add_devices(sh4202_devices,
ARRAY_SIZE(sh4202_devices));
}
-__initcall(sh4202_devices_setup);
+arch_initcall(sh4202_devices_setup);
+
+static struct platform_device *sh4202_early_devices[] __initdata = {
+ &scif0_device,
+ &tmu0_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 */
+ __raw_writew(__raw_readw(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 ec884039b91..5f08c59b9f3 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -1,5 +1,5 @@
/*
- * SH7750/SH7751 Setup
+ * SH7091/SH7750/SH7750S/SH7750R/SH7751/SH7751R Setup
*
* Copyright (C) 2006 Paul Mundt
* Copyright (C) 2006 Jamie Lenehan
@@ -12,7 +12,10 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/io.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/serial_sci.h>
+#include <generated/machtypes.h>
static struct resource rtc_resources[] = {
[0] = {
@@ -21,18 +24,8 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- /* Period IRQ */
- .start = 21,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- /* Carry IRQ */
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- /* Alarm IRQ */
- .start = 20,
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -44,86 +37,176 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
-static struct plat_sci_port sci_platform_data[] = {
- {
-#ifndef CONFIG_SH_RTS7751R2D
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
- .irqs = { 23, 24, 25, 0 },
- }, {
-#endif
- .mapbase = 0xffe80000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
- }, {
- .flags = 0,
- }
+static struct plat_sci_port sci_platform_data = {
+ .port_reg = 0xffe0001C,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE,
+ .type = PORT_SCI,
+ .regshift = 2,
+};
+
+static struct resource sci_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x4e0)),
};
static struct platform_device sci_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 0,
+ .resource = sci_resources,
+ .num_resources = ARRAY_SIZE(sci_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &sci_platform_data,
+ },
+};
+
+static struct plat_sci_port scif_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_TE | SCSCR_RE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif_resources[] = {
+ DEFINE_RES_MEM(0xffe80000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+};
+
+static struct platform_device scif_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif_resources,
+ .num_resources = ARRAY_SIZE(scif_resources),
+ .dev = {
+ .platform_data = &scif_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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),
+};
+
+/* 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 tmu1_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xfe100000, 0x20),
+ DEFINE_RES_IRQ(evt2irq(0xb00)),
+ DEFINE_RES_IRQ(evt2irq(0xb80)),
+};
+
+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),
};
+#endif
+
static struct platform_device *sh7750_devices[] __initdata = {
&rtc_device,
- &sci_device,
+ &tmu0_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+ &tmu1_device,
+#endif
};
static int __init sh7750_devices_setup(void)
{
+ if (mach_is_rts7751r2d()) {
+ platform_device_register(&scif_device);
+ } else {
+ platform_device_register(&sci_device);
+ platform_device_register(&scif_device);
+ }
+
return platform_add_devices(sh7750_devices,
ARRAY_SIZE(sh7750_devices));
}
-__initcall(sh7750_devices_setup);
+arch_initcall(sh7750_devices_setup);
+
+static struct platform_device *sh7750_early_devices[] __initdata = {
+ &tmu0_device,
+#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
+ &tmu1_device,
+#endif
+};
+
+void __init plat_early_device_setup(void)
+{
+ struct platform_device *dev[1];
+
+ if (mach_is_rts7751r2d()) {
+ scif_platform_data.scscr |= SCSCR_CKE1;
+ dev[0] = &scif_device;
+ early_platform_add_devices(dev, 1);
+ } else {
+ dev[0] = &sci_device;
+ early_platform_add_devices(dev, 1);
+ dev[0] = &scif_device;
+ early_platform_add_devices(dev, 1);
+ }
+
+ early_platform_add_devices(sh7750_early_devices,
+ ARRAY_SIZE(sh7750_early_devices));
+}
enum {
UNUSED = 0,
/* interrupt sources */
IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */
- HUDI, GPIOI,
- DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3,
- DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7,
- DMAC_DMAE,
+ HUDI, GPIOI, DMAC,
PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON,
PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3,
- TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI,
- RTC_ATI, RTC_PRI, RTC_CUI,
- SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI,
- SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI,
- WDT,
- REF_RCMI, REF_ROVI,
+ TMU3, TMU4, TMU0, TMU1, TMU2, RTC, SCI1, SCIF, WDT, REF,
/* interrupt groups */
- DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF,
+ PCIC1,
};
static struct intc_vect vectors[] __initdata = {
INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
- INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
- INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
- INTC_VECT(RTC_CUI, 0x4c0),
- INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500),
- INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540),
- INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720),
- INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2, 0x460),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
+ INTC_VECT(SCI1, 0x4e0), INTC_VECT(SCI1, 0x500),
+ INTC_VECT(SCI1, 0x520), INTC_VECT(SCI1, 0x540),
+ INTC_VECT(SCIF, 0x700), INTC_VECT(SCIF, 0x720),
+ INTC_VECT(SCIF, 0x740), INTC_VECT(SCIF, 0x760),
INTC_VECT(WDT, 0x560),
- INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0),
-};
-
-static struct intc_group groups[] __initdata = {
- INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI),
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
- INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI),
- INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI),
- INTC_GROUP(REF, REF_RCMI, REF_ROVI),
+ INTC_VECT(REF, 0x580), INTC_VECT(REF, 0x5a0),
};
static struct intc_prio_reg prio_registers[] __initdata = {
@@ -136,7 +219,7 @@ static struct intc_prio_reg prio_registers[] __initdata = {
PCIC1, PCIC0_PCISERR } },
};
-static DECLARE_INTC_DESC(intc_desc, "sh7750", vectors, groups,
+static DECLARE_INTC_DESC(intc_desc, "sh7750", vectors, NULL,
NULL, prio_registers, NULL);
/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */
@@ -145,39 +228,28 @@ static DECLARE_INTC_DESC(intc_desc, "sh7750", vectors, groups,
defined(CONFIG_CPU_SUBTYPE_SH7751) || \
defined(CONFIG_CPU_SUBTYPE_SH7091)
static struct intc_vect vectors_dma4[] __initdata = {
- INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660),
- INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0),
- INTC_VECT(DMAC_DMAE, 0x6c0),
-};
-
-static struct intc_group groups_dma4[] __initdata = {
- INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
- DMAC_DMTE3, DMAC_DMAE),
+ INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+ INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+ INTC_VECT(DMAC, 0x6c0),
};
static DECLARE_INTC_DESC(intc_desc_dma4, "sh7750_dma4",
- vectors_dma4, groups_dma4,
+ vectors_dma4, NULL,
NULL, prio_registers, NULL);
#endif
/* SH7750R and SH7751R both have 8-channel DMA controllers */
#if defined(CONFIG_CPU_SUBTYPE_SH7750R) || defined(CONFIG_CPU_SUBTYPE_SH7751R)
static struct intc_vect vectors_dma8[] __initdata = {
- 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),
-};
-
-static struct intc_group groups_dma8[] __initdata = {
- INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2,
- DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5,
- DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE),
+ 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),
};
static DECLARE_INTC_DESC(intc_desc_dma8, "sh7750_dma8",
- vectors_dma8, groups_dma8,
+ vectors_dma8, NULL,
NULL, prio_registers, NULL);
#endif
@@ -285,7 +357,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);
+ __raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
register_intc_controller(&intc_desc_irlm);
break;
default:
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 254c5c55ab9..973b736b3b9 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -10,17 +10,17 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/serial_sci.h>
+#include <linux/io.h>
enum {
UNUSED = 0,
/* 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,
@@ -35,21 +35,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),
@@ -73,23 +72,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 = {
@@ -133,42 +127,133 @@ static struct intc_vect vectors_irq[] __initdata = {
static DECLARE_INTC_DESC(intc_desc_irq, "sh7760-irq", vectors_irq, groups,
mask_registers, prio_registers, NULL);
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xfe600000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 52, 53, 55, 54 },
- }, {
- .mapbase = 0xfe610000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 72, 73, 75, 74 },
- }, {
- .mapbase = 0xfe620000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 76, 77, 79, 78 },
- }, {
- .mapbase = 0xfe480000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
- .irqs = { 80, 81, 82, 0 },
- }, {
- .flags = 0,
- }
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xfe600000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
+ DEFINE_RES_IRQ(evt2irq(0x8a0)),
+ DEFINE_RES_IRQ(evt2irq(0x8e0)),
+ DEFINE_RES_IRQ(evt2irq(0x8c0)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .type = PORT_SCIF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xfe610000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xb00)),
+ DEFINE_RES_IRQ(evt2irq(0xb20)),
+ DEFINE_RES_IRQ(evt2irq(0xb60)),
+ DEFINE_RES_IRQ(evt2irq(0xb40)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xfe620000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xb80)),
+ DEFINE_RES_IRQ(evt2irq(0xba0)),
+ DEFINE_RES_IRQ(evt2irq(0xbe0)),
+ DEFINE_RES_IRQ(evt2irq(0xbc0)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCI,
+ .regshift = 2,
};
-static struct platform_device sci_device = {
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xfe480000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
+ DEFINE_RES_IRQ(evt2irq(0xc20)),
+ DEFINE_RES_IRQ(evt2irq(0xc40)),
+};
+
+static struct platform_device scif3_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 platform_device *sh7760_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &tmu0_device,
};
static int __init sh7760_devices_setup(void)
@@ -176,12 +261,30 @@ static int __init sh7760_devices_setup(void)
return platform_add_devices(sh7760_devices,
ARRAY_SIZE(sh7760_devices));
}
-__initcall(sh7760_devices_setup);
+arch_initcall(sh7760_devices_setup);
+
+static struct platform_device *sh7760_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &tmu0_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)
void __init plat_irq_setup_pins(int mode)
{
switch (mode) {
case IRQ_MODE_IRQ:
+ __raw_writew(__raw_readw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
register_intc_controller(&intc_desc_irq);
break;
default:
diff --git a/arch/sh/kernel/cpu/sh4/softfloat.c b/arch/sh/kernel/cpu/sh4/softfloat.c
index 828cb57cb95..42edf2e54e8 100644
--- a/arch/sh/kernel/cpu/sh4/softfloat.c
+++ b/arch/sh/kernel/cpu/sh4/softfloat.c
@@ -37,6 +37,7 @@
*/
#include <linux/kernel.h>
#include <cpu/fpu.h>
+#include <asm/div64.h>
#define LIT64( a ) a##LL
@@ -67,16 +68,16 @@ typedef unsigned long long float64;
extern void float_raise(unsigned int flags); /* in fpu.c */
extern int float_rounding_mode(void); /* in fpu.c */
-inline bits64 extractFloat64Frac(float64 a);
-inline flag extractFloat64Sign(float64 a);
-inline int16 extractFloat64Exp(float64 a);
-inline int16 extractFloat32Exp(float32 a);
-inline flag extractFloat32Sign(float32 a);
-inline bits32 extractFloat32Frac(float32 a);
-inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig);
-inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr);
-inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig);
-inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr);
+bits64 extractFloat64Frac(float64 a);
+flag extractFloat64Sign(float64 a);
+int16 extractFloat64Exp(float64 a);
+int16 extractFloat32Exp(float32 a);
+flag extractFloat32Sign(float32 a);
+bits32 extractFloat32Frac(float32 a);
+float64 packFloat64(flag zSign, int16 zExp, bits64 zSig);
+void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr);
+float32 packFloat32(flag zSign, int16 zExp, bits32 zSig);
+void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr);
float64 float64_sub(float64 a, float64 b);
float32 float32_sub(float32 a, float32 b);
float32 float32_add(float32 a, float32 b);
@@ -85,11 +86,12 @@ float64 float64_div(float64 a, float64 b);
float32 float32_div(float32 a, float32 b);
float32 float32_mul(float32 a, float32 b);
float64 float64_mul(float64 a, float64 b);
-inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
+float32 float64_to_float32(float64 a);
+void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
bits64 * z1Ptr);
-inline void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
+void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
bits64 * z1Ptr);
-inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr);
+void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr);
static int8 countLeadingZeros32(bits32 a);
static int8 countLeadingZeros64(bits64 a);
@@ -109,42 +111,42 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b);
static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr,
bits32 * zSigPtr);
-inline bits64 extractFloat64Frac(float64 a)
+bits64 extractFloat64Frac(float64 a)
{
return a & LIT64(0x000FFFFFFFFFFFFF);
}
-inline flag extractFloat64Sign(float64 a)
+flag extractFloat64Sign(float64 a)
{
return a >> 63;
}
-inline int16 extractFloat64Exp(float64 a)
+int16 extractFloat64Exp(float64 a)
{
return (a >> 52) & 0x7FF;
}
-inline int16 extractFloat32Exp(float32 a)
+int16 extractFloat32Exp(float32 a)
{
return (a >> 23) & 0xFF;
}
-inline flag extractFloat32Sign(float32 a)
+flag extractFloat32Sign(float32 a)
{
return a >> 31;
}
-inline bits32 extractFloat32Frac(float32 a)
+bits32 extractFloat32Frac(float32 a)
{
return a & 0x007FFFFF;
}
-inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig)
+float64 packFloat64(flag zSign, int16 zExp, bits64 zSig)
{
return (((bits64) zSign) << 63) + (((bits64) zExp) << 52) + zSig;
}
-inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr)
+void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr)
{
bits64 z;
@@ -337,12 +339,12 @@ static float64 addFloat64Sigs(float64 a, float64 b, flag zSign)
}
-inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig)
+float32 packFloat32(flag zSign, int16 zExp, bits32 zSig)
{
return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig;
}
-inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr)
+void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr)
{
bits32 z;
if (count == 0) {
@@ -633,7 +635,7 @@ normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr, bits64 * zSigPtr)
*zExpPtr = 1 - shiftCount;
}
-inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
+void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
bits64 * z1Ptr)
{
bits64 z1;
@@ -643,7 +645,7 @@ inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
*z0Ptr = a0 + b0 + (z1 < a1);
}
-inline void
+void
sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
bits64 * z1Ptr)
{
@@ -655,11 +657,14 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b)
{
bits64 b0, b1;
bits64 rem0, rem1, term0, term1;
- bits64 z;
+ bits64 z, tmp;
if (b <= a0)
return LIT64(0xFFFFFFFFFFFFFFFF);
b0 = b >> 32;
- z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : (a0 / b0) << 32;
+ tmp = a0;
+ do_div(tmp, b0);
+
+ z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : tmp << 32;
mul64To128(b, z, &term0, &term1);
sub128(a0, a1, term0, term1, &rem0, &rem1);
while (((sbits64) rem0) < 0) {
@@ -668,11 +673,13 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b)
add128(rem0, rem1, b0, b1, &rem0, &rem1);
}
rem0 = (rem0 << 32) | (rem1 >> 32);
- z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : rem0 / b0;
+ tmp = rem0;
+ do_div(tmp, b0);
+ z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : tmp;
return z;
}
-inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr)
+void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr)
{
bits32 aHigh, aLow, bHigh, bLow;
bits64 z0, zMiddleA, zMiddleB, z1;
@@ -768,7 +775,8 @@ float32 float32_div(float32 a, float32 b)
{
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
- bits32 aSig, bSig, zSig;
+ bits32 aSig, bSig;
+ uint64_t zSig;
aSig = extractFloat32Frac(a);
aExp = extractFloat32Exp(a);
@@ -803,11 +811,13 @@ float32 float32_div(float32 a, float32 b)
aSig >>= 1;
++zExp;
}
- zSig = (((bits64) aSig) << 32) / bSig;
+ zSig = (((bits64) aSig) << 32);
+ do_div(zSig, bSig);
+
if ((zSig & 0x3F) == 0) {
zSig |= (((bits64) bSig) * zSig != ((bits64) aSig) << 32);
}
- return roundAndPackFloat32(zSign, zExp, zSig);
+ return roundAndPackFloat32(zSign, zExp, (bits32)zSig);
}
@@ -890,3 +900,31 @@ float64 float64_mul(float64 a, float64 b)
}
return roundAndPackFloat64(zSign, zExp, zSig0);
}
+
+/*
+ * -------------------------------------------------------------------------------
+ * Returns the result of converting the double-precision floating-point value
+ * `a' to the single-precision floating-point format. The conversion is
+ * performed according to the IEC/IEEE Standard for Binary Floating-point
+ * Arithmetic.
+ * -------------------------------------------------------------------------------
+ * */
+float32 float64_to_float32(float64 a)
+{
+ flag aSign;
+ int16 aExp;
+ bits64 aSig;
+ bits32 zSig;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+
+ shift64RightJamming( aSig, 22, &aSig );
+ zSig = aSig;
+ if ( aExp || zSig ) {
+ zSig |= 0x40000000;
+ aExp -= 0x381;
+ }
+ return roundAndPackFloat32(aSign, aExp, zSig);
+}
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 8a8a993f55e..0a47bd3e7be 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -13,13 +13,14 @@
#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/bitmap.h>
-#include <linux/sysdev.h>
+#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/io.h>
+#include <linux/prefetch.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
#include <cpu/sq.h>
@@ -43,9 +44,9 @@ static unsigned long *sq_bitmap;
#define store_queue_barrier() \
do { \
- (void)ctrl_inl(P4SEG_STORE_QUE); \
- ctrl_outl(0, P4SEG_STORE_QUE + 0); \
- ctrl_outl(0, P4SEG_STORE_QUE + 8); \
+ (void)__raw_readl(P4SEG_STORE_QUE); \
+ __raw_writel(0, P4SEG_STORE_QUE + 0); \
+ __raw_writel(0, P4SEG_STORE_QUE + 8); \
} while (0);
/**
@@ -100,7 +101,7 @@ static inline void sq_mapping_list_del(struct sq_mapping *map)
spin_unlock_irq(&sq_mapping_lock);
}
-static int __sq_remap(struct sq_mapping *map, unsigned long flags)
+static int __sq_remap(struct sq_mapping *map, pgprot_t prot)
{
#if defined(CONFIG_MMU)
struct vm_struct *vma;
@@ -113,7 +114,7 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
if (ioremap_page_range((unsigned long)vma->addr,
(unsigned long)vma->addr + map->size,
- vma->phys_addr, __pgprot(flags))) {
+ vma->phys_addr, prot)) {
vunmap(vma->addr);
return -EAGAIN;
}
@@ -123,8 +124,8 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
* straightforward, as we can just load up each queue's QACR with
* the physical address appropriately masked.
*/
- ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
- ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
+ __raw_writel(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
+ __raw_writel(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
#endif
return 0;
@@ -135,14 +136,14 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
* @phys: Physical address of mapping.
* @size: Length of mapping.
* @name: User invoking mapping.
- * @flags: Protection flags.
+ * @prot: Protection bits.
*
* Remaps the physical address @phys through the next available store queue
* address of @size length. @name is logged at boot time as well as through
* the sysfs interface.
*/
unsigned long sq_remap(unsigned long phys, unsigned int size,
- const char *name, unsigned long flags)
+ const char *name, pgprot_t prot)
{
struct sq_mapping *map;
unsigned long end;
@@ -177,7 +178,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
- ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
+ ret = __sq_remap(map, prot);
if (unlikely(ret != 0))
goto out;
@@ -309,8 +310,7 @@ static ssize_t mapping_store(const char *buf, size_t count)
return -EIO;
if (likely(len)) {
- int ret = sq_remap(base, len, "Userspace",
- pgprot_val(PAGE_SHARED));
+ int ret = sq_remap(base, len, "Userspace", PAGE_SHARED);
if (ret < 0)
return ret;
} else
@@ -327,7 +327,7 @@ static struct attribute *sq_sysfs_attrs[] = {
NULL,
};
-static struct sysfs_ops sq_sysfs_ops = {
+static const struct sysfs_ops sq_sysfs_ops = {
.show = sq_sysfs_show,
.store = sq_sysfs_store,
};
@@ -337,9 +337,9 @@ static struct kobj_type ktype_percpu_entry = {
.default_attrs = sq_sysfs_attrs,
};
-static int __devinit sq_sysdev_add(struct sys_device *sysdev)
+static int sq_dev_add(struct device *dev, struct subsys_interface *sif)
{
- unsigned int cpu = sysdev->id;
+ unsigned int cpu = dev->id;
struct kobject *kobj;
int error;
@@ -348,25 +348,27 @@ static int __devinit sq_sysdev_add(struct sys_device *sysdev)
return -ENOMEM;
kobj = sq_kobject[cpu];
- error = kobject_init_and_add(kobj, &ktype_percpu_entry, &sysdev->kobj,
+ error = kobject_init_and_add(kobj, &ktype_percpu_entry, &dev->kobj,
"%s", "sq");
if (!error)
kobject_uevent(kobj, KOBJ_ADD);
return error;
}
-static int __devexit sq_sysdev_remove(struct sys_device *sysdev)
+static int sq_dev_remove(struct device *dev, struct subsys_interface *sif)
{
- unsigned int cpu = sysdev->id;
+ unsigned int cpu = dev->id;
struct kobject *kobj = sq_kobject[cpu];
kobject_put(kobj);
return 0;
}
-static struct sysdev_driver sq_sysdev_driver = {
- .add = sq_sysdev_add,
- .remove = __devexit_p(sq_sysdev_remove),
+static struct subsys_interface sq_interface = {
+ .name = "sq",
+ .subsys = &cpu_subsys,
+ .add_dev = sq_dev_add,
+ .remove_dev = sq_dev_remove,
};
static int __init sq_api_init(void)
@@ -386,7 +388,7 @@ static int __init sq_api_init(void)
if (unlikely(!sq_bitmap))
goto out;
- ret = sysdev_driver_register(&cpu_sysdev_class, &sq_sysdev_driver);
+ ret = subsys_interface_register(&sq_interface);
if (unlikely(ret != 0))
goto out;
@@ -401,7 +403,7 @@ out:
static void __exit sq_api_exit(void)
{
- sysdev_driver_unregister(&cpu_sysdev_class, &sq_sysdev_driver);
+ subsys_interface_unregister(&sq_interface);
kfree(sq_bitmap);
kmem_cache_destroy(sq_cache);
}
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
index 9381ad8da26..0705df77520 100644
--- a/arch/sh/kernel/cpu/sh4a/Makefile
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -3,29 +3,50 @@
#
# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7757) += setup-sh7757.o
obj-$(CONFIG_CPU_SUBTYPE_SH7763) += setup-sh7763.o
obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786) += setup-sh7786.o intc-shx3.o
obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o serial-sh7722.o
obj-$(CONFIG_CPU_SUBTYPE_SH7723) += setup-sh7723.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7724) += setup-sh7724.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7734) += setup-sh7734.o
obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o
-obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o
+obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o intc-shx3.o
# SMP setup
-smp-$(CONFIG_CPU_SUBTYPE_SHX3) := smp-shx3.o
+smp-$(CONFIG_CPU_SHX3) := smp-shx3.o
# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SUBTYPE_SH7757) := clock-sh7757.o
clock-$(CONFIG_CPU_SUBTYPE_SH7763) := clock-sh7763.o
clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7722.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7734) := clock-sh7734.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o
clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o
-obj-y += $(clock-y)
-obj-$(CONFIG_SMP) += $(smp-y)
+# Pinmux setup
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7722) := pinmux-sh7722.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7723) := pinmux-sh7723.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7724) := pinmux-sh7724.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7734) := pinmux-sh7734.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7757) := pinmux-sh7757.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7785) := pinmux-sh7785.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7786) := pinmux-sh7786.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SHX3) := pinmux-shx3.o
+
+obj-y += $(clock-y)
+obj-$(CONFIG_SMP) += $(smp-y)
+obj-$(CONFIG_GPIOLIB) += $(pinmux-y)
+obj-$(CONFIG_PERF_EVENTS) += perf_event.o
+obj-$(CONFIG_HAVE_HW_BREAKPOINT) += ubc.o
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
new file mode 100644
index 00000000000..9edc06c02dc
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -0,0 +1,289 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7343.c
+ *
+ * SH7343 clock framework support
+ *
+ * Copyright (C) 2009 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; either 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+/* SH7343 registers */
+#define FRQCR 0xa4150000
+#define VCLKCR 0xa4150004
+#define SCLKACR 0xa4150008
+#define SCLKBCR 0xa415000c
+#define PLLCR 0xa4150024
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+#define DLLFRQ 0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
+{
+ unsigned long mult;
+
+ if (__raw_readl(PLLCR) & 0x1000)
+ mult = __raw_readl(DLLFRQ);
+ else
+ mult = 0;
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops dll_clk_ops = {
+ .recalc = dll_recalc,
+};
+
+static struct clk dll_clk = {
+ .ops = &dll_clk_ops,
+ .parent = &r_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long mult = 1;
+
+ if (__raw_readl(PLLCR) & 0x4000)
+ mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &dll_clk,
+ &pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+ .multipliers = multipliers,
+ .nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
+ DIV4_SIUA, DIV4_SIUB, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
+ [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
+ [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
+};
+
+enum { DIV6_V, DIV6_NR };
+
+struct clk div6_clks[DIV6_NR] = {
+ [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
+};
+
+#define MSTP(_parent, _reg, _bit, _flags) \
+ SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
+
+enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
+ MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
+ MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
+ MSTP007, MSTP006, MSTP005, MSTP004, MSTP003, MSTP002, MSTP001,
+ MSTP109, MSTP108, MSTP100,
+ MSTP225, MSTP224, MSTP218, MSTP217, MSTP216,
+ MSTP214, MSTP213, MSTP212, MSTP211, MSTP208,
+ MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
+ [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
+ [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
+ [MSTP028] = MSTP(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+ [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+ [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
+ [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
+ [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
+ [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
+ [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
+ [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
+ [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
+ [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
+ [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
+ [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+ [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
+ [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
+ [MSTP004] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
+ [MSTP003] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
+ [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+ [MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
+
+ [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+ [MSTP108] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
+
+ [MSTP225] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 25, 0),
+ [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
+ [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
+ [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
+ [MSTP216] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 16, 0),
+ [MSTP214] = MSTP(&r_clk, MSTPCR2, 14, 0),
+ [MSTP213] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 13, 0),
+ [MSTP212] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 12, 0),
+ [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
+ [MSTP208] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 8, 0),
+ [MSTP206] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT),
+ [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
+ [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
+ [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
+ [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
+ [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
+ [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("dll_clk", &dll_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
+ CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
+
+ /* MSTP32 clocks */
+ CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
+ CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
+ CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
+ CLKDEV_CON_ID("uram0", &mstp_clks[MSTP028]),
+ CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
+ CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
+ CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
+ CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
+ CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
+ CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
+ CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
+ CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[MSTP014]),
+ CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
+ CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
+ CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
+
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP004]),
+
+ CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]),
+ CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]),
+ CLKDEV_CON_ID("siof1", &mstp_clks[MSTP001]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP108]),
+ CLKDEV_CON_ID("tpu0", &mstp_clks[MSTP225]),
+ CLKDEV_CON_ID("irda0", &mstp_clks[MSTP224]),
+ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
+ CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
+ CLKDEV_CON_ID("sim0", &mstp_clks[MSTP216]),
+ CLKDEV_CON_ID("keysc0", &mstp_clks[MSTP214]),
+ CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP213]),
+ CLKDEV_CON_ID("s3d40", &mstp_clks[MSTP212]),
+ CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
+ CLKDEV_CON_ID("siu0", &mstp_clks[MSTP208]),
+ CLKDEV_CON_ID("jpu0", &mstp_clks[MSTP206]),
+ CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
+ CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
+ CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
+ CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
+ CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
+ CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ /* autodetect extal or dll configuration */
+ if (__raw_readl(PLLCR) & 0x1000)
+ pll_clk.parent = &dll_clk;
+ else
+ pll_clk.parent = &extal_clk;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
new file mode 100644
index 00000000000..955b9add781
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c
@@ -0,0 +1,282 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7366.c
+ *
+ * SH7366 clock framework support
+ *
+ * Copyright (C) 2009 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; either 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+
+/* SH7366 registers */
+#define FRQCR 0xa4150000
+#define VCLKCR 0xa4150004
+#define SCLKACR 0xa4150008
+#define SCLKBCR 0xa415000c
+#define PLLCR 0xa4150024
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+#define DLLFRQ 0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
+{
+ unsigned long mult;
+
+ if (__raw_readl(PLLCR) & 0x1000)
+ mult = __raw_readl(DLLFRQ);
+ else
+ mult = 0;
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops dll_clk_ops = {
+ .recalc = dll_recalc,
+};
+
+static struct clk dll_clk = {
+ .ops = &dll_clk_ops,
+ .parent = &r_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long mult = 1;
+ unsigned long div = 1;
+
+ if (__raw_readl(PLLCR) & 0x4000)
+ mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+ else
+ div = 2;
+
+ return (clk->parent->rate * mult) / div;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &dll_clk,
+ &pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+ .multipliers = multipliers,
+ .nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P,
+ DIV4_SIUA, DIV4_SIUB, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
+ [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
+ [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
+ [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
+};
+
+enum { DIV6_V, DIV6_NR };
+
+struct clk div6_clks[DIV6_NR] = {
+ [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
+};
+
+#define MSTP(_parent, _reg, _bit, _flags) \
+ SH_CLK_MSTP32(_parent, _reg, _bit, _flags)
+
+enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026,
+ MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016,
+ MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010,
+ MSTP007, MSTP006, MSTP005, MSTP002, MSTP001,
+ MSTP109, MSTP100,
+ MSTP227, MSTP226, MSTP224, MSTP223, MSTP222, MSTP218, MSTP217,
+ MSTP211, MSTP207, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */
+ [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
+ [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
+ [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
+ [MSTP028] = MSTP(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+ [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+ [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
+ [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
+ [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
+ [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
+ [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
+ [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
+ [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0),
+ [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0),
+ [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
+ [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+ [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
+ [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
+ [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+ [MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
+
+ [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+
+ [MSTP227] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 27, 0),
+ [MSTP226] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 26, 0),
+ [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
+ [MSTP223] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 23, 0),
+ [MSTP222] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 22, 0),
+ [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
+ [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0),
+ [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
+ [MSTP207] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT),
+ [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
+ [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
+ [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
+ [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT),
+ [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT),
+ [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("dll_clk", &dll_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]),
+ CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
+
+ /* MSTP32 clocks */
+ CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]),
+ CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]),
+ CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]),
+ CLKDEV_CON_ID("rsmem0", &mstp_clks[MSTP028]),
+ CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]),
+ CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]),
+ CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]),
+ CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]),
+ CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]),
+ CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]),
+ CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]),
+ CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[MSTP014]),
+ CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]),
+ CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]),
+ CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]),
+
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP007]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP006]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP005]),
+
+ CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]),
+ CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP109]),
+ CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]),
+ CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]),
+ CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]),
+ CLKDEV_CON_ID("dacy0", &mstp_clks[MSTP223]),
+ CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP222]),
+ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]),
+ CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]),
+ CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]),
+ CLKDEV_CON_ID("veu1", &mstp_clks[MSTP207]),
+ CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]),
+ CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]),
+ CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]),
+ CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]),
+ CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]),
+ CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ /* autodetect extal or dll configuration */
+ if (__raw_readl(PLLCR) & 0x1000)
+ pll_clk.parent = &dll_clk;
+ else
+ pll_clk.parent = &extal_clk;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
index db913855c2f..8f07a1a3869 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
@@ -1,730 +1,265 @@
/*
* arch/sh/kernel/cpu/sh4a/clock-sh7722.c
*
- * SH7343, SH7722, SH7723 & SH7366 support for the clock framework
+ * SH7722 clock framework support
*
- * Copyright (c) 2006-2007 Nomad Global Solutions Inc
- * Based on code for sh7343 by 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
- * for more details.
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/io.h>
-#include <linux/errno.h>
-#include <linux/stringify.h>
+#include <linux/clkdev.h>
+#include <linux/sh_clk.h>
#include <asm/clock.h>
-#include <asm/freq.h>
-
-#define N (-1)
-#define NM (-2)
-#define ROUND_NEAREST 0
-#define ROUND_DOWN -1
-#define ROUND_UP +1
-
-static int adjust_algos[][3] = {
- {}, /* NO_CHANGE */
- { NM, N, 1 }, /* N:1, N:1 */
- { 3, 2, 2 }, /* 3:2:2 */
- { 5, 2, 2 }, /* 5:2:2 */
- { N, 1, 1 }, /* N:1:1 */
-
- { N, 1 }, /* N:1 */
-
- { N, 1 }, /* N:1 */
- { 3, 2 },
- { 4, 3 },
- { 5, 4 },
-
- { N, 1 }
+#include <cpu/sh7722.h>
+
+/* SH7722 registers */
+#define FRQCR 0xa4150000
+#define VCLKCR 0xa4150004
+#define SCLKACR 0xa4150008
+#define SCLKBCR 0xa415000c
+#define IRDACLKCR 0xa4150018
+#define PLLCR 0xa4150024
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+#define DLLFRQ 0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+ .rate = 32768,
};
-static unsigned long adjust_pair_of_clocks(unsigned long r1, unsigned long r2,
- int m1, int m2, int round_flag)
-{
- unsigned long rem, div;
- int the_one = 0;
-
- pr_debug( "Actual values: r1 = %ld\n", r1);
- pr_debug( "...............r2 = %ld\n", r2);
-
- if (m1 == m2) {
- r2 = r1;
- pr_debug( "setting equal rates: r2 now %ld\n", r2);
- } else if ((m2 == N && m1 == 1) ||
- (m2 == NM && m1 == N)) { /* N:1 or NM:N */
- pr_debug( "Setting rates as 1:N (N:N*M)\n");
- rem = r2 % r1;
- pr_debug( "...remainder = %ld\n", rem);
- if (rem) {
- div = r2 / r1;
- pr_debug( "...div = %ld\n", div);
- switch (round_flag) {
- case ROUND_NEAREST:
- the_one = rem >= r1/2 ? 1 : 0; break;
- case ROUND_UP:
- the_one = 1; break;
- case ROUND_DOWN:
- the_one = 0; break;
- }
-
- r2 = r1 * (div + the_one);
- pr_debug( "...setting r2 to %ld\n", r2);
- }
- } else if ((m2 == 1 && m1 == N) ||
- (m2 == N && m1 == NM)) { /* 1:N or N:NM */
- pr_debug( "Setting rates as N:1 (N*M:N)\n");
- rem = r1 % r2;
- pr_debug( "...remainder = %ld\n", rem);
- if (rem) {
- div = r1 / r2;
- pr_debug( "...div = %ld\n", div);
- switch (round_flag) {
- case ROUND_NEAREST:
- the_one = rem > r2/2 ? 1 : 0; break;
- case ROUND_UP:
- the_one = 0; break;
- case ROUND_DOWN:
- the_one = 1; break;
- }
-
- r2 = r1 / (div + the_one);
- pr_debug( "...setting r2 to %ld\n", r2);
- }
- } else { /* value:value */
- pr_debug( "Setting rates as %d:%d\n", m1, m2);
- div = r1 / m1;
- r2 = div * m2;
- pr_debug( "...div = %ld\n", div);
- pr_debug( "...setting r2 to %ld\n", r2);
- }
-
- return r2;
-}
-
-static void adjust_clocks(int originate, int *l, unsigned long v[],
- int n_in_line)
-{
- int x;
-
- pr_debug( "Go down from %d...\n", originate);
- /* go up recalculation clocks */
- for (x = originate; x>0; x -- )
- v[x-1] = adjust_pair_of_clocks(v[x], v[x-1],
- l[x], l[x-1],
- ROUND_UP);
-
- pr_debug( "Go up from %d...\n", originate);
- /* go down recalculation clocks */
- for (x = originate; x<n_in_line - 1; x ++ )
- v[x+1] = adjust_pair_of_clocks(v[x], v[x+1],
- l[x], l[x+1],
- ROUND_UP);
-}
-
-
/*
- * SH7722 uses a common set of multipliers and divisors, so this
- * is quite simple..
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
*/
+struct clk extal_clk = {
+ .rate = 33333333,
+};
-/*
- * Instead of having two separate multipliers/divisors set, like this:
- *
- * static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
- * static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
- *
- * I created the divisors2 array, which is used to calculate rate like
- * rate = parent * 2 / divisors2[ divisor ];
-*/
-static int divisors2[] = { 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40 };
-
-static void master_clk_recalc(struct clk *clk)
+/* The dll block multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
{
- unsigned frqcr = ctrl_inl(FRQCR);
+ unsigned long mult;
- clk->rate = CONFIG_SH_PCLK_FREQ * (((frqcr >> 24) & 0x1f) + 1);
-}
+ if (__raw_readl(PLLCR) & 0x1000)
+ mult = __raw_readl(DLLFRQ);
+ else
+ mult = 0;
-static void master_clk_init(struct clk *clk)
-{
- clk->parent = NULL;
- clk->flags |= CLK_RATE_PROPAGATES;
- clk->rate = CONFIG_SH_PCLK_FREQ;
- master_clk_recalc(clk);
+ return clk->parent->rate * mult;
}
+static struct sh_clk_ops dll_clk_ops = {
+ .recalc = dll_recalc,
+};
-static void module_clk_recalc(struct clk *clk)
-{
- unsigned long frqcr = ctrl_inl(FRQCR);
-
- clk->rate = clk->parent->rate / (((frqcr >> 24) & 0x1f) + 1);
-}
+static struct clk dll_clk = {
+ .ops = &dll_clk_ops,
+ .parent = &r_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
-static int master_clk_setrate(struct clk *clk, unsigned long rate, int id)
+static unsigned long pll_recalc(struct clk *clk)
{
- int div = rate / clk->rate;
- int master_divs[] = { 2, 3, 4, 6, 8, 16 };
- int index;
- unsigned long frqcr;
-
- for (index = 1; index < ARRAY_SIZE(master_divs); index++)
- if (div >= master_divs[index - 1] && div < master_divs[index])
- break;
+ unsigned long mult = 1;
+ unsigned long div = 1;
- if (index >= ARRAY_SIZE(master_divs))
- index = ARRAY_SIZE(master_divs);
- div = master_divs[index - 1];
-
- frqcr = ctrl_inl(FRQCR);
- frqcr &= ~(0xF << 24);
- frqcr |= ( (div-1) << 24);
- ctrl_outl(frqcr, FRQCR);
+ if (__raw_readl(PLLCR) & 0x4000)
+ mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+ else
+ div = 2;
- return 0;
+ return (clk->parent->rate * mult) / div;
}
-static struct clk_ops sh7722_master_clk_ops = {
- .init = master_clk_init,
- .recalc = master_clk_recalc,
- .set_rate = master_clk_setrate,
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
};
-static struct clk_ops sh7722_module_clk_ops = {
- .recalc = module_clk_recalc,
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
};
-struct frqcr_context {
- unsigned mask;
- unsigned shift;
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &dll_clk,
+ &pll_clk,
};
-struct frqcr_context sh7722_get_clk_context(const char *name)
-{
- struct frqcr_context ctx = { 0, };
-
- if (!strcmp(name, "peripheral_clk")) {
- ctx.shift = 0;
- ctx.mask = 0xF;
- } else if (!strcmp(name, "sdram_clk")) {
- ctx.shift = 4;
- ctx.mask = 0xF;
- } else if (!strcmp(name, "bus_clk")) {
- ctx.shift = 8;
- ctx.mask = 0xF;
- } else if (!strcmp(name, "sh_clk")) {
- ctx.shift = 12;
- ctx.mask = 0xF;
- } else if (!strcmp(name, "umem_clk")) {
- ctx.shift = 16;
- ctx.mask = 0xF;
- } else if (!strcmp(name, "cpu_clk")) {
- ctx.shift = 20;
- ctx.mask = 7;
- }
- return ctx;
-}
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
-/**
- * sh7722_find_divisors - find divisor for setting rate
- *
- * All sh7722 clocks use the same set of multipliers/divisors. This function
- * chooses correct divisor to set the rate of clock with parent clock that
- * generates frequency of 'parent_rate'
- *
- * @parent_rate: rate of parent clock
- * @rate: requested rate to be set
- */
-static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate)
-{
- unsigned div2 = parent_rate * 2 / rate;
- int index;
-
- if (rate > parent_rate)
- return -EINVAL;
-
- for (index = 1; index < ARRAY_SIZE(divisors2); index++) {
- if (div2 > divisors2[index] && div2 <= divisors2[index])
- break;
- }
- if (index >= ARRAY_SIZE(divisors2))
- index = ARRAY_SIZE(divisors2) - 1;
- return divisors2[index];
-}
-
-static void sh7722_frqcr_recalc(struct clk *clk)
-{
- struct frqcr_context ctx = sh7722_get_clk_context(clk->name);
- unsigned long frqcr = ctrl_inl(FRQCR);
- int index;
-
- index = (frqcr >> ctx.shift) & ctx.mask;
- clk->rate = clk->parent->rate * 2 / divisors2[index];
-}
-
-static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate,
- int algo_id)
-{
- struct frqcr_context ctx = sh7722_get_clk_context(clk->name);
- unsigned long parent_rate = clk->parent->rate;
- int div;
- unsigned long frqcr;
- int err = 0;
-
- /* pretty invalid */
- if (parent_rate < rate)
- return -EINVAL;
-
- /* look for multiplier/divisor pair */
- div = sh7722_find_divisors(parent_rate, rate);
- if (div<0)
- return div;
-
- /* calculate new value of clock rate */
- clk->rate = parent_rate * 2 / div;
- frqcr = ctrl_inl(FRQCR);
-
- /* FIXME: adjust as algo_id specifies */
- if (algo_id != NO_CHANGE) {
- int originator;
- char *algo_group_1[] = { "cpu_clk", "umem_clk", "sh_clk" };
- char *algo_group_2[] = { "sh_clk", "bus_clk" };
- char *algo_group_3[] = { "sh_clk", "sdram_clk" };
- char *algo_group_4[] = { "bus_clk", "peripheral_clk" };
- char *algo_group_5[] = { "cpu_clk", "peripheral_clk" };
- char **algo_current = NULL;
- /* 3 is the maximum number of clocks in relation */
- struct clk *ck[3];
- unsigned long values[3]; /* the same comment as above */
- int part_length = -1;
- int i;
-
- /*
- * all the steps below only required if adjustion was
- * requested
- */
- if (algo_id == IUS_N1_N1 ||
- algo_id == IUS_322 ||
- algo_id == IUS_522 ||
- algo_id == IUS_N11) {
- algo_current = algo_group_1;
- part_length = 3;
- }
- if (algo_id == SB_N1) {
- algo_current = algo_group_2;
- part_length = 2;
- }
- if (algo_id == SB3_N1 ||
- algo_id == SB3_32 ||
- algo_id == SB3_43 ||
- algo_id == SB3_54) {
- algo_current = algo_group_3;
- part_length = 2;
- }
- if (algo_id == BP_N1) {
- algo_current = algo_group_4;
- part_length = 2;
- }
- if (algo_id == IP_N1) {
- algo_current = algo_group_5;
- part_length = 2;
- }
- if (!algo_current)
- goto incorrect_algo_id;
-
- originator = -1;
- for (i = 0; i < part_length; i ++ ) {
- if (originator >= 0 && !strcmp(clk->name,
- algo_current[i]))
- originator = i;
- ck[i] = clk_get(NULL, algo_current[i]);
- values[i] = clk_get_rate(ck[i]);
- }
-
- if (originator >= 0)
- adjust_clocks(originator, adjust_algos[algo_id],
- values, part_length);
-
- for (i = 0; i < part_length; i ++ ) {
- struct frqcr_context part_ctx;
- int part_div;
-
- if (likely(!err)) {
- part_div = sh7722_find_divisors(parent_rate,
- rate);
- if (part_div > 0) {
- part_ctx = sh7722_get_clk_context(
- ck[i]->name);
- frqcr &= ~(part_ctx.mask <<
- part_ctx.shift);
- frqcr |= part_div << part_ctx.shift;
- } else
- err = part_div;
- }
-
- ck[i]->ops->recalc(ck[i]);
- clk_put(ck[i]);
- }
- }
-
- /* was there any error during recalculation ? If so, bail out.. */
- if (unlikely(err!=0))
- goto out_err;
-
- /* clear FRQCR bits */
- frqcr &= ~(ctx.mask << ctx.shift);
- frqcr |= div << ctx.shift;
-
- /* ...and perform actual change */
- ctrl_outl(frqcr, FRQCR);
- return 0;
-
-incorrect_algo_id:
- return -EINVAL;
-out_err:
- return err;
-}
-
-static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate)
-{
- unsigned long parent_rate = clk->parent->rate;
- int div;
-
- /* look for multiplier/divisor pair */
- div = sh7722_find_divisors(parent_rate, rate);
- if (div < 0)
- return clk->rate;
-
- /* calculate new value of clock rate */
- return parent_rate * 2 / div;
-}
-
-static struct clk_ops sh7722_frqcr_clk_ops = {
- .recalc = sh7722_frqcr_recalc,
- .set_rate = sh7722_frqcr_set_rate,
- .round_rate = sh7722_frqcr_round_rate,
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+ .multipliers = multipliers,
+ .nr_multipliers = ARRAY_SIZE(multipliers),
};
-/*
- * clock ops methods for SIU A/B and IrDA clock
- *
- */
-
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
-
-static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id)
-{
- unsigned long r;
- int div;
-
- r = ctrl_inl(clk->arch_flags);
- div = sh7722_find_divisors(clk->parent->rate, rate);
- if (div < 0)
- return div;
- r = (r & ~0xF) | div;
- ctrl_outl(r, clk->arch_flags);
- return 0;
-}
-
-static void sh7722_siu_recalc(struct clk *clk)
-{
- unsigned long r;
-
- r = ctrl_inl(clk->arch_flags);
- clk->rate = clk->parent->rate * 2 / divisors2[r & 0xF];
-}
-
-static int sh7722_siu_start_stop(struct clk *clk, int enable)
-{
- unsigned long r;
-
- r = ctrl_inl(clk->arch_flags);
- if (enable)
- ctrl_outl(r & ~(1 << 8), clk->arch_flags);
- else
- ctrl_outl(r | (1 << 8), clk->arch_flags);
- return 0;
-}
-
-static void sh7722_siu_enable(struct clk *clk)
-{
- sh7722_siu_start_stop(clk, 1);
-}
-
-static void sh7722_siu_disable(struct clk *clk)
-{
- sh7722_siu_start_stop(clk, 0);
-}
-
-static struct clk_ops sh7722_siu_clk_ops = {
- .recalc = sh7722_siu_recalc,
- .set_rate = sh7722_siu_set_rate,
- .enable = sh7722_siu_enable,
- .disable = sh7722_siu_disable,
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
};
-#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
-
-static void sh7722_video_enable(struct clk *clk)
-{
- unsigned long r;
-
- r = ctrl_inl(VCLKCR);
- ctrl_outl( r & ~(1<<8), VCLKCR);
-}
-
-static void sh7722_video_disable(struct clk *clk)
-{
- unsigned long r;
-
- r = ctrl_inl(VCLKCR);
- ctrl_outl( r | (1<<8), VCLKCR);
-}
-
-static int sh7722_video_set_rate(struct clk *clk, unsigned long rate,
- int algo_id)
-{
- unsigned long r;
-
- r = ctrl_inl(VCLKCR);
- r &= ~0x3F;
- r |= ((clk->parent->rate / rate - 1) & 0x3F);
- ctrl_outl(r, VCLKCR);
- return 0;
-}
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
-static void sh7722_video_recalc(struct clk *clk)
-{
- unsigned long r;
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
- r = ctrl_inl(VCLKCR);
- clk->rate = clk->parent->rate / ((r & 0x3F) + 1);
-}
-
-static struct clk_ops sh7722_video_clk_ops = {
- .recalc = sh7722_video_recalc,
- .set_rate = sh7722_video_set_rate,
- .enable = sh7722_video_enable,
- .disable = sh7722_video_disable,
-};
-/*
- * and at last, clock definitions themselves
- */
-static struct clk sh7722_umem_clock = {
- .name = "umem_clk",
- .ops = &sh7722_frqcr_clk_ops,
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),
+ [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),
};
-static struct clk sh7722_sh_clock = {
- .name = "sh_clk",
- .ops = &sh7722_frqcr_clk_ops,
-};
+enum { DIV4_IRDA, DIV4_ENABLE_NR };
-static struct clk sh7722_peripheral_clock = {
- .name = "peripheral_clk",
- .ops = &sh7722_frqcr_clk_ops,
+struct clk div4_enable_clks[DIV4_ENABLE_NR] = {
+ [DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x1fff, 0),
};
-static struct clk sh7722_sdram_clock = {
- .name = "sdram_clk",
- .ops = &sh7722_frqcr_clk_ops,
-};
+enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
-
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
-
-/*
- * these three clocks - SIU A, SIU B, IrDA - share the same clk_ops
- * methods of clk_ops determine which register they should access by
- * examining clk->name field
- */
-static struct clk sh7722_siu_a_clock = {
- .name = "siu_a_clk",
- .arch_flags = SCLKACR,
- .ops = &sh7722_siu_clk_ops,
+struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
+ [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),
+ [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),
};
-static struct clk sh7722_siu_b_clock = {
- .name = "siu_b_clk",
- .arch_flags = SCLKBCR,
- .ops = &sh7722_siu_clk_ops,
+enum { DIV6_V, DIV6_NR };
+
+struct clk div6_clks[DIV6_NR] = {
+ [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
};
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
-static struct clk sh7722_irda_clock = {
- .name = "irda_clk",
- .arch_flags = IrDACLKCR,
- .ops = &sh7722_siu_clk_ops,
+static struct clk mstp_clks[HWBLK_NR] = {
+ [HWBLK_URAM] = SH_CLK_MSTP32(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+ [HWBLK_XYMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+ [HWBLK_TMU] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [HWBLK_CMT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 14, 0),
+ [HWBLK_RWDT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 13, 0),
+ [HWBLK_FLCTL] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [HWBLK_SCIF0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+ [HWBLK_SCIF1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 6, 0),
+ [HWBLK_SCIF2] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
+
+ [HWBLK_IIC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+ [HWBLK_RTC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 8, 0),
+
+ [HWBLK_SDHI] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 18, 0),
+ [HWBLK_KEYSC] = SH_CLK_MSTP32(&r_clk, MSTPCR2, 14, 0),
+ [HWBLK_USBF] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 11, 0),
+ [HWBLK_2DG] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 9, 0),
+ [HWBLK_SIU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 8, 0),
+ [HWBLK_JPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 6, 0),
+ [HWBLK_VOU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
+ [HWBLK_BEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
+ [HWBLK_CEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
+ [HWBLK_VEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 2, 0),
+ [HWBLK_VPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 1, 0),
+ [HWBLK_LCDC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 0, 0),
};
-#endif
-#endif /* CONFIG_CPU_SUBTYPE_SH7343 */
-static struct clk sh7722_video_clock = {
- .name = "video_clk",
- .ops = &sh7722_video_clk_ops,
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("dll_clk", &dll_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]),
+ CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]),
+ CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
+
+ /* MSTP clocks */
+ CLKDEV_CON_ID("uram0", &mstp_clks[HWBLK_URAM]),
+ CLKDEV_CON_ID("xymem0", &mstp_clks[HWBLK_XYMEM]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU]),
+
+ CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),
+ CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
+ CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
+
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI]),
+ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[HWBLK_KEYSC]),
+ CLKDEV_CON_ID("usbf0", &mstp_clks[HWBLK_USBF]),
+ CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]),
+ CLKDEV_DEV_ID("siu-pcm-audio", &mstp_clks[HWBLK_SIU]),
+ CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]),
+ CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]),
+ CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]),
+ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU]),
+ CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU]),
+ CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),
+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),
};
-static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg,
- int enable)
+int __init arch_clk_init(void)
{
- unsigned long bit = clk->arch_flags;
- unsigned long r;
+ int k, ret = 0;
- r = ctrl_inl(reg);
-
- if (enable)
- r &= ~(1 << bit);
+ /* autodetect extal or dll configuration */
+ if (__raw_readl(PLLCR) & 0x1000)
+ pll_clk.parent = &dll_clk;
else
- r |= (1 << bit);
+ pll_clk.parent = &extal_clk;
- ctrl_outl(r, reg);
- return 0;
-}
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
-static void sh7722_mstpcr0_enable(struct clk *clk)
-{
- sh7722_mstpcr_start_stop(clk, MSTPCR0, 1);
-}
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-static void sh7722_mstpcr0_disable(struct clk *clk)
-{
- sh7722_mstpcr_start_stop(clk, MSTPCR0, 0);
-}
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
-static void sh7722_mstpcr1_enable(struct clk *clk)
-{
- sh7722_mstpcr_start_stop(clk, MSTPCR1, 1);
-}
+ if (!ret)
+ ret = sh_clk_div4_enable_register(div4_enable_clks,
+ DIV4_ENABLE_NR, &div4_table);
-static void sh7722_mstpcr1_disable(struct clk *clk)
-{
- sh7722_mstpcr_start_stop(clk, MSTPCR1, 0);
-}
+ if (!ret)
+ ret = sh_clk_div4_reparent_register(div4_reparent_clks,
+ DIV4_REPARENT_NR, &div4_table);
-static void sh7722_mstpcr2_enable(struct clk *clk)
-{
- sh7722_mstpcr_start_stop(clk, MSTPCR2, 1);
-}
-
-static void sh7722_mstpcr2_disable(struct clk *clk)
-{
- sh7722_mstpcr_start_stop(clk, MSTPCR2, 0);
-}
+ if (!ret)
+ ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-static struct clk_ops sh7722_mstpcr0_clk_ops = {
- .enable = sh7722_mstpcr0_enable,
- .disable = sh7722_mstpcr0_disable,
-};
-
-static struct clk_ops sh7722_mstpcr1_clk_ops = {
- .enable = sh7722_mstpcr1_enable,
- .disable = sh7722_mstpcr1_disable,
-};
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR);
-static struct clk_ops sh7722_mstpcr2_clk_ops = {
- .enable = sh7722_mstpcr2_enable,
- .disable = sh7722_mstpcr2_disable,
-};
-
-#define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \
-{ \
- .name = "mstp" __stringify(regnr) bitstr, \
- .arch_flags = bitnr, \
- .ops = &sh7722_mstpcr ## regnr ## _clk_ops, \
-}
-
-#define DECLARE_MSTPCR(regnr) \
- DECLARE_MSTPCRN(regnr, 31, "31"), \
- DECLARE_MSTPCRN(regnr, 30, "30"), \
- DECLARE_MSTPCRN(regnr, 29, "29"), \
- DECLARE_MSTPCRN(regnr, 28, "28"), \
- DECLARE_MSTPCRN(regnr, 27, "27"), \
- DECLARE_MSTPCRN(regnr, 26, "26"), \
- DECLARE_MSTPCRN(regnr, 25, "25"), \
- DECLARE_MSTPCRN(regnr, 24, "24"), \
- DECLARE_MSTPCRN(regnr, 23, "23"), \
- DECLARE_MSTPCRN(regnr, 22, "22"), \
- DECLARE_MSTPCRN(regnr, 21, "21"), \
- DECLARE_MSTPCRN(regnr, 20, "20"), \
- DECLARE_MSTPCRN(regnr, 19, "19"), \
- DECLARE_MSTPCRN(regnr, 18, "18"), \
- DECLARE_MSTPCRN(regnr, 17, "17"), \
- DECLARE_MSTPCRN(regnr, 16, "16"), \
- DECLARE_MSTPCRN(regnr, 15, "15"), \
- DECLARE_MSTPCRN(regnr, 14, "14"), \
- DECLARE_MSTPCRN(regnr, 13, "13"), \
- DECLARE_MSTPCRN(regnr, 12, "12"), \
- DECLARE_MSTPCRN(regnr, 11, "11"), \
- DECLARE_MSTPCRN(regnr, 10, "10"), \
- DECLARE_MSTPCRN(regnr, 9, "09"), \
- DECLARE_MSTPCRN(regnr, 8, "08"), \
- DECLARE_MSTPCRN(regnr, 7, "07"), \
- DECLARE_MSTPCRN(regnr, 6, "06"), \
- DECLARE_MSTPCRN(regnr, 5, "05"), \
- DECLARE_MSTPCRN(regnr, 4, "04"), \
- DECLARE_MSTPCRN(regnr, 3, "03"), \
- DECLARE_MSTPCRN(regnr, 2, "02"), \
- DECLARE_MSTPCRN(regnr, 1, "01"), \
- DECLARE_MSTPCRN(regnr, 0, "00")
-
-static struct clk sh7722_mstpcr[] = {
- DECLARE_MSTPCR(0),
- DECLARE_MSTPCR(1),
- DECLARE_MSTPCR(2),
-};
-
-static struct clk *sh7722_clocks[] = {
- &sh7722_umem_clock,
- &sh7722_sh_clock,
- &sh7722_peripheral_clock,
- &sh7722_sdram_clock,
-#ifndef CONFIG_CPU_SUBTYPE_SH7343
- &sh7722_siu_a_clock,
- &sh7722_siu_b_clock,
-#if defined(CONFIG_CPU_SUBTYPE_SH7722)
- &sh7722_irda_clock,
-#endif
-#endif
- &sh7722_video_clock,
-};
-
-/*
- * init in order: master, module, bus, cpu
- */
-struct clk_ops *onchip_ops[] = {
- &sh7722_master_clk_ops,
- &sh7722_module_clk_ops,
- &sh7722_frqcr_clk_ops,
- &sh7722_frqcr_clk_ops,
-};
-
-void __init
-arch_init_clk_ops(struct clk_ops **ops, int type)
-{
- BUG_ON(type < 0 || type > ARRAY_SIZE(onchip_ops));
- *ops = onchip_ops[type];
-}
-
-int __init arch_clk_init(void)
-{
- struct clk *master;
- int i;
-
- master = clk_get(NULL, "master_clk");
- for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) {
- pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name);
- sh7722_clocks[i]->parent = master;
- clk_register(sh7722_clocks[i]);
- }
- clk_put(master);
-
- for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) {
- pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name);
- clk_register(&sh7722_mstpcr[i]);
- }
-
- return 0;
+ return ret;
}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
new file mode 100644
index 00000000000..ccbcab550df
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c
@@ -0,0 +1,313 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7723.c
+ *
+ * SH7723 clock framework support
+ *
+ * Copyright (C) 2009 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; either 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/sh_clk.h>
+#include <asm/clock.h>
+#include <cpu/sh7723.h>
+
+/* SH7723 registers */
+#define FRQCR 0xa4150000
+#define VCLKCR 0xa4150004
+#define SCLKACR 0xa4150008
+#define SCLKBCR 0xa415000c
+#define IRDACLKCR 0xa4150018
+#define PLLCR 0xa4150024
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+#define DLLFRQ 0xa4150050
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+/* The dll multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long dll_recalc(struct clk *clk)
+{
+ unsigned long mult;
+
+ if (__raw_readl(PLLCR) & 0x1000)
+ mult = __raw_readl(DLLFRQ);
+ else
+ mult = 0;
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops dll_clk_ops = {
+ .recalc = dll_recalc,
+};
+
+static struct clk dll_clk = {
+ .ops = &dll_clk_ops,
+ .parent = &r_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long mult = 1;
+ unsigned long div = 1;
+
+ if (__raw_readl(PLLCR) & 0x4000)
+ mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);
+ else
+ div = 2;
+
+ return (clk->parent->rate * mult) / div;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &dll_clk,
+ &pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+ .multipliers = multipliers,
+ .nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT),
+ [DIV4_U] = DIV4(FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT),
+ [DIV4_B3] = DIV4(FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCR, 0, 0x0dbf, 0),
+};
+
+enum { DIV4_IRDA, DIV4_ENABLE_NR };
+
+struct clk div4_enable_clks[DIV4_ENABLE_NR] = {
+ [DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x0dbf, 0),
+};
+
+enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };
+
+struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {
+ [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x0dbf, 0),
+ [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x0dbf, 0),
+};
+enum { DIV6_V, DIV6_NR };
+
+struct clk div6_clks[DIV6_NR] = {
+ [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),
+};
+
+static struct clk mstp_clks[] = {
+ /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */
+ [HWBLK_TLB] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
+ [HWBLK_IC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
+ [HWBLK_OC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
+ [HWBLK_L2C] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+ [HWBLK_ILMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 27, CLK_ENABLE_ON_INIT),
+ [HWBLK_FPU] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 24, CLK_ENABLE_ON_INIT),
+ [HWBLK_INTC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 22, CLK_ENABLE_ON_INIT),
+ [HWBLK_DMAC0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 21, 0),
+ [HWBLK_SHYWAY] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 20, CLK_ENABLE_ON_INIT),
+ [HWBLK_HUDI] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
+ [HWBLK_UBC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 17, 0),
+ [HWBLK_TMU0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [HWBLK_CMT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 14, 0),
+ [HWBLK_RWDT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 13, 0),
+ [HWBLK_DMAC1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 12, 0),
+ [HWBLK_TMU1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
+ [HWBLK_FLCTL] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [HWBLK_SCIF0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [HWBLK_SCIF1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [HWBLK_SCIF2] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+ [HWBLK_SCIF3] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 6, 0),
+ [HWBLK_SCIF4] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 5, 0),
+ [HWBLK_SCIF5] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 4, 0),
+ [HWBLK_MSIOF0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 2, 0),
+ [HWBLK_MSIOF1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 1, 0),
+ [HWBLK_MERAM] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 0, 0),
+
+ [HWBLK_IIC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+ [HWBLK_RTC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 8, 0),
+
+ [HWBLK_ATAPI] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR2, 28, 0),
+ [HWBLK_ADC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 27, 0),
+ [HWBLK_TPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 25, 0),
+ [HWBLK_IRDA] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
+ [HWBLK_TSIF] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 22, 0),
+ [HWBLK_ICB] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 21, CLK_ENABLE_ON_INIT),
+ [HWBLK_SDHI0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 18, 0),
+ [HWBLK_SDHI1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 17, 0),
+ [HWBLK_KEYSC] = SH_CLK_MSTP32(&r_clk, MSTPCR2, 14, 0),
+ [HWBLK_USB] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 11, 0),
+ [HWBLK_2DG] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 10, 0),
+ [HWBLK_SIU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 8, 0),
+ [HWBLK_VEU2H1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 6, 0),
+ [HWBLK_VOU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
+ [HWBLK_BEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
+ [HWBLK_CEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
+ [HWBLK_VEU2H0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 2, 0),
+ [HWBLK_VPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 1, 0),
+ [HWBLK_LCDC] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("dll_clk", &dll_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]),
+ CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]),
+ CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
+
+ /* MSTP clocks */
+ CLKDEV_CON_ID("tlb0", &mstp_clks[HWBLK_TLB]),
+ CLKDEV_CON_ID("ic0", &mstp_clks[HWBLK_IC]),
+ CLKDEV_CON_ID("oc0", &mstp_clks[HWBLK_OC]),
+ CLKDEV_CON_ID("l2c0", &mstp_clks[HWBLK_L2C]),
+ CLKDEV_CON_ID("ilmem0", &mstp_clks[HWBLK_ILMEM]),
+ CLKDEV_CON_ID("fpu0", &mstp_clks[HWBLK_FPU]),
+ CLKDEV_CON_ID("intc0", &mstp_clks[HWBLK_INTC]),
+ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[HWBLK_DMAC0]),
+ CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]),
+ CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]),
+ CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]),
+ CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),
+ CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
+ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]),
+ CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
+ CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[HWBLK_MSIOF0]),
+ CLKDEV_DEV_ID("spi_sh_msiof.1", &mstp_clks[HWBLK_MSIOF1]),
+ CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[HWBLK_MERAM]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
+ CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[HWBLK_ADC]),
+ CLKDEV_CON_ID("tpu0", &mstp_clks[HWBLK_TPU]),
+ CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]),
+ CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]),
+ CLKDEV_CON_ID("icb0", &mstp_clks[HWBLK_ICB]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]),
+ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[HWBLK_KEYSC]),
+ CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB]),
+ CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]),
+ CLKDEV_DEV_ID("siu-pcm-audio", &mstp_clks[HWBLK_SIU]),
+ CLKDEV_CON_ID("veu1", &mstp_clks[HWBLK_VEU2H1]),
+ CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]),
+ CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]),
+ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU]),
+ CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU2H0]),
+ CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU0]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]),
+
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
+
+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ /* autodetect extal or dll configuration */
+ if (__raw_readl(PLLCR) & 0x1000)
+ pll_clk.parent = &dll_clk;
+ else
+ pll_clk.parent = &extal_clk;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret |= clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div4_enable_register(div4_enable_clks,
+ DIV4_ENABLE_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div4_reparent_register(div4_reparent_clks,
+ DIV4_REPARENT_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
new file mode 100644
index 00000000000..f579dd52819
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c
@@ -0,0 +1,377 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7724.c
+ *
+ * SH7724 clock framework support
+ *
+ * Copyright (C) 2009 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; either 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/sh_clk.h>
+#include <asm/clock.h>
+#include <cpu/sh7724.h>
+
+/* SH7724 registers */
+#define FRQCRA 0xa4150000
+#define FRQCRB 0xa4150004
+#define VCLKCR 0xa4150048
+#define FCLKACR 0xa4150008
+#define FCLKBCR 0xa415000c
+#define IRDACLKCR 0xa4150018
+#define PLLCR 0xa4150024
+#define MSTPCR0 0xa4150030
+#define MSTPCR1 0xa4150034
+#define MSTPCR2 0xa4150038
+#define SPUCLKCR 0xa415003c
+#define FLLFRQ 0xa4150050
+#define LSTATS 0xa4150060
+
+/* Fixed 32 KHz root clock for RTC and Power Management purposes */
+static struct clk r_clk = {
+ .rate = 32768,
+};
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+/* The fll multiplies the 32khz r_clk, may be used instead of extal */
+static unsigned long fll_recalc(struct clk *clk)
+{
+ unsigned long mult = 0;
+ unsigned long div = 1;
+
+ if (__raw_readl(PLLCR) & 0x1000)
+ mult = __raw_readl(FLLFRQ) & 0x3ff;
+
+ if (__raw_readl(FLLFRQ) & 0x4000)
+ div = 2;
+
+ return (clk->parent->rate * mult) / div;
+}
+
+static struct sh_clk_ops fll_clk_ops = {
+ .recalc = fll_recalc,
+};
+
+static struct clk fll_clk = {
+ .ops = &fll_clk_ops,
+ .parent = &r_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ unsigned long mult = 1;
+
+ if (__raw_readl(PLLCR) & 0x4000)
+ mult = (((__raw_readl(FRQCRA) >> 24) & 0x3f) + 1) * 2;
+
+ return clk->parent->rate * mult;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+/* A fixed divide-by-3 block use by the div6 clocks */
+static unsigned long div3_recalc(struct clk *clk)
+{
+ return clk->parent->rate / 3;
+}
+
+static struct sh_clk_ops div3_clk_ops = {
+ .recalc = div3_recalc,
+};
+
+static struct clk div3_clk = {
+ .ops = &div3_clk_ops,
+ .parent = &pll_clk,
+};
+
+/* External input clock (pin name: FSIMCKA/FSIMCKB/DV_CLKI ) */
+struct clk sh7724_fsimcka_clk = {
+};
+
+struct clk sh7724_fsimckb_clk = {
+};
+
+struct clk sh7724_dv_clki = {
+};
+
+static struct clk *main_clks[] = {
+ &r_clk,
+ &extal_clk,
+ &fll_clk,
+ &pll_clk,
+ &div3_clk,
+ &sh7724_fsimcka_clk,
+ &sh7724_fsimckb_clk,
+ &sh7724_dv_clki,
+};
+
+static void div4_kick(struct clk *clk)
+{
+ unsigned long value;
+
+ /* set KICK bit in FRQCRA to update hardware setting */
+ value = __raw_readl(FRQCRA);
+ value |= (1 << 31);
+ __raw_writel(value, FRQCRA);
+}
+
+static int divisors[] = { 2, 3, 4, 6, 8, 12, 16, 0, 24, 32, 36, 48, 0, 72 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+ .kick = div4_kick,
+};
+
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQCRA, 0, 0x2f7c, 0),
+ [DIV4_M1] = DIV4(FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
+};
+
+enum { DIV6_V, DIV6_I, DIV6_S, DIV6_FA, DIV6_FB, DIV6_NR };
+
+/* Indices are important - they are the actual src selecting values */
+static struct clk *common_parent[] = {
+ [0] = &div3_clk,
+ [1] = NULL,
+};
+
+static struct clk *vclkcr_parent[8] = {
+ [0] = &div3_clk,
+ [2] = &sh7724_dv_clki,
+ [4] = &extal_clk,
+};
+
+static struct clk *fclkacr_parent[] = {
+ [0] = &div3_clk,
+ [1] = NULL,
+ [2] = &sh7724_fsimcka_clk,
+ [3] = NULL,
+};
+
+static struct clk *fclkbcr_parent[] = {
+ [0] = &div3_clk,
+ [1] = NULL,
+ [2] = &sh7724_fsimckb_clk,
+ [3] = NULL,
+};
+
+static struct clk div6_clks[DIV6_NR] = {
+ [DIV6_V] = SH_CLK_DIV6_EXT(VCLKCR, 0,
+ vclkcr_parent, ARRAY_SIZE(vclkcr_parent), 12, 3),
+ [DIV6_I] = SH_CLK_DIV6_EXT(IRDACLKCR, 0,
+ common_parent, ARRAY_SIZE(common_parent), 6, 1),
+ [DIV6_S] = SH_CLK_DIV6_EXT(SPUCLKCR, CLK_ENABLE_ON_INIT,
+ common_parent, ARRAY_SIZE(common_parent), 6, 1),
+ [DIV6_FA] = SH_CLK_DIV6_EXT(FCLKACR, 0,
+ fclkacr_parent, ARRAY_SIZE(fclkacr_parent), 6, 2),
+ [DIV6_FB] = SH_CLK_DIV6_EXT(FCLKBCR, 0,
+ fclkbcr_parent, ARRAY_SIZE(fclkbcr_parent), 6, 2),
+};
+
+static struct clk mstp_clks[HWBLK_NR] = {
+ [HWBLK_TLB] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT),
+ [HWBLK_IC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT),
+ [HWBLK_OC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT),
+ [HWBLK_RSMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 28, CLK_ENABLE_ON_INIT),
+ [HWBLK_ILMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 27, CLK_ENABLE_ON_INIT),
+ [HWBLK_L2C] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 26, CLK_ENABLE_ON_INIT),
+ [HWBLK_FPU] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 24, CLK_ENABLE_ON_INIT),
+ [HWBLK_INTC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, CLK_ENABLE_ON_INIT),
+ [HWBLK_DMAC0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 21, 0),
+ [HWBLK_SHYWAY] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 20, CLK_ENABLE_ON_INIT),
+ [HWBLK_HUDI] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
+ [HWBLK_UBC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 17, 0),
+ [HWBLK_TMU0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [HWBLK_CMT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 14, 0),
+ [HWBLK_RWDT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 13, 0),
+ [HWBLK_DMAC1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 12, 0),
+ [HWBLK_TMU1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [HWBLK_SCIF0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [HWBLK_SCIF1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [HWBLK_SCIF2] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+ [HWBLK_SCIF3] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 6, 0),
+ [HWBLK_SCIF4] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 5, 0),
+ [HWBLK_SCIF5] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 4, 0),
+ [HWBLK_MSIOF0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 2, 0),
+ [HWBLK_MSIOF1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 1, 0),
+
+ [HWBLK_KEYSC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 12, 0),
+ [HWBLK_RTC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 11, 0),
+ [HWBLK_IIC0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+ [HWBLK_IIC1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
+
+ [HWBLK_MMC] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 29, 0),
+ [HWBLK_ETHER] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 28, 0),
+ [HWBLK_ATAPI] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 26, 0),
+ [HWBLK_TPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 25, 0),
+ [HWBLK_IRDA] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 24, 0),
+ [HWBLK_TSIF] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 22, 0),
+ [HWBLK_USB1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 21, 0),
+ [HWBLK_USB0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 20, 0),
+ [HWBLK_2DG] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 19, 0),
+ [HWBLK_SDHI0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 18, 0),
+ [HWBLK_SDHI1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 17, 0),
+ [HWBLK_VEU1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 15, 0),
+ [HWBLK_CEU1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 13, 0),
+ [HWBLK_BEU1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 12, 0),
+ [HWBLK_2DDMAC] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR2, 10, 0),
+ [HWBLK_SPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 9, 0),
+ [HWBLK_JPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 6, 0),
+ [HWBLK_VOU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 5, 0),
+ [HWBLK_BEU0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 4, 0),
+ [HWBLK_CEU0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 3, 0),
+ [HWBLK_VEU0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 2, 0),
+ [HWBLK_VPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 1, 0),
+ [HWBLK_LCDC] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 0, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("rclk", &r_clk),
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("fll_clk", &fll_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+ CLKDEV_CON_ID("div3_clk", &div3_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("vpu_clk", &div4_clks[DIV4_M1]),
+
+ /* DIV6 clocks */
+ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
+ CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]),
+ CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FB]),
+ CLKDEV_CON_ID("irda_clk", &div6_clks[DIV6_I]),
+ CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_S]),
+
+ /* MSTP clocks */
+ CLKDEV_CON_ID("tlb0", &mstp_clks[HWBLK_TLB]),
+ CLKDEV_CON_ID("ic0", &mstp_clks[HWBLK_IC]),
+ CLKDEV_CON_ID("oc0", &mstp_clks[HWBLK_OC]),
+ CLKDEV_CON_ID("rs0", &mstp_clks[HWBLK_RSMEM]),
+ CLKDEV_CON_ID("ilmem0", &mstp_clks[HWBLK_ILMEM]),
+ CLKDEV_CON_ID("l2c0", &mstp_clks[HWBLK_L2C]),
+ CLKDEV_CON_ID("fpu0", &mstp_clks[HWBLK_FPU]),
+ CLKDEV_CON_ID("intc0", &mstp_clks[HWBLK_INTC]),
+ CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[HWBLK_DMAC0]),
+ CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]),
+ CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]),
+ CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU0]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[HWBLK_TMU1]),
+
+ CLKDEV_ICK_ID("fck", "sh-cmt-16.0", &mstp_clks[HWBLK_CMT]),
+ CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),
+ CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]),
+
+ CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+ CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+ CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+ CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
+ CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
+ CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
+
+ CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[HWBLK_MSIOF0]),
+ CLKDEV_DEV_ID("spi_sh_msiof.1", &mstp_clks[HWBLK_MSIOF1]),
+ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[HWBLK_KEYSC]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC0]),
+ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[HWBLK_IIC1]),
+ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[HWBLK_MMC]),
+ CLKDEV_DEV_ID("sh7724-ether.0", &mstp_clks[HWBLK_ETHER]),
+ CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]),
+ CLKDEV_CON_ID("tpu0", &mstp_clks[HWBLK_TPU]),
+ CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]),
+ CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]),
+ CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[HWBLK_USB1]),
+ CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[HWBLK_USB0]),
+ CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]),
+ CLKDEV_CON_ID("veu1", &mstp_clks[HWBLK_VEU1]),
+ CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[HWBLK_CEU1]),
+ CLKDEV_CON_ID("beu1", &mstp_clks[HWBLK_BEU1]),
+ CLKDEV_CON_ID("2ddmac0", &mstp_clks[HWBLK_2DDMAC]),
+ CLKDEV_DEV_ID("sh_fsi.0", &mstp_clks[HWBLK_SPU]),
+ CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]),
+ CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]),
+ CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU0]),
+ CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU0]),
+ CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU0]),
+ CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),
+ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),
+};
+
+int __init arch_clk_init(void)
+{
+ int k, ret = 0;
+
+ /* autodetect extal or fll configuration */
+ if (__raw_readl(PLLCR) & 0x1000)
+ pll_clk.parent = &fll_clk;
+ else
+ pll_clk.parent = &extal_clk;
+
+ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
+ ret = clk_register(main_clks[k]);
+
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
+
+ if (!ret)
+ ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7734.c b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c
new file mode 100644
index 00000000000..1fdf1ee672d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7734.c
@@ -0,0 +1,260 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7734.c
+ *
+ * Clock framework for SH7734
+ *
+ * Copyright (C) 2011, 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2011, 2012 Renesas Solutions Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+static struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+#define MODEMR (0xFFCC0020)
+#define MODEMR_MASK (0x6)
+#define MODEMR_533MHZ (0x2)
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ int mode = 12;
+ u32 r = __raw_readl(MODEMR);
+
+ if ((r & MODEMR_MASK) & MODEMR_533MHZ)
+ mode = 16;
+
+ return clk->parent->rate * mode;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static struct clk *main_clks[] = {
+ &extal_clk,
+ &pll_clk,
+};
+
+static int multipliers[] = { 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = divisors,
+ .nr_divisors = ARRAY_SIZE(divisors),
+ .multipliers = multipliers,
+ .nr_multipliers = ARRAY_SIZE(multipliers),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_S, DIV4_B, DIV4_M, DIV4_S1, DIV4_P, DIV4_NR };
+
+#define DIV4(_reg, _bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_I] = DIV4(FRQMR1, 28, 0x0003, CLK_ENABLE_ON_INIT),
+ [DIV4_S] = DIV4(FRQMR1, 20, 0x000C, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(FRQMR1, 16, 0x0140, CLK_ENABLE_ON_INIT),
+ [DIV4_M] = DIV4(FRQMR1, 12, 0x0004, CLK_ENABLE_ON_INIT),
+ [DIV4_S1] = DIV4(FRQMR1, 4, 0x0030, CLK_ENABLE_ON_INIT),
+ [DIV4_P] = DIV4(FRQMR1, 0, 0x0140, CLK_ENABLE_ON_INIT),
+};
+
+#define MSTPCR0 0xFFC80030
+#define MSTPCR1 0xFFC80034
+#define MSTPCR3 0xFFC8003C
+
+enum {
+ MSTP030, MSTP029, /* IIC */
+ MSTP026, MSTP025, MSTP024, /* SCIF */
+ MSTP023,
+ MSTP022, MSTP021,
+ MSTP019, /* HSCIF */
+ MSTP016, MSTP015, MSTP014, /* TMU / TIMER */
+ MSTP012, MSTP011, MSTP010, MSTP009, MSTP008, /* SSI */
+ MSTP007, /* HSPI */
+ MSTP115, /* ADMAC */
+ MSTP114, /* GETHER */
+ MSTP111, /* DMAC */
+ MSTP109, /* VIDEOIN1 */
+ MSTP108, /* VIDEOIN0 */
+ MSTP107, /* RGPVBG */
+ MSTP106, /* 2DG */
+ MSTP103, /* VIEW */
+ MSTP100, /* USB */
+ MSTP331, /* MMC */
+ MSTP330, /* MIMLB */
+ MSTP323, /* SDHI0 */
+ MSTP322, /* SDHI1 */
+ MSTP321, /* SDHI2 */
+ MSTP320, /* RQSPI */
+ MSTP319, /* SRC0 */
+ MSTP318, /* SRC1 */
+ MSTP317, /* RSPI */
+ MSTP316, /* RCAN0 */
+ MSTP315, /* RCAN1 */
+ MSTP314, /* FLTCL */
+ MSTP313, /* ADC */
+ MSTP312, /* MTU */
+ MSTP304, /* IE-BUS */
+ MSTP303, /* RTC */
+ MSTP302, /* HIF */
+ MSTP301, /* STIF0 */
+ MSTP300, /* STIF1 */
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* MSTPCR0 */
+ [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0),
+ [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
+ [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+ [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+ [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+ [MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
+ [MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
+ [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
+ [MSTP019] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 19, 0),
+ [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
+ [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0),
+ [MSTP012] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 12, 0),
+ [MSTP011] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
+ [MSTP010] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [MSTP007] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0),
+
+ /* MSTPCR1 */
+ [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0),
+ [MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0),
+ [MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0),
+ [MSTP109] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0),
+ [MSTP108] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 8, 0),
+ [MSTP107] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 7, 0),
+ [MSTP106] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 6, 0),
+ [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
+ [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 0, 0),
+
+ /* MSTPCR3 */
+ [MSTP331] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 31, 0),
+ [MSTP330] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 30, 0),
+ [MSTP323] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 23, 0),
+ [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0),
+ [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0),
+ [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0),
+ [MSTP319] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 19, 0),
+ [MSTP318] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 18, 0),
+ [MSTP317] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 17, 0),
+ [MSTP316] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 16, 0),
+ [MSTP315] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 15, 0),
+ [MSTP314] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 14, 0),
+ [MSTP313] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 13, 0),
+ [MSTP312] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 12, 0),
+ [MSTP304] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 4, 0),
+ [MSTP303] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 3, 0),
+ [MSTP302] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 2, 0),
+ [MSTP301] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 1, 0),
+ [MSTP300] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 0, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* clocks */
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_S]),
+ CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_M]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("shyway_clk1", &div4_clks[DIV4_S1]),
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("i2c-sh7734.0", &mstp_clks[MSTP030]),
+ CLKDEV_DEV_ID("i2c-sh7734.1", &mstp_clks[MSTP029]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP026]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP024]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP023]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP022]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP021]),
+ CLKDEV_CON_ID("hscif", &mstp_clks[MSTP019]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP016]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP015]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.2", &mstp_clks[MSTP014]),
+ CLKDEV_CON_ID("ssi0", &mstp_clks[MSTP012]),
+ CLKDEV_CON_ID("ssi1", &mstp_clks[MSTP011]),
+ CLKDEV_CON_ID("ssi2", &mstp_clks[MSTP010]),
+ CLKDEV_CON_ID("ssi3", &mstp_clks[MSTP009]),
+ CLKDEV_CON_ID("sss", &mstp_clks[MSTP008]),
+ CLKDEV_CON_ID("hspi", &mstp_clks[MSTP007]),
+ CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP100]),
+ CLKDEV_CON_ID("videoin0", &mstp_clks[MSTP109]),
+ CLKDEV_CON_ID("videoin1", &mstp_clks[MSTP108]),
+ CLKDEV_CON_ID("rgpvg", &mstp_clks[MSTP107]),
+ CLKDEV_CON_ID("2dg", &mstp_clks[MSTP106]),
+ CLKDEV_CON_ID("view", &mstp_clks[MSTP103]),
+
+ CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP331]),
+ CLKDEV_CON_ID("mimlb0", &mstp_clks[MSTP330]),
+ CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP323]),
+ CLKDEV_CON_ID("sdhi1", &mstp_clks[MSTP322]),
+ CLKDEV_CON_ID("sdhi2", &mstp_clks[MSTP321]),
+ CLKDEV_CON_ID("rqspi0", &mstp_clks[MSTP320]),
+ CLKDEV_CON_ID("src0", &mstp_clks[MSTP319]),
+ CLKDEV_CON_ID("src1", &mstp_clks[MSTP318]),
+ CLKDEV_CON_ID("rsp0", &mstp_clks[MSTP317]),
+ CLKDEV_CON_ID("rcan0", &mstp_clks[MSTP316]),
+ CLKDEV_CON_ID("rcan1", &mstp_clks[MSTP315]),
+ CLKDEV_CON_ID("fltcl0", &mstp_clks[MSTP314]),
+ CLKDEV_CON_ID("adc0", &mstp_clks[MSTP313]),
+ CLKDEV_CON_ID("mtu0", &mstp_clks[MSTP312]),
+ CLKDEV_CON_ID("iebus0", &mstp_clks[MSTP304]),
+ CLKDEV_DEV_ID("sh7734-gether.0", &mstp_clks[MSTP114]),
+ CLKDEV_CON_ID("rtc0", &mstp_clks[MSTP303]),
+ CLKDEV_CON_ID("hif0", &mstp_clks[MSTP302]),
+ CLKDEV_CON_ID("stif0", &mstp_clks[MSTP301]),
+ CLKDEV_CON_ID("stif1", &mstp_clks[MSTP300]),
+};
+
+int __init arch_clk_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(main_clks); i++)
+ ret |= clk_register(main_clks[i]);
+
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+ &div4_table);
+
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
new file mode 100644
index 00000000000..9a28fdb3638
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -0,0 +1,155 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7757.c
+ *
+ * SH7757 support for the clock framework
+ *
+ * Copyright (C) 2009-2010 Renesas Solutions Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 48000000,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ int multiplier;
+
+ multiplier = test_mode_pin(MODE_PIN0) ? 24 : 16;
+
+ return clk->parent->rate * multiplier;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static struct clk *clks[] = {
+ &extal_clk,
+ &pll_clk,
+};
+
+static unsigned int div2[] = { 1, 1, 2, 1, 1, 4, 1, 6,
+ 1, 1, 1, 16, 1, 24, 1, 1 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_SH, DIV4_P, DIV4_NR };
+
+#define DIV4(_bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, FRQCR, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ /*
+ * P clock is always enable, because some P clock modules is used
+ * by Host PC.
+ */
+ [DIV4_P] = DIV4(0, 0x2800, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(12, 0x00a0, CLK_ENABLE_ON_INIT),
+ [DIV4_I] = DIV4(20, 0x0004, CLK_ENABLE_ON_INIT),
+};
+
+#define MSTPCR0 0xffc80030
+#define MSTPCR1 0xffc80034
+#define MSTPCR2 0xffc10028
+
+enum { MSTP004, MSTP000, MSTP127, MSTP114, MSTP113, MSTP112,
+ MSTP111, MSTP110, MSTP103, MSTP102, MSTP220,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* MSTPCR0 */
+ [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
+ [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),
+
+ /* MSTPCR1 */
+ [MSTP127] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 27, 0),
+ [MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0),
+ [MSTP113] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 13, 0),
+ [MSTP112] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 12, 0),
+ [MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0),
+ [MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
+ [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
+ [MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
+
+ /* MSTPCR2 */
+ [MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+ /* MSTP32 clocks */
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP004]),
+ CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic3", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic4", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic5", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic6", &mstp_clks[MSTP000]),
+ CLKDEV_CON_ID("riic7", &mstp_clks[MSTP000]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP113]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP114]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP112]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP111]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
+
+ CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
+ CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]),
+ CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
+ CLKDEV_DEV_ID("rspi.2", &mstp_clks[MSTP127]),
+};
+
+int __init arch_clk_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ ret |= clk_register(clks[i]);
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+ &div4_table);
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
+
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
index 45889d412c8..7707e35aea4 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c
@@ -12,79 +12,74 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
#include <asm/clock.h>
#include <asm/freq.h>
#include <asm/io.h>
static int bfc_divisors[] = { 1, 1, 1, 8, 1, 1, 1, 1 };
static int p0fc_divisors[] = { 1, 1, 1, 8, 1, 1, 1, 1 };
-static int p1fc_divisors[] = { 1, 1, 1, 16, 1, 1, 1, 1 };
static int cfc_divisors[] = { 1, 1, 4, 1, 1, 1, 1, 1 };
static void master_clk_init(struct clk *clk)
{
- clk->rate *= p0fc_divisors[(ctrl_inl(FRQCR) >> 4) & 0x07];
+ clk->rate *= p0fc_divisors[(__raw_readl(FRQCR) >> 4) & 0x07];
}
-static struct clk_ops sh7763_master_clk_ops = {
+static struct sh_clk_ops sh7763_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_inl(FRQCR) >> 4) & 0x07);
- clk->rate = clk->parent->rate / p0fc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 4) & 0x07);
+ return clk->parent->rate / p0fc_divisors[idx];
}
-static struct clk_ops sh7763_module_clk_ops = {
+static struct sh_clk_ops sh7763_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_inl(FRQCR) >> 16) & 0x07);
- clk->rate = clk->parent->rate / bfc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 16) & 0x07);
+ return clk->parent->rate / bfc_divisors[idx];
}
-static struct clk_ops sh7763_bus_clk_ops = {
+static struct sh_clk_ops sh7763_bus_clk_ops = {
.recalc = bus_clk_recalc,
};
-static void cpu_clk_recalc(struct clk *clk)
-{
- clk->rate = clk->parent->rate;
-}
-
-static struct clk_ops sh7763_cpu_clk_ops = {
- .recalc = cpu_clk_recalc,
+static struct sh_clk_ops sh7763_cpu_clk_ops = {
+ .recalc = followparent_recalc,
};
-static struct clk_ops *sh7763_clk_ops[] = {
+static struct sh_clk_ops *sh7763_clk_ops[] = {
&sh7763_master_clk_ops,
&sh7763_module_clk_ops,
&sh7763_bus_clk_ops,
&sh7763_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7763_clk_ops))
*ops = sh7763_clk_ops[idx];
}
-static void shyway_clk_recalc(struct clk *clk)
+static unsigned long shyway_clk_recalc(struct clk *clk)
{
- int idx = ((ctrl_inl(FRQCR) >> 20) & 0x07);
- clk->rate = clk->parent->rate / cfc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 20) & 0x07);
+ return clk->parent->rate / cfc_divisors[idx];
}
-static struct clk_ops sh7763_shyway_clk_ops = {
+static struct sh_clk_ops sh7763_shyway_clk_ops = {
.recalc = shyway_clk_recalc,
};
static struct clk sh7763_shyway_clk = {
- .name = "shyway_clk",
- .flags = CLK_ALWAYS_ENABLED,
+ .flags = CLK_ENABLE_ON_INIT,
.ops = &sh7763_shyway_clk_ops,
};
@@ -96,31 +91,29 @@ static struct clk *sh7763_onchip_clocks[] = {
&sh7763_shyway_clk,
};
-static int __init sh7763_clk_init(void)
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("shyway_clk", &sh7763_shyway_clk),
+};
+
+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(sh7763_onchip_clocks); i++) {
struct clk *clkp = sh7763_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;
-}
-
-arch_initcall(sh7763_clk_init);
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
index 8e236062c72..5d36f334bb0 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
@@ -21,51 +21,51 @@ static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 };
static void master_clk_init(struct clk *clk)
{
- clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f];
+ clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> 28) & 0x000f];
}
-static struct clk_ops sh7770_master_clk_ops = {
+static struct sh_clk_ops sh7770_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_inl(FRQCR) >> 28) & 0x000f);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 28) & 0x000f);
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7770_module_clk_ops = {
+static struct sh_clk_ops sh7770_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_inl(FRQCR) & 0x000f);
- clk->rate = clk->parent->rate / bfc_divisors[idx];
+ int idx = (__raw_readl(FRQCR) & 0x000f);
+ return clk->parent->rate / bfc_divisors[idx];
}
-static struct clk_ops sh7770_bus_clk_ops = {
+static struct sh_clk_ops sh7770_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_inl(FRQCR) >> 24) & 0x000f);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 24) & 0x000f);
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh7770_cpu_clk_ops = {
+static struct sh_clk_ops sh7770_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7770_clk_ops[] = {
+static struct sh_clk_ops *sh7770_clk_ops[] = {
&sh7770_master_clk_ops,
&sh7770_module_clk_ops,
&sh7770_bus_clk_ops,
&sh7770_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7770_clk_ops))
*ops = sh7770_clk_ops[idx];
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
index 01f3da619d3..793dae42a2f 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
@@ -11,6 +11,8 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
#include <asm/clock.h>
#include <asm/freq.h>
#include <asm/io.h>
@@ -22,69 +24,68 @@ static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 };
static void master_clk_init(struct clk *clk)
{
- clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003];
+ clk->rate *= pfc_divisors[__raw_readl(FRQCR) & 0x0003];
}
-static struct clk_ops sh7780_master_clk_ops = {
+static struct sh_clk_ops sh7780_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_inl(FRQCR) & 0x0003);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ int idx = (__raw_readl(FRQCR) & 0x0003);
+ return clk->parent->rate / pfc_divisors[idx];
}
-static struct clk_ops sh7780_module_clk_ops = {
+static struct sh_clk_ops sh7780_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_inl(FRQCR) >> 16) & 0x0007);
- clk->rate = clk->parent->rate / bfc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 16) & 0x0007);
+ return clk->parent->rate / bfc_divisors[idx];
}
-static struct clk_ops sh7780_bus_clk_ops = {
+static struct sh_clk_ops sh7780_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_inl(FRQCR) >> 24) & 0x0001);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 24) & 0x0001);
+ return clk->parent->rate / ifc_divisors[idx];
}
-static struct clk_ops sh7780_cpu_clk_ops = {
+static struct sh_clk_ops sh7780_cpu_clk_ops = {
.recalc = cpu_clk_recalc,
};
-static struct clk_ops *sh7780_clk_ops[] = {
+static struct sh_clk_ops *sh7780_clk_ops[] = {
&sh7780_master_clk_ops,
&sh7780_module_clk_ops,
&sh7780_bus_clk_ops,
&sh7780_cpu_clk_ops,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
{
if (idx < ARRAY_SIZE(sh7780_clk_ops))
*ops = sh7780_clk_ops[idx];
}
-static void shyway_clk_recalc(struct clk *clk)
+static unsigned long shyway_clk_recalc(struct clk *clk)
{
- int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007);
- clk->rate = clk->parent->rate / cfc_divisors[idx];
+ int idx = ((__raw_readl(FRQCR) >> 20) & 0x0007);
+ return clk->parent->rate / cfc_divisors[idx];
}
-static struct clk_ops sh7780_shyway_clk_ops = {
+static struct sh_clk_ops sh7780_shyway_clk_ops = {
.recalc = shyway_clk_recalc,
};
static struct clk sh7780_shyway_clk = {
- .name = "shyway_clk",
- .flags = CLK_ALWAYS_ENABLED,
+ .flags = CLK_ENABLE_ON_INIT,
.ops = &sh7780_shyway_clk_ops,
};
@@ -96,31 +97,29 @@ static struct clk *sh7780_onchip_clocks[] = {
&sh7780_shyway_clk,
};
-static int __init sh7780_clk_init(void)
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("shyway_clk", &sh7780_shyway_clk),
+};
+
+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(sh7780_onchip_clocks); i++) {
struct clk *clkp = sh7780_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;
-}
-
-arch_initcall(sh7780_clk_init);
+ clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
index 27fa81bef6a..17d0ea55a5a 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c
@@ -3,7 +3,7 @@
*
* SH7785 support for the clock framework
*
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2010 Paul Mundt
*
* 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,152 +11,167 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/cpufreq.h>
+#include <linux/clkdev.h>
#include <asm/clock.h>
#include <asm/freq.h>
-#include <asm/io.h>
-
-static int ifc_divisors[] = { 1, 2, 4, 6 };
-static int ufc_divisors[] = { 1, 1, 4, 6 };
-static int sfc_divisors[] = { 1, 1, 4, 6 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18,
- 24, 32, 36, 48, 1, 1, 1, 1 };
-static int mfc_divisors[] = { 1, 1, 4, 6 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18,
- 24, 32, 36, 48, 1, 1, 1, 1 };
-
-static void master_clk_init(struct clk *clk)
-{
- clk->rate *= pfc_divisors[ctrl_inl(FRQMR1) & 0x000f];
-}
+#include <cpu/sh7785.h>
-static struct clk_ops sh7785_master_clk_ops = {
- .init = master_clk_init,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 33333333,
};
-static void module_clk_recalc(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
{
- int idx = (ctrl_inl(FRQMR1) & 0x000f);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
-}
+ int multiplier;
-static struct clk_ops sh7785_module_clk_ops = {
- .recalc = module_clk_recalc,
-};
+ multiplier = test_mode_pin(MODE_PIN4) ? 36 : 72;
-static void bus_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQMR1) >> 16) & 0x000f);
- clk->rate = clk->parent->rate / bfc_divisors[idx];
+ return clk->parent->rate * multiplier;
}
-static struct clk_ops sh7785_bus_clk_ops = {
- .recalc = bus_clk_recalc,
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
};
-static void cpu_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQMR1) >> 28) & 0x0003);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
-}
-
-static struct clk_ops sh7785_cpu_clk_ops = {
- .recalc = cpu_clk_recalc,
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
};
-static struct clk_ops *sh7785_clk_ops[] = {
- &sh7785_master_clk_ops,
- &sh7785_module_clk_ops,
- &sh7785_bus_clk_ops,
- &sh7785_cpu_clk_ops,
+static struct clk *clks[] = {
+ &extal_clk,
+ &pll_clk,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
- if (idx < ARRAY_SIZE(sh7785_clk_ops))
- *ops = sh7785_clk_ops[idx];
-}
-
-static void shyway_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQMR1) >> 20) & 0x0003);
- clk->rate = clk->parent->rate / sfc_divisors[idx];
-}
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+ 24, 32, 36, 48 };
-static struct clk_ops sh7785_shyway_clk_ops = {
- .recalc = shyway_clk_recalc,
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
};
-static struct clk sh7785_shyway_clk = {
- .name = "shyway_clk",
- .flags = CLK_ALWAYS_ENABLED,
- .ops = &sh7785_shyway_clk_ops,
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
};
-static void ddr_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQMR1) >> 12) & 0x0003);
- clk->rate = clk->parent->rate / mfc_divisors[idx];
-}
-
-static struct clk_ops sh7785_ddr_clk_ops = {
- .recalc = ddr_clk_recalc,
-};
-
-static struct clk sh7785_ddr_clk = {
- .name = "ddr_clk",
- .flags = CLK_ALWAYS_ENABLED,
- .ops = &sh7785_ddr_clk_ops,
-};
-
-static void ram_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQMR1) >> 24) & 0x0003);
- clk->rate = clk->parent->rate / ufc_divisors[idx];
-}
-
-static struct clk_ops sh7785_ram_clk_ops = {
- .recalc = ram_clk_recalc,
+enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA,
+ DIV4_DU, DIV4_P, DIV4_NR };
+
+#define DIV4(_bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_P] = DIV4(0, 0x0f80, 0),
+ [DIV4_DU] = DIV4(4, 0x0ff0, 0),
+ [DIV4_GA] = DIV4(8, 0x0030, 0),
+ [DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT),
+ [DIV4_U] = DIV4(24, 0x000c, CLK_ENABLE_ON_INIT),
+ [DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT),
};
-static struct clk sh7785_ram_clk = {
- .name = "ram_clk",
- .flags = CLK_ALWAYS_ENABLED,
- .ops = &sh7785_ram_clk_ops,
+#define MSTPCR0 0xffc80030
+#define MSTPCR1 0xffc80034
+
+enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024,
+ MSTP021, MSTP020, MSTP017, MSTP016,
+ MSTP013, MSTP012, MSTP009, MSTP008, MSTP003, MSTP002,
+ MSTP119, MSTP117, MSTP105, MSTP104, MSTP100,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* MSTPCR0 */
+ [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
+ [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0),
+ [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
+ [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+ [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+ [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+ [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
+ [MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
+ [MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
+ [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
+ [MSTP013] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 13, 0),
+ [MSTP012] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 12, 0),
+ [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
+ [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+
+ /* MSTPCR1 */
+ [MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0),
+ [MSTP117] = SH_CLK_MSTP32(NULL, MSTPCR1, 17, 0),
+ [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
+ [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
+ [MSTP100] = SH_CLK_MSTP32(NULL, MSTPCR1, 0, 0),
};
-/*
- * Additional SH7785-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *sh7785_onchip_clocks[] = {
- &sh7785_shyway_clk,
- &sh7785_ddr_clk,
- &sh7785_ram_clk,
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]),
+ CLKDEV_CON_ID("ga_clk", &div4_clks[DIV4_GA]),
+ CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+ /* MSTP32 clocks */
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
+ CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
+ CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
+ CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]),
+ CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
+ CLKDEV_CON_ID("mmcif_fck", &mstp_clks[MSTP013]),
+ CLKDEV_CON_ID("flctl_fck", &mstp_clks[MSTP012]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP008]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP009]),
+
+ CLKDEV_CON_ID("siof_fck", &mstp_clks[MSTP003]),
+ CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
+ CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
+ CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP117]),
+ CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
+ CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
+ CLKDEV_CON_ID("gdta_fck", &mstp_clks[MSTP100]),
};
-static int __init sh7785_clk_init(void)
+int __init arch_clk_init(void)
{
- struct clk *clk = clk_get(NULL, "master_clk");
- int i;
-
- for (i = 0; i < ARRAY_SIZE(sh7785_onchip_clocks); i++) {
- struct clk *clkp = sh7785_onchip_clocks[i];
-
- clkp->parent = clk;
- clk_register(clkp);
- clk_enable(clkp);
- }
+ int i, ret = 0;
- /*
- * 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));
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ ret |= clk_register(clks[i]);
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
- clk_put(clk);
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+ &div4_table);
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
- return 0;
+ return ret;
}
-arch_initcall(sh7785_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
new file mode 100644
index 00000000000..bec2a83f1ba
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c
@@ -0,0 +1,192 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/clock-sh7786.c
+ *
+ * SH7786 support for the clock framework
+ *
+ * Copyright (C) 2010 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 33333333,
+};
+
+static unsigned long pll_recalc(struct clk *clk)
+{
+ int multiplier;
+
+ /*
+ * Clock modes 0, 1, and 2 use an x64 multiplier against PLL1,
+ * while modes 3, 4, and 5 use an x32.
+ */
+ multiplier = (sh_mv.mv_mode_pins() & 0xf) < 3 ? 64 : 32;
+
+ return clk->parent->rate * multiplier;
+}
+
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
+};
+
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
+
+static struct clk *clks[] = {
+ &extal_clk,
+ &pll_clk,
+};
+
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+ 24, 32, 36, 48 };
+
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
+};
+
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
+};
+
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR };
+
+#define DIV4(_bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
+
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_P] = DIV4(0, 0x0b40, 0),
+ [DIV4_DU] = DIV4(4, 0x0010, 0),
+ [DIV4_DDR] = DIV4(12, 0x0002, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(16, 0x0360, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(20, 0x0002, CLK_ENABLE_ON_INIT),
+ [DIV4_I] = DIV4(28, 0x0006, CLK_ENABLE_ON_INIT),
+};
+
+#define MSTPCR0 0xffc40030
+#define MSTPCR1 0xffc40034
+
+enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024,
+ MSTP023, MSTP022, MSTP021, MSTP020, MSTP017, MSTP016,
+ MSTP015, MSTP014, MSTP011, MSTP010, MSTP009, MSTP008,
+ MSTP005, MSTP004, MSTP002,
+ MSTP112, MSTP110, MSTP109, MSTP108,
+ MSTP105, MSTP104, MSTP103, MSTP102,
+ MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* MSTPCR0 */
+ [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0),
+ [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0),
+ [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
+ [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+ [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+ [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+ [MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0),
+ [MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0),
+ [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0),
+ [MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0),
+ [MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0),
+ [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0),
+ [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),
+ [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0),
+ [MSTP011] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0),
+ [MSTP010] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),
+ [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [MSTP005] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0),
+ [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
+ [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+
+ /* MSTPCR1 */
+ [MSTP112] = SH_CLK_MSTP32(NULL, MSTPCR1, 12, 0),
+ [MSTP110] = SH_CLK_MSTP32(NULL, MSTPCR1, 10, 0),
+ [MSTP109] = SH_CLK_MSTP32(NULL, MSTPCR1, 9, 0),
+ [MSTP108] = SH_CLK_MSTP32(NULL, MSTPCR1, 8, 0),
+ [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
+ [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
+ [MSTP103] = SH_CLK_MSTP32(NULL, MSTPCR1, 3, 0),
+ [MSTP102] = SH_CLK_MSTP32(NULL, MSTPCR1, 2, 0),
+};
+
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]),
+ CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+ /* MSTP32 clocks */
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[MSTP029]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[MSTP028]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
+ CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]),
+ CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]),
+ CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]),
+ CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]),
+ CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]),
+ CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]),
+ CLKDEV_CON_ID("i2c1_fck", &mstp_clks[MSTP015]),
+ CLKDEV_CON_ID("i2c0_fck", &mstp_clks[MSTP014]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP008]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP009]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.2", &mstp_clks[MSTP010]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.3", &mstp_clks[MSTP011]),
+
+ CLKDEV_CON_ID("sdif1_fck", &mstp_clks[MSTP005]),
+ CLKDEV_CON_ID("sdif0_fck", &mstp_clks[MSTP004]),
+ CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]),
+ CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP112]),
+ CLKDEV_CON_ID("pcie2_fck", &mstp_clks[MSTP110]),
+ CLKDEV_CON_ID("pcie1_fck", &mstp_clks[MSTP109]),
+ CLKDEV_CON_ID("pcie0_fck", &mstp_clks[MSTP108]),
+ CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
+ CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
+ CLKDEV_CON_ID("du_fck", &mstp_clks[MSTP103]),
+ CLKDEV_CON_ID("ether_fck", &mstp_clks[MSTP102]),
+};
+
+int __init arch_clk_init(void)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ ret |= clk_register(clks[i]);
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
+
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+ &div4_table);
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
+
+ return ret;
+}
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
index c630b29e06a..9a49a44f6f9 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 2006-2007 Renesas Technology Corp.
* Copyright (C) 2006-2007 Renesas Solutions Corp.
- * Copyright (C) 2006-2007 Paul Mundt
+ * Copyright (C) 2006-2010 Paul Mundt
*
* 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
@@ -13,123 +13,139 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
#include <asm/clock.h>
#include <asm/freq.h>
-#include <asm/io.h>
-
-static int ifc_divisors[] = { 1, 2, 4 ,6 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
-static int cfc_divisors[] = { 1, 1, 4, 6 };
-
-#define IFC_POS 28
-#define IFC_MSK 0x0003
-#define BFC_MSK 0x000f
-#define PFC_MSK 0x000f
-#define CFC_MSK 0x0003
-#define BFC_POS 16
-#define PFC_POS 0
-#define CFC_POS 20
-
-static void master_clk_init(struct clk *clk)
-{
- clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK];
-}
-static struct clk_ops shx3_master_clk_ops = {
- .init = master_clk_init,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+ .rate = 16666666,
};
-static void module_clk_recalc(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
{
- int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK);
- clk->rate = clk->parent->rate / pfc_divisors[idx];
+ /* PLL1 has a fixed x72 multiplier. */
+ return clk->parent->rate * 72;
}
-static struct clk_ops shx3_module_clk_ops = {
- .recalc = module_clk_recalc,
+static struct sh_clk_ops pll_clk_ops = {
+ .recalc = pll_recalc,
};
-static void bus_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK);
- clk->rate = clk->parent->rate / bfc_divisors[idx];
-}
+static struct clk pll_clk = {
+ .ops = &pll_clk_ops,
+ .parent = &extal_clk,
+ .flags = CLK_ENABLE_ON_INIT,
+};
-static struct clk_ops shx3_bus_clk_ops = {
- .recalc = bus_clk_recalc,
+static struct clk *clks[] = {
+ &extal_clk,
+ &pll_clk,
};
-static void cpu_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK);
- clk->rate = clk->parent->rate / ifc_divisors[idx];
-}
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+ 24, 32, 36, 48 };
-static struct clk_ops shx3_cpu_clk_ops = {
- .recalc = cpu_clk_recalc,
+static struct clk_div_mult_table div4_div_mult_table = {
+ .divisors = div2,
+ .nr_divisors = ARRAY_SIZE(div2),
};
-static struct clk_ops *shx3_clk_ops[] = {
- &shx3_master_clk_ops,
- &shx3_module_clk_ops,
- &shx3_bus_clk_ops,
- &shx3_cpu_clk_ops,
+static struct clk_div4_table div4_table = {
+ .div_mult_table = &div4_div_mult_table,
};
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
- if (idx < ARRAY_SIZE(shx3_clk_ops))
- *ops = shx3_clk_ops[idx];
-}
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_SHA, DIV4_P, DIV4_NR };
-static void shyway_clk_recalc(struct clk *clk)
-{
- int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK);
- clk->rate = clk->parent->rate / cfc_divisors[idx];
-}
+#define DIV4(_bit, _mask, _flags) \
+ SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
-static struct clk_ops shx3_shyway_clk_ops = {
- .recalc = shyway_clk_recalc,
+struct clk div4_clks[DIV4_NR] = {
+ [DIV4_P] = DIV4(0, 0x0f80, 0),
+ [DIV4_SHA] = DIV4(4, 0x0ff0, 0),
+ [DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT),
+ [DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT),
+ [DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT),
+ [DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT),
};
-static struct clk shx3_shyway_clk = {
- .name = "shyway_clk",
- .flags = CLK_ALWAYS_ENABLED,
- .ops = &shx3_shyway_clk_ops,
+#define MSTPCR0 0xffc00030
+#define MSTPCR1 0xffc00034
+
+enum { MSTP027, MSTP026, MSTP025, MSTP024,
+ MSTP009, MSTP008, MSTP003, MSTP002,
+ MSTP001, MSTP000, MSTP119, MSTP105,
+ MSTP104, MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+ /* MSTPCR0 */
+ [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
+ [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+ [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+ [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+ [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+ [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+ [MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
+ [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+ [MSTP001] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
+ [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),
+
+ /* MSTPCR1 */
+ [MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0),
+ [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
+ [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
};
-/*
- * Additional SHx3-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *shx3_onchip_clocks[] = {
- &shx3_shyway_clk,
+static struct clk_lookup lookups[] = {
+ /* main clocks */
+ CLKDEV_CON_ID("extal", &extal_clk),
+ CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+ /* DIV4 clocks */
+ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+ CLKDEV_CON_ID("shywaya_clk", &div4_clks[DIV4_SHA]),
+ CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
+ CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+ CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+ /* MSTP32 clocks */
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[MSTP027]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[MSTP026]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[MSTP025]),
+ CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP024]),
+
+ CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
+ CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),
+ CLKDEV_CON_ID("fe1_fck", &mstp_clks[MSTP001]),
+ CLKDEV_CON_ID("fe0_fck", &mstp_clks[MSTP000]),
+
+ CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[MSTP008]),
+ CLKDEV_ICK_ID("fck", "sh-tmu.1", &mstp_clks[MSTP009]),
+
+ CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
+ CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
+ CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
};
-static int __init shx3_clk_init(void)
+int __init arch_clk_init(void)
{
- struct clk *clk = clk_get(NULL, "master_clk");
- int i;
-
- for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
- struct clk *clkp = shx3_onchip_clocks[i];
-
- clkp->parent = clk;
- clk_register(clkp);
- clk_enable(clkp);
- }
+ int i, ret = 0;
- /*
- * 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));
+ for (i = 0; i < ARRAY_SIZE(clks); i++)
+ ret |= clk_register(clks[i]);
+ for (i = 0; i < ARRAY_SIZE(lookups); i++)
+ clkdev_add(&lookups[i]);
- clk_put(clk);
+ if (!ret)
+ ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+ &div4_table);
+ if (!ret)
+ ret = sh_clk_mstp_register(mstp_clks, MSTP_NR);
- return 0;
+ return ret;
}
-arch_initcall(shx3_clk_init);
diff --git a/arch/sh/kernel/cpu/sh4a/intc-shx3.c b/arch/sh/kernel/cpu/sh4a/intc-shx3.c
new file mode 100644
index 00000000000..78c971486b4
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/intc-shx3.c
@@ -0,0 +1,34 @@
+/*
+ * Shared support for SH-X3 interrupt controllers.
+ *
+ * Copyright (C) 2009 - 2010 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/init.h>
+
+#define INTACK 0xfe4100b8
+#define INTACKCLR 0xfe4100bc
+#define INTC_USERIMASK 0xfe411000
+
+#ifdef CONFIG_INTC_BALANCING
+unsigned int irq_lookup(unsigned int irq)
+{
+ return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE;
+}
+
+void irq_finish(unsigned int irq)
+{
+ __raw_writel(irq2evt(irq), INTACKCLR);
+}
+#endif
+
+static int __init shx3_irq_setup(void)
+{
+ return register_intc_userimask(INTC_USERIMASK);
+}
+arch_initcall(shx3_irq_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/perf_event.c b/arch/sh/kernel/cpu/sh4a/perf_event.c
new file mode 100644
index 00000000000..84a2c396cee
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/perf_event.c
@@ -0,0 +1,302 @@
+/*
+ * Performance events support for SH-4A performance counters
+ *
+ * Copyright (C) 2009, 2010 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/perf_event.h>
+#include <asm/processor.h>
+
+#define PPC_CCBR(idx) (0xff200800 + (sizeof(u32) * idx))
+#define PPC_PMCTR(idx) (0xfc100000 + (sizeof(u32) * idx))
+
+#define CCBR_CIT_MASK (0x7ff << 6)
+#define CCBR_DUC (1 << 3)
+#define CCBR_CMDS (1 << 1)
+#define CCBR_PPCE (1 << 0)
+
+#ifdef CONFIG_CPU_SHX3
+/*
+ * The PMCAT location for SH-X3 CPUs was quietly moved, while the CCBR
+ * and PMCTR locations remains tentatively constant. This change remains
+ * wholly undocumented, and was simply found through trial and error.
+ *
+ * Early cuts of SH-X3 still appear to use the SH-X/SH-X2 locations, and
+ * it's unclear when this ceased to be the case. For now we always use
+ * the new location (if future parts keep up with this trend then
+ * scanning for them at runtime also remains a viable option.)
+ *
+ * The gap in the register space also suggests that there are other
+ * undocumented counters, so this will need to be revisited at a later
+ * point in time.
+ */
+#define PPC_PMCAT 0xfc100240
+#else
+#define PPC_PMCAT 0xfc100080
+#endif
+
+#define PMCAT_OVF3 (1 << 27)
+#define PMCAT_CNN3 (1 << 26)
+#define PMCAT_CLR3 (1 << 25)
+#define PMCAT_OVF2 (1 << 19)
+#define PMCAT_CLR2 (1 << 17)
+#define PMCAT_OVF1 (1 << 11)
+#define PMCAT_CNN1 (1 << 10)
+#define PMCAT_CLR1 (1 << 9)
+#define PMCAT_OVF0 (1 << 3)
+#define PMCAT_CLR0 (1 << 1)
+
+static struct sh_pmu sh4a_pmu;
+
+/*
+ * Supported raw event codes:
+ *
+ * Event Code Description
+ * ---------- -----------
+ *
+ * 0x0000 number of elapsed cycles
+ * 0x0200 number of elapsed cycles in privileged mode
+ * 0x0280 number of elapsed cycles while SR.BL is asserted
+ * 0x0202 instruction execution
+ * 0x0203 instruction execution in parallel
+ * 0x0204 number of unconditional branches
+ * 0x0208 number of exceptions
+ * 0x0209 number of interrupts
+ * 0x0220 UTLB miss caused by instruction fetch
+ * 0x0222 UTLB miss caused by operand access
+ * 0x02a0 number of ITLB misses
+ * 0x0028 number of accesses to instruction memories
+ * 0x0029 number of accesses to instruction cache
+ * 0x002a instruction cache miss
+ * 0x022e number of access to instruction X/Y memory
+ * 0x0030 number of reads to operand memories
+ * 0x0038 number of writes to operand memories
+ * 0x0031 number of operand cache read accesses
+ * 0x0039 number of operand cache write accesses
+ * 0x0032 operand cache read miss
+ * 0x003a operand cache write miss
+ * 0x0236 number of reads to operand X/Y memory
+ * 0x023e number of writes to operand X/Y memory
+ * 0x0237 number of reads to operand U memory
+ * 0x023f number of writes to operand U memory
+ * 0x0337 number of U memory read buffer misses
+ * 0x02b4 number of wait cycles due to operand read access
+ * 0x02bc number of wait cycles due to operand write access
+ * 0x0033 number of wait cycles due to operand cache read miss
+ * 0x003b number of wait cycles due to operand cache write miss
+ */
+
+/*
+ * Special reserved bits used by hardware emulators, read values will
+ * vary, but writes must always be 0.
+ */
+#define PMCAT_EMU_CLR_MASK ((1 << 24) | (1 << 16) | (1 << 8) | (1 << 0))
+
+static const int sh4a_general_events[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = 0x0000,
+ [PERF_COUNT_HW_INSTRUCTIONS] = 0x0202,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = 0x0029, /* I-cache */
+ [PERF_COUNT_HW_CACHE_MISSES] = 0x002a, /* I-cache */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x0204,
+ [PERF_COUNT_HW_BRANCH_MISSES] = -1,
+ [PERF_COUNT_HW_BUS_CYCLES] = -1,
+};
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+static const int sh4a_cache_events
+ [PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0031,
+ [ C(RESULT_MISS) ] = 0x0032,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0039,
+ [ C(RESULT_MISS) ] = 0x003a,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(L1I) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0029,
+ [ C(RESULT_MISS) ] = 0x002a,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(LL) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0030,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0038,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(DTLB) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0x0222,
+ [ C(RESULT_MISS) ] = 0x0220,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0,
+ },
+ },
+
+ [ C(ITLB) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = 0,
+ [ C(RESULT_MISS) ] = 0x02a0,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+
+ [ C(BPU) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+
+ [ C(NODE) ] = {
+ [ C(OP_READ) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_WRITE) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ [ C(OP_PREFETCH) ] = {
+ [ C(RESULT_ACCESS) ] = -1,
+ [ C(RESULT_MISS) ] = -1,
+ },
+ },
+};
+
+static int sh4a_event_map(int event)
+{
+ return sh4a_general_events[event];
+}
+
+static u64 sh4a_pmu_read(int idx)
+{
+ return __raw_readl(PPC_PMCTR(idx));
+}
+
+static void sh4a_pmu_disable(struct hw_perf_event *hwc, int idx)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readl(PPC_CCBR(idx));
+ tmp &= ~(CCBR_CIT_MASK | CCBR_DUC);
+ __raw_writel(tmp, PPC_CCBR(idx));
+}
+
+static void sh4a_pmu_enable(struct hw_perf_event *hwc, int idx)
+{
+ unsigned int tmp;
+
+ tmp = __raw_readl(PPC_PMCAT);
+ tmp &= ~PMCAT_EMU_CLR_MASK;
+ tmp |= idx ? PMCAT_CLR1 : PMCAT_CLR0;
+ __raw_writel(tmp, PPC_PMCAT);
+
+ tmp = __raw_readl(PPC_CCBR(idx));
+ tmp |= (hwc->config << 6) | CCBR_CMDS | CCBR_PPCE;
+ __raw_writel(tmp, PPC_CCBR(idx));
+
+ __raw_writel(__raw_readl(PPC_CCBR(idx)) | CCBR_DUC, PPC_CCBR(idx));
+}
+
+static void sh4a_pmu_disable_all(void)
+{
+ int i;
+
+ for (i = 0; i < sh4a_pmu.num_events; i++)
+ __raw_writel(__raw_readl(PPC_CCBR(i)) & ~CCBR_DUC, PPC_CCBR(i));
+}
+
+static void sh4a_pmu_enable_all(void)
+{
+ int i;
+
+ for (i = 0; i < sh4a_pmu.num_events; i++)
+ __raw_writel(__raw_readl(PPC_CCBR(i)) | CCBR_DUC, PPC_CCBR(i));
+}
+
+static struct sh_pmu sh4a_pmu = {
+ .name = "sh4a",
+ .num_events = 2,
+ .event_map = sh4a_event_map,
+ .max_events = ARRAY_SIZE(sh4a_general_events),
+ .raw_event_mask = 0x3ff,
+ .cache_events = &sh4a_cache_events,
+ .read = sh4a_pmu_read,
+ .disable = sh4a_pmu_disable,
+ .enable = sh4a_pmu_enable,
+ .disable_all = sh4a_pmu_disable_all,
+ .enable_all = sh4a_pmu_enable_all,
+};
+
+static int __init sh4a_pmu_init(void)
+{
+ /*
+ * Make sure this CPU actually has perf counters.
+ */
+ if (!(boot_cpu_data.flags & CPU_HAS_PERF_COUNTER)) {
+ pr_notice("HW perf events unsupported, software events only.\n");
+ return -ENODEV;
+ }
+
+ return register_sh_pmu(&sh4a_pmu);
+}
+early_initcall(sh4a_pmu_init);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
new file mode 100644
index 00000000000..271bbc86492
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
@@ -0,0 +1,20 @@
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7722_pfc_resources[] = {
+ [0] = {
+ .start = 0xa4050100,
+ .end = 0xa405018f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7722", sh7722_pfc_resources,
+ ARRAY_SIZE(sh7722_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
new file mode 100644
index 00000000000..99c637d5bf7
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
@@ -0,0 +1,30 @@
+/*
+ * SH7723 Pinmux
+ *
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7723_pfc_resources[] = {
+ [0] = {
+ .start = 0xa4050100,
+ .end = 0xa405016f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7723", sh7723_pfc_resources,
+ ARRAY_SIZE(sh7723_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
new file mode 100644
index 00000000000..63be4749e34
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7724.c
@@ -0,0 +1,35 @@
+/*
+ * SH7724 Pinmux
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7723 Pinmux
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7724_pfc_resources[] = {
+ [0] = {
+ .start = 0xa4050100,
+ .end = 0xa405016f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7724", sh7724_pfc_resources,
+ ARRAY_SIZE(sh7724_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c
new file mode 100644
index 00000000000..ea2db632a76
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7734.c
@@ -0,0 +1,35 @@
+/*
+ * SH7734 processor support - PFC hardware block
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Copyright (C) 2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7734_pfc_resources[] = {
+ [0] = { /* PFC */
+ .start = 0xFFFC0000,
+ .end = 0xFFFC011C,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = { /* GPIO */
+ .start = 0xFFC40000,
+ .end = 0xFFC4502B,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7734", sh7734_pfc_resources,
+ ARRAY_SIZE(sh7734_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
new file mode 100644
index 00000000000..567745d4422
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
@@ -0,0 +1,35 @@
+/*
+ * SH7757 (B0 step) Pinmux
+ *
+ * Copyright (C) 2009-2010 Renesas Solutions Corp.
+ *
+ * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
+ *
+ * Based on SH7723 Pinmux
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7757_pfc_resources[] = {
+ [0] = {
+ .start = 0xffec0000,
+ .end = 0xffec008f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7757", sh7757_pfc_resources,
+ ARRAY_SIZE(sh7757_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c
new file mode 100644
index 00000000000..e336ab8b512
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7785.c
@@ -0,0 +1,30 @@
+/*
+ * SH7785 Pinmux
+ *
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7785_pfc_resources[] = {
+ [0] = {
+ .start = 0xffe70000,
+ .end = 0xffe7008f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7785", sh7785_pfc_resources,
+ ARRAY_SIZE(sh7785_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
new file mode 100644
index 00000000000..9a459556a2f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-sh7786.c
@@ -0,0 +1,35 @@
+/*
+ * SH7786 Pinmux
+ *
+ * Copyright (C) 2008, 2009 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7785 pinmux
+ *
+ * Copyright (C) 2008 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
+ * for more details.
+ */
+
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource sh7786_pfc_resources[] = {
+ [0] = {
+ .start = 0xffcc0000,
+ .end = 0xffcc008f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-sh7786", sh7786_pfc_resources,
+ ARRAY_SIZE(sh7786_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c b/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
new file mode 100644
index 00000000000..444bf25c60f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
@@ -0,0 +1,29 @@
+/*
+ * SH-X3 prototype CPU pinmux
+ *
+ * Copyright (C) 2010 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/bug.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <cpu/pfc.h>
+
+static struct resource shx3_pfc_resources[] = {
+ [0] = {
+ .start = 0xffc70000,
+ .end = 0xffc7001f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static int __init plat_pinmux_setup(void)
+{
+ return sh_pfc_register("pfc-shx3", shx3_pfc_resources,
+ ARRAY_SIZE(shx3_pfc_resources));
+}
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/serial-sh7722.c b/arch/sh/kernel/cpu/sh4a/serial-sh7722.c
new file mode 100644
index 00000000000..59bc3a72702
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/serial-sh7722.c
@@ -0,0 +1,23 @@
+#include <linux/serial_sci.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+
+#define PSCR 0xA405011E
+
+static void sh7722_sci_init_pins(struct uart_port *port, unsigned int cflag)
+{
+ unsigned short data;
+
+ if (port->mapbase == 0xffe00000) {
+ data = __raw_readw(PSCR);
+ data &= ~0x03cf;
+ if (!(cflag & CRTSCTS))
+ data |= 0x0340;
+
+ __raw_writew(data, PSCR);
+ }
+}
+
+struct plat_sci_port_ops sh7722_sci_port_ops = {
+ .init_pins = sh7722_sci_init_pins,
+};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 78881b4214d..ceb3dedad98 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -12,8 +12,95 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/clock.h>
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe10000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc20)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffe20000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc40)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xffe30000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc60)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
static struct resource iic0_resources[] = {
[0] = {
.name = "IIC0",
@@ -22,14 +109,15 @@ static struct resource iic0_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device iic0_device = {
.name = "i2c-sh_mobile",
+ .id = 0, /* "i2c0" clock */
.num_resources = ARRAY_SIZE(iic0_resources),
.resource = iic0_resources,
};
@@ -42,14 +130,15 @@ static struct resource iic1_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 44,
- .end = 47,
+ .start = evt2irq(0x780),
+ .end = evt2irq(0x7e0),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device iic1_device = {
.name = "i2c-sh_mobile",
+ .id = 1, /* "i2c1" clock */
.num_resources = ARRAY_SIZE(iic1_resources),
.resource = iic1_resources,
};
@@ -57,7 +146,7 @@ static struct platform_device iic1_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU4",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -85,7 +174,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu_resources[] = {
@@ -110,58 +199,118 @@ static struct platform_device veu_device = {
.num_resources = ARRAY_SIZE(veu_resources),
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 80, 81, 83, 82 },
- }, {
- .flags = 0,
- }
+static struct uio_info jpu_platform_data = {
+ .name = "JPU",
+ .version = "0",
+ .irq = evt2irq(0x560),
};
-static struct platform_device sci_device = {
- .name = "sh-sci",
- .id = -1,
- .dev = {
- .platform_data = sci_platform_data,
+static struct resource jpu_resources[] = {
+ [0] = {
+ .name = "JPU",
+ .start = 0xfea00000,
+ .end = 0xfea102d3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device jpu_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 2,
+ .dev = {
+ .platform_data = &jpu_platform_data,
+ },
+ .resource = jpu_resources,
+ .num_resources = ARRAY_SIZE(jpu_resources),
+};
+
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 0x20,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0x044a0000, 0x70),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-32",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
},
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 platform_device *sh7343_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &cmt_device,
+ &tmu0_device,
&iic0_device,
&iic1_device,
- &sci_device,
&vpu_device,
&veu_device,
+ &jpu_device,
};
static int __init sh7343_devices_setup(void)
{
- clk_always_enable("mstp031"); /* TLB */
- clk_always_enable("mstp030"); /* IC */
- clk_always_enable("mstp029"); /* OC */
- clk_always_enable("mstp028"); /* URAM */
- clk_always_enable("mstp026"); /* XYMEM */
- clk_always_enable("mstp023"); /* INTC3 */
- clk_always_enable("mstp022"); /* INTC */
- clk_always_enable("mstp020"); /* SuperHyway */
- clk_always_enable("mstp109"); /* I2C0 */
- clk_always_enable("mstp108"); /* I2C1 */
- clk_always_enable("mstp202"); /* VEU */
- clk_always_enable("mstp201"); /* VPU */
-
platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
+ platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20);
return platform_add_devices(sh7343_devices,
ARRAY_SIZE(sh7343_devices));
}
-__initcall(sh7343_devices_setup);
+arch_initcall(sh7343_devices_setup);
+
+static struct platform_device *sh7343_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &cmt_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7343_early_devices,
+ ARRAY_SIZE(sh7343_early_devices));
+}
enum {
UNUSED = 0,
+ ENABLED,
+ DISABLED,
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -171,21 +320,19 @@ enum {
MMC_ERR, MMC_TRAN, MMC_FSTAT, MMC_FRDY,
DMAC4, DMAC5, DMAC_DADERR,
KEYSC,
- SCIF, SCIF1, SCIF2, SCIF3, SCIF4,
+ SCIF, SCIF1, SCIF2, SCIF3,
SIOF0, SIOF1, SIO,
FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI,
- IRDA,
- SDHI0, SDHI1, SDHI2, SDHI3,
- CMT, TSIF, SIU,
+ IRDA, SDHI, CMT, TSIF, SIU,
TMU0, TMU1, TMU2,
JPU, LCDC,
/* interrupt groups */
- DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C0, I2C1, SIM, SDHI, USB,
+ DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C0, I2C1, SIM, USB,
};
static struct intc_vect vectors[] __initdata = {
@@ -214,8 +361,8 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
INTC_VECT(I2C0_ALI, 0xe00), INTC_VECT(I2C0_TACKI, 0xe20),
INTC_VECT(I2C0_WAITI, 0xe40), INTC_VECT(I2C0_DTEI, 0xe60),
- INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
- INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+ INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0),
+ INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0),
INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
INTC_VECT(SIU, 0xf80),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -233,7 +380,6 @@ static struct intc_group groups[] __initdata = {
INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
INTC_GROUP(SIM, SIM_TEI, SIM_TXI, SIM_RXI, SIM_ERI),
- INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
INTC_GROUP(USB, USBI0, USBI1),
};
@@ -254,7 +400,7 @@ static struct intc_mask_reg mask_registers[] __initdata = {
{ I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
- { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } },
+ { DISABLED, ENABLED, ENABLED, ENABLED, 0, 0, 0, SIU } },
{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
{ 0, 0, 0, CMT, 0, USBI1, USBI0 } },
{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -290,9 +436,13 @@ static struct intc_mask_reg ack_registers[] __initdata = {
{ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
};
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7343", vectors, groups,
- mask_registers, prio_registers, sense_registers,
- ack_registers);
+static struct intc_desc intc_desc __initdata = {
+ .name = "sh7343",
+ .force_enable = ENABLED,
+ .force_disable = DISABLED,
+ .hw = INTC_HW_DESC(vectors, groups, mask_registers,
+ prio_registers, sense_registers, ack_registers),
+};
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index 6851dba02f3..f75f6734313 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -14,8 +14,33 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <linux/usb/r8a66597.h>
#include <asm/clock.h>
+static struct plat_sci_port scif0_platform_data = {
+ .port_reg = 0xa405013e,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
static struct resource iic_resources[] = {
[0] = {
.name = "IIC",
@@ -24,22 +49,52 @@ static struct resource iic_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device iic_device = {
.name = "i2c-sh_mobile",
+ .id = 0, /* "i2c0" clock */
.num_resources = ARRAY_SIZE(iic_resources),
.resource = iic_resources,
};
+static struct r8a66597_platdata r8a66597_data = {
+ .on_chip = 1,
+};
+
+static struct resource usb_host_resources[] = {
+ [0] = {
+ .start = 0xa4d80000,
+ .end = 0xa4d800ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+ },
+};
+
+static struct platform_device usb_host_device = {
+ .name = "r8a66597_hcd",
+ .id = -1,
+ .dev = {
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ .platform_data = &r8a66597_data,
+ },
+ .num_resources = ARRAY_SIZE(usb_host_resources),
+ .resource = usb_host_resources,
+};
+
static struct uio_info vpu_platform_data = {
.name = "VPU5",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -67,7 +122,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu0_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu0_resources[] = {
@@ -95,7 +150,7 @@ static struct platform_device veu0_device = {
static struct uio_info veu1_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource veu1_resources[] = {
@@ -120,28 +175,52 @@ static struct platform_device veu1_device = {
.num_resources = ARRAY_SIZE(veu1_resources),
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
- }, {
- .flags = 0,
- }
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 0x20,
};
-static struct platform_device sci_device = {
- .name = "sh-sci",
- .id = -1,
- .dev = {
- .platform_data = sci_platform_data,
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0x044a0000, 0x70),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-32",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 platform_device *sh7366_devices[] __initdata = {
+ &scif0_device,
+ &cmt_device,
+ &tmu0_device,
&iic_device,
- &sci_device,
+ &usb_host_device,
&vpu_device,
&veu0_device,
&veu1_device,
@@ -149,19 +228,6 @@ static struct platform_device *sh7366_devices[] __initdata = {
static int __init sh7366_devices_setup(void)
{
- clk_always_enable("mstp031"); /* TLB */
- clk_always_enable("mstp030"); /* IC */
- clk_always_enable("mstp029"); /* OC */
- clk_always_enable("mstp028"); /* RSMEM */
- clk_always_enable("mstp026"); /* XYMEM */
- clk_always_enable("mstp023"); /* INTC3 */
- clk_always_enable("mstp022"); /* INTC */
- clk_always_enable("mstp020"); /* SuperHyway */
- clk_always_enable("mstp109"); /* I2C */
- clk_always_enable("mstp207"); /* VEU-2 */
- clk_always_enable("mstp202"); /* VEU-1 */
- clk_always_enable("mstp201"); /* VPU */
-
platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
@@ -169,10 +235,24 @@ static int __init sh7366_devices_setup(void)
return platform_add_devices(sh7366_devices,
ARRAY_SIZE(sh7366_devices));
}
-__initcall(sh7366_devices_setup);
+arch_initcall(sh7366_devices_setup);
+
+static struct platform_device *sh7366_early_devices[] __initdata = {
+ &scif0_device,
+ &cmt_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7366_early_devices,
+ ARRAY_SIZE(sh7366_early_devices));
+}
enum {
UNUSED=0,
+ ENABLED,
+ DISABLED,
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -186,14 +266,13 @@ enum {
DENC, MSIOF,
FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI,
- SDHI0, SDHI1, SDHI2, SDHI3,
- CMT, TSIF, SIU,
+ SDHI, CMT, TSIF, SIU,
TMU0, TMU1, TMU2,
VEU2, LCDC,
/* interrupt groups */
- DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C, SDHI,
+ DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C,
};
static struct intc_vect vectors[] __initdata = {
@@ -218,8 +297,8 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20),
INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60),
- INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
- INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+ INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0),
+ INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0),
INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
INTC_VECT(SIU, 0xf80),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -235,7 +314,6 @@ static struct intc_group groups[] __initdata = {
INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI,
FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI),
- INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -257,7 +335,7 @@ static struct intc_mask_reg mask_registers[] __initdata = {
{ I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
- { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } },
+ { DISABLED, ENABLED, ENABLED, ENABLED, 0, 0, 0, SIU } },
{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
{ 0, 0, 0, CMT, 0, USB, } },
{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -295,9 +373,13 @@ static struct intc_mask_reg ack_registers[] __initdata = {
{ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
};
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7366", vectors, groups,
- mask_registers, prio_registers, sense_registers,
- ack_registers);
+static struct intc_desc intc_desc __initdata = {
+ .name = "sh7366",
+ .force_enable = ENABLED,
+ .force_disable = DISABLED,
+ .hw = INTC_HW_DESC(vectors, groups, mask_registers,
+ prio_registers, sense_registers, ack_registers),
+};
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index de1ede92176..57f83a92a50 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -1,41 +1,307 @@
/*
* SH7722 Setup
*
- * Copyright (C) 2006 - 2007 Paul Mundt
+ * Copyright (C) 2006 - 2008 Paul Mundt
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
-#include <linux/platform_device.h>
#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
-#include <linux/mm.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/uio_driver.h>
+#include <linux/usb/m66592.h>
+
#include <asm/clock.h>
#include <asm/mmzone.h>
+#include <asm/siu.h>
+
+#include <cpu/dma-register.h>
+#include <cpu/sh7722.h>
+#include <cpu/serial.h>
+
+static const struct sh_dmae_slave_config sh7722_dmae_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SCIF0_TX,
+ .addr = 0xffe0000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF0_RX,
+ .addr = 0xffe00014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_TX,
+ .addr = 0xffe1000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x25,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_RX,
+ .addr = 0xffe10014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x26,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_TX,
+ .addr = 0xffe2000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_RX,
+ .addr = 0xffe20014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUA_TX,
+ .addr = 0xa454c098,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb1,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUA_RX,
+ .addr = 0xa454c090,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb2,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUB_TX,
+ .addr = 0xa454c09c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb5,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUB_RX,
+ .addr = 0xa454c094,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb6,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_TX,
+ .addr = 0x04ce0030,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc1,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_RX,
+ .addr = 0x04ce0030,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc2,
+ },
+};
+
+static const struct sh_dmae_channel sh7722_dmae_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma_platform_data = {
+ .slave = sh7722_dmae_slaves,
+ .slave_num = ARRAY_SIZE(sh7722_dmae_slaves),
+ .channel = sh7722_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7722_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct resource sh7722_dmae_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfe008020,
+ .end = 0xfe00808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xfe009000,
+ .end = 0xfe00900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0xbc0),
+ .end = evt2irq(0xbc0),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-3 */
+ .start = evt2irq(0x800),
+ .end = evt2irq(0x860),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 4-5 */
+ .start = evt2irq(0xb80),
+ .end = evt2irq(0xba0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device dma_device = {
+ .name = "sh-dma-engine",
+ .id = -1,
+ .resource = sh7722_dmae_resources,
+ .num_resources = ARRAY_SIZE(sh7722_dmae_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+};
+
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .ops = &sh7722_sci_port_ops,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .ops = &sh7722_sci_port_ops,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe10000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc20)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .ops = &sh7722_sci_port_ops,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffe20000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc40)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xa465fec0,
+ .end = 0xa465fec0 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = evt2irq(0x7a0),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = evt2irq(0x7c0),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = evt2irq(0x780),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+static struct m66592_platdata usbf_platdata = {
+ .on_chip = 1,
+};
static struct resource usbf_resources[] = {
[0] = {
- .name = "m66592_udc",
+ .name = "USBF",
.start = 0x04480000,
.end = 0x044800FF,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device usbf_device = {
.name = "m66592_udc",
- .id = -1,
+ .id = 0, /* "usbf0" clock */
.dev = {
.dma_mask = NULL,
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &usbf_platdata,
},
.num_resources = ARRAY_SIZE(usbf_resources),
.resource = usbf_resources,
@@ -49,14 +315,15 @@ static struct resource iic_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device iic_device = {
.name = "i2c-sh_mobile",
+ .id = 0, /* "i2c0" clock */
.num_resources = ARRAY_SIZE(iic_resources),
.resource = iic_resources,
};
@@ -64,7 +331,7 @@ static struct platform_device iic_device = {
static struct uio_info vpu_platform_data = {
.name = "VPU4",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -92,7 +359,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu_platform_data = {
.name = "VEU",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu_resources[] = {
@@ -117,70 +384,148 @@ static struct platform_device veu_device = {
.num_resources = ARRAY_SIZE(veu_resources),
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
+static struct uio_info jpu_platform_data = {
+ .name = "JPU",
+ .version = "0",
+ .irq = evt2irq(0x560),
+};
+
+static struct resource jpu_resources[] = {
+ [0] = {
+ .name = "JPU",
+ .start = 0xfea00000,
+ .end = 0xfea102d3,
+ .flags = IORESOURCE_MEM,
},
- {
- .mapbase = 0xffe10000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
+ [1] = {
+ /* place holder for contiguous memory */
},
- {
- .mapbase = 0xffe20000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 82, 82, 82, 82 },
+};
+
+static struct platform_device jpu_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 2,
+ .dev = {
+ .platform_data = &jpu_platform_data,
},
- {
- .flags = 0,
- }
+ .resource = jpu_resources,
+ .num_resources = ARRAY_SIZE(jpu_resources),
};
-static struct platform_device sci_device = {
- .name = "sh-sci",
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 0x20,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0x044a0000, 0x70),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-32",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 siu_platform siu_platform_data = {
+ .dma_slave_tx_a = SHDMA_SLAVE_SIUA_TX,
+ .dma_slave_rx_a = SHDMA_SLAVE_SIUA_RX,
+ .dma_slave_tx_b = SHDMA_SLAVE_SIUB_TX,
+ .dma_slave_rx_b = SHDMA_SLAVE_SIUB_RX,
+};
+
+static struct resource siu_resources[] = {
+ [0] = {
+ .start = 0xa4540000,
+ .end = 0xa454c10f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0xf80),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device siu_device = {
+ .name = "siu-pcm-audio",
.id = -1,
- .dev = {
- .platform_data = sci_platform_data,
+ .dev = {
+ .platform_data = &siu_platform_data,
},
+ .resource = siu_resources,
+ .num_resources = ARRAY_SIZE(siu_resources),
};
static struct platform_device *sh7722_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &cmt_device,
+ &tmu0_device,
+ &rtc_device,
&usbf_device,
&iic_device,
- &sci_device,
&vpu_device,
&veu_device,
+ &jpu_device,
+ &siu_device,
+ &dma_device,
};
static int __init sh7722_devices_setup(void)
{
- clk_always_enable("mstp031"); /* TLB */
- clk_always_enable("mstp030"); /* IC */
- clk_always_enable("mstp029"); /* OC */
- clk_always_enable("mstp028"); /* URAM */
- clk_always_enable("mstp026"); /* XYMEM */
- clk_always_enable("mstp022"); /* INTC */
- clk_always_enable("mstp020"); /* SuperHyway */
- clk_always_enable("mstp109"); /* I2C */
- clk_always_enable("mstp211"); /* USB */
- clk_always_enable("mstp202"); /* VEU */
- clk_always_enable("mstp201"); /* VPU */
-
platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20);
platform_resource_setup_memory(&veu_device, "veu", 2 << 20);
+ platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20);
return platform_add_devices(sh7722_devices,
ARRAY_SIZE(sh7722_devices));
}
-__initcall(sh7722_devices_setup);
+arch_initcall(sh7722_devices_setup);
+
+static struct platform_device *sh7722_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &cmt_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7722_early_devices,
+ ARRAY_SIZE(sh7722_early_devices));
+}
enum {
UNUSED=0,
+ ENABLED,
+ DISABLED,
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -196,13 +541,11 @@ enum {
SCIF0, SCIF1, SCIF2, SIOF0, SIOF1, SIO,
FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI,
- SDHI0, SDHI1, SDHI2, SDHI3,
CMT, TSIF, SIU, TWODG,
TMU0, TMU1, TMU2,
IRDA, JPU, LCDC,
/* interrupt groups */
-
SIM, RTC, DMAC0123, VIOVOU, USB, DMAC45, FLCTL, I2C, SDHI,
};
@@ -230,8 +573,8 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0),
INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20),
INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60),
- INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0),
- INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0),
+ INTC_VECT(SDHI, 0xe80), INTC_VECT(SDHI, 0xea0),
+ INTC_VECT(SDHI, 0xec0), INTC_VECT(SDHI, 0xee0),
INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20),
INTC_VECT(SIU, 0xf80), INTC_VECT(TWODG, 0xfa0),
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
@@ -249,7 +592,6 @@ static struct intc_group groups[] __initdata = {
INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI,
FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI),
- INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -271,7 +613,7 @@ static struct intc_mask_reg mask_registers[] __initdata = {
{ I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } },
{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
- { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, TWODG, SIU } },
+ { DISABLED, ENABLED, ENABLED, ENABLED, 0, 0, TWODG, SIU } },
{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
{ 0, 0, 0, CMT, 0, USB_USBI1, USB_USBI0, } },
{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -309,9 +651,13 @@ static struct intc_mask_reg ack_registers[] __initdata = {
{ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
};
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7722", vectors, groups,
- mask_registers, prio_registers, sense_registers,
- ack_registers);
+static struct intc_desc intc_desc __initdata = {
+ .name = "sh7722",
+ .force_enable = ENABLED,
+ .force_disable = DISABLED,
+ .hw = INTC_HW_DESC(vectors, groups, mask_registers,
+ prio_registers, sense_registers, ack_registers),
+};
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index a7412cede53..3533b56dd46 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -13,13 +13,157 @@
#include <linux/mm.h>
#include <linux/serial_sci.h>
#include <linux/uio_driver.h>
+#include <linux/usb/r8a66597.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <linux/io.h>
#include <asm/clock.h>
#include <asm/mmzone.h>
+#include <cpu/sh7723.h>
+
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+ .port_reg = 0xa4050160,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe10000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc20)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffe20000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc40)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .sampling_rate = 8,
+ .type = PORT_SCIFA,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xa4e30000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .sampling_rate = 8,
+ .type = PORT_SCIFA,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xa4e40000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xd00)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .sampling_rate = 8,
+ .type = PORT_SCIFA,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xa4e50000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xfa0)),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
static struct uio_info vpu_platform_data = {
.name = "VPU5",
.version = "0",
- .irq = 60,
+ .irq = evt2irq(0x980),
};
static struct resource vpu_resources[] = {
@@ -47,7 +191,7 @@ static struct platform_device vpu_device = {
static struct uio_info veu0_platform_data = {
.name = "VEU2H",
.version = "0",
- .irq = 54,
+ .irq = evt2irq(0x8c0),
};
static struct resource veu0_resources[] = {
@@ -75,7 +219,7 @@ static struct platform_device veu0_device = {
static struct uio_info veu1_platform_data = {
.name = "VEU2H",
.version = "0",
- .irq = 27,
+ .irq = evt2irq(0x560),
};
static struct resource veu1_resources[] = {
@@ -100,48 +244,65 @@ static struct platform_device veu1_device = {
.num_resources = ARRAY_SIZE(veu1_resources),
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 80, 80, 80, 80 },
- },{
- .mapbase = 0xffe10000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 81, 81, 81, 81 },
- },{
- .mapbase = 0xffe20000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 82, 82, 82, 82 },
- },{
- .mapbase = 0xa4e30000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
- .irqs = { 56, 56, 56, 56 },
- },{
- .mapbase = 0xa4e40000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
- .irqs = { 88, 88, 88, 88 },
- },{
- .mapbase = 0xa4e50000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCI,
- .irqs = { 109, 109, 109, 109 },
- }, {
- .flags = 0,
- }
-};
-
-static struct platform_device sci_device = {
- .name = "sh-sci",
- .id = -1,
- .dev = {
- .platform_data = sci_platform_data,
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 0x20,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0x044a0000, 0x70),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-32",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffd90000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x920)),
+ DEFINE_RES_IRQ(evt2irq(0x940)),
+ DEFINE_RES_IRQ(evt2irq(0x960)),
+};
+
+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 resource rtc_resources[] = {
@@ -152,17 +313,17 @@ static struct resource rtc_resources[] = {
},
[1] = {
/* Period IRQ */
- .start = 69,
+ .start = evt2irq(0xaa0),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* Carry IRQ */
- .start = 70,
+ .start = evt2irq(0xac0),
.flags = IORESOURCE_IRQ,
},
[3] = {
/* Alarm IRQ */
- .start = 68,
+ .start = evt2irq(0xa80),
.flags = IORESOURCE_IRQ,
},
};
@@ -174,17 +335,20 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
+static struct r8a66597_platdata r8a66597_data = {
+ .on_chip = 1,
+};
+
static struct resource sh7723_usb_host_resources[] = {
[0] = {
- .name = "r8a66597_hcd",
.start = 0xa4d80000,
.end = 0xa4d800ff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 65,
- .end = 65,
- .flags = IORESOURCE_IRQ,
+ .start = evt2irq(0xa20),
+ .end = evt2irq(0xa20),
+ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
},
};
@@ -194,6 +358,7 @@ static struct platform_device sh7723_usb_host_device = {
.dev = {
.dma_mask = NULL, /* not use dma */
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &r8a66597_data,
},
.num_resources = ARRAY_SIZE(sh7723_usb_host_resources),
.resource = sh7723_usb_host_resources,
@@ -207,20 +372,29 @@ static struct resource iic_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 96,
- .end = 99,
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device iic_device = {
.name = "i2c-sh_mobile",
+ .id = 0, /* "i2c0" clock */
.num_resources = ARRAY_SIZE(iic_resources),
.resource = iic_resources,
};
static struct platform_device *sh7723_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &cmt_device,
+ &tmu0_device,
+ &tmu1_device,
&rtc_device,
&iic_device,
&sh7723_usb_host_device,
@@ -231,20 +405,6 @@ static struct platform_device *sh7723_devices[] __initdata = {
static int __init sh7723_devices_setup(void)
{
- clk_always_enable("mstp031"); /* TLB */
- clk_always_enable("mstp030"); /* IC */
- clk_always_enable("mstp029"); /* OC */
- clk_always_enable("mstp024"); /* FPU */
- clk_always_enable("mstp022"); /* INTC */
- clk_always_enable("mstp020"); /* SuperHyway */
- clk_always_enable("mstp000"); /* MERAM */
- clk_always_enable("mstp109"); /* I2C */
- clk_always_enable("mstp108"); /* RTC */
- clk_always_enable("mstp211"); /* USB */
- clk_always_enable("mstp206"); /* VEU2H1 */
- clk_always_enable("mstp202"); /* VEU2H0 */
- clk_always_enable("mstp201"); /* VPU */
-
platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
@@ -252,10 +412,40 @@ static int __init sh7723_devices_setup(void)
return platform_add_devices(sh7723_devices,
ARRAY_SIZE(sh7723_devices));
}
-__initcall(sh7723_devices_setup);
+arch_initcall(sh7723_devices_setup);
+
+static struct platform_device *sh7723_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7723_early_devices,
+ ARRAY_SIZE(sh7723_early_devices));
+}
+
+#define RAMCR_CACHE_L2FC 0x0002
+#define RAMCR_CACHE_L2E 0x0001
+#define L2_CACHE_ENABLE (RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC)
+
+void l2_cache_init(void)
+{
+ /* Enable L2 cache */
+ __raw_writel(L2_CACHE_ENABLE, RAMCR);
+}
enum {
UNUSED=0,
+ ENABLED,
+ DISABLED,
/* interrupt sources */
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
@@ -278,7 +468,6 @@ enum {
SCIFA_SCIFA1,
FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I,
I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI,
- SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2,
CMT_CMTI,
TSIF_TSIFI,
SIU_SIUI,
@@ -286,7 +475,6 @@ enum {
TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
IRDA_IRDAI,
ATAPI_ATAPII,
- SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2,
VEU2H1_VEU2HI,
LCDC_LCDCI,
TMU1_TUNI0,TMU1_TUNI1,TMU1_TUNI2,
@@ -357,9 +545,9 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(I2C_WAITI,0xE40),
INTC_VECT(I2C_DTEI,0xE60),
- INTC_VECT(SDHI0_SDHII0,0xE80),
- INTC_VECT(SDHI0_SDHII1,0xEA0),
- INTC_VECT(SDHI0_SDHII2,0xEC0),
+ INTC_VECT(SDHI0, 0xE80),
+ INTC_VECT(SDHI0, 0xEA0),
+ INTC_VECT(SDHI0, 0xEC0),
INTC_VECT(CMT_CMTI,0xF00),
INTC_VECT(TSIF_TSIFI,0xF20),
@@ -373,9 +561,9 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(IRDA_IRDAI,0x480),
INTC_VECT(ATAPI_ATAPII,0x4A0),
- INTC_VECT(SDHI1_SDHII0,0x4E0),
- INTC_VECT(SDHI1_SDHII1,0x500),
- INTC_VECT(SDHI1_SDHII2,0x520),
+ INTC_VECT(SDHI1, 0x4E0),
+ INTC_VECT(SDHI1, 0x500),
+ INTC_VECT(SDHI1, 0x520),
INTC_VECT(VEU2H1_VEU2HI,0x560),
INTC_VECT(LCDC_LCDCI,0x580),
@@ -394,15 +582,14 @@ static struct intc_group groups[] __initdata = {
INTC_GROUP(FLCTL,FLCTL_FLSTEI,FLCTL_FLTENDI,FLCTL_FLTREQ0I,FLCTL_FLTREQ1I),
INTC_GROUP(I2C,I2C_ALI,I2C_TACKI,I2C_WAITI,I2C_DTEI),
INTC_GROUP(_2DG, _2DG_TRI,_2DG_INI,_2DG_CEI),
- INTC_GROUP(SDHI1, SDHI1_SDHII0,SDHI1_SDHII1,SDHI1_SDHII2),
INTC_GROUP(RTC, RTC_ATI,RTC_PRI,RTC_CUI),
INTC_GROUP(DMAC1B, DMAC1B_DEI4,DMAC1B_DEI5,DMAC1B_DADERR),
- INTC_GROUP(SDHI0,SDHI0_SDHII0,SDHI0_SDHII1,SDHI0_SDHII2),
};
static struct intc_mask_reg mask_registers[] __initdata = {
{ 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
- { 0, TMU1_TUNI2,TMU1_TUNI1,TMU1_TUNI0,0,SDHI1_SDHII2,SDHI1_SDHII1,SDHI1_SDHII0} },
+ { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
+ 0, ENABLED, ENABLED, ENABLED } },
{ 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
{ VIO_VOUI, VIO_VEU2HI,VIO_BEUI,VIO_CEUI,DMAC0A_DEI3,DMAC0A_DEI2,DMAC0A_DEI1,DMAC0A_DEI0 } },
{ 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
@@ -419,7 +606,8 @@ static struct intc_mask_reg mask_registers[] __initdata = {
{ I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI,
FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
{ 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
- { 0,SDHI0_SDHII2,SDHI0_SDHII1,SDHI0_SDHII0,0,0,SCIFA_SCIFA2,SIU_SIUI } },
+ { 0, ENABLED, ENABLED, ENABLED,
+ 0, 0, SCIFA_SCIFA2, SIU_SIUI } },
{ 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
{ 0, 0, 0, CMT_CMTI, 0, 0, USB_USI0,0 } },
{ 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
@@ -459,9 +647,13 @@ static struct intc_mask_reg ack_registers[] __initdata = {
{ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
};
-static DECLARE_INTC_DESC_ACK(intc_desc, "sh7723", vectors, groups,
- mask_registers, prio_registers, sense_registers,
- ack_registers);
+static struct intc_desc intc_desc __initdata = {
+ .name = "sh7723",
+ .force_enable = ENABLED,
+ .force_disable = DISABLED,
+ .hw = INTC_HW_DESC(vectors, groups, mask_registers,
+ prio_registers, sense_registers, ack_registers),
+};
void __init plat_irq_setup(void)
{
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
new file mode 100644
index 00000000000..b9e84b1d3aa
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -0,0 +1,1305 @@
+/*
+ * SH7724 Setup
+ *
+ * Copyright (C) 2009 Renesas Solutions Corp.
+ *
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ *
+ * Based on SH7723 Setup
+ * Copyright (C) 2008 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/serial_sci.h>
+#include <linux/uio_driver.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <linux/io.h>
+#include <linux/notifier.h>
+
+#include <asm/suspend.h>
+#include <asm/clock.h>
+#include <asm/mmzone.h>
+
+#include <cpu/dma-register.h>
+#include <cpu/sh7724.h>
+
+/* DMA */
+static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SCIF0_TX,
+ .addr = 0xffe0000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF0_RX,
+ .addr = 0xffe00014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_TX,
+ .addr = 0xffe1000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x25,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_RX,
+ .addr = 0xffe10014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x26,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_TX,
+ .addr = 0xffe2000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_RX,
+ .addr = 0xffe20014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF3_TX,
+ .addr = 0xa4e30020,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2d,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF3_RX,
+ .addr = 0xa4e30024,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2e,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF4_TX,
+ .addr = 0xa4e40020,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x31,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF4_RX,
+ .addr = 0xa4e40024,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x32,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF5_TX,
+ .addr = 0xa4e50020,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x35,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF5_RX,
+ .addr = 0xa4e50024,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x36,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB0D0_TX,
+ .addr = 0xA4D80100,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0x73,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB0D0_RX,
+ .addr = 0xA4D80100,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0x73,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB0D1_TX,
+ .addr = 0xA4D80120,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0x77,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB0D1_RX,
+ .addr = 0xA4D80120,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0x77,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB1D0_TX,
+ .addr = 0xA4D90100,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xab,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB1D0_RX,
+ .addr = 0xA4D90100,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xab,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB1D1_TX,
+ .addr = 0xA4D90120,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xaf,
+ }, {
+ .slave_id = SHDMA_SLAVE_USB1D1_RX,
+ .addr = 0xA4D90120,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xaf,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_TX,
+ .addr = 0x04ce0030,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc1,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI0_RX,
+ .addr = 0x04ce0030,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc2,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI1_TX,
+ .addr = 0x04cf0030,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc9,
+ }, {
+ .slave_id = SHDMA_SLAVE_SDHI1_RX,
+ .addr = 0x04cf0030,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xca,
+ },
+};
+
+static const struct sh_dmae_channel sh7724_dmae_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma_platform_data = {
+ .slave = sh7724_dmae_slaves,
+ .slave_num = ARRAY_SIZE(sh7724_dmae_slaves),
+ .channel = sh7724_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7724_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+/* Resource order important! */
+static struct resource sh7724_dmae0_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfe008020,
+ .end = 0xfe00808f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfe009000,
+ .end = 0xfe00900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0xbc0),
+ .end = evt2irq(0xbc0),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-3 */
+ .start = evt2irq(0x800),
+ .end = evt2irq(0x860),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 4-5 */
+ .start = evt2irq(0xb80),
+ .end = evt2irq(0xba0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* Resource order important! */
+static struct resource sh7724_dmae1_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfdc08020,
+ .end = 0xfdc0808f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfdc09000,
+ .end = 0xfdc0900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0xb40),
+ .end = evt2irq(0xb40),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-3 */
+ .start = evt2irq(0x700),
+ .end = evt2irq(0x760),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 4-5 */
+ .start = evt2irq(0xb00),
+ .end = evt2irq(0xb20),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = sh7724_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7724_dmae0_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7724_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7724_dmae1_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+};
+
+/* Serial */
+static struct plat_sci_port scif0_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc00)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe10000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc20)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffe20000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xc40)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE,
+ .sampling_rate = 8,
+ .type = PORT_SCIFA,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xa4e30000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE,
+ .sampling_rate = 8,
+ .type = PORT_SCIFA,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xa4e40000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xd00)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .port_reg = SCIx_NOT_SUPPORTED,
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE,
+ .sampling_rate = 8,
+ .type = PORT_SCIFA,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xa4e50000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xfa0)),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+/* RTC */
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = 0xa465fec0,
+ .end = 0xa465fec0 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = evt2irq(0xaa0),
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = evt2irq(0xac0),
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = evt2irq(0xa80),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* I2C0 */
+static struct resource iic0_resources[] = {
+ [0] = {
+ .name = "IIC0",
+ .start = 0x04470000,
+ .end = 0x04470018 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0xe00),
+ .end = evt2irq(0xe60),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device iic0_device = {
+ .name = "i2c-sh_mobile",
+ .id = 0, /* "i2c0" clock */
+ .num_resources = ARRAY_SIZE(iic0_resources),
+ .resource = iic0_resources,
+};
+
+/* I2C1 */
+static struct resource iic1_resources[] = {
+ [0] = {
+ .name = "IIC1",
+ .start = 0x04750000,
+ .end = 0x04750018 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0xd80),
+ .end = evt2irq(0xde0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device iic1_device = {
+ .name = "i2c-sh_mobile",
+ .id = 1, /* "i2c1" clock */
+ .num_resources = ARRAY_SIZE(iic1_resources),
+ .resource = iic1_resources,
+};
+
+/* VPU */
+static struct uio_info vpu_platform_data = {
+ .name = "VPU5F",
+ .version = "0",
+ .irq = evt2irq(0x980),
+};
+
+static struct resource vpu_resources[] = {
+ [0] = {
+ .name = "VPU",
+ .start = 0xfe900000,
+ .end = 0xfe902807,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device vpu_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 0,
+ .dev = {
+ .platform_data = &vpu_platform_data,
+ },
+ .resource = vpu_resources,
+ .num_resources = ARRAY_SIZE(vpu_resources),
+};
+
+/* VEU0 */
+static struct uio_info veu0_platform_data = {
+ .name = "VEU3F0",
+ .version = "0",
+ .irq = evt2irq(0xc60),
+};
+
+static struct resource veu0_resources[] = {
+ [0] = {
+ .name = "VEU3F0",
+ .start = 0xfe920000,
+ .end = 0xfe9200cb,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device veu0_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 1,
+ .dev = {
+ .platform_data = &veu0_platform_data,
+ },
+ .resource = veu0_resources,
+ .num_resources = ARRAY_SIZE(veu0_resources),
+};
+
+/* VEU1 */
+static struct uio_info veu1_platform_data = {
+ .name = "VEU3F1",
+ .version = "0",
+ .irq = evt2irq(0x8c0),
+};
+
+static struct resource veu1_resources[] = {
+ [0] = {
+ .name = "VEU3F1",
+ .start = 0xfe924000,
+ .end = 0xfe9240cb,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device veu1_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 2,
+ .dev = {
+ .platform_data = &veu1_platform_data,
+ },
+ .resource = veu1_resources,
+ .num_resources = ARRAY_SIZE(veu1_resources),
+};
+
+/* BEU0 */
+static struct uio_info beu0_platform_data = {
+ .name = "BEU0",
+ .version = "0",
+ .irq = evt2irq(0x8A0),
+};
+
+static struct resource beu0_resources[] = {
+ [0] = {
+ .name = "BEU0",
+ .start = 0xfe930000,
+ .end = 0xfe933400,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device beu0_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 6,
+ .dev = {
+ .platform_data = &beu0_platform_data,
+ },
+ .resource = beu0_resources,
+ .num_resources = ARRAY_SIZE(beu0_resources),
+};
+
+/* BEU1 */
+static struct uio_info beu1_platform_data = {
+ .name = "BEU1",
+ .version = "0",
+ .irq = evt2irq(0xA00),
+};
+
+static struct resource beu1_resources[] = {
+ [0] = {
+ .name = "BEU1",
+ .start = 0xfe940000,
+ .end = 0xfe943400,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device beu1_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 7,
+ .dev = {
+ .platform_data = &beu1_platform_data,
+ },
+ .resource = beu1_resources,
+ .num_resources = ARRAY_SIZE(beu1_resources),
+};
+
+static struct sh_timer_config cmt_platform_data = {
+ .channels_mask = 0x20,
+};
+
+static struct resource cmt_resources[] = {
+ DEFINE_RES_MEM(0x044a0000, 0x70),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device cmt_device = {
+ .name = "sh-cmt-32",
+ .id = 0,
+ .dev = {
+ .platform_data = &cmt_platform_data,
+ },
+ .resource = cmt_resources,
+ .num_resources = ARRAY_SIZE(cmt_resources),
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffd90000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x920)),
+ DEFINE_RES_IRQ(evt2irq(0x940)),
+ DEFINE_RES_IRQ(evt2irq(0x960)),
+};
+
+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),
+};
+
+/* JPU */
+static struct uio_info jpu_platform_data = {
+ .name = "JPU",
+ .version = "0",
+ .irq = evt2irq(0x560),
+};
+
+static struct resource jpu_resources[] = {
+ [0] = {
+ .name = "JPU",
+ .start = 0xfe980000,
+ .end = 0xfe9902d3,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device jpu_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 3,
+ .dev = {
+ .platform_data = &jpu_platform_data,
+ },
+ .resource = jpu_resources,
+ .num_resources = ARRAY_SIZE(jpu_resources),
+};
+
+/* SPU2DSP0 */
+static struct uio_info spu0_platform_data = {
+ .name = "SPU2DSP0",
+ .version = "0",
+ .irq = evt2irq(0xcc0),
+};
+
+static struct resource spu0_resources[] = {
+ [0] = {
+ .name = "SPU2DSP0",
+ .start = 0xFE200000,
+ .end = 0xFE2FFFFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device spu0_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 4,
+ .dev = {
+ .platform_data = &spu0_platform_data,
+ },
+ .resource = spu0_resources,
+ .num_resources = ARRAY_SIZE(spu0_resources),
+};
+
+/* SPU2DSP1 */
+static struct uio_info spu1_platform_data = {
+ .name = "SPU2DSP1",
+ .version = "0",
+ .irq = evt2irq(0xce0),
+};
+
+static struct resource spu1_resources[] = {
+ [0] = {
+ .name = "SPU2DSP1",
+ .start = 0xFE300000,
+ .end = 0xFE3FFFFF,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* place holder for contiguous memory */
+ },
+};
+
+static struct platform_device spu1_device = {
+ .name = "uio_pdrv_genirq",
+ .id = 5,
+ .dev = {
+ .platform_data = &spu1_platform_data,
+ },
+ .resource = spu1_resources,
+ .num_resources = ARRAY_SIZE(spu1_resources),
+};
+
+static struct platform_device *sh7724_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+ &dma0_device,
+ &dma1_device,
+ &rtc_device,
+ &iic0_device,
+ &iic1_device,
+ &vpu_device,
+ &veu0_device,
+ &veu1_device,
+ &beu0_device,
+ &beu1_device,
+ &jpu_device,
+ &spu0_device,
+ &spu1_device,
+};
+
+static int __init sh7724_devices_setup(void)
+{
+ platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20);
+ platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20);
+ platform_resource_setup_memory(&veu1_device, "veu1", 2 << 20);
+ platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20);
+ platform_resource_setup_memory(&spu0_device, "spu0", 2 << 20);
+ platform_resource_setup_memory(&spu1_device, "spu1", 2 << 20);
+
+ return platform_add_devices(sh7724_devices,
+ ARRAY_SIZE(sh7724_devices));
+}
+arch_initcall(sh7724_devices_setup);
+
+static struct platform_device *sh7724_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &cmt_device,
+ &tmu0_device,
+ &tmu1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7724_early_devices,
+ ARRAY_SIZE(sh7724_early_devices));
+}
+
+#define RAMCR_CACHE_L2FC 0x0002
+#define RAMCR_CACHE_L2E 0x0001
+#define L2_CACHE_ENABLE (RAMCR_CACHE_L2E|RAMCR_CACHE_L2FC)
+
+void l2_cache_init(void)
+{
+ /* Enable L2 cache */
+ __raw_writel(L2_CACHE_ENABLE, RAMCR);
+}
+
+enum {
+ UNUSED = 0,
+ ENABLED,
+ DISABLED,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ HUDI,
+ DMAC1A_DEI0, DMAC1A_DEI1, DMAC1A_DEI2, DMAC1A_DEI3,
+ _2DG_TRI, _2DG_INI, _2DG_CEI,
+ DMAC0A_DEI0, DMAC0A_DEI1, DMAC0A_DEI2, DMAC0A_DEI3,
+ VIO_CEU0, VIO_BEU0, VIO_VEU1, VIO_VOU,
+ SCIFA3,
+ VPU,
+ TPU,
+ CEU1,
+ BEU1,
+ USB0, USB1,
+ ATAPI,
+ RTC_ATI, RTC_PRI, RTC_CUI,
+ DMAC1B_DEI4, DMAC1B_DEI5, DMAC1B_DADERR,
+ DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR,
+ KEYSC,
+ SCIF_SCIF0, SCIF_SCIF1, SCIF_SCIF2,
+ VEU0,
+ MSIOF_MSIOFI0, MSIOF_MSIOFI1,
+ SPU_SPUI0, SPU_SPUI1,
+ SCIFA4,
+ ICB,
+ ETHI,
+ I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI,
+ I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI,
+ CMT,
+ TSIF,
+ FSI,
+ SCIFA5,
+ TMU0_TUNI0, TMU0_TUNI1, TMU0_TUNI2,
+ IRDA,
+ JPU,
+ _2DDMAC,
+ MMC_MMC2I, MMC_MMC3I,
+ LCDC,
+ TMU1_TUNI0, TMU1_TUNI1, TMU1_TUNI2,
+
+ /* interrupt groups */
+ DMAC1A, _2DG, DMAC0A, VIO, USB, RTC,
+ DMAC1B, DMAC0B, I2C0, I2C1, SDHI0, SDHI1, SPU, MMCIF,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+ INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0),
+
+ INTC_VECT(DMAC1A_DEI0, 0x700),
+ INTC_VECT(DMAC1A_DEI1, 0x720),
+ INTC_VECT(DMAC1A_DEI2, 0x740),
+ INTC_VECT(DMAC1A_DEI3, 0x760),
+
+ INTC_VECT(_2DG_TRI, 0x780),
+ INTC_VECT(_2DG_INI, 0x7A0),
+ INTC_VECT(_2DG_CEI, 0x7C0),
+
+ INTC_VECT(DMAC0A_DEI0, 0x800),
+ INTC_VECT(DMAC0A_DEI1, 0x820),
+ INTC_VECT(DMAC0A_DEI2, 0x840),
+ INTC_VECT(DMAC0A_DEI3, 0x860),
+
+ INTC_VECT(VIO_CEU0, 0x880),
+ INTC_VECT(VIO_BEU0, 0x8A0),
+ INTC_VECT(VIO_VEU1, 0x8C0),
+ INTC_VECT(VIO_VOU, 0x8E0),
+
+ INTC_VECT(SCIFA3, 0x900),
+ INTC_VECT(VPU, 0x980),
+ INTC_VECT(TPU, 0x9A0),
+ INTC_VECT(CEU1, 0x9E0),
+ INTC_VECT(BEU1, 0xA00),
+ INTC_VECT(USB0, 0xA20),
+ INTC_VECT(USB1, 0xA40),
+ INTC_VECT(ATAPI, 0xA60),
+
+ INTC_VECT(RTC_ATI, 0xA80),
+ INTC_VECT(RTC_PRI, 0xAA0),
+ INTC_VECT(RTC_CUI, 0xAC0),
+
+ INTC_VECT(DMAC1B_DEI4, 0xB00),
+ INTC_VECT(DMAC1B_DEI5, 0xB20),
+ INTC_VECT(DMAC1B_DADERR, 0xB40),
+
+ INTC_VECT(DMAC0B_DEI4, 0xB80),
+ INTC_VECT(DMAC0B_DEI5, 0xBA0),
+ INTC_VECT(DMAC0B_DADERR, 0xBC0),
+
+ INTC_VECT(KEYSC, 0xBE0),
+ INTC_VECT(SCIF_SCIF0, 0xC00),
+ INTC_VECT(SCIF_SCIF1, 0xC20),
+ INTC_VECT(SCIF_SCIF2, 0xC40),
+ INTC_VECT(VEU0, 0xC60),
+ INTC_VECT(MSIOF_MSIOFI0, 0xC80),
+ INTC_VECT(MSIOF_MSIOFI1, 0xCA0),
+ INTC_VECT(SPU_SPUI0, 0xCC0),
+ INTC_VECT(SPU_SPUI1, 0xCE0),
+ INTC_VECT(SCIFA4, 0xD00),
+
+ INTC_VECT(ICB, 0xD20),
+ INTC_VECT(ETHI, 0xD60),
+
+ INTC_VECT(I2C1_ALI, 0xD80),
+ INTC_VECT(I2C1_TACKI, 0xDA0),
+ INTC_VECT(I2C1_WAITI, 0xDC0),
+ INTC_VECT(I2C1_DTEI, 0xDE0),
+
+ INTC_VECT(I2C0_ALI, 0xE00),
+ INTC_VECT(I2C0_TACKI, 0xE20),
+ INTC_VECT(I2C0_WAITI, 0xE40),
+ INTC_VECT(I2C0_DTEI, 0xE60),
+
+ INTC_VECT(SDHI0, 0xE80),
+ INTC_VECT(SDHI0, 0xEA0),
+ INTC_VECT(SDHI0, 0xEC0),
+ INTC_VECT(SDHI0, 0xEE0),
+
+ INTC_VECT(CMT, 0xF00),
+ INTC_VECT(TSIF, 0xF20),
+ INTC_VECT(FSI, 0xF80),
+ INTC_VECT(SCIFA5, 0xFA0),
+
+ INTC_VECT(TMU0_TUNI0, 0x400),
+ INTC_VECT(TMU0_TUNI1, 0x420),
+ INTC_VECT(TMU0_TUNI2, 0x440),
+
+ INTC_VECT(IRDA, 0x480),
+
+ INTC_VECT(SDHI1, 0x4E0),
+ INTC_VECT(SDHI1, 0x500),
+ INTC_VECT(SDHI1, 0x520),
+
+ INTC_VECT(JPU, 0x560),
+ INTC_VECT(_2DDMAC, 0x4A0),
+
+ INTC_VECT(MMC_MMC2I, 0x5A0),
+ INTC_VECT(MMC_MMC3I, 0x5C0),
+
+ INTC_VECT(LCDC, 0xF40),
+
+ INTC_VECT(TMU1_TUNI0, 0x920),
+ INTC_VECT(TMU1_TUNI1, 0x940),
+ INTC_VECT(TMU1_TUNI2, 0x960),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(DMAC1A, DMAC1A_DEI0, DMAC1A_DEI1, DMAC1A_DEI2, DMAC1A_DEI3),
+ INTC_GROUP(_2DG, _2DG_TRI, _2DG_INI, _2DG_CEI),
+ INTC_GROUP(DMAC0A, DMAC0A_DEI0, DMAC0A_DEI1, DMAC0A_DEI2, DMAC0A_DEI3),
+ INTC_GROUP(VIO, VIO_CEU0, VIO_BEU0, VIO_VEU1, VIO_VOU),
+ INTC_GROUP(USB, USB0, USB1),
+ INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
+ INTC_GROUP(DMAC1B, DMAC1B_DEI4, DMAC1B_DEI5, DMAC1B_DADERR),
+ INTC_GROUP(DMAC0B, DMAC0B_DEI4, DMAC0B_DEI5, DMAC0B_DADERR),
+ INTC_GROUP(I2C0, I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI),
+ INTC_GROUP(I2C1, I2C1_ALI, I2C1_TACKI, I2C1_WAITI, I2C1_DTEI),
+ INTC_GROUP(SPU, SPU_SPUI0, SPU_SPUI1),
+ INTC_GROUP(MMCIF, MMC_MMC2I, MMC_MMC3I),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */
+ { 0, TMU1_TUNI2, TMU1_TUNI1, TMU1_TUNI0,
+ 0, ENABLED, ENABLED, ENABLED } },
+ { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */
+ { VIO_VOU, VIO_VEU1, VIO_BEU0, VIO_CEU0,
+ DMAC0A_DEI3, DMAC0A_DEI2, DMAC0A_DEI1, DMAC0A_DEI0 } },
+ { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */
+ { 0, 0, 0, VPU, ATAPI, ETHI, 0, SCIFA3 } },
+ { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */
+ { DMAC1A_DEI3, DMAC1A_DEI2, DMAC1A_DEI1, DMAC1A_DEI0,
+ SPU_SPUI1, SPU_SPUI0, BEU1, IRDA } },
+ { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */
+ { 0, TMU0_TUNI2, TMU0_TUNI1, TMU0_TUNI0,
+ JPU, 0, 0, LCDC } },
+ { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */
+ { KEYSC, DMAC0B_DADERR, DMAC0B_DEI5, DMAC0B_DEI4,
+ VEU0, SCIF_SCIF2, SCIF_SCIF1, SCIF_SCIF0 } },
+ { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */
+ { 0, 0, ICB, SCIFA4,
+ CEU1, 0, MSIOF_MSIOFI1, MSIOF_MSIOFI0 } },
+ { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */
+ { I2C0_DTEI, I2C0_WAITI, I2C0_TACKI, I2C0_ALI,
+ I2C1_DTEI, I2C1_WAITI, I2C1_TACKI, I2C1_ALI } },
+ { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */
+ { DISABLED, ENABLED, ENABLED, ENABLED,
+ 0, 0, SCIFA5, FSI } },
+ { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */
+ { 0, 0, 0, CMT, 0, USB1, USB0, 0 } },
+ { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */
+ { 0, DMAC1B_DADERR, DMAC1B_DEI5, DMAC1B_DEI4,
+ 0, RTC_CUI, RTC_PRI, RTC_ATI } },
+ { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */
+ { 0, _2DG_CEI, _2DG_INI, _2DG_TRI,
+ 0, TPU, 0, TSIF } },
+ { 0xa40800b0, 0xa40800f0, 8, /* IMR12 / IMCR12 */
+ { 0, 0, MMC_MMC3I, MMC_MMC2I, 0, 0, 0, _2DDMAC } },
+ { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0_TUNI0, TMU0_TUNI1,
+ TMU0_TUNI2, IRDA } },
+ { 0xa4080004, 0, 16, 4, /* IPRB */ { JPU, LCDC, DMAC1A, BEU1 } },
+ { 0xa4080008, 0, 16, 4, /* IPRC */ { TMU1_TUNI0, TMU1_TUNI1,
+ TMU1_TUNI2, SPU } },
+ { 0xa408000c, 0, 16, 4, /* IPRD */ { 0, MMCIF, 0, ATAPI } },
+ { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0A, VIO, SCIFA3, VPU } },
+ { 0xa4080014, 0, 16, 4, /* IPRF */ { KEYSC, DMAC0B, USB, CMT } },
+ { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF_SCIF0, SCIF_SCIF1,
+ SCIF_SCIF2, VEU0 } },
+ { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF_MSIOFI0, MSIOF_MSIOFI1,
+ I2C1, I2C0 } },
+ { 0xa4080020, 0, 16, 4, /* IPRI */ { SCIFA4, ICB, TSIF, _2DG } },
+ { 0xa4080024, 0, 16, 4, /* IPRJ */ { CEU1, ETHI, FSI, SDHI1 } },
+ { 0xa4080028, 0, 16, 4, /* IPRK */ { RTC, DMAC1B, 0, SDHI0 } },
+ { 0xa408002c, 0, 16, 4, /* IPRL */ { SCIFA5, 0, TPU, _2DDMAC } },
+ { 0xa4140010, 0, 32, 4, /* INTPRI00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+ { 0xa414001c, 16, 2, /* ICR1 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+ { 0xa4140024, 0, 8, /* INTREQ00 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_desc intc_desc __initdata = {
+ .name = "sh7724",
+ .force_enable = ENABLED,
+ .force_disable = DISABLED,
+ .hw = INTC_HW_DESC(vectors, groups, mask_registers,
+ prio_registers, sense_registers, ack_registers),
+};
+
+void __init plat_irq_setup(void)
+{
+ register_intc_controller(&intc_desc);
+}
+
+static struct {
+ /* BSC */
+ unsigned long mmselr;
+ unsigned long cs0bcr;
+ unsigned long cs4bcr;
+ unsigned long cs5abcr;
+ unsigned long cs5bbcr;
+ unsigned long cs6abcr;
+ unsigned long cs6bbcr;
+ unsigned long cs4wcr;
+ unsigned long cs5awcr;
+ unsigned long cs5bwcr;
+ unsigned long cs6awcr;
+ unsigned long cs6bwcr;
+ /* INTC */
+ unsigned short ipra;
+ unsigned short iprb;
+ unsigned short iprc;
+ unsigned short iprd;
+ unsigned short ipre;
+ unsigned short iprf;
+ unsigned short iprg;
+ unsigned short iprh;
+ unsigned short ipri;
+ unsigned short iprj;
+ unsigned short iprk;
+ unsigned short iprl;
+ unsigned char imr0;
+ unsigned char imr1;
+ unsigned char imr2;
+ unsigned char imr3;
+ unsigned char imr4;
+ unsigned char imr5;
+ unsigned char imr6;
+ unsigned char imr7;
+ unsigned char imr8;
+ unsigned char imr9;
+ unsigned char imr10;
+ unsigned char imr11;
+ unsigned char imr12;
+ /* RWDT */
+ unsigned short rwtcnt;
+ unsigned short rwtcsr;
+ /* CPG */
+ unsigned long irdaclk;
+ unsigned long spuclk;
+} sh7724_rstandby_state;
+
+static int sh7724_pre_sleep_notifier_call(struct notifier_block *nb,
+ unsigned long flags, void *unused)
+{
+ if (!(flags & SUSP_SH_RSTANDBY))
+ return NOTIFY_DONE;
+
+ /* BCR */
+ sh7724_rstandby_state.mmselr = __raw_readl(0xff800020); /* MMSELR */
+ sh7724_rstandby_state.mmselr |= 0xa5a50000;
+ sh7724_rstandby_state.cs0bcr = __raw_readl(0xfec10004); /* CS0BCR */
+ sh7724_rstandby_state.cs4bcr = __raw_readl(0xfec10010); /* CS4BCR */
+ sh7724_rstandby_state.cs5abcr = __raw_readl(0xfec10014); /* CS5ABCR */
+ sh7724_rstandby_state.cs5bbcr = __raw_readl(0xfec10018); /* CS5BBCR */
+ sh7724_rstandby_state.cs6abcr = __raw_readl(0xfec1001c); /* CS6ABCR */
+ sh7724_rstandby_state.cs6bbcr = __raw_readl(0xfec10020); /* CS6BBCR */
+ sh7724_rstandby_state.cs4wcr = __raw_readl(0xfec10030); /* CS4WCR */
+ sh7724_rstandby_state.cs5awcr = __raw_readl(0xfec10034); /* CS5AWCR */
+ sh7724_rstandby_state.cs5bwcr = __raw_readl(0xfec10038); /* CS5BWCR */
+ sh7724_rstandby_state.cs6awcr = __raw_readl(0xfec1003c); /* CS6AWCR */
+ sh7724_rstandby_state.cs6bwcr = __raw_readl(0xfec10040); /* CS6BWCR */
+
+ /* INTC */
+ sh7724_rstandby_state.ipra = __raw_readw(0xa4080000); /* IPRA */
+ sh7724_rstandby_state.iprb = __raw_readw(0xa4080004); /* IPRB */
+ sh7724_rstandby_state.iprc = __raw_readw(0xa4080008); /* IPRC */
+ sh7724_rstandby_state.iprd = __raw_readw(0xa408000c); /* IPRD */
+ sh7724_rstandby_state.ipre = __raw_readw(0xa4080010); /* IPRE */
+ sh7724_rstandby_state.iprf = __raw_readw(0xa4080014); /* IPRF */
+ sh7724_rstandby_state.iprg = __raw_readw(0xa4080018); /* IPRG */
+ sh7724_rstandby_state.iprh = __raw_readw(0xa408001c); /* IPRH */
+ sh7724_rstandby_state.ipri = __raw_readw(0xa4080020); /* IPRI */
+ sh7724_rstandby_state.iprj = __raw_readw(0xa4080024); /* IPRJ */
+ sh7724_rstandby_state.iprk = __raw_readw(0xa4080028); /* IPRK */
+ sh7724_rstandby_state.iprl = __raw_readw(0xa408002c); /* IPRL */
+ sh7724_rstandby_state.imr0 = __raw_readb(0xa4080080); /* IMR0 */
+ sh7724_rstandby_state.imr1 = __raw_readb(0xa4080084); /* IMR1 */
+ sh7724_rstandby_state.imr2 = __raw_readb(0xa4080088); /* IMR2 */
+ sh7724_rstandby_state.imr3 = __raw_readb(0xa408008c); /* IMR3 */
+ sh7724_rstandby_state.imr4 = __raw_readb(0xa4080090); /* IMR4 */
+ sh7724_rstandby_state.imr5 = __raw_readb(0xa4080094); /* IMR5 */
+ sh7724_rstandby_state.imr6 = __raw_readb(0xa4080098); /* IMR6 */
+ sh7724_rstandby_state.imr7 = __raw_readb(0xa408009c); /* IMR7 */
+ sh7724_rstandby_state.imr8 = __raw_readb(0xa40800a0); /* IMR8 */
+ sh7724_rstandby_state.imr9 = __raw_readb(0xa40800a4); /* IMR9 */
+ sh7724_rstandby_state.imr10 = __raw_readb(0xa40800a8); /* IMR10 */
+ sh7724_rstandby_state.imr11 = __raw_readb(0xa40800ac); /* IMR11 */
+ sh7724_rstandby_state.imr12 = __raw_readb(0xa40800b0); /* IMR12 */
+
+ /* RWDT */
+ sh7724_rstandby_state.rwtcnt = __raw_readb(0xa4520000); /* RWTCNT */
+ sh7724_rstandby_state.rwtcnt |= 0x5a00;
+ sh7724_rstandby_state.rwtcsr = __raw_readb(0xa4520004); /* RWTCSR */
+ sh7724_rstandby_state.rwtcsr |= 0xa500;
+ __raw_writew(sh7724_rstandby_state.rwtcsr & 0x07, 0xa4520004);
+
+ /* CPG */
+ sh7724_rstandby_state.irdaclk = __raw_readl(0xa4150018); /* IRDACLKCR */
+ sh7724_rstandby_state.spuclk = __raw_readl(0xa415003c); /* SPUCLKCR */
+
+ return NOTIFY_DONE;
+}
+
+static int sh7724_post_sleep_notifier_call(struct notifier_block *nb,
+ unsigned long flags, void *unused)
+{
+ if (!(flags & SUSP_SH_RSTANDBY))
+ return NOTIFY_DONE;
+
+ /* BCR */
+ __raw_writel(sh7724_rstandby_state.mmselr, 0xff800020); /* MMSELR */
+ __raw_writel(sh7724_rstandby_state.cs0bcr, 0xfec10004); /* CS0BCR */
+ __raw_writel(sh7724_rstandby_state.cs4bcr, 0xfec10010); /* CS4BCR */
+ __raw_writel(sh7724_rstandby_state.cs5abcr, 0xfec10014); /* CS5ABCR */
+ __raw_writel(sh7724_rstandby_state.cs5bbcr, 0xfec10018); /* CS5BBCR */
+ __raw_writel(sh7724_rstandby_state.cs6abcr, 0xfec1001c); /* CS6ABCR */
+ __raw_writel(sh7724_rstandby_state.cs6bbcr, 0xfec10020); /* CS6BBCR */
+ __raw_writel(sh7724_rstandby_state.cs4wcr, 0xfec10030); /* CS4WCR */
+ __raw_writel(sh7724_rstandby_state.cs5awcr, 0xfec10034); /* CS5AWCR */
+ __raw_writel(sh7724_rstandby_state.cs5bwcr, 0xfec10038); /* CS5BWCR */
+ __raw_writel(sh7724_rstandby_state.cs6awcr, 0xfec1003c); /* CS6AWCR */
+ __raw_writel(sh7724_rstandby_state.cs6bwcr, 0xfec10040); /* CS6BWCR */
+
+ /* INTC */
+ __raw_writew(sh7724_rstandby_state.ipra, 0xa4080000); /* IPRA */
+ __raw_writew(sh7724_rstandby_state.iprb, 0xa4080004); /* IPRB */
+ __raw_writew(sh7724_rstandby_state.iprc, 0xa4080008); /* IPRC */
+ __raw_writew(sh7724_rstandby_state.iprd, 0xa408000c); /* IPRD */
+ __raw_writew(sh7724_rstandby_state.ipre, 0xa4080010); /* IPRE */
+ __raw_writew(sh7724_rstandby_state.iprf, 0xa4080014); /* IPRF */
+ __raw_writew(sh7724_rstandby_state.iprg, 0xa4080018); /* IPRG */
+ __raw_writew(sh7724_rstandby_state.iprh, 0xa408001c); /* IPRH */
+ __raw_writew(sh7724_rstandby_state.ipri, 0xa4080020); /* IPRI */
+ __raw_writew(sh7724_rstandby_state.iprj, 0xa4080024); /* IPRJ */
+ __raw_writew(sh7724_rstandby_state.iprk, 0xa4080028); /* IPRK */
+ __raw_writew(sh7724_rstandby_state.iprl, 0xa408002c); /* IPRL */
+ __raw_writeb(sh7724_rstandby_state.imr0, 0xa4080080); /* IMR0 */
+ __raw_writeb(sh7724_rstandby_state.imr1, 0xa4080084); /* IMR1 */
+ __raw_writeb(sh7724_rstandby_state.imr2, 0xa4080088); /* IMR2 */
+ __raw_writeb(sh7724_rstandby_state.imr3, 0xa408008c); /* IMR3 */
+ __raw_writeb(sh7724_rstandby_state.imr4, 0xa4080090); /* IMR4 */
+ __raw_writeb(sh7724_rstandby_state.imr5, 0xa4080094); /* IMR5 */
+ __raw_writeb(sh7724_rstandby_state.imr6, 0xa4080098); /* IMR6 */
+ __raw_writeb(sh7724_rstandby_state.imr7, 0xa408009c); /* IMR7 */
+ __raw_writeb(sh7724_rstandby_state.imr8, 0xa40800a0); /* IMR8 */
+ __raw_writeb(sh7724_rstandby_state.imr9, 0xa40800a4); /* IMR9 */
+ __raw_writeb(sh7724_rstandby_state.imr10, 0xa40800a8); /* IMR10 */
+ __raw_writeb(sh7724_rstandby_state.imr11, 0xa40800ac); /* IMR11 */
+ __raw_writeb(sh7724_rstandby_state.imr12, 0xa40800b0); /* IMR12 */
+
+ /* RWDT */
+ __raw_writew(sh7724_rstandby_state.rwtcnt, 0xa4520000); /* RWTCNT */
+ __raw_writew(sh7724_rstandby_state.rwtcsr, 0xa4520004); /* RWTCSR */
+
+ /* CPG */
+ __raw_writel(sh7724_rstandby_state.irdaclk, 0xa4150018); /* IRDACLKCR */
+ __raw_writel(sh7724_rstandby_state.spuclk, 0xa415003c); /* SPUCLKCR */
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block sh7724_pre_sleep_notifier = {
+ .notifier_call = sh7724_pre_sleep_notifier_call,
+ .priority = SH_MOBILE_PRE(SH_MOBILE_SLEEP_CPU),
+};
+
+static struct notifier_block sh7724_post_sleep_notifier = {
+ .notifier_call = sh7724_post_sleep_notifier_call,
+ .priority = SH_MOBILE_POST(SH_MOBILE_SLEEP_CPU),
+};
+
+static int __init sh7724_sleep_setup(void)
+{
+ atomic_notifier_chain_register(&sh_mobile_pre_sleep_notifier_list,
+ &sh7724_pre_sleep_notifier);
+
+ atomic_notifier_chain_register(&sh_mobile_post_sleep_notifier_list,
+ &sh7724_post_sleep_notifier);
+ return 0;
+}
+arch_initcall(sh7724_sleep_setup);
+
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7734.c b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
new file mode 100644
index 00000000000..f617bcb734d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7734.c
@@ -0,0 +1,629 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/setup-sh7734.c
+
+ * SH7734 Setup
+ *
+ * Copyright (C) 2011,2012 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ * Copyright (C) 2011,2012 Renesas Solutions Corp.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/irq.h>
+#include <cpu/sh7734.h>
+
+/* SCIF */
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe40000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x8c0)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe41000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x8e0)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffe42000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xffe43000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x920)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xffe44000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x940)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_REGTYPE,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xffe43000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x960)),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+/* RTC */
+static struct resource rtc_resources[] = {
+ [0] = {
+ .name = "rtc",
+ .start = 0xFFFC5000,
+ .end = 0xFFFC5000 + 0x26 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .start = evt2irq(0xC00),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+/* I2C 0 */
+static struct resource i2c0_resources[] = {
+ [0] = {
+ .name = "IIC0",
+ .start = 0xFFC70000,
+ .end = 0xFFC7000A - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x860),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device i2c0_device = {
+ .name = "i2c-sh7734",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(i2c0_resources),
+ .resource = i2c0_resources,
+};
+
+/* TMU */
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffd81000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x480)),
+ DEFINE_RES_IRQ(evt2irq(0x4a0)),
+ DEFINE_RES_IRQ(evt2irq(0x4c0)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu2_resources[] = {
+ DEFINE_RES_MEM(0xffd82000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x500)),
+ DEFINE_RES_IRQ(evt2irq(0x520)),
+ DEFINE_RES_IRQ(evt2irq(0x540)),
+};
+
+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 *sh7734_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+ &rtc_device,
+};
+
+static struct platform_device *sh7734_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7734_early_devices,
+ ARRAY_SIZE(sh7734_early_devices));
+}
+
+#define GROUP 0
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+
+ IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+ IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+ IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+ IRL0_HHLL, IRL0_HHLH, IRL0_HHHL,
+
+ IRQ0, IRQ1, IRQ2, IRQ3,
+ DU,
+ TMU00, TMU10, TMU20, TMU21,
+ TMU30, TMU40, TMU50, TMU51,
+ TMU60, TMU70, TMU80,
+ RESET_WDT,
+ USB,
+ HUDI,
+ SHDMAC,
+ SSI0, SSI1, SSI2, SSI3,
+ VIN0,
+ RGPVG,
+ _2DG,
+ MMC,
+ HSPI,
+ LBSCATA,
+ I2C0,
+ RCAN0,
+ MIMLB,
+ SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5,
+ LBSCDMAC0, LBSCDMAC1, LBSCDMAC2,
+ RCAN1,
+ SDHI0, SDHI1,
+ IEBUS,
+ HPBDMAC0_3, HPBDMAC4_10, HPBDMAC11_18, HPBDMAC19_22, HPBDMAC23_25_27_28,
+ RTC,
+ VIN1,
+ LCDC,
+ SRC0, SRC1,
+ GETHER,
+ SDHI2,
+ GPIO0_3, GPIO4_5,
+ STIF0, STIF1,
+ ADMAC,
+ HIF,
+ FLCTL,
+ ADC,
+ MTU2,
+ RSPI,
+ QSPI,
+ HSCIF,
+ VEU3F_VE3,
+
+ /* Group */
+ /* Mask */
+ STIF_M,
+ GPIO_M,
+ HPBDMAC_M,
+ LBSCDMAC_M,
+ RCAN_M,
+ SRC_M,
+ SCIF_M,
+ LCDC_M,
+ _2DG_M,
+ VIN_M,
+ TMU_3_M,
+ TMU_0_M,
+
+ /* Priority */
+ RCAN_P,
+ LBSCDMAC_P,
+
+ /* Common */
+ SDHI,
+ SSI,
+ SPI,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(DU, 0x3E0),
+ INTC_VECT(TMU00, 0x400),
+ INTC_VECT(TMU10, 0x420),
+ INTC_VECT(TMU20, 0x440),
+ INTC_VECT(TMU30, 0x480),
+ INTC_VECT(TMU40, 0x4A0),
+ INTC_VECT(TMU50, 0x4C0),
+ INTC_VECT(TMU51, 0x4E0),
+ INTC_VECT(TMU60, 0x500),
+ INTC_VECT(TMU70, 0x520),
+ INTC_VECT(TMU80, 0x540),
+ INTC_VECT(RESET_WDT, 0x560),
+ INTC_VECT(USB, 0x580),
+ INTC_VECT(HUDI, 0x600),
+ INTC_VECT(SHDMAC, 0x620),
+ INTC_VECT(SSI0, 0x6C0),
+ INTC_VECT(SSI1, 0x6E0),
+ INTC_VECT(SSI2, 0x700),
+ INTC_VECT(SSI3, 0x720),
+ INTC_VECT(VIN0, 0x740),
+ INTC_VECT(RGPVG, 0x760),
+ INTC_VECT(_2DG, 0x780),
+ INTC_VECT(MMC, 0x7A0),
+ INTC_VECT(HSPI, 0x7E0),
+ INTC_VECT(LBSCATA, 0x840),
+ INTC_VECT(I2C0, 0x860),
+ INTC_VECT(RCAN0, 0x880),
+ INTC_VECT(SCIF0, 0x8A0),
+ INTC_VECT(SCIF1, 0x8C0),
+ INTC_VECT(SCIF2, 0x900),
+ INTC_VECT(SCIF3, 0x920),
+ INTC_VECT(SCIF4, 0x940),
+ INTC_VECT(SCIF5, 0x960),
+ INTC_VECT(LBSCDMAC0, 0x9E0),
+ INTC_VECT(LBSCDMAC1, 0xA00),
+ INTC_VECT(LBSCDMAC2, 0xA20),
+ INTC_VECT(RCAN1, 0xA60),
+ INTC_VECT(SDHI0, 0xAE0),
+ INTC_VECT(SDHI1, 0xB00),
+ INTC_VECT(IEBUS, 0xB20),
+ INTC_VECT(HPBDMAC0_3, 0xB60),
+ INTC_VECT(HPBDMAC4_10, 0xB80),
+ INTC_VECT(HPBDMAC11_18, 0xBA0),
+ INTC_VECT(HPBDMAC19_22, 0xBC0),
+ INTC_VECT(HPBDMAC23_25_27_28, 0xBE0),
+ INTC_VECT(RTC, 0xC00),
+ INTC_VECT(VIN1, 0xC20),
+ INTC_VECT(LCDC, 0xC40),
+ INTC_VECT(SRC0, 0xC60),
+ INTC_VECT(SRC1, 0xC80),
+ INTC_VECT(GETHER, 0xCA0),
+ INTC_VECT(SDHI2, 0xCC0),
+ INTC_VECT(GPIO0_3, 0xCE0),
+ INTC_VECT(GPIO4_5, 0xD00),
+ INTC_VECT(STIF0, 0xD20),
+ INTC_VECT(STIF1, 0xD40),
+ INTC_VECT(ADMAC, 0xDA0),
+ INTC_VECT(HIF, 0xDC0),
+ INTC_VECT(FLCTL, 0xDE0),
+ INTC_VECT(ADC, 0xE00),
+ INTC_VECT(MTU2, 0xE20),
+ INTC_VECT(RSPI, 0xE40),
+ INTC_VECT(QSPI, 0xE60),
+ INTC_VECT(HSCIF, 0xFC0),
+ INTC_VECT(VEU3F_VE3, 0xF40),
+};
+
+static struct intc_group groups[] __initdata = {
+ /* Common */
+ INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2),
+ INTC_GROUP(SPI, HSPI, RSPI, QSPI),
+ INTC_GROUP(SSI, SSI0, SSI1, SSI2, SSI3),
+
+ /* Mask group */
+ INTC_GROUP(STIF_M, STIF0, STIF1), /* 22 */
+ INTC_GROUP(GPIO_M, GPIO0_3, GPIO4_5), /* 21 */
+ INTC_GROUP(HPBDMAC_M, HPBDMAC0_3, HPBDMAC4_10, HPBDMAC11_18,
+ HPBDMAC19_22, HPBDMAC23_25_27_28), /* 19 */
+ INTC_GROUP(LBSCDMAC_M, LBSCDMAC0, LBSCDMAC1, LBSCDMAC2), /* 18 */
+ INTC_GROUP(RCAN_M, RCAN0, RCAN1, IEBUS), /* 17 */
+ INTC_GROUP(SRC_M, SRC0, SRC1), /* 16 */
+ INTC_GROUP(SCIF_M, SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5,
+ HSCIF), /* 14 */
+ INTC_GROUP(LCDC_M, LCDC, MIMLB), /* 13 */
+ INTC_GROUP(_2DG_M, _2DG, RGPVG), /* 12 */
+ INTC_GROUP(VIN_M, VIN0, VIN1), /* 10 */
+ INTC_GROUP(TMU_3_M, TMU30, TMU40, TMU50, TMU51,
+ TMU60, TMU60, TMU70, TMU80), /* 2 */
+ INTC_GROUP(TMU_0_M, TMU00, TMU10, TMU20, TMU21), /* 1 */
+
+ /* Priority group*/
+ INTC_GROUP(RCAN_P, RCAN0, RCAN1), /* INT2PRI5 */
+ INTC_GROUP(LBSCDMAC_P, LBSCDMAC0, LBSCDMAC1), /* INT2PRI5 */
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xFF804040, 0xFF804044, 32, /* INT2MSKRG / INT2MSKCR */
+ { 0,
+ VEU3F_VE3,
+ SDHI, /* SDHI 0-2 */
+ ADMAC,
+ FLCTL,
+ RESET_WDT,
+ HIF,
+ ADC,
+ MTU2,
+ STIF_M, /* STIF 0,1 */
+ GPIO_M, /* GPIO 0-5*/
+ GETHER,
+ HPBDMAC_M, /* HPBDMAC 0_3 - 23_25_27_28 */
+ LBSCDMAC_M, /* LBSCDMAC 0 - 2 */
+ RCAN_M, /* RCAN, IEBUS */
+ SRC_M, /* SRC 0,1 */
+ LBSCATA,
+ SCIF_M, /* SCIF 0-5, HSCIF */
+ LCDC_M, /* LCDC, MIMLB */
+ _2DG_M, /* 2DG, RGPVG */
+ SPI, /* HSPI, RSPI, QSPI */
+ VIN_M, /* VIN0, 1 */
+ SSI, /* SSI 0-3 */
+ USB,
+ SHDMAC,
+ HUDI,
+ MMC,
+ RTC,
+ I2C0, /* I2C */ /* I2C 0, 1*/
+ TMU_3_M, /* TMU30 - TMU80 */
+ TMU_0_M, /* TMU00 - TMU21 */
+ DU } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xFF804000, 0, 32, 8, /* INT2PRI0 */
+ { DU, TMU00, TMU10, TMU20 } },
+ { 0xFF804004, 0, 32, 8, /* INT2PRI1 */
+ { TMU30, TMU60, RTC, SDHI } },
+ { 0xFF804008, 0, 32, 8, /* INT2PRI2 */
+ { HUDI, SHDMAC, USB, SSI } },
+ { 0xFF80400C, 0, 32, 8, /* INT2PRI3 */
+ { VIN0, SPI, _2DG, LBSCATA } },
+ { 0xFF804010, 0, 32, 8, /* INT2PRI4 */
+ { SCIF0, SCIF3, HSCIF, LCDC } },
+ { 0xFF804014, 0, 32, 8, /* INT2PRI5 */
+ { RCAN_P, LBSCDMAC_P, LBSCDMAC2, MMC } },
+ { 0xFF804018, 0, 32, 8, /* INT2PRI6 */
+ { HPBDMAC0_3, HPBDMAC4_10, HPBDMAC11_18, HPBDMAC19_22 } },
+ { 0xFF80401C, 0, 32, 8, /* INT2PRI7 */
+ { HPBDMAC23_25_27_28, I2C0, SRC0, SRC1 } },
+ { 0xFF804020, 0, 32, 8, /* INT2PRI8 */
+ { 0 /* ADIF */, VIN1, RESET_WDT, HIF } },
+ { 0xFF804024, 0, 32, 8, /* INT2PRI9 */
+ { ADMAC, FLCTL, GPIO0_3, GPIO4_5 } },
+ { 0xFF804028, 0, 32, 8, /* INT2PRI10 */
+ { STIF0, STIF1, VEU3F_VE3, GETHER } },
+ { 0xFF80402C, 0, 32, 8, /* INT2PRI11 */
+ { MTU2, RGPVG, MIMLB, IEBUS } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7734", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+
+static struct intc_vect irq3210_vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+ INTC_VECT(IRQ2, 0x2C0), INTC_VECT(IRQ3, 0x300),
+};
+
+static struct intc_sense_reg irq3210_sense_registers[] __initdata = {
+ { 0xFF80201C, 32, 2, /* ICR1 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static struct intc_mask_reg irq3210_ack_registers[] __initdata = {
+ { 0xFF802024, 0, 32, /* INTREQ */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static struct intc_mask_reg irq3210_mask_registers[] __initdata = {
+ { 0xFF802044, 0xFF802064, 32, /* INTMSK0 / INTMSKCLR0 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static struct intc_prio_reg irq3210_prio_registers[] __initdata = {
+ { 0xFF802010, 0, 32, 4, /* INTPRI */
+ { IRQ0, IRQ1, IRQ2, IRQ3, } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq3210, "sh7734-irq3210",
+ irq3210_vectors, NULL,
+ irq3210_mask_registers, irq3210_prio_registers,
+ irq3210_sense_registers, irq3210_ack_registers);
+
+/* External interrupt pins in IRL mode */
+
+static struct intc_vect vectors_irl3210[] __initdata = {
+ INTC_VECT(IRL0_LLLL, 0x200), INTC_VECT(IRL0_LLLH, 0x220),
+ INTC_VECT(IRL0_LLHL, 0x240), INTC_VECT(IRL0_LLHH, 0x260),
+ INTC_VECT(IRL0_LHLL, 0x280), INTC_VECT(IRL0_LHLH, 0x2a0),
+ INTC_VECT(IRL0_LHHL, 0x2c0), INTC_VECT(IRL0_LHHH, 0x2e0),
+ INTC_VECT(IRL0_HLLL, 0x300), INTC_VECT(IRL0_HLLH, 0x320),
+ INTC_VECT(IRL0_HLHL, 0x340), INTC_VECT(IRL0_HLHH, 0x360),
+ INTC_VECT(IRL0_HHLL, 0x380), INTC_VECT(IRL0_HHLH, 0x3a0),
+ INTC_VECT(IRL0_HHHL, 0x3c0),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irl3210, "sh7734-irl3210",
+ vectors_irl3210, NULL, mask_registers, NULL, NULL);
+
+#define INTC_ICR0 0xFF802000
+#define INTC_INTMSK0 0xFF802044
+#define INTC_INTMSK1 0xFF802048
+#define INTC_INTMSKCLR0 0xFF802064
+#define INTC_INTMSKCLR1 0xFF802068
+
+void __init plat_irq_setup(void)
+{
+ /* disable IRQ3-0 */
+ __raw_writel(0xF0000000, INTC_INTMSK0);
+
+ /* disable IRL3-0 */
+ __raw_writel(0x80000000, INTC_INTMSK1);
+
+ /* select IRL mode for IRL3-0 */
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00800000, INTC_ICR0);
+
+ /* disable holding function, ie enable "SH-4 Mode (LVLMODE)" */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+
+ register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+ switch (mode) {
+ case IRQ_MODE_IRQ3210:
+ /* select IRQ mode for IRL3-0 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+ register_intc_controller(&intc_desc_irq3210);
+ break;
+ case IRQ_MODE_IRL3210:
+ /* enable IRL0-3 but don't provide any masking */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xf0000000, INTC_INTMSKCLR0);
+ break;
+ case IRQ_MODE_IRL3210_MASK:
+ /* enable IRL0-3 and mask using cpu intc controller */
+ __raw_writel(0x80000000, INTC_INTMSKCLR0);
+ register_intc_controller(&intc_desc_irl3210);
+ break;
+ default:
+ BUG();
+ }
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
new file mode 100644
index 00000000000..7b24ec4b409
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -0,0 +1,1247 @@
+/*
+ * SH7757 Setup
+ *
+ * Copyright (C) 2009, 2011 Renesas Solutions Corp.
+ *
+ * based on setup-sh7785.c : Copyright (C) 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <cpu/dma-register.h>
+#include <cpu/sh7757.h>
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xfe4b0000, 0x100), /* SCIF2 */
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xfe4c0000, 0x100), /* SCIF3 */
+ DEFINE_RES_IRQ(evt2irq(0xb80)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xfe4d0000, 0x100), /* SCIF4 */
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 3,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xfe430000, 0x20),
+ DEFINE_RES_IRQ(evt2irq(0x580)),
+ DEFINE_RES_IRQ(evt2irq(0x5a0)),
+};
+
+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 resource spi0_resources[] = {
+ [0] = {
+ .start = 0xfe002000,
+ .end = 0xfe0020ff,
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT,
+ },
+ [1] = {
+ .start = evt2irq(0xcc0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* DMA */
+static const struct sh_dmae_slave_config sh7757_dmae0_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SDHI_TX,
+ .addr = 0x1fe50030,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc5,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_SDHI_RX,
+ .addr = 0x1fe50030,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc6,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_MMCIF_TX,
+ .addr = 0x1fcb0034,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xd3,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_MMCIF_RX,
+ .addr = 0x1fcb0034,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xd7,
+ },
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SCIF2_TX,
+ .addr = 0x1f4b000c,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_SCIF2_RX,
+ .addr = 0x1f4b0014,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_SCIF3_TX,
+ .addr = 0x1f4c000c,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_SCIF3_RX,
+ .addr = 0x1f4c0014,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_SCIF4_TX,
+ .addr = 0x1f4d000c,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x41,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_SCIF4_RX,
+ .addr = 0x1f4d0014,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x42,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RSPI_TX,
+ .addr = 0xfe480004,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc1,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RSPI_RX,
+ .addr = 0xfe480004,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_16BIT),
+ .mid_rid = 0xc2,
+ },
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_RIIC0_TX,
+ .addr = 0x1e500012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC0_RX,
+ .addr = 0x1e500013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC1_TX,
+ .addr = 0x1e510012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC1_RX,
+ .addr = 0x1e510013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC2_TX,
+ .addr = 0x1e520012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0xa1,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC2_RX,
+ .addr = 0x1e520013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0xa2,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC3_TX,
+ .addr = 0x1e530012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0xa9,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC3_RX,
+ .addr = 0x1e530013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0xaf,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC4_TX,
+ .addr = 0x1e540012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0xc5,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC4_RX,
+ .addr = 0x1e540013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0xc6,
+ },
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_RIIC5_TX,
+ .addr = 0x1e550012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC5_RX,
+ .addr = 0x1e550013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC6_TX,
+ .addr = 0x1e560012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC6_RX,
+ .addr = 0x1e560013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC7_TX,
+ .addr = 0x1e570012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x41,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC7_RX,
+ .addr = 0x1e570013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x42,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC8_TX,
+ .addr = 0x1e580012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x45,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC8_RX,
+ .addr = 0x1e580013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x46,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC9_TX,
+ .addr = 0x1e590012,
+ .chcr = SM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x51,
+ },
+ {
+ .slave_id = SHDMA_SLAVE_RIIC9_RX,
+ .addr = 0x1e590013,
+ .chcr = DM_INC | 0x800 | 0x40000000 |
+ TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x52,
+ },
+};
+
+static const struct sh_dmae_channel sh7757_dmae_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .slave = sh7757_dmae0_slaves,
+ .slave_num = ARRAY_SIZE(sh7757_dmae0_slaves),
+ .channel = sh7757_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7757_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+ .slave = sh7757_dmae1_slaves,
+ .slave_num = ARRAY_SIZE(sh7757_dmae1_slaves),
+ .channel = sh7757_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7757_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma2_platform_data = {
+ .slave = sh7757_dmae2_slaves,
+ .slave_num = ARRAY_SIZE(sh7757_dmae2_slaves),
+ .channel = sh7757_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7757_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma3_platform_data = {
+ .slave = sh7757_dmae3_slaves,
+ .slave_num = ARRAY_SIZE(sh7757_dmae3_slaves),
+ .channel = sh7757_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7757_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+/* channel 0 to 5 */
+static struct resource sh7757_dmae0_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xff608020,
+ .end = 0xff60808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xff609000,
+ .end = 0xff60900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0x640),
+ .end = evt2irq(0x640),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+/* channel 6 to 11 */
+static struct resource sh7757_dmae1_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xff618020,
+ .end = 0xff61808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xff619000,
+ .end = 0xff61900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0x640),
+ .end = evt2irq(0x640),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 4 */
+ .start = evt2irq(0x7c0),
+ .end = evt2irq(0x7c0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 5 */
+ .start = evt2irq(0x7c0),
+ .end = evt2irq(0x7c0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 6 */
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 7 */
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 8 */
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 9 */
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 10 */
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+ {
+ /* IRQ for channels 11 */
+ .start = evt2irq(0xd00),
+ .end = evt2irq(0xd00),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+/* channel 12 to 17 */
+static struct resource sh7757_dmae2_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xff708020,
+ .end = 0xff70808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xff709000,
+ .end = 0xff70900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0x2a60),
+ .end = evt2irq(0x2a60),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 12 to 16 */
+ .start = evt2irq(0x2400),
+ .end = evt2irq(0x2480),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channel 17 */
+ .start = evt2irq(0x24e0),
+ .end = evt2irq(0x24e0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* channel 18 to 23 */
+static struct resource sh7757_dmae3_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xff718020,
+ .end = 0xff71808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xff719000,
+ .end = 0xff71900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "error_irq",
+ .start = evt2irq(0x2a80),
+ .end = evt2irq(0x2a80),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 18 to 22 */
+ .start = evt2irq(0x2500),
+ .end = evt2irq(0x2580),
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channel 23 */
+ .start = evt2irq(0x2600),
+ .end = evt2irq(0x2600),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = sh7757_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7757_dmae0_resources),
+ .dev = {
+ .platform_data = &dma0_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7757_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7757_dmae1_resources),
+ .dev = {
+ .platform_data = &dma1_platform_data,
+ },
+};
+
+static struct platform_device dma2_device = {
+ .name = "sh-dma-engine",
+ .id = 2,
+ .resource = sh7757_dmae2_resources,
+ .num_resources = ARRAY_SIZE(sh7757_dmae2_resources),
+ .dev = {
+ .platform_data = &dma2_platform_data,
+ },
+};
+
+static struct platform_device dma3_device = {
+ .name = "sh-dma-engine",
+ .id = 3,
+ .resource = sh7757_dmae3_resources,
+ .num_resources = ARRAY_SIZE(sh7757_dmae3_resources),
+ .dev = {
+ .platform_data = &dma3_platform_data,
+ },
+};
+
+static struct platform_device spi0_device = {
+ .name = "sh_spi",
+ .id = 0,
+ .dev = {
+ .dma_mask = NULL,
+ .coherent_dma_mask = 0xffffffff,
+ },
+ .num_resources = ARRAY_SIZE(spi0_resources),
+ .resource = spi0_resources,
+};
+
+static struct resource spi1_resources[] = {
+ {
+ .start = 0xffd8ee70,
+ .end = 0xffd8eeff,
+ .flags = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+ },
+ {
+ .start = evt2irq(0x8c0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device spi1_device = {
+ .name = "sh_spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(spi1_resources),
+ .resource = spi1_resources,
+};
+
+static struct resource rspi_resources[] = {
+ {
+ .start = 0xfe480000,
+ .end = 0xfe4800ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = evt2irq(0x1d80),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rspi_device = {
+ .name = "rspi",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(rspi_resources),
+ .resource = rspi_resources,
+};
+
+static struct resource usb_ehci_resources[] = {
+ [0] = {
+ .start = 0xfe4f1000,
+ .end = 0xfe4f10ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x920),
+ .end = evt2irq(0x920),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usb_ehci_device = {
+ .name = "sh_ehci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &usb_ehci_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(usb_ehci_resources),
+ .resource = usb_ehci_resources,
+};
+
+static struct resource usb_ohci_resources[] = {
+ [0] = {
+ .start = 0xfe4f1800,
+ .end = 0xfe4f18ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0x920),
+ .end = evt2irq(0x920),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct usb_ohci_pdata usb_ohci_pdata;
+
+static struct platform_device usb_ohci_device = {
+ .name = "ohci-platform",
+ .id = -1,
+ .dev = {
+ .dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &usb_ohci_pdata,
+ },
+ .num_resources = ARRAY_SIZE(usb_ohci_resources),
+ .resource = usb_ohci_resources,
+};
+
+static struct platform_device *sh7757_devices[] __initdata = {
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &tmu0_device,
+ &dma0_device,
+ &dma1_device,
+ &dma2_device,
+ &dma3_device,
+ &spi0_device,
+ &spi1_device,
+ &rspi_device,
+ &usb_ehci_device,
+ &usb_ohci_device,
+};
+
+static int __init sh7757_devices_setup(void)
+{
+ return platform_add_devices(sh7757_devices,
+ ARRAY_SIZE(sh7757_devices));
+}
+arch_initcall(sh7757_devices_setup);
+
+static struct platform_device *sh7757_early_devices[] __initdata = {
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &tmu0_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7757_early_devices,
+ ARRAY_SIZE(sh7757_early_devices));
+}
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+
+ IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+ IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+ IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+ IRL0_HHLL, IRL0_HHLH, IRL0_HHHL,
+
+ IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+ IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+ IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+ IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+
+ SDHI, DVC,
+ IRQ8, IRQ9, IRQ11, IRQ10, IRQ12, IRQ13, IRQ14, IRQ15,
+ TMU0, TMU1, TMU2, TMU2_TICPI, TMU3, TMU4, TMU5,
+ HUDI,
+ ARC4,
+ DMAC0_5, DMAC6_7, DMAC8_11,
+ SCIF0, SCIF1, SCIF2, SCIF3, SCIF4,
+ USB0, USB1,
+ JMC,
+ SPI0, SPI1,
+ TMR01, TMR23, TMR45,
+ FRT,
+ LPC, LPC5, LPC6, LPC7, LPC8,
+ PECI0, PECI1, PECI2, PECI3, PECI4, PECI5,
+ ETHERC,
+ ADC0, ADC1,
+ SIM,
+ IIC0_0, IIC0_1, IIC0_2, IIC0_3,
+ IIC1_0, IIC1_1, IIC1_2, IIC1_3,
+ IIC2_0, IIC2_1, IIC2_2, IIC2_3,
+ IIC3_0, IIC3_1, IIC3_2, IIC3_3,
+ IIC4_0, IIC4_1, IIC4_2, IIC4_3,
+ IIC5_0, IIC5_1, IIC5_2, IIC5_3,
+ IIC6_0, IIC6_1, IIC6_2, IIC6_3,
+ IIC7_0, IIC7_1, IIC7_2, IIC7_3,
+ IIC8_0, IIC8_1, IIC8_2, IIC8_3,
+ IIC9_0, IIC9_1, IIC9_2, IIC9_3,
+ ONFICTL,
+ MMC1, MMC2,
+ ECCU,
+ PCIC,
+ G200,
+ RSPI,
+ SGPIO,
+ DMINT12, DMINT13, DMINT14, DMINT15, DMINT16, DMINT17, DMINT18, DMINT19,
+ DMINT20, DMINT21, DMINT22, DMINT23,
+ DDRECC,
+ TSIP,
+ PCIE_BRIDGE,
+ WDT0B, WDT1B, WDT2B, WDT3B, WDT4B, WDT5B, WDT6B, WDT7B, WDT8B,
+ GETHER0, GETHER1, GETHER2,
+ PBIA, PBIB, PBIC,
+ DMAE2, DMAE3,
+ SERMUX2, SERMUX3,
+
+ /* interrupt groups */
+
+ TMU012, TMU345,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(SDHI, 0x480), INTC_VECT(SDHI, 0x04a0),
+ INTC_VECT(SDHI, 0x4c0),
+ INTC_VECT(DVC, 0x4e0),
+ INTC_VECT(IRQ8, 0x500), INTC_VECT(IRQ9, 0x520),
+ INTC_VECT(IRQ10, 0x540),
+ INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
+ INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
+ INTC_VECT(HUDI, 0x600),
+ INTC_VECT(ARC4, 0x620),
+ INTC_VECT(DMAC0_5, 0x640), INTC_VECT(DMAC0_5, 0x660),
+ INTC_VECT(DMAC0_5, 0x680), INTC_VECT(DMAC0_5, 0x6a0),
+ INTC_VECT(DMAC0_5, 0x6c0),
+ INTC_VECT(IRQ11, 0x6e0),
+ INTC_VECT(SCIF2, 0x700), INTC_VECT(SCIF2, 0x720),
+ INTC_VECT(SCIF2, 0x740), INTC_VECT(SCIF2, 0x760),
+ INTC_VECT(DMAC0_5, 0x780), INTC_VECT(DMAC0_5, 0x7a0),
+ INTC_VECT(DMAC6_7, 0x7c0), INTC_VECT(DMAC6_7, 0x7e0),
+ INTC_VECT(USB0, 0x840),
+ INTC_VECT(IRQ12, 0x880),
+ INTC_VECT(JMC, 0x8a0),
+ INTC_VECT(SPI1, 0x8c0),
+ INTC_VECT(IRQ13, 0x8e0), INTC_VECT(IRQ14, 0x900),
+ INTC_VECT(USB1, 0x920),
+ INTC_VECT(TMR01, 0xa00), INTC_VECT(TMR23, 0xa20),
+ INTC_VECT(TMR45, 0xa40),
+ INTC_VECT(FRT, 0xa80),
+ INTC_VECT(LPC, 0xaa0), INTC_VECT(LPC, 0xac0),
+ INTC_VECT(LPC, 0xae0), INTC_VECT(LPC, 0xb00),
+ INTC_VECT(LPC, 0xb20),
+ INTC_VECT(SCIF0, 0xb40), INTC_VECT(SCIF1, 0xb60),
+ INTC_VECT(SCIF3, 0xb80), INTC_VECT(SCIF3, 0xba0),
+ INTC_VECT(SCIF3, 0xbc0), INTC_VECT(SCIF3, 0xbe0),
+ INTC_VECT(PECI0, 0xc00), INTC_VECT(PECI1, 0xc20),
+ INTC_VECT(PECI2, 0xc40),
+ INTC_VECT(IRQ15, 0xc60),
+ INTC_VECT(ETHERC, 0xc80), INTC_VECT(ETHERC, 0xca0),
+ INTC_VECT(SPI0, 0xcc0),
+ INTC_VECT(ADC1, 0xce0),
+ INTC_VECT(DMAC8_11, 0xd00), INTC_VECT(DMAC8_11, 0xd20),
+ INTC_VECT(DMAC8_11, 0xd40), INTC_VECT(DMAC8_11, 0xd60),
+ INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0),
+ INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0),
+ INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
+ INTC_VECT(TMU5, 0xe40),
+ INTC_VECT(ADC0, 0xe60),
+ INTC_VECT(SCIF4, 0xf00), INTC_VECT(SCIF4, 0xf20),
+ INTC_VECT(SCIF4, 0xf40), INTC_VECT(SCIF4, 0xf60),
+ INTC_VECT(IIC0_0, 0x1400), INTC_VECT(IIC0_1, 0x1420),
+ INTC_VECT(IIC0_2, 0x1440), INTC_VECT(IIC0_3, 0x1460),
+ INTC_VECT(IIC1_0, 0x1480), INTC_VECT(IIC1_1, 0x14e0),
+ INTC_VECT(IIC1_2, 0x1500), INTC_VECT(IIC1_3, 0x1520),
+ INTC_VECT(IIC2_0, 0x1540), INTC_VECT(IIC2_1, 0x1560),
+ INTC_VECT(IIC2_2, 0x1580), INTC_VECT(IIC2_3, 0x1600),
+ INTC_VECT(IIC3_0, 0x1620), INTC_VECT(IIC3_1, 0x1640),
+ INTC_VECT(IIC3_2, 0x16e0), INTC_VECT(IIC3_3, 0x1700),
+ INTC_VECT(IIC4_0, 0x17c0), INTC_VECT(IIC4_1, 0x1800),
+ INTC_VECT(IIC4_2, 0x1820), INTC_VECT(IIC4_3, 0x1840),
+ INTC_VECT(IIC5_0, 0x1860), INTC_VECT(IIC5_1, 0x1880),
+ INTC_VECT(IIC5_2, 0x18a0), INTC_VECT(IIC5_3, 0x18c0),
+ INTC_VECT(IIC6_0, 0x18e0), INTC_VECT(IIC6_1, 0x1900),
+ INTC_VECT(IIC6_2, 0x1920),
+ INTC_VECT(ONFICTL, 0x1960),
+ INTC_VECT(IIC6_3, 0x1980),
+ INTC_VECT(IIC7_0, 0x19a0), INTC_VECT(IIC7_1, 0x1a00),
+ INTC_VECT(IIC7_2, 0x1a20), INTC_VECT(IIC7_3, 0x1a40),
+ INTC_VECT(IIC8_0, 0x1a60), INTC_VECT(IIC8_1, 0x1a80),
+ INTC_VECT(IIC8_2, 0x1aa0), INTC_VECT(IIC8_3, 0x1b40),
+ INTC_VECT(IIC9_0, 0x1b60), INTC_VECT(IIC9_1, 0x1b80),
+ INTC_VECT(IIC9_2, 0x1c00), INTC_VECT(IIC9_3, 0x1c20),
+ INTC_VECT(MMC1, 0x1c60), INTC_VECT(MMC2, 0x1c80),
+ INTC_VECT(ECCU, 0x1cc0),
+ INTC_VECT(PCIC, 0x1ce0),
+ INTC_VECT(G200, 0x1d00),
+ INTC_VECT(RSPI, 0x1d80), INTC_VECT(RSPI, 0x1da0),
+ INTC_VECT(RSPI, 0x1dc0), INTC_VECT(RSPI, 0x1de0),
+ INTC_VECT(PECI3, 0x1ec0), INTC_VECT(PECI4, 0x1ee0),
+ INTC_VECT(PECI5, 0x1f00),
+ INTC_VECT(SGPIO, 0x1f80), INTC_VECT(SGPIO, 0x1fa0),
+ INTC_VECT(SGPIO, 0x1fc0),
+ INTC_VECT(DMINT12, 0x2400), INTC_VECT(DMINT13, 0x2420),
+ INTC_VECT(DMINT14, 0x2440), INTC_VECT(DMINT15, 0x2460),
+ INTC_VECT(DMINT16, 0x2480), INTC_VECT(DMINT17, 0x24e0),
+ INTC_VECT(DMINT18, 0x2500), INTC_VECT(DMINT19, 0x2520),
+ INTC_VECT(DMINT20, 0x2540), INTC_VECT(DMINT21, 0x2560),
+ INTC_VECT(DMINT22, 0x2580), INTC_VECT(DMINT23, 0x2600),
+ INTC_VECT(DDRECC, 0x2620),
+ INTC_VECT(TSIP, 0x2640),
+ INTC_VECT(PCIE_BRIDGE, 0x27c0),
+ INTC_VECT(WDT0B, 0x2800), INTC_VECT(WDT1B, 0x2820),
+ INTC_VECT(WDT2B, 0x2840), INTC_VECT(WDT3B, 0x2860),
+ INTC_VECT(WDT4B, 0x2880), INTC_VECT(WDT5B, 0x28a0),
+ INTC_VECT(WDT6B, 0x28c0), INTC_VECT(WDT7B, 0x28e0),
+ INTC_VECT(WDT8B, 0x2900),
+ INTC_VECT(GETHER0, 0x2960), INTC_VECT(GETHER1, 0x2980),
+ INTC_VECT(GETHER2, 0x29a0),
+ INTC_VECT(PBIA, 0x2a00), INTC_VECT(PBIB, 0x2a20),
+ INTC_VECT(PBIC, 0x2a40),
+ INTC_VECT(DMAE2, 0x2a60), INTC_VECT(DMAE3, 0x2a80),
+ INTC_VECT(SERMUX2, 0x2aa0), INTC_VECT(SERMUX3, 0x2b40),
+ INTC_VECT(LPC5, 0x2b60), INTC_VECT(LPC6, 0x2b80),
+ INTC_VECT(LPC7, 0x2c00), INTC_VECT(LPC8, 0x2c20),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
+ INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xffd00044, 0xffd00064, 32, /* INTMSK0 / INTMSKCLR0 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+
+ { 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */
+ { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+ IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+ IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+ IRL0_HHLL, IRL0_HHLH, IRL0_HHHL, 0,
+ IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+ IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+ IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+ IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } },
+
+ { 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
+ { 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, DMAC8_11, 0, PECI0, LPC, FRT, 0, TMR45,
+ TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0_5,
+ HUDI, 0, 0, SCIF3, SCIF2, SDHI, TMU345, TMU012
+ } },
+
+ { 0xffd400d0, 0xffd400d4, 32, /* INT2MSKR1 / INT2MSKCR1 */
+ { IRQ15, IRQ14, IRQ13, IRQ12, IRQ11, IRQ10, SCIF4, ETHERC,
+ IRQ9, IRQ8, SCIF1, SCIF0, USB0, 0, 0, USB1,
+ ADC1, 0, DMAC6_7, ADC0, SPI0, SIM, PECI2, PECI1,
+ ARC4, 0, SPI1, JMC, 0, 0, 0, DVC
+ } },
+
+ { 0xffd10038, 0xffd1003c, 32, /* INT2MSKR2 / INT2MSKCR2 */
+ { IIC4_1, IIC4_2, IIC5_0, ONFICTL, 0, 0, SGPIO, 0,
+ 0, G200, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3,
+ IIC7_2, IIC7_1, IIC6_3, IIC0_0, IIC0_1, IIC0_2, IIC0_3, IIC3_1,
+ IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, 0, IIC2_2
+ } },
+
+ { 0xffd100d0, 0xffd100d4, 32, /* INT2MSKR3 / INT2MSKCR3 */
+ { MMC1, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, PECI5, MMC2,
+ IIC1_3, IIC1_2, IIC9_0, IIC8_3, IIC4_3, IIC7_0, 0, IIC6_2,
+ PCIC, 0, IIC4_0, 0, ECCU, RSPI, 0, IIC9_3,
+ IIC3_0, 0, IIC5_3, IIC5_2, 0, 0, 0, IIC1_1
+ } },
+
+ { 0xffd20038, 0xffd2003c, 32, /* INT2MSKR4 / INT2MSKCR4 */
+ { WDT0B, WDT1B, WDT3B, GETHER0, 0, 0, 0, 0,
+ 0, 0, 0, LPC7, SERMUX2, DMAE3, DMAE2, PBIC,
+ PBIB, PBIA, GETHER1, DMINT12, DMINT13, DMINT14, DMINT15, TSIP,
+ DMINT23, 0, DMINT21, LPC6, 0, DMINT16, 0, DMINT22
+ } },
+
+ { 0xffd200d0, 0xffd200d4, 32, /* INT2MSKR5 / INT2MSKCR5 */
+ { 0, WDT8B, WDT7B, WDT4B, 0, DMINT20, 0, 0,
+ DMINT19, DMINT18, LPC5, SERMUX3, WDT2B, GETHER2, 0, 0,
+ 0, 0, PCIE_BRIDGE, 0, 0, 0, 0, LPC8,
+ DDRECC, 0, WDT6B, WDT5B, 0, 0, 0, DMINT17
+ } },
+};
+
+#define INTPRI 0xffd00010
+#define INT2PRI0 0xffd40000
+#define INT2PRI1 0xffd40004
+#define INT2PRI2 0xffd40008
+#define INT2PRI3 0xffd4000c
+#define INT2PRI4 0xffd40010
+#define INT2PRI5 0xffd40014
+#define INT2PRI6 0xffd40018
+#define INT2PRI7 0xffd4001c
+#define INT2PRI8 0xffd400a0
+#define INT2PRI9 0xffd400a4
+#define INT2PRI10 0xffd400a8
+#define INT2PRI11 0xffd400ac
+#define INT2PRI12 0xffd400b0
+#define INT2PRI13 0xffd400b4
+#define INT2PRI14 0xffd400b8
+#define INT2PRI15 0xffd400bc
+#define INT2PRI16 0xffd10000
+#define INT2PRI17 0xffd10004
+#define INT2PRI18 0xffd10008
+#define INT2PRI19 0xffd1000c
+#define INT2PRI20 0xffd10010
+#define INT2PRI21 0xffd10014
+#define INT2PRI22 0xffd10018
+#define INT2PRI23 0xffd1001c
+#define INT2PRI24 0xffd100a0
+#define INT2PRI25 0xffd100a4
+#define INT2PRI26 0xffd100a8
+#define INT2PRI27 0xffd100ac
+#define INT2PRI28 0xffd100b0
+#define INT2PRI29 0xffd100b4
+#define INT2PRI30 0xffd100b8
+#define INT2PRI31 0xffd100bc
+#define INT2PRI32 0xffd20000
+#define INT2PRI33 0xffd20004
+#define INT2PRI34 0xffd20008
+#define INT2PRI35 0xffd2000c
+#define INT2PRI36 0xffd20010
+#define INT2PRI37 0xffd20014
+#define INT2PRI38 0xffd20018
+#define INT2PRI39 0xffd2001c
+#define INT2PRI40 0xffd200a0
+#define INT2PRI41 0xffd200a4
+#define INT2PRI42 0xffd200a8
+#define INT2PRI43 0xffd200ac
+#define INT2PRI44 0xffd200b0
+#define INT2PRI45 0xffd200b4
+#define INT2PRI46 0xffd200b8
+#define INT2PRI47 0xffd200bc
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { INTPRI, 0, 32, 4, { IRQ0, IRQ1, IRQ2, IRQ3,
+ IRQ4, IRQ5, IRQ6, IRQ7 } },
+
+ { INT2PRI0, 0, 32, 8, { TMU0, TMU1, TMU2, TMU2_TICPI } },
+ { INT2PRI1, 0, 32, 8, { TMU3, TMU4, TMU5, SDHI } },
+ { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, 0, IRQ8 } },
+ { INT2PRI3, 0, 32, 8, { HUDI, DMAC0_5, ADC0, IRQ9 } },
+ { INT2PRI4, 0, 32, 8, { IRQ10, 0, TMR01, TMR23 } },
+ { INT2PRI5, 0, 32, 8, { TMR45, 0, FRT, LPC } },
+ { INT2PRI6, 0, 32, 8, { PECI0, ETHERC, DMAC8_11, 0 } },
+ { INT2PRI7, 0, 32, 8, { SCIF4, 0, IRQ11, IRQ12 } },
+ { INT2PRI8, 0, 32, 8, { 0, 0, 0, DVC } },
+ { INT2PRI9, 0, 32, 8, { ARC4, 0, SPI1, JMC } },
+ { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2, PECI1 } },
+ { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC6_7, IRQ14 } },
+ { INT2PRI12, 0, 32, 8, { USB0, 0, IRQ15, USB1 } },
+ { INT2PRI13, 0, 32, 8, { 0, 0, SCIF1, SCIF0 } },
+
+ { INT2PRI16, 0, 32, 8, { IIC2_2, 0, 0, 0 } },
+ { INT2PRI17, 0, 32, 8, { 0, 0, 0, IIC1_0 } },
+ { INT2PRI18, 0, 32, 8, { IIC3_3, IIC9_1, IIC2_1, IIC1_2 } },
+ { INT2PRI19, 0, 32, 8, { IIC2_3, IIC3_1, 0, IIC1_3 } },
+ { INT2PRI20, 0, 32, 8, { IIC2_0, IIC6_3, IIC7_1, IIC7_2 } },
+ { INT2PRI21, 0, 32, 8, { IIC7_3, IIC8_0, IIC8_1, IIC8_2 } },
+ { INT2PRI22, 0, 32, 8, { IIC9_2, MMC2, G200, 0 } },
+ { INT2PRI23, 0, 32, 8, { PECI5, SGPIO, IIC3_2, IIC5_1 } },
+ { INT2PRI24, 0, 32, 8, { PECI4, PECI3, 0, IIC1_1 } },
+ { INT2PRI25, 0, 32, 8, { IIC3_0, 0, IIC5_3, IIC5_2 } },
+ { INT2PRI26, 0, 32, 8, { ECCU, RSPI, 0, IIC9_3 } },
+ { INT2PRI27, 0, 32, 8, { PCIC, IIC6_0, IIC4_0, IIC6_1 } },
+ { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, MMC1, IIC6_2 } },
+ { INT2PRI29, 0, 32, 8, { 0, 0, IIC9_0, IIC8_3 } },
+ { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, ONFICTL } },
+ { INT2PRI31, 0, 32, 8, { IIC0_0, IIC0_1, IIC0_2, IIC0_3 } },
+ { INT2PRI32, 0, 32, 8, { DMINT22, 0, 0, 0 } },
+ { INT2PRI33, 0, 32, 8, { 0, 0, 0, DMINT16 } },
+ { INT2PRI34, 0, 32, 8, { 0, LPC6, DMINT21, DMINT18 } },
+ { INT2PRI35, 0, 32, 8, { DMINT23, TSIP, 0, DMINT19 } },
+ { INT2PRI36, 0, 32, 8, { DMINT20, GETHER1, PBIA, PBIB } },
+ { INT2PRI37, 0, 32, 8, { PBIC, DMAE2, DMAE3, SERMUX2 } },
+ { INT2PRI38, 0, 32, 8, { LPC7, 0, 0, 0 } },
+ { INT2PRI39, 0, 32, 8, { 0, 0, 0, WDT4B } },
+ { INT2PRI40, 0, 32, 8, { 0, 0, 0, DMINT17 } },
+ { INT2PRI41, 0, 32, 8, { DDRECC, 0, WDT6B, WDT5B } },
+ { INT2PRI42, 0, 32, 8, { 0, 0, 0, LPC8 } },
+ { INT2PRI43, 0, 32, 8, { 0, WDT7B, PCIE_BRIDGE, WDT8B } },
+ { INT2PRI44, 0, 32, 8, { WDT2B, GETHER2, 0, 0 } },
+ { INT2PRI45, 0, 32, 8, { 0, 0, LPC5, SERMUX3 } },
+ { INT2PRI46, 0, 32, 8, { WDT0B, WDT1B, WDT3B, GETHER0 } },
+ { INT2PRI47, 0, 32, 8, { DMINT12, DMINT13, DMINT14, DMINT15 } },
+};
+
+static struct intc_sense_reg sense_registers_irq8to15[] __initdata = {
+ { 0xffd100f8, 32, 2, /* ICR2 */ { IRQ15, IRQ14, IRQ13, IRQ12,
+ IRQ11, IRQ10, IRQ9, IRQ8 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups,
+ mask_registers, prio_registers,
+ sense_registers_irq8to15);
+
+/* Support for external interrupt pins in IRQ mode */
+static struct intc_vect vectors_irq0123[] __initdata = {
+ INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240),
+ INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0),
+};
+
+static struct intc_vect vectors_irq4567[] __initdata = {
+ INTC_VECT(IRQ4, 0x300), INTC_VECT(IRQ5, 0x340),
+ INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0),
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+ { 0xffd0001c, 32, 2, /* ICR1 */ { IRQ0, IRQ1, IRQ2, IRQ3,
+ IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+ { 0xffd00024, 0, 32, /* INTREQ */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7757-irq0123",
+ vectors_irq0123, NULL, mask_registers,
+ prio_registers, sense_registers, ack_registers);
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7757-irq4567",
+ vectors_irq4567, NULL, mask_registers,
+ prio_registers, sense_registers, ack_registers);
+
+/* External interrupt pins in IRL mode */
+static struct intc_vect vectors_irl0123[] __initdata = {
+ INTC_VECT(IRL0_LLLL, 0x200), INTC_VECT(IRL0_LLLH, 0x220),
+ INTC_VECT(IRL0_LLHL, 0x240), INTC_VECT(IRL0_LLHH, 0x260),
+ INTC_VECT(IRL0_LHLL, 0x280), INTC_VECT(IRL0_LHLH, 0x2a0),
+ INTC_VECT(IRL0_LHHL, 0x2c0), INTC_VECT(IRL0_LHHH, 0x2e0),
+ INTC_VECT(IRL0_HLLL, 0x300), INTC_VECT(IRL0_HLLH, 0x320),
+ INTC_VECT(IRL0_HLHL, 0x340), INTC_VECT(IRL0_HLHH, 0x360),
+ INTC_VECT(IRL0_HHLL, 0x380), INTC_VECT(IRL0_HHLH, 0x3a0),
+ INTC_VECT(IRL0_HHHL, 0x3c0),
+};
+
+static struct intc_vect vectors_irl4567[] __initdata = {
+ INTC_VECT(IRL4_LLLL, 0x200), INTC_VECT(IRL4_LLLH, 0x220),
+ INTC_VECT(IRL4_LLHL, 0x240), INTC_VECT(IRL4_LLHH, 0x260),
+ INTC_VECT(IRL4_LHLL, 0x280), INTC_VECT(IRL4_LHLH, 0x2a0),
+ INTC_VECT(IRL4_LHHL, 0x2c0), INTC_VECT(IRL4_LHHH, 0x2e0),
+ INTC_VECT(IRL4_HLLL, 0x300), INTC_VECT(IRL4_HLLH, 0x320),
+ INTC_VECT(IRL4_HLHL, 0x340), INTC_VECT(IRL4_HLHH, 0x360),
+ INTC_VECT(IRL4_HHLL, 0x380), INTC_VECT(IRL4_HHLH, 0x3a0),
+ INTC_VECT(IRL4_HHHL, 0x3c0),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7757-irl0123", vectors_irl0123,
+ NULL, mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7757-irl4567", vectors_irl4567,
+ NULL, mask_registers, NULL, NULL);
+
+#define INTC_ICR0 0xffd00000
+#define INTC_INTMSK0 0xffd00044
+#define INTC_INTMSK1 0xffd00048
+#define INTC_INTMSK2 0xffd40080
+#define INTC_INTMSKCLR1 0xffd00068
+#define INTC_INTMSKCLR2 0xffd40084
+
+void __init plat_irq_setup(void)
+{
+ /* disable IRQ3-0 + IRQ7-4 */
+ __raw_writel(0xff000000, INTC_INTMSK0);
+
+ /* disable IRL3-0 + IRL7-4 */
+ __raw_writel(0xc0000000, INTC_INTMSK1);
+ __raw_writel(0xfffefffe, INTC_INTMSK2);
+
+ /* select IRL mode for IRL3-0 + IRL7-4 */
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+
+ /* disable holding function, ie enable "SH-4 Mode" */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+
+ register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+ switch (mode) {
+ case IRQ_MODE_IRQ7654:
+ /* select IRQ mode for IRL7-4 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+ register_intc_controller(&intc_desc_irq4567);
+ break;
+ case IRQ_MODE_IRQ3210:
+ /* select IRQ mode for IRL3-0 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+ register_intc_controller(&intc_desc_irq0123);
+ break;
+ case IRQ_MODE_IRL7654:
+ /* enable IRL7-4 but don't provide any masking */
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x0000fffe, INTC_INTMSKCLR2);
+ break;
+ case IRQ_MODE_IRL3210:
+ /* enable IRL0-3 but don't provide any masking */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xfffe0000, INTC_INTMSKCLR2);
+ break;
+ case IRQ_MODE_IRL7654_MASK:
+ /* enable IRL7-4 and mask using cpu intc controller */
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ register_intc_controller(&intc_desc_irl4567);
+ break;
+ case IRQ_MODE_IRL3210_MASK:
+ /* enable IRL0-3 and mask using cpu intc controller */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ register_intc_controller(&intc_desc_irl0123);
+ break;
+ default:
+ BUG();
+ }
+}
+
+void __init plat_mem_setup(void)
+{
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
index 3c5b629887a..5a47d670dde 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2006 Paul Mundt
* Copyright (C) 2007 Yoshihiro Shimoda
- * Copyright (C) 2008 Nobuhiro Iwamatsu
+ * Copyright (C) 2008, 2009 Nobuhiro Iwamatsu
*
* 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
@@ -12,8 +12,77 @@
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/serial.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <linux/io.h>
#include <linux/serial_sci.h>
+#include <linux/usb/ohci_pdriver.h>
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe08000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xb80)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffe10000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xf00)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
static struct resource rtc_resources[] = {
[0] = {
@@ -22,18 +91,8 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- /* Period IRQ */
- .start = 21,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- /* Carry IRQ */
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- /* Alarm IRQ */
- .start = 20,
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -45,35 +104,6 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
- }, {
- .mapbase = 0xffe08000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 76, 77, 79, 78 },
- }, {
- .mapbase = 0xffe10000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 104, 105, 107, 106 },
- }, {
- .flags = 0,
- }
-};
-
-static struct platform_device sci_device = {
- .name = "sh-sci",
- .id = -1,
- .dev = {
- .platform_data = sci_platform_data,
- },
-};
-
static struct resource usb_ohci_resources[] = {
[0] = {
.start = 0xffec8000,
@@ -81,19 +111,23 @@ static struct resource usb_ohci_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 83,
- .end = 83,
+ .start = evt2irq(0xc60),
+ .end = evt2irq(0xc60),
.flags = IORESOURCE_IRQ,
},
};
static u64 usb_ohci_dma_mask = 0xffffffffUL;
+
+static struct usb_ohci_pdata usb_ohci_pdata;
+
static struct platform_device usb_ohci_device = {
- .name = "sh_ohci",
+ .name = "ohci-platform",
.id = -1,
.dev = {
.dma_mask = &usb_ohci_dma_mask,
.coherent_dma_mask = 0xffffffff,
+ .platform_data = &usb_ohci_pdata,
},
.num_resources = ARRAY_SIZE(usb_ohci_resources),
.resource = usb_ohci_resources,
@@ -106,8 +140,8 @@ static struct resource usbf_resources[] = {
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = 84,
- .end = 84,
+ .start = evt2irq(0xc80),
+ .end = evt2irq(0xc80),
.flags = IORESOURCE_IRQ,
},
};
@@ -123,9 +157,55 @@ static struct platform_device usbf_device = {
.resource = usbf_resources,
};
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x580)),
+ DEFINE_RES_IRQ(evt2irq(0x5a0)),
+ DEFINE_RES_IRQ(evt2irq(0x5c0)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffd88000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0xe00)),
+ DEFINE_RES_IRQ(evt2irq(0xe20)),
+ DEFINE_RES_IRQ(evt2irq(0xe40)),
+};
+
+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 platform_device *sh7763_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &tmu0_device,
+ &tmu1_device,
&rtc_device,
- &sci_device,
&usb_ohci_device,
&usbf_device,
};
@@ -135,7 +215,21 @@ static int __init sh7763_devices_setup(void)
return platform_add_devices(sh7763_devices,
ARRAY_SIZE(sh7763_devices));
}
-__initcall(sh7763_devices_setup);
+arch_initcall(sh7763_devices_setup);
+
+static struct platform_device *sh7763_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &tmu0_device,
+ &tmu1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7763_early_devices,
+ ARRAY_SIZE(sh7763_early_devices));
+}
enum {
UNUSED = 0,
@@ -148,93 +242,65 @@ enum {
IRL_HHLL, IRL_HHLH, IRL_HHHL,
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
- RTC_ATI, RTC_PRI, RTC_CUI,
- WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
- HUDI, LCDC,
- DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, DMAC0_DMAE,
- SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
- DMAC0_DMINT4, DMAC0_DMINT5,
- IIC0, IIC1,
- CMT,
- GEINT0, GEINT1, GEINT2,
- HAC,
- PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
- PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
- STIF0, STIF1,
- SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
- SIOF0, SIOF1, SIOF2,
- USBH, USBFI0, USBFI1,
- TPU, PCC,
- MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
- SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND,
+ RTC, WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
+ HUDI, LCDC, DMAC, SCIF0, IIC0, IIC1, CMT, GETHER, HAC,
+ PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD, PCIC5,
+ STIF0, STIF1, SCIF1, SIOF0, SIOF1, SIOF2,
+ USBH, USBF, TPU, PCC, MMCIF, SIM,
TMU3, TMU4, TMU5, ADC, SSI0, SSI1, SSI2, SSI3,
- SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI,
- GPIO_CH0, GPIO_CH1, GPIO_CH2, GPIO_CH3,
+ SCIF2, GPIO,
/* interrupt groups */
- TMU012, TMU345, RTC, DMAC, SCIF0, GETHER, PCIC5,
- SCIF1, USBF, MMCIF, SIM, SCIF2, GPIO,
+ TMU012, TMU345,
};
static struct intc_vect vectors[] __initdata = {
- INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
- INTC_VECT(RTC_CUI, 0x4c0),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
INTC_VECT(WDT, 0x560), INTC_VECT(TMU0, 0x580),
INTC_VECT(TMU1, 0x5a0), INTC_VECT(TMU2, 0x5c0),
INTC_VECT(TMU2_TICPI, 0x5e0), INTC_VECT(HUDI, 0x600),
INTC_VECT(LCDC, 0x620),
- INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
- INTC_VECT(DMAC0_DMINT2, 0x680), INTC_VECT(DMAC0_DMINT3, 0x6a0),
- INTC_VECT(DMAC0_DMAE, 0x6c0),
- INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
- INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
- INTC_VECT(DMAC0_DMINT4, 0x780), INTC_VECT(DMAC0_DMINT5, 0x7a0),
+ INTC_VECT(DMAC, 0x640), INTC_VECT(DMAC, 0x660),
+ INTC_VECT(DMAC, 0x680), INTC_VECT(DMAC, 0x6a0),
+ INTC_VECT(DMAC, 0x6c0),
+ INTC_VECT(SCIF0, 0x700), INTC_VECT(SCIF0, 0x720),
+ INTC_VECT(SCIF0, 0x740), INTC_VECT(SCIF0, 0x760),
+ INTC_VECT(DMAC, 0x780), INTC_VECT(DMAC, 0x7a0),
INTC_VECT(IIC0, 0x8A0), INTC_VECT(IIC1, 0x8C0),
- INTC_VECT(CMT, 0x900), INTC_VECT(GEINT0, 0x920),
- INTC_VECT(GEINT1, 0x940), INTC_VECT(GEINT2, 0x960),
+ INTC_VECT(CMT, 0x900), INTC_VECT(GETHER, 0x920),
+ INTC_VECT(GETHER, 0x940), INTC_VECT(GETHER, 0x960),
INTC_VECT(HAC, 0x980),
INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
- INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
- INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
- INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
+ INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIC5, 0xaa0),
+ INTC_VECT(PCIC5, 0xac0), INTC_VECT(PCIC5, 0xae0),
+ INTC_VECT(PCIC5, 0xb00), INTC_VECT(PCIC5, 0xb20),
INTC_VECT(STIF0, 0xb40), INTC_VECT(STIF1, 0xb60),
- INTC_VECT(SCIF1_ERI, 0xb80), INTC_VECT(SCIF1_RXI, 0xba0),
- INTC_VECT(SCIF1_BRI, 0xbc0), INTC_VECT(SCIF1_TXI, 0xbe0),
+ INTC_VECT(SCIF1, 0xb80), INTC_VECT(SCIF1, 0xba0),
+ INTC_VECT(SCIF1, 0xbc0), INTC_VECT(SCIF1, 0xbe0),
INTC_VECT(SIOF0, 0xc00), INTC_VECT(SIOF1, 0xc20),
- INTC_VECT(USBH, 0xc60), INTC_VECT(USBFI0, 0xc80),
- INTC_VECT(USBFI1, 0xca0),
+ INTC_VECT(USBH, 0xc60), INTC_VECT(USBF, 0xc80),
+ INTC_VECT(USBF, 0xca0),
INTC_VECT(TPU, 0xcc0), INTC_VECT(PCC, 0xce0),
- INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
- INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
- INTC_VECT(SIM_ERI, 0xd80), INTC_VECT(SIM_RXI, 0xda0),
- INTC_VECT(SIM_TXI, 0xdc0), INTC_VECT(SIM_TEND, 0xde0),
+ INTC_VECT(MMCIF, 0xd00), INTC_VECT(MMCIF, 0xd20),
+ INTC_VECT(MMCIF, 0xd40), INTC_VECT(MMCIF, 0xd60),
+ INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0),
+ INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0),
INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
INTC_VECT(TMU5, 0xe40), INTC_VECT(ADC, 0xe60),
INTC_VECT(SSI0, 0xe80), INTC_VECT(SSI1, 0xea0),
INTC_VECT(SSI2, 0xec0), INTC_VECT(SSI3, 0xee0),
- INTC_VECT(SCIF2_ERI, 0xf00), INTC_VECT(SCIF2_RXI, 0xf20),
- INTC_VECT(SCIF2_BRI, 0xf40), INTC_VECT(SCIF2_TXI, 0xf60),
- INTC_VECT(GPIO_CH0, 0xf80), INTC_VECT(GPIO_CH1, 0xfa0),
- INTC_VECT(GPIO_CH2, 0xfc0), INTC_VECT(GPIO_CH3, 0xfe0),
+ INTC_VECT(SCIF2, 0xf00), INTC_VECT(SCIF2, 0xf20),
+ INTC_VECT(SCIF2, 0xf40), INTC_VECT(SCIF2, 0xf60),
+ INTC_VECT(GPIO, 0xf80), INTC_VECT(GPIO, 0xfa0),
+ INTC_VECT(GPIO, 0xfc0), INTC_VECT(GPIO, 0xfe0),
};
static struct intc_group groups[] __initdata = {
INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
- INTC_GROUP(DMAC, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
- DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
- INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
- INTC_GROUP(GETHER, GEINT0, GEINT1, GEINT2),
- INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
- INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
- INTC_GROUP(USBF, USBFI0, USBFI1),
- INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
- INTC_GROUP(SIM, SIM_ERI, SIM_RXI, SIM_TXI, SIM_TEND),
- INTC_GROUP(SCIF2, SCIF2_ERI, SCIF2_RXI, SCIF2_BRI, SCIF2_TXI),
- INTC_GROUP(GPIO, GPIO_CH0, GPIO_CH1, GPIO_CH2, GPIO_CH3),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -351,11 +417,11 @@ static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7763-irl3210", irl_vectors,
void __init plat_irq_setup(void)
{
/* disable IRQ7-0 */
- ctrl_outl(0xff000000, INTC_INTMSK0);
+ __raw_writel(0xff000000, INTC_INTMSK0);
/* disable IRL3-0 + IRL7-4 */
- ctrl_outl(0xc0000000, INTC_INTMSK1);
- ctrl_outl(0xfffefffe, INTC_INTMSK2);
+ __raw_writel(0xc0000000, INTC_INTMSK1);
+ __raw_writel(0xfffefffe, INTC_INTMSK2);
register_intc_controller(&intc_desc);
}
@@ -365,27 +431,27 @@ void __init plat_irq_setup_pins(int mode)
switch (mode) {
case IRQ_MODE_IRQ:
/* select IRQ mode for IRL3-0 + IRL7-4 */
- ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
register_intc_controller(&intc_irq_desc);
break;
case IRQ_MODE_IRL7654:
/* enable IRL7-4 but don't provide any masking */
- ctrl_outl(0x40000000, INTC_INTMSKCLR1);
- ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x0000fffe, INTC_INTMSKCLR2);
break;
case IRQ_MODE_IRL3210:
/* enable IRL0-3 but don't provide any masking */
- ctrl_outl(0x80000000, INTC_INTMSKCLR1);
- ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xfffe0000, INTC_INTMSKCLR2);
break;
case IRQ_MODE_IRL7654_MASK:
/* enable IRL7-4 and mask using cpu intc controller */
- ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
register_intc_controller(&intc_irl7654_desc);
break;
case IRQ_MODE_IRL3210_MASK:
/* enable IRL0-3 and mask using cpu intc controller */
- ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
register_intc_controller(&intc_irl3210_desc);
break;
default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index b73578ee295..e9b532a76c3 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
@@ -11,73 +11,297 @@
#include <linux/init.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <linux/io.h>
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xff923000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 61, 61, 61, 61 },
- }, {
- .mapbase = 0xff924000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 62, 62, 62, 62 },
- }, {
- .mapbase = 0xff925000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 63, 63, 63, 63 },
- }, {
- .mapbase = 0xff926000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 64, 64, 64, 64 },
- }, {
- .mapbase = 0xff927000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 65, 65, 65, 65 },
- }, {
- .mapbase = 0xff928000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 66, 66, 66, 66 },
- }, {
- .mapbase = 0xff929000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 67, 67, 67, 67 },
- }, {
- .mapbase = 0xff92a000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 68, 68, 68, 68 },
- }, {
- .mapbase = 0xff92b000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 69, 69, 69, 69 },
- }, {
- .mapbase = 0xff92c000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 70, 70, 70, 70 },
- }, {
- .flags = 0,
- }
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xff923000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x9a0)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xff924000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x9c0)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xff925000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x9e0)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xff926000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xa00)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xff927000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xa20)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xff928000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xa40)),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct plat_sci_port scif6_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif6_resources[] = {
+ DEFINE_RES_MEM(0xff929000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xa60)),
};
-static struct platform_device sci_device = {
+static struct platform_device scif6_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 6,
+ .resource = scif6_resources,
+ .num_resources = ARRAY_SIZE(scif6_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif6_platform_data,
},
};
+static struct plat_sci_port scif7_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif7_resources[] = {
+ DEFINE_RES_MEM(0xff92a000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xa80)),
+};
+
+static struct platform_device scif7_device = {
+ .name = "sh-sci",
+ .id = 7,
+ .resource = scif7_resources,
+ .num_resources = ARRAY_SIZE(scif7_resources),
+ .dev = {
+ .platform_data = &scif7_platform_data,
+ },
+};
+
+static struct plat_sci_port scif8_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif8_resources[] = {
+ DEFINE_RES_MEM(0xff92b000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xaa0)),
+};
+
+static struct platform_device scif8_device = {
+ .name = "sh-sci",
+ .id = 8,
+ .resource = scif8_resources,
+ .num_resources = ARRAY_SIZE(scif8_resources),
+ .dev = {
+ .platform_data = &scif8_platform_data,
+ },
+};
+
+static struct plat_sci_port scif9_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_TOIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif9_resources[] = {
+ DEFINE_RES_MEM(0xff92c000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xac0)),
+};
+
+static struct platform_device scif9_device = {
+ .name = "sh-sci",
+ .id = 9,
+ .resource = scif9_resources,
+ .num_resources = ARRAY_SIZE(scif9_resources),
+ .dev = {
+ .platform_data = &scif9_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffd81000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x460)),
+ DEFINE_RES_IRQ(evt2irq(0x480)),
+ DEFINE_RES_IRQ(evt2irq(0x4a0)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu2_resources[] = {
+ DEFINE_RES_MEM(0xffd82000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x4c0)),
+ DEFINE_RES_IRQ(evt2irq(0x4e0)),
+ DEFINE_RES_IRQ(evt2irq(0x500)),
+};
+
+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 *sh7770_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &scif8_device,
+ &scif9_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
};
static int __init sh7770_devices_setup(void)
@@ -85,8 +309,275 @@ static int __init sh7770_devices_setup(void)
return platform_add_devices(sh7770_devices,
ARRAY_SIZE(sh7770_devices));
}
-__initcall(sh7770_devices_setup);
+arch_initcall(sh7770_devices_setup);
+
+static struct platform_device *sh7770_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &scif6_device,
+ &scif7_device,
+ &scif8_device,
+ &scif9_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7770_early_devices,
+ ARRAY_SIZE(sh7770_early_devices));
+}
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+ IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+ IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+ IRL_HHLL, IRL_HHLH, IRL_HHHL,
+
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
+
+ GPIO,
+ TMU0, TMU1, TMU2, TMU2_TICPI,
+ TMU3, TMU4, TMU5, TMU5_TICPI,
+ TMU6, TMU7, TMU8,
+ HAC, IPI, SPDIF, HUDI, I2C,
+ DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
+ I2S0, I2S1, I2S2, I2S3,
+ SRC_RX, SRC_TX, SRC_SPDIF,
+ DU, VIDEO_IN, REMOTE, YUV, USB, ATAPI, CAN, GPS, GFX2D,
+ GFX3D_MBX, GFX3D_DMAC,
+ EXBUS_ATA,
+ SPI0, SPI1,
+ SCIF089, SCIF1234, SCIF567,
+ ADC,
+ BBDMAC_0_3, BBDMAC_4_7, BBDMAC_8_10, BBDMAC_11_14,
+ BBDMAC_15_18, BBDMAC_19_22, BBDMAC_23_26, BBDMAC_27,
+ BBDMAC_28, BBDMAC_29, BBDMAC_30, BBDMAC_31,
+
+ /* interrupt groups */
+ TMU, DMAC, I2S, SRC, GFX3D, SPI, SCIF, BBDMAC,
+};
+
+static struct intc_vect vectors[] __initdata = {
+ INTC_VECT(GPIO, 0x3e0),
+ INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420),
+ INTC_VECT(TMU2, 0x440), INTC_VECT(TMU2_TICPI, 0x460),
+ INTC_VECT(TMU3, 0x480), INTC_VECT(TMU4, 0x4a0),
+ INTC_VECT(TMU5, 0x4c0), INTC_VECT(TMU5_TICPI, 0x4e0),
+ INTC_VECT(TMU6, 0x500), INTC_VECT(TMU7, 0x520),
+ INTC_VECT(TMU8, 0x540),
+ INTC_VECT(HAC, 0x580), INTC_VECT(IPI, 0x5c0),
+ INTC_VECT(SPDIF, 0x5e0),
+ INTC_VECT(HUDI, 0x600), INTC_VECT(I2C, 0x620),
+ INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
+ INTC_VECT(DMAC0_DMINT2, 0x680),
+ INTC_VECT(I2S0, 0x6a0), INTC_VECT(I2S1, 0x6c0),
+ INTC_VECT(I2S2, 0x6e0), INTC_VECT(I2S3, 0x700),
+ INTC_VECT(SRC_RX, 0x720), INTC_VECT(SRC_TX, 0x740),
+ INTC_VECT(SRC_SPDIF, 0x760),
+ INTC_VECT(DU, 0x780), INTC_VECT(VIDEO_IN, 0x7a0),
+ INTC_VECT(REMOTE, 0x7c0), INTC_VECT(YUV, 0x7e0),
+ INTC_VECT(USB, 0x840), INTC_VECT(ATAPI, 0x860),
+ INTC_VECT(CAN, 0x880), INTC_VECT(GPS, 0x8a0),
+ INTC_VECT(GFX2D, 0x8c0),
+ INTC_VECT(GFX3D_MBX, 0x900), INTC_VECT(GFX3D_DMAC, 0x920),
+ INTC_VECT(EXBUS_ATA, 0x940),
+ INTC_VECT(SPI0, 0x960), INTC_VECT(SPI1, 0x980),
+ INTC_VECT(SCIF089, 0x9a0), INTC_VECT(SCIF1234, 0x9c0),
+ INTC_VECT(SCIF1234, 0x9e0), INTC_VECT(SCIF1234, 0xa00),
+ INTC_VECT(SCIF1234, 0xa20), INTC_VECT(SCIF567, 0xa40),
+ INTC_VECT(SCIF567, 0xa60), INTC_VECT(SCIF567, 0xa80),
+ INTC_VECT(SCIF089, 0xaa0), INTC_VECT(SCIF089, 0xac0),
+ INTC_VECT(ADC, 0xb20),
+ INTC_VECT(BBDMAC_0_3, 0xba0), INTC_VECT(BBDMAC_0_3, 0xbc0),
+ INTC_VECT(BBDMAC_0_3, 0xbe0), INTC_VECT(BBDMAC_0_3, 0xc00),
+ INTC_VECT(BBDMAC_4_7, 0xc20), INTC_VECT(BBDMAC_4_7, 0xc40),
+ INTC_VECT(BBDMAC_4_7, 0xc60), INTC_VECT(BBDMAC_4_7, 0xc80),
+ INTC_VECT(BBDMAC_8_10, 0xca0), INTC_VECT(BBDMAC_8_10, 0xcc0),
+ INTC_VECT(BBDMAC_8_10, 0xce0), INTC_VECT(BBDMAC_11_14, 0xd00),
+ INTC_VECT(BBDMAC_11_14, 0xd20), INTC_VECT(BBDMAC_11_14, 0xd40),
+ INTC_VECT(BBDMAC_11_14, 0xd60), INTC_VECT(BBDMAC_15_18, 0xd80),
+ INTC_VECT(BBDMAC_15_18, 0xda0), INTC_VECT(BBDMAC_15_18, 0xdc0),
+ INTC_VECT(BBDMAC_15_18, 0xde0), INTC_VECT(BBDMAC_19_22, 0xe00),
+ INTC_VECT(BBDMAC_19_22, 0xe20), INTC_VECT(BBDMAC_19_22, 0xe40),
+ INTC_VECT(BBDMAC_19_22, 0xe60), INTC_VECT(BBDMAC_23_26, 0xe80),
+ INTC_VECT(BBDMAC_23_26, 0xea0), INTC_VECT(BBDMAC_23_26, 0xec0),
+ INTC_VECT(BBDMAC_23_26, 0xee0), INTC_VECT(BBDMAC_27, 0xf00),
+ INTC_VECT(BBDMAC_28, 0xf20), INTC_VECT(BBDMAC_29, 0xf40),
+ INTC_VECT(BBDMAC_30, 0xf60), INTC_VECT(BBDMAC_31, 0xf80),
+};
+
+static struct intc_group groups[] __initdata = {
+ INTC_GROUP(TMU, TMU0, TMU1, TMU2, TMU2_TICPI, TMU3, TMU4, TMU5,
+ TMU5_TICPI, TMU6, TMU7, TMU8),
+ INTC_GROUP(DMAC, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2),
+ INTC_GROUP(I2S, I2S0, I2S1, I2S2, I2S3),
+ INTC_GROUP(SRC, SRC_RX, SRC_TX, SRC_SPDIF),
+ INTC_GROUP(GFX3D, GFX3D_MBX, GFX3D_DMAC),
+ INTC_GROUP(SPI, SPI0, SPI1),
+ INTC_GROUP(SCIF, SCIF089, SCIF1234, SCIF567),
+ INTC_GROUP(BBDMAC,
+ BBDMAC_0_3, BBDMAC_4_7, BBDMAC_8_10, BBDMAC_11_14,
+ BBDMAC_15_18, BBDMAC_19_22, BBDMAC_23_26, BBDMAC_27,
+ BBDMAC_28, BBDMAC_29, BBDMAC_30, BBDMAC_31),
+};
+
+static struct intc_mask_reg mask_registers[] __initdata = {
+ { 0xffe00040, 0xffe00044, 32, /* INT2MSKR / INT2MSKCR */
+ { 0, BBDMAC, ADC, SCIF, SPI, EXBUS_ATA, GFX3D, GFX2D,
+ GPS, CAN, ATAPI, USB, YUV, REMOTE, VIDEO_IN, DU, SRC, I2S,
+ DMAC, I2C, HUDI, SPDIF, IPI, HAC, TMU, GPIO } },
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xffe00000, 0, 32, 8, /* INT2PRI0 */ { GPIO, TMU0, 0, HAC } },
+ { 0xffe00004, 0, 32, 8, /* INT2PRI1 */ { IPI, SPDIF, HUDI, I2C } },
+ { 0xffe00008, 0, 32, 8, /* INT2PRI2 */ { DMAC, I2S, SRC, DU } },
+ { 0xffe0000c, 0, 32, 8, /* INT2PRI3 */ { VIDEO_IN, REMOTE, YUV, USB } },
+ { 0xffe00010, 0, 32, 8, /* INT2PRI4 */ { ATAPI, CAN, GPS, GFX2D } },
+ { 0xffe00014, 0, 32, 8, /* INT2PRI5 */ { 0, GFX3D, EXBUS_ATA, SPI } },
+ { 0xffe00018, 0, 32, 8, /* INT2PRI6 */ { SCIF1234, SCIF567, SCIF089 } },
+ { 0xffe0001c, 0, 32, 8, /* INT2PRI7 */ { ADC, 0, 0, BBDMAC_0_3 } },
+ { 0xffe00020, 0, 32, 8, /* INT2PRI8 */
+ { BBDMAC_4_7, BBDMAC_8_10, BBDMAC_11_14, BBDMAC_15_18 } },
+ { 0xffe00024, 0, 32, 8, /* INT2PRI9 */
+ { BBDMAC_19_22, BBDMAC_23_26, BBDMAC_27, BBDMAC_28 } },
+ { 0xffe00028, 0, 32, 8, /* INT2PRI10 */
+ { BBDMAC_29, BBDMAC_30, BBDMAC_31 } },
+ { 0xffe0002c, 0, 32, 8, /* INT2PRI11 */
+ { TMU1, TMU2, TMU2_TICPI, TMU3 } },
+ { 0xffe00030, 0, 32, 8, /* INT2PRI12 */
+ { TMU4, TMU5, TMU5_TICPI, TMU6 } },
+ { 0xffe00034, 0, 32, 8, /* INT2PRI13 */
+ { TMU7, TMU8 } },
+};
+
+static DECLARE_INTC_DESC(intc_desc, "sh7770", vectors, groups,
+ mask_registers, prio_registers, NULL);
+
+/* Support for external interrupt pins in IRQ mode */
+static struct intc_vect irq_vectors[] __initdata = {
+ INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
+ INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
+ INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380),
+};
+
+static struct intc_mask_reg irq_mask_registers[] __initdata = {
+ { 0xffd00044, 0xffd00064, 32, /* INTMSK0 / INTMSKCLR0 */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, } },
+};
+
+static struct intc_prio_reg irq_prio_registers[] __initdata = {
+ { 0xffd00010, 0, 32, 4, /* INTPRI */ { IRQ0, IRQ1, IRQ2, IRQ3,
+ IRQ4, IRQ5, } },
+};
+
+static struct intc_sense_reg irq_sense_registers[] __initdata = {
+ { 0xffd0001c, 32, 2, /* ICR1 */ { IRQ0, IRQ1, IRQ2, IRQ3,
+ IRQ4, IRQ5, } },
+};
+
+static DECLARE_INTC_DESC(intc_irq_desc, "sh7770-irq", irq_vectors,
+ NULL, irq_mask_registers, irq_prio_registers,
+ irq_sense_registers);
+
+/* External interrupt pins in IRL mode */
+static struct intc_vect irl_vectors[] __initdata = {
+ INTC_VECT(IRL_LLLL, 0x200), INTC_VECT(IRL_LLLH, 0x220),
+ INTC_VECT(IRL_LLHL, 0x240), INTC_VECT(IRL_LLHH, 0x260),
+ INTC_VECT(IRL_LHLL, 0x280), INTC_VECT(IRL_LHLH, 0x2a0),
+ INTC_VECT(IRL_LHHL, 0x2c0), INTC_VECT(IRL_LHHH, 0x2e0),
+ INTC_VECT(IRL_HLLL, 0x300), INTC_VECT(IRL_HLLH, 0x320),
+ INTC_VECT(IRL_HLHL, 0x340), INTC_VECT(IRL_HLHH, 0x360),
+ INTC_VECT(IRL_HHLL, 0x380), INTC_VECT(IRL_HHLH, 0x3a0),
+ INTC_VECT(IRL_HHHL, 0x3c0),
+};
+
+static struct intc_mask_reg irl3210_mask_registers[] __initdata = {
+ { 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */
+ { IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+ IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+ IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+ IRL_HHLL, IRL_HHLH, IRL_HHHL, } },
+};
+
+static struct intc_mask_reg irl7654_mask_registers[] __initdata = {
+ { 0xffd40080, 0xffd40084, 32, /* INTMSK2 / INTMSKCLR2 */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ IRL_LLLL, IRL_LLLH, IRL_LLHL, IRL_LLHH,
+ IRL_LHLL, IRL_LHLH, IRL_LHHL, IRL_LHHH,
+ IRL_HLLL, IRL_HLLH, IRL_HLHL, IRL_HLHH,
+ IRL_HHLL, IRL_HHLH, IRL_HHHL, } },
+};
+
+static DECLARE_INTC_DESC(intc_irl7654_desc, "sh7780-irl7654", irl_vectors,
+ NULL, irl7654_mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors,
+ NULL, irl3210_mask_registers, NULL, NULL);
+
+#define INTC_ICR0 0xffd00000
+#define INTC_INTMSK0 0xffd00044
+#define INTC_INTMSK1 0xffd00048
+#define INTC_INTMSK2 0xffd40080
+#define INTC_INTMSKCLR1 0xffd00068
+#define INTC_INTMSKCLR2 0xffd40084
void __init plat_irq_setup(void)
{
+ /* disable IRQ7-0 */
+ __raw_writel(0xff000000, INTC_INTMSK0);
+
+ /* disable IRL3-0 + IRL7-4 */
+ __raw_writel(0xc0000000, INTC_INTMSK1);
+ __raw_writel(0xfffefffe, INTC_INTMSK2);
+
+ /* select IRL mode for IRL3-0 + IRL7-4 */
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+
+ /* disable holding function, ie enable "SH-4 Mode" */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+
+ register_intc_controller(&intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+ switch (mode) {
+ case IRQ_MODE_IRQ:
+ /* select IRQ mode for IRL3-0 + IRL7-4 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+ register_intc_controller(&intc_irq_desc);
+ break;
+ case IRQ_MODE_IRL7654:
+ /* enable IRL7-4 but don't provide any masking */
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x0000fffe, INTC_INTMSKCLR2);
+ break;
+ case IRQ_MODE_IRL3210:
+ /* enable IRL0-3 but don't provide any masking */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xfffe0000, INTC_INTMSKCLR2);
+ break;
+ case IRQ_MODE_IRL7654_MASK:
+ /* enable IRL7-4 and mask using cpu intc controller */
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ register_intc_controller(&intc_irl7654_desc);
+ break;
+ case IRQ_MODE_IRL3210_MASK:
+ /* enable IRL0-3 and mask using cpu intc controller */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ register_intc_controller(&intc_irl3210_desc);
+ break;
+ default:
+ BUG();
+ }
}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index fb8200cc744..3ee7dd9b3a6 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -12,6 +12,96 @@
#include <linux/serial.h>
#include <linux/io.h>
#include <linux/serial_sci.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <cpu/dma-register.h>
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffe00000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffe10000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0xb80)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x580)),
+ DEFINE_RES_IRQ(evt2irq(0x5a0)),
+ DEFINE_RES_IRQ(evt2irq(0x5c0)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffdc0000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0xe00)),
+ DEFINE_RES_IRQ(evt2irq(0xe20)),
+ DEFINE_RES_IRQ(evt2irq(0xe40)),
+};
+
+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 resource rtc_resources[] = {
[0] = {
@@ -20,18 +110,8 @@ static struct resource rtc_resources[] = {
.flags = IORESOURCE_IO,
},
[1] = {
- /* Period IRQ */
- .start = 21,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- /* Carry IRQ */
- .start = 22,
- .flags = IORESOURCE_IRQ,
- },
- [3] = {
- /* Alarm IRQ */
- .start = 20,
+ /* Shared Period/Carry/Alarm IRQ */
+ .start = evt2irq(0x480),
.flags = IORESOURCE_IRQ,
},
};
@@ -43,33 +123,150 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
-static struct plat_sci_port sci_platform_data[] = {
+/* DMA */
+static const struct sh_dmae_channel sh7780_dmae0_channels[] = {
{
- .mapbase = 0xffe00000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
}, {
- .mapbase = 0xffe10000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 76, 77, 79, 78 },
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
}, {
- .flags = 0,
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
}
};
-static struct platform_device sci_device = {
- .name = "sh-sci",
- .id = -1,
+static const struct sh_dmae_channel sh7780_dmae1_channels[] = {
+ {
+ .offset = 0,
+ }, {
+ .offset = 0x10,
+ }, {
+ .offset = 0x20,
+ }, {
+ .offset = 0x30,
+ }, {
+ .offset = 0x50,
+ }, {
+ .offset = 0x60,
+ }
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .channel = sh7780_dmae0_channels,
+ .channel_num = ARRAY_SIZE(sh7780_dmae0_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+ .channel = sh7780_dmae1_channels,
+ .channel_num = ARRAY_SIZE(sh7780_dmae1_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct resource sh7780_dmae0_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfc808020,
+ .end = 0xfc80808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xfc809000,
+ .end = 0xfc80900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /*
+ * Real DMA error vector is 0x6c0, and channel
+ * vectors are 0x640-0x6a0, 0x780-0x7a0
+ */
+ .name = "error_irq",
+ .start = evt2irq(0x640),
+ .end = evt2irq(0x640),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct resource sh7780_dmae1_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfc818020,
+ .end = 0xfc81808f,
+ .flags = IORESOURCE_MEM,
+ },
+ /* DMAC1 has no DMARS */
+ {
+ /*
+ * Real DMA error vector is 0x6c0, and channel
+ * vectors are 0x7c0-0x7e0, 0xd80-0xde0
+ */
+ .name = "error_irq",
+ .start = evt2irq(0x7c0),
+ .end = evt2irq(0x7c0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = sh7780_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7780_dmae0_resources),
+ .dev = {
+ .platform_data = &dma0_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7780_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7780_dmae1_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &dma1_platform_data,
},
};
static struct platform_device *sh7780_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &tmu0_device,
+ &tmu1_device,
&rtc_device,
- &sci_device,
+ &dma0_device,
+ &dma1_device,
};
static int __init sh7780_devices_setup(void)
@@ -77,7 +274,25 @@ static int __init sh7780_devices_setup(void)
return platform_add_devices(sh7780_devices,
ARRAY_SIZE(sh7780_devices));
}
-__initcall(sh7780_devices_setup);
+arch_initcall(sh7780_devices_setup);
+
+static struct platform_device *sh7780_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &tmu0_device,
+ &tmu1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ if (mach_is_sh2007()) {
+ scif0_platform_data.scscr &= ~SCSCR_CKE1;
+ scif1_platform_data.scscr &= ~SCSCR_CKE1;
+ }
+
+ early_platform_add_devices(sh7780_early_devices,
+ ARRAY_SIZE(sh7780_early_devices));
+}
enum {
UNUSED = 0,
@@ -90,82 +305,55 @@ enum {
IRL_HHLL, IRL_HHLH, IRL_HHHL,
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
- RTC_ATI, RTC_PRI, RTC_CUI,
- WDT,
- TMU0, TMU1, TMU2, TMU2_TICPI,
- HUDI,
- DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3, DMAC0_DMAE,
- SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
- DMAC0_DMINT4, DMAC0_DMINT5, DMAC1_DMINT6, DMAC1_DMINT7,
- CMT, HAC,
- PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
- PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
- SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
- SIOF, HSPI,
- MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
- DMAC1_DMINT8, DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11,
- TMU3, TMU4, TMU5,
- SSI,
- FLCTL_FLSTE, FLCTL_FLEND, FLCTL_FLTRQ0, FLCTL_FLTRQ1,
- GPIOI0, GPIOI1, GPIOI2, GPIOI3,
+ RTC, WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
+ HUDI, DMAC0, SCIF0, DMAC1, CMT, HAC,
+ PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD, PCIC5,
+ SCIF1, SIOF, HSPI, MMCIF, TMU3, TMU4, TMU5, SSI, FLCTL, GPIO,
/* interrupt groups */
- RTC, TMU012, DMAC0, SCIF0, DMAC45, DMAC1,
- PCIC5, SCIF1, MMCIF, TMU345, FLCTL, GPIO,
+ TMU012, TMU345,
};
static struct intc_vect vectors[] __initdata = {
- INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0),
- INTC_VECT(RTC_CUI, 0x4c0),
+ INTC_VECT(RTC, 0x480), INTC_VECT(RTC, 0x4a0),
+ INTC_VECT(RTC, 0x4c0),
INTC_VECT(WDT, 0x560),
INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
INTC_VECT(HUDI, 0x600),
- INTC_VECT(DMAC0_DMINT0, 0x640), INTC_VECT(DMAC0_DMINT1, 0x660),
- INTC_VECT(DMAC0_DMINT2, 0x680), INTC_VECT(DMAC0_DMINT3, 0x6a0),
- INTC_VECT(DMAC0_DMAE, 0x6c0),
- INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
- INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
- INTC_VECT(DMAC0_DMINT4, 0x780), INTC_VECT(DMAC0_DMINT5, 0x7a0),
- INTC_VECT(DMAC1_DMINT6, 0x7c0), INTC_VECT(DMAC1_DMINT7, 0x7e0),
+ INTC_VECT(DMAC0, 0x640), INTC_VECT(DMAC0, 0x660),
+ INTC_VECT(DMAC0, 0x680), INTC_VECT(DMAC0, 0x6a0),
+ INTC_VECT(DMAC0, 0x6c0),
+ INTC_VECT(SCIF0, 0x700), INTC_VECT(SCIF0, 0x720),
+ INTC_VECT(SCIF0, 0x740), INTC_VECT(SCIF0, 0x760),
+ INTC_VECT(DMAC0, 0x780), INTC_VECT(DMAC0, 0x7a0),
+ INTC_VECT(DMAC1, 0x7c0), INTC_VECT(DMAC1, 0x7e0),
INTC_VECT(CMT, 0x900), INTC_VECT(HAC, 0x980),
INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
- INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
- INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
- INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
- INTC_VECT(SCIF1_ERI, 0xb80), INTC_VECT(SCIF1_RXI, 0xba0),
- INTC_VECT(SCIF1_BRI, 0xbc0), INTC_VECT(SCIF1_TXI, 0xbe0),
+ INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIC5, 0xaa0),
+ INTC_VECT(PCIC5, 0xac0), INTC_VECT(PCIC5, 0xae0),
+ INTC_VECT(PCIC5, 0xb00), INTC_VECT(PCIC5, 0xb20),
+ INTC_VECT(SCIF1, 0xb80), INTC_VECT(SCIF1, 0xba0),
+ INTC_VECT(SCIF1, 0xbc0), INTC_VECT(SCIF1, 0xbe0),
INTC_VECT(SIOF, 0xc00), INTC_VECT(HSPI, 0xc80),
- INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
- INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
- INTC_VECT(DMAC1_DMINT8, 0xd80), INTC_VECT(DMAC1_DMINT9, 0xda0),
- INTC_VECT(DMAC1_DMINT10, 0xdc0), INTC_VECT(DMAC1_DMINT11, 0xde0),
+ INTC_VECT(MMCIF, 0xd00), INTC_VECT(MMCIF, 0xd20),
+ INTC_VECT(MMCIF, 0xd40), INTC_VECT(MMCIF, 0xd60),
+ INTC_VECT(DMAC1, 0xd80), INTC_VECT(DMAC1, 0xda0),
+ INTC_VECT(DMAC1, 0xdc0), INTC_VECT(DMAC1, 0xde0),
INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
INTC_VECT(TMU5, 0xe40),
INTC_VECT(SSI, 0xe80),
- INTC_VECT(FLCTL_FLSTE, 0xf00), INTC_VECT(FLCTL_FLEND, 0xf20),
- INTC_VECT(FLCTL_FLTRQ0, 0xf40), INTC_VECT(FLCTL_FLTRQ1, 0xf60),
- INTC_VECT(GPIOI0, 0xf80), INTC_VECT(GPIOI1, 0xfa0),
- INTC_VECT(GPIOI2, 0xfc0), INTC_VECT(GPIOI3, 0xfe0),
+ INTC_VECT(FLCTL, 0xf00), INTC_VECT(FLCTL, 0xf20),
+ INTC_VECT(FLCTL, 0xf40), INTC_VECT(FLCTL, 0xf60),
+ INTC_VECT(GPIO, 0xf80), INTC_VECT(GPIO, 0xfa0),
+ INTC_VECT(GPIO, 0xfc0), INTC_VECT(GPIO, 0xfe0),
};
static struct intc_group groups[] __initdata = {
- INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI),
INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
- INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
- DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
- INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
- INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
- DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
- INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
- INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
- INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
- INTC_GROUP(FLCTL, FLCTL_FLSTE, FLCTL_FLEND,
- FLCTL_FLTRQ0, FLCTL_FLTRQ1),
- INTC_GROUP(GPIO, GPIOI0, GPIOI1, GPIOI2, GPIOI3),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -272,17 +460,17 @@ static DECLARE_INTC_DESC(intc_irl3210_desc, "sh7780-irl3210", irl_vectors,
void __init plat_irq_setup(void)
{
/* disable IRQ7-0 */
- ctrl_outl(0xff000000, INTC_INTMSK0);
+ __raw_writel(0xff000000, INTC_INTMSK0);
/* disable IRL3-0 + IRL7-4 */
- ctrl_outl(0xc0000000, INTC_INTMSK1);
- ctrl_outl(0xfffefffe, INTC_INTMSK2);
+ __raw_writel(0xc0000000, INTC_INTMSK1);
+ __raw_writel(0xfffefffe, INTC_INTMSK2);
/* select IRL mode for IRL3-0 + IRL7-4 */
- ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
/* disable holding function, ie enable "SH-4 Mode" */
- ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
register_intc_controller(&intc_desc);
}
@@ -292,27 +480,27 @@ void __init plat_irq_setup_pins(int mode)
switch (mode) {
case IRQ_MODE_IRQ:
/* select IRQ mode for IRL3-0 + IRL7-4 */
- ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00c00000, INTC_ICR0);
register_intc_controller(&intc_irq_desc);
break;
case IRQ_MODE_IRL7654:
/* enable IRL7-4 but don't provide any masking */
- ctrl_outl(0x40000000, INTC_INTMSKCLR1);
- ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x0000fffe, INTC_INTMSKCLR2);
break;
case IRQ_MODE_IRL3210:
/* enable IRL0-3 but don't provide any masking */
- ctrl_outl(0x80000000, INTC_INTMSKCLR1);
- ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xfffe0000, INTC_INTMSKCLR2);
break;
case IRQ_MODE_IRL7654_MASK:
/* enable IRL7-4 and mask using cpu intc controller */
- ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
register_intc_controller(&intc_irl7654_desc);
break;
case IRQ_MODE_IRL3210_MASK:
/* enable IRL0-3 and mask using cpu intc controller */
- ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
register_intc_controller(&intc_irl3210_desc);
break;
default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 30baa63b24c..c72d5a5d099 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -13,59 +13,333 @@
#include <linux/serial_sci.h>
#include <linux/io.h>
#include <linux/mm.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
#include <asm/mmzone.h>
+#include <cpu/dma-register.h>
-static struct plat_sci_port sci_platform_data[] = {
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffea0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffeb0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x780)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffec0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x980)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xffed0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x9a0)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xffee0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x9c0)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xffef0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x9e0)),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x580)),
+ DEFINE_RES_IRQ(evt2irq(0x5a0)),
+ DEFINE_RES_IRQ(evt2irq(0x5c0)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffdc0000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0xe00)),
+ DEFINE_RES_IRQ(evt2irq(0xe20)),
+ DEFINE_RES_IRQ(evt2irq(0xe40)),
+};
+
+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),
+};
+
+/* DMA */
+static const struct sh_dmae_channel sh7785_dmae0_channels[] = {
{
- .mapbase = 0xffea0000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
}, {
- .mapbase = 0xffeb0000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 44, 45, 47, 46 },
- },
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
- /*
- * The rest of these all have multiplexed IRQs
- */
+static const struct sh_dmae_channel sh7785_dmae1_channels[] = {
{
- .mapbase = 0xffec0000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 60, 60, 60, 60 },
+ .offset = 0,
}, {
- .mapbase = 0xffed0000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 61, 61, 61, 61 },
+ .offset = 0x10,
}, {
- .mapbase = 0xffee0000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 62, 62, 62, 62 },
+ .offset = 0x20,
}, {
- .mapbase = 0xffef0000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 63, 63, 63, 63 },
+ .offset = 0x30,
}, {
- .flags = 0,
+ .offset = 0x50,
+ }, {
+ .offset = 0x60,
}
};
-static struct platform_device sci_device = {
- .name = "sh-sci",
- .id = -1,
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .channel = sh7785_dmae0_channels,
+ .channel_num = ARRAY_SIZE(sh7785_dmae0_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+ .channel = sh7785_dmae1_channels,
+ .channel_num = ARRAY_SIZE(sh7785_dmae1_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct resource sh7785_dmae0_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfc808020,
+ .end = 0xfc80808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xfc809000,
+ .end = 0xfc80900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /*
+ * Real DMA error vector is 0x6e0, and channel
+ * vectors are 0x620-0x6c0
+ */
+ .name = "error_irq",
+ .start = evt2irq(0x620),
+ .end = evt2irq(0x620),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct resource sh7785_dmae1_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfcc08020,
+ .end = 0xfcc0808f,
+ .flags = IORESOURCE_MEM,
+ },
+ /* DMAC1 has no DMARS */
+ {
+ /*
+ * Real DMA error vector is 0x940, and channel
+ * vectors are 0x880-0x920
+ */
+ .name = "error_irq",
+ .start = evt2irq(0x880),
+ .end = evt2irq(0x880),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = sh7785_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7785_dmae0_resources),
+ .dev = {
+ .platform_data = &dma0_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7785_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7785_dmae1_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &dma1_platform_data,
},
};
static struct platform_device *sh7785_devices[] __initdata = {
- &sci_device,
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+ &dma0_device,
+ &dma1_device,
};
static int __init sh7785_devices_setup(void)
@@ -73,7 +347,24 @@ static int __init sh7785_devices_setup(void)
return platform_add_devices(sh7785_devices,
ARRAY_SIZE(sh7785_devices));
}
-__initcall(sh7785_devices_setup);
+arch_initcall(sh7785_devices_setup);
+
+static struct platform_device *sh7785_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+};
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7785_early_devices,
+ ARRAY_SIZE(sh7785_early_devices));
+}
enum {
UNUSED = 0,
@@ -91,33 +382,19 @@ enum {
IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
- WDT,
- TMU0, TMU1, TMU2, TMU2_TICPI,
- HUDI,
- DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2, DMAC0_DMINT3,
- DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE,
- SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI,
- SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI,
- DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8, DMAC1_DMINT9,
- DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE,
- HSPI,
+ WDT, TMU0, TMU1, TMU2, TMU2_TICPI,
+ HUDI, DMAC0, SCIF0, SCIF1, DMAC1, HSPI,
SCIF2, SCIF3, SCIF4, SCIF5,
- PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD,
- PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0,
- SIOF,
- MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY,
- DU,
- GDTA_GACLI, GDTA_GAMCI, GDTA_GAERI,
+ PCISERR, PCIINTA, PCIINTB, PCIINTC, PCIINTD, PCIC5,
+ SIOF, MMCIF, DU, GDTA,
TMU3, TMU4, TMU5,
SSI0, SSI1,
HAC0, HAC1,
- FLCTL_FLSTE, FLCTL_FLEND, FLCTL_FLTRQ0, FLCTL_FLTRQ1,
- GPIOI0, GPIOI1, GPIOI2, GPIOI3,
+ FLCTL, GPIO,
/* interrupt groups */
- TMU012, DMAC0, SCIF0, SCIF1, DMAC1,
- PCIC5, MMCIF, GDTA, TMU345, FLCTL, GPIO
+ TMU012, TMU345
};
static struct intc_vect vectors[] __initdata = {
@@ -125,57 +402,45 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
INTC_VECT(HUDI, 0x600),
- INTC_VECT(DMAC0_DMINT0, 0x620), INTC_VECT(DMAC0_DMINT1, 0x640),
- INTC_VECT(DMAC0_DMINT2, 0x660), INTC_VECT(DMAC0_DMINT3, 0x680),
- INTC_VECT(DMAC0_DMINT4, 0x6a0), INTC_VECT(DMAC0_DMINT5, 0x6c0),
- INTC_VECT(DMAC0_DMAE, 0x6e0),
- INTC_VECT(SCIF0_ERI, 0x700), INTC_VECT(SCIF0_RXI, 0x720),
- INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
- INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0),
- INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0),
- INTC_VECT(DMAC1_DMINT6, 0x880), INTC_VECT(DMAC1_DMINT7, 0x8a0),
- INTC_VECT(DMAC1_DMINT8, 0x8c0), INTC_VECT(DMAC1_DMINT9, 0x8e0),
- INTC_VECT(DMAC1_DMINT10, 0x900), INTC_VECT(DMAC1_DMINT11, 0x920),
- INTC_VECT(DMAC1_DMAE, 0x940),
+ INTC_VECT(DMAC0, 0x620), INTC_VECT(DMAC0, 0x640),
+ INTC_VECT(DMAC0, 0x660), INTC_VECT(DMAC0, 0x680),
+ INTC_VECT(DMAC0, 0x6a0), INTC_VECT(DMAC0, 0x6c0),
+ INTC_VECT(DMAC0, 0x6e0),
+ INTC_VECT(SCIF0, 0x700), INTC_VECT(SCIF0, 0x720),
+ INTC_VECT(SCIF0, 0x740), INTC_VECT(SCIF0, 0x760),
+ INTC_VECT(SCIF1, 0x780), INTC_VECT(SCIF1, 0x7a0),
+ INTC_VECT(SCIF1, 0x7c0), INTC_VECT(SCIF1, 0x7e0),
+ INTC_VECT(DMAC1, 0x880), INTC_VECT(DMAC1, 0x8a0),
+ INTC_VECT(DMAC1, 0x8c0), INTC_VECT(DMAC1, 0x8e0),
+ INTC_VECT(DMAC1, 0x900), INTC_VECT(DMAC1, 0x920),
+ INTC_VECT(DMAC1, 0x940),
INTC_VECT(HSPI, 0x960),
INTC_VECT(SCIF2, 0x980), INTC_VECT(SCIF3, 0x9a0),
INTC_VECT(SCIF4, 0x9c0), INTC_VECT(SCIF5, 0x9e0),
INTC_VECT(PCISERR, 0xa00), INTC_VECT(PCIINTA, 0xa20),
INTC_VECT(PCIINTB, 0xa40), INTC_VECT(PCIINTC, 0xa60),
- INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIERR, 0xaa0),
- INTC_VECT(PCIPWD3, 0xac0), INTC_VECT(PCIPWD2, 0xae0),
- INTC_VECT(PCIPWD1, 0xb00), INTC_VECT(PCIPWD0, 0xb20),
+ INTC_VECT(PCIINTD, 0xa80), INTC_VECT(PCIC5, 0xaa0),
+ INTC_VECT(PCIC5, 0xac0), INTC_VECT(PCIC5, 0xae0),
+ INTC_VECT(PCIC5, 0xb00), INTC_VECT(PCIC5, 0xb20),
INTC_VECT(SIOF, 0xc00),
- INTC_VECT(MMCIF_FSTAT, 0xd00), INTC_VECT(MMCIF_TRAN, 0xd20),
- INTC_VECT(MMCIF_ERR, 0xd40), INTC_VECT(MMCIF_FRDY, 0xd60),
+ INTC_VECT(MMCIF, 0xd00), INTC_VECT(MMCIF, 0xd20),
+ INTC_VECT(MMCIF, 0xd40), INTC_VECT(MMCIF, 0xd60),
INTC_VECT(DU, 0xd80),
- INTC_VECT(GDTA_GACLI, 0xda0), INTC_VECT(GDTA_GAMCI, 0xdc0),
- INTC_VECT(GDTA_GAERI, 0xde0),
+ INTC_VECT(GDTA, 0xda0), INTC_VECT(GDTA, 0xdc0),
+ INTC_VECT(GDTA, 0xde0),
INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
INTC_VECT(TMU5, 0xe40),
INTC_VECT(SSI0, 0xe80), INTC_VECT(SSI1, 0xea0),
INTC_VECT(HAC0, 0xec0), INTC_VECT(HAC1, 0xee0),
- INTC_VECT(FLCTL_FLSTE, 0xf00), INTC_VECT(FLCTL_FLEND, 0xf20),
- INTC_VECT(FLCTL_FLTRQ0, 0xf40), INTC_VECT(FLCTL_FLTRQ1, 0xf60),
- INTC_VECT(GPIOI0, 0xf80), INTC_VECT(GPIOI1, 0xfa0),
- INTC_VECT(GPIOI2, 0xfc0), INTC_VECT(GPIOI3, 0xfe0),
+ INTC_VECT(FLCTL, 0xf00), INTC_VECT(FLCTL, 0xf20),
+ INTC_VECT(FLCTL, 0xf40), INTC_VECT(FLCTL, 0xf60),
+ INTC_VECT(GPIO, 0xf80), INTC_VECT(GPIO, 0xfa0),
+ INTC_VECT(GPIO, 0xfc0), INTC_VECT(GPIO, 0xfe0),
};
static struct intc_group groups[] __initdata = {
INTC_GROUP(TMU012, TMU0, TMU1, TMU2, TMU2_TICPI),
- INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
- DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
- INTC_GROUP(SCIF0, SCIF0_ERI, SCIF0_RXI, SCIF0_BRI, SCIF0_TXI),
- INTC_GROUP(SCIF1, SCIF1_ERI, SCIF1_RXI, SCIF1_BRI, SCIF1_TXI),
- INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
- DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE),
- INTC_GROUP(PCIC5, PCIERR, PCIPWD3, PCIPWD2, PCIPWD1, PCIPWD0),
- INTC_GROUP(MMCIF, MMCIF_FSTAT, MMCIF_TRAN, MMCIF_ERR, MMCIF_FRDY),
- INTC_GROUP(GDTA, GDTA_GACLI, GDTA_GAMCI, GDTA_GAERI),
INTC_GROUP(TMU345, TMU3, TMU4, TMU5),
- INTC_GROUP(FLCTL, FLCTL_FLSTE, FLCTL_FLEND,
- FLCTL_FLTRQ0, FLCTL_FLTRQ1),
- INTC_GROUP(GPIO, GPIOI0, GPIOI1, GPIOI2, GPIOI3),
};
static struct intc_mask_reg mask_registers[] __initdata = {
@@ -291,17 +556,17 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7785-irl4567", vectors_irl4567,
void __init plat_irq_setup(void)
{
/* disable IRQ3-0 + IRQ7-4 */
- ctrl_outl(0xff000000, INTC_INTMSK0);
+ __raw_writel(0xff000000, INTC_INTMSK0);
/* disable IRL3-0 + IRL7-4 */
- ctrl_outl(0xc0000000, INTC_INTMSK1);
- ctrl_outl(0xfffefffe, INTC_INTMSK2);
+ __raw_writel(0xc0000000, INTC_INTMSK1);
+ __raw_writel(0xfffefffe, INTC_INTMSK2);
/* select IRL mode for IRL3-0 + IRL7-4 */
- ctrl_outl(ctrl_inl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
/* disable holding function, ie enable "SH-4 Mode" */
- ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00200000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00200000, INTC_ICR0);
register_intc_controller(&intc_desc);
}
@@ -311,32 +576,32 @@ void __init plat_irq_setup_pins(int mode)
switch (mode) {
case IRQ_MODE_IRQ7654:
/* select IRQ mode for IRL7-4 */
- ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0);
register_intc_controller(&intc_desc_irq4567);
break;
case IRQ_MODE_IRQ3210:
/* select IRQ mode for IRL3-0 */
- ctrl_outl(ctrl_inl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
register_intc_controller(&intc_desc_irq0123);
break;
case IRQ_MODE_IRL7654:
/* enable IRL7-4 but don't provide any masking */
- ctrl_outl(0x40000000, INTC_INTMSKCLR1);
- ctrl_outl(0x0000fffe, INTC_INTMSKCLR2);
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x0000fffe, INTC_INTMSKCLR2);
break;
case IRQ_MODE_IRL3210:
/* enable IRL0-3 but don't provide any masking */
- ctrl_outl(0x80000000, INTC_INTMSKCLR1);
- ctrl_outl(0xfffe0000, INTC_INTMSKCLR2);
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xfffe0000, INTC_INTMSKCLR2);
break;
case IRQ_MODE_IRL7654_MASK:
/* enable IRL7-4 and mask using cpu intc controller */
- ctrl_outl(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
register_intc_controller(&intc_desc_irl4567);
break;
case IRQ_MODE_IRL3210_MASK:
/* enable IRL0-3 and mask using cpu intc controller */
- ctrl_outl(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
register_intc_controller(&intc_desc_irl0123);
break;
default:
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
new file mode 100644
index 00000000000..479e79bdd3d
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
@@ -0,0 +1,848 @@
+/*
+ * SH7786 Setup
+ *
+ * Copyright (C) 2009 - 2011 Renesas Solutions Corp.
+ * Kuninori Morimoto <morimoto.kuninori@renesas.com>
+ * Paul Mundt <paul.mundt@renesas.com>
+ *
+ * Based on SH7785 Setup
+ *
+ * Copyright (C) 2007 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_dma.h>
+#include <linux/sh_intc.h>
+#include <linux/usb/ohci_pdriver.h>
+#include <cpu/dma-register.h>
+#include <asm/mmzone.h>
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffea0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+ DEFINE_RES_IRQ(evt2irq(0x720)),
+ DEFINE_RES_IRQ(evt2irq(0x760)),
+ DEFINE_RES_IRQ(evt2irq(0x740)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+/*
+ * The rest of these all have multiplexed IRQs
+ */
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffeb0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x780)),
+};
+
+static struct resource scif1_demux_resources[] = {
+ DEFINE_RES_MEM(0xffeb0000, 0x100),
+ /* Placeholders, see sh7786_devices_setup() */
+ DEFINE_RES_IRQ(0),
+ DEFINE_RES_IRQ(0),
+ DEFINE_RES_IRQ(0),
+ DEFINE_RES_IRQ(0),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffec0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x840)),
+};
+
+static struct platform_device scif2_device = {
+ .name = "sh-sci",
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
+ .dev = {
+ .platform_data = &scif2_platform_data,
+ },
+};
+
+static struct plat_sci_port scif3_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif3_resources[] = {
+ DEFINE_RES_MEM(0xffed0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x860)),
+};
+
+static struct platform_device scif3_device = {
+ .name = "sh-sci",
+ .id = 3,
+ .resource = scif3_resources,
+ .num_resources = ARRAY_SIZE(scif3_resources),
+ .dev = {
+ .platform_data = &scif3_platform_data,
+ },
+};
+
+static struct plat_sci_port scif4_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif4_resources[] = {
+ DEFINE_RES_MEM(0xffee0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
+};
+
+static struct platform_device scif4_device = {
+ .name = "sh-sci",
+ .id = 4,
+ .resource = scif4_resources,
+ .num_resources = ARRAY_SIZE(scif4_resources),
+ .dev = {
+ .platform_data = &scif4_platform_data,
+ },
+};
+
+static struct plat_sci_port scif5_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE | SCSCR_CKE1,
+ .type = PORT_SCIF,
+ .regtype = SCIx_SH4_SCIF_FIFODATA_REGTYPE,
+};
+
+static struct resource scif5_resources[] = {
+ DEFINE_RES_MEM(0xffef0000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x8a0)),
+};
+
+static struct platform_device scif5_device = {
+ .name = "sh-sci",
+ .id = 5,
+ .resource = scif5_resources,
+ .num_resources = ARRAY_SIZE(scif5_resources),
+ .dev = {
+ .platform_data = &scif5_platform_data,
+ },
+};
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffd80000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffda0000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x480)),
+ DEFINE_RES_IRQ(evt2irq(0x4a0)),
+ DEFINE_RES_IRQ(evt2irq(0x4c0)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu2_resources[] = {
+ DEFINE_RES_MEM(0xffdc0000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x7a0)),
+ DEFINE_RES_IRQ(evt2irq(0x7a0)),
+ DEFINE_RES_IRQ(evt2irq(0x7a0)),
+};
+
+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 sh_timer_config tmu3_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu3_resources[] = {
+ DEFINE_RES_MEM(0xffde0000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x7c0)),
+ DEFINE_RES_IRQ(evt2irq(0x7c0)),
+ DEFINE_RES_IRQ(evt2irq(0x7c0)),
+};
+
+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 const struct sh_dmae_channel dmac0_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .channel = dmac0_channels,
+ .channel_num = ARRAY_SIZE(dmac0_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+/* Resource order important! */
+static struct resource dmac0_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfe008020,
+ .end = 0xfe00808f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ /* DMARSx */
+ .start = 0xfe009000,
+ .end = 0xfe00900b,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "error_irq",
+ .start = evt2irq(0x5c0),
+ .end = evt2irq(0x5c0),
+ .flags = IORESOURCE_IRQ,
+ }, {
+ /* IRQ for channels 0-5 */
+ .start = evt2irq(0x500),
+ .end = evt2irq(0x5a0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = dmac0_resources,
+ .num_resources = ARRAY_SIZE(dmac0_resources),
+ .dev = {
+ .platform_data = &dma0_platform_data,
+ },
+};
+
+#define USB_EHCI_START 0xffe70000
+#define USB_OHCI_START 0xffe70400
+
+static struct resource usb_ehci_resources[] = {
+ [0] = {
+ .start = USB_EHCI_START,
+ .end = USB_EHCI_START + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0xba0),
+ .end = evt2irq(0xba0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device usb_ehci_device = {
+ .name = "sh_ehci",
+ .id = -1,
+ .dev = {
+ .dma_mask = &usb_ehci_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(usb_ehci_resources),
+ .resource = usb_ehci_resources,
+};
+
+static struct resource usb_ohci_resources[] = {
+ [0] = {
+ .start = USB_OHCI_START,
+ .end = USB_OHCI_START + 0x3ff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = evt2irq(0xba0),
+ .end = evt2irq(0xba0),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct usb_ohci_pdata usb_ohci_pdata;
+
+static struct platform_device usb_ohci_device = {
+ .name = "ohci-platform",
+ .id = -1,
+ .dev = {
+ .dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &usb_ohci_pdata,
+ },
+ .num_resources = ARRAY_SIZE(usb_ohci_resources),
+ .resource = usb_ohci_resources,
+};
+
+static struct platform_device *sh7786_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &scif3_device,
+ &scif4_device,
+ &scif5_device,
+ &tmu0_device,
+ &tmu1_device,
+ &tmu2_device,
+};
+
+static struct platform_device *sh7786_devices[] __initdata = {
+ &dma0_device,
+ &usb_ehci_device,
+ &usb_ohci_device,
+};
+
+/*
+ * Please call this function if your platform board
+ * use external clock for USB
+ * */
+#define USBCTL0 0xffe70858
+#define CLOCK_MODE_MASK 0xffffff7f
+#define EXT_CLOCK_MODE 0x00000080
+
+void __init sh7786_usb_use_exclock(void)
+{
+ u32 val = __raw_readl(USBCTL0) & CLOCK_MODE_MASK;
+ __raw_writel(val | EXT_CLOCK_MODE, USBCTL0);
+}
+
+#define USBINITREG1 0xffe70094
+#define USBINITREG2 0xffe7009c
+#define USBINITVAL1 0x00ff0040
+#define USBINITVAL2 0x00000001
+
+#define USBPCTL1 0xffe70804
+#define USBST 0xffe70808
+#define PHY_ENB 0x00000001
+#define PLL_ENB 0x00000002
+#define PHY_RST 0x00000004
+#define ACT_PLL_STATUS 0xc0000000
+
+static void __init sh7786_usb_setup(void)
+{
+ int i = 1000000;
+
+ /*
+ * USB initial settings
+ *
+ * The following settings are necessary
+ * for using the USB modules.
+ *
+ * see "USB Initial Settings" for detail
+ */
+ __raw_writel(USBINITVAL1, USBINITREG1);
+ __raw_writel(USBINITVAL2, USBINITREG2);
+
+ /*
+ * Set the PHY and PLL enable bit
+ */
+ __raw_writel(PHY_ENB | PLL_ENB, USBPCTL1);
+ while (i--) {
+ if (ACT_PLL_STATUS == (__raw_readl(USBST) & ACT_PLL_STATUS)) {
+ /* Set the PHY RST bit */
+ __raw_writel(PHY_ENB | PLL_ENB | PHY_RST, USBPCTL1);
+ printk(KERN_INFO "sh7786 usb setup done\n");
+ break;
+ }
+ cpu_relax();
+ }
+}
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+ IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+ IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+ IRL0_HHLL, IRL0_HHLH, IRL0_HHHL,
+
+ IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+ IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+ IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+ IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
+
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
+ WDT,
+ TMU0_0, TMU0_1, TMU0_2, TMU0_3,
+ TMU1_0, TMU1_1, TMU1_2,
+ DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6,
+ HUDI1, HUDI0,
+ DMAC1_0, DMAC1_1, DMAC1_2, DMAC1_3,
+ HPB_0, HPB_1, HPB_2,
+ SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3,
+ SCIF1,
+ TMU2, TMU3,
+ SCIF2, SCIF3, SCIF4, SCIF5,
+ Eth_0, Eth_1,
+ PCIeC0_0, PCIeC0_1, PCIeC0_2,
+ PCIeC1_0, PCIeC1_1, PCIeC1_2,
+ USB,
+ I2C0, I2C1,
+ DU,
+ SSI0, SSI1, SSI2, SSI3,
+ PCIeC2_0, PCIeC2_1, PCIeC2_2,
+ HAC0, HAC1,
+ FLCTL,
+ HSPI,
+ GPIO0, GPIO1,
+ Thermal,
+ INTICI0, INTICI1, INTICI2, INTICI3,
+ INTICI4, INTICI5, INTICI6, INTICI7,
+
+ /* Muxed sub-events */
+ TXI1, BRI1, RXI1, ERI1,
+};
+
+static struct intc_vect sh7786_vectors[] __initdata = {
+ INTC_VECT(WDT, 0x3e0),
+ INTC_VECT(TMU0_0, 0x400), INTC_VECT(TMU0_1, 0x420),
+ INTC_VECT(TMU0_2, 0x440), INTC_VECT(TMU0_3, 0x460),
+ INTC_VECT(TMU1_0, 0x480), INTC_VECT(TMU1_1, 0x4a0),
+ INTC_VECT(TMU1_2, 0x4c0),
+ INTC_VECT(DMAC0_0, 0x500), INTC_VECT(DMAC0_1, 0x520),
+ INTC_VECT(DMAC0_2, 0x540), INTC_VECT(DMAC0_3, 0x560),
+ INTC_VECT(DMAC0_4, 0x580), INTC_VECT(DMAC0_5, 0x5a0),
+ INTC_VECT(DMAC0_6, 0x5c0),
+ INTC_VECT(HUDI1, 0x5e0), INTC_VECT(HUDI0, 0x600),
+ INTC_VECT(DMAC1_0, 0x620), INTC_VECT(DMAC1_1, 0x640),
+ INTC_VECT(DMAC1_2, 0x660), INTC_VECT(DMAC1_3, 0x680),
+ INTC_VECT(HPB_0, 0x6a0), INTC_VECT(HPB_1, 0x6c0),
+ INTC_VECT(HPB_2, 0x6e0),
+ INTC_VECT(SCIF0_0, 0x700), INTC_VECT(SCIF0_1, 0x720),
+ INTC_VECT(SCIF0_2, 0x740), INTC_VECT(SCIF0_3, 0x760),
+ INTC_VECT(SCIF1, 0x780),
+ INTC_VECT(TMU2, 0x7a0), INTC_VECT(TMU3, 0x7c0),
+ INTC_VECT(SCIF2, 0x840), INTC_VECT(SCIF3, 0x860),
+ INTC_VECT(SCIF4, 0x880), INTC_VECT(SCIF5, 0x8a0),
+ INTC_VECT(Eth_0, 0x8c0), INTC_VECT(Eth_1, 0x8e0),
+ INTC_VECT(PCIeC0_0, 0xae0), INTC_VECT(PCIeC0_1, 0xb00),
+ INTC_VECT(PCIeC0_2, 0xb20),
+ INTC_VECT(PCIeC1_0, 0xb40), INTC_VECT(PCIeC1_1, 0xb60),
+ INTC_VECT(PCIeC1_2, 0xb80),
+ INTC_VECT(USB, 0xba0),
+ INTC_VECT(I2C0, 0xcc0), INTC_VECT(I2C1, 0xce0),
+ INTC_VECT(DU, 0xd00),
+ INTC_VECT(SSI0, 0xd20), INTC_VECT(SSI1, 0xd40),
+ INTC_VECT(SSI2, 0xd60), INTC_VECT(SSI3, 0xd80),
+ INTC_VECT(PCIeC2_0, 0xda0), INTC_VECT(PCIeC2_1, 0xdc0),
+ INTC_VECT(PCIeC2_2, 0xde0),
+ INTC_VECT(HAC0, 0xe00), INTC_VECT(HAC1, 0xe20),
+ INTC_VECT(FLCTL, 0xe40),
+ INTC_VECT(HSPI, 0xe80),
+ INTC_VECT(GPIO0, 0xea0), INTC_VECT(GPIO1, 0xec0),
+ INTC_VECT(Thermal, 0xee0),
+ INTC_VECT(INTICI0, 0xf00), INTC_VECT(INTICI1, 0xf20),
+ INTC_VECT(INTICI2, 0xf40), INTC_VECT(INTICI3, 0xf60),
+ INTC_VECT(INTICI4, 0xf80), INTC_VECT(INTICI5, 0xfa0),
+ INTC_VECT(INTICI6, 0xfc0), INTC_VECT(INTICI7, 0xfe0),
+};
+
+#define CnINTMSK0 0xfe410030
+#define CnINTMSK1 0xfe410040
+#define CnINTMSKCLR0 0xfe410050
+#define CnINTMSKCLR1 0xfe410060
+#define CnINT2MSKR0 0xfe410a20
+#define CnINT2MSKR1 0xfe410a24
+#define CnINT2MSKR2 0xfe410a28
+#define CnINT2MSKR3 0xfe410a2c
+#define CnINT2MSKCR0 0xfe410a30
+#define CnINT2MSKCR1 0xfe410a34
+#define CnINT2MSKCR2 0xfe410a38
+#define CnINT2MSKCR3 0xfe410a3c
+#define INTMSK2 0xfe410068
+#define INTMSKCLR2 0xfe41006c
+
+#define INTDISTCR0 0xfe4100b0
+#define INTDISTCR1 0xfe4100b4
+#define INT2DISTCR0 0xfe410900
+#define INT2DISTCR1 0xfe410904
+#define INT2DISTCR2 0xfe410908
+#define INT2DISTCR3 0xfe41090c
+
+static struct intc_mask_reg sh7786_mask_registers[] __initdata = {
+ { CnINTMSK0, CnINTMSKCLR0, 32,
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 },
+ INTC_SMP_BALANCING(INTDISTCR0) },
+ { INTMSK2, INTMSKCLR2, 32,
+ { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
+ IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
+ IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
+ IRL0_HHLL, IRL0_HHLH, IRL0_HHHL, 0,
+ IRL4_LLLL, IRL4_LLLH, IRL4_LLHL, IRL4_LLHH,
+ IRL4_LHLL, IRL4_LHLH, IRL4_LHHL, IRL4_LHHH,
+ IRL4_HLLL, IRL4_HLLH, IRL4_HLHL, IRL4_HLHH,
+ IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } },
+ { CnINT2MSKR0, CnINT2MSKCR0 , 32,
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WDT },
+ INTC_SMP_BALANCING(INT2DISTCR0) },
+ { CnINT2MSKR1, CnINT2MSKCR1, 32,
+ { TMU0_0, TMU0_1, TMU0_2, TMU0_3, TMU1_0, TMU1_1, TMU1_2, 0,
+ DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6,
+ HUDI1, HUDI0,
+ DMAC1_0, DMAC1_1, DMAC1_2, DMAC1_3,
+ HPB_0, HPB_1, HPB_2,
+ SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3,
+ SCIF1,
+ TMU2, TMU3, 0, }, INTC_SMP_BALANCING(INT2DISTCR1) },
+ { CnINT2MSKR2, CnINT2MSKCR2, 32,
+ { 0, 0, SCIF2, SCIF3, SCIF4, SCIF5,
+ Eth_0, Eth_1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ PCIeC0_0, PCIeC0_1, PCIeC0_2,
+ PCIeC1_0, PCIeC1_1, PCIeC1_2,
+ USB, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR2) },
+ { CnINT2MSKR3, CnINT2MSKCR3, 32,
+ { 0, 0, 0, 0, 0, 0,
+ I2C0, I2C1,
+ DU, SSI0, SSI1, SSI2, SSI3,
+ PCIeC2_0, PCIeC2_1, PCIeC2_2,
+ HAC0, HAC1,
+ FLCTL, 0,
+ HSPI, GPIO0, GPIO1, Thermal,
+ 0, 0, 0, 0, 0, 0, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR3) },
+};
+
+static struct intc_prio_reg sh7786_prio_registers[] __initdata = {
+ { 0xfe410010, 0, 32, 4, /* INTPRI */ { IRQ0, IRQ1, IRQ2, IRQ3,
+ IRQ4, IRQ5, IRQ6, IRQ7 } },
+ { 0xfe410800, 0, 32, 8, /* INT2PRI0 */ { 0, 0, 0, WDT } },
+ { 0xfe410804, 0, 32, 8, /* INT2PRI1 */ { TMU0_0, TMU0_1,
+ TMU0_2, TMU0_3 } },
+ { 0xfe410808, 0, 32, 8, /* INT2PRI2 */ { TMU1_0, TMU1_1,
+ TMU1_2, 0 } },
+ { 0xfe41080c, 0, 32, 8, /* INT2PRI3 */ { DMAC0_0, DMAC0_1,
+ DMAC0_2, DMAC0_3 } },
+ { 0xfe410810, 0, 32, 8, /* INT2PRI4 */ { DMAC0_4, DMAC0_5,
+ DMAC0_6, HUDI1 } },
+ { 0xfe410814, 0, 32, 8, /* INT2PRI5 */ { HUDI0, DMAC1_0,
+ DMAC1_1, DMAC1_2 } },
+ { 0xfe410818, 0, 32, 8, /* INT2PRI6 */ { DMAC1_3, HPB_0,
+ HPB_1, HPB_2 } },
+ { 0xfe41081c, 0, 32, 8, /* INT2PRI7 */ { SCIF0_0, SCIF0_1,
+ SCIF0_2, SCIF0_3 } },
+ { 0xfe410820, 0, 32, 8, /* INT2PRI8 */ { SCIF1, TMU2, TMU3, 0 } },
+ { 0xfe410824, 0, 32, 8, /* INT2PRI9 */ { 0, 0, SCIF2, SCIF3 } },
+ { 0xfe410828, 0, 32, 8, /* INT2PRI10 */ { SCIF4, SCIF5,
+ Eth_0, Eth_1 } },
+ { 0xfe41082c, 0, 32, 8, /* INT2PRI11 */ { 0, 0, 0, 0 } },
+ { 0xfe410830, 0, 32, 8, /* INT2PRI12 */ { 0, 0, 0, 0 } },
+ { 0xfe410834, 0, 32, 8, /* INT2PRI13 */ { 0, 0, 0, 0 } },
+ { 0xfe410838, 0, 32, 8, /* INT2PRI14 */ { 0, 0, 0, PCIeC0_0 } },
+ { 0xfe41083c, 0, 32, 8, /* INT2PRI15 */ { PCIeC0_1, PCIeC0_2,
+ PCIeC1_0, PCIeC1_1 } },
+ { 0xfe410840, 0, 32, 8, /* INT2PRI16 */ { PCIeC1_2, USB, 0, 0 } },
+ { 0xfe410844, 0, 32, 8, /* INT2PRI17 */ { 0, 0, 0, 0 } },
+ { 0xfe410848, 0, 32, 8, /* INT2PRI18 */ { 0, 0, I2C0, I2C1 } },
+ { 0xfe41084c, 0, 32, 8, /* INT2PRI19 */ { DU, SSI0, SSI1, SSI2 } },
+ { 0xfe410850, 0, 32, 8, /* INT2PRI20 */ { SSI3, PCIeC2_0,
+ PCIeC2_1, PCIeC2_2 } },
+ { 0xfe410854, 0, 32, 8, /* INT2PRI21 */ { HAC0, HAC1, FLCTL, 0 } },
+ { 0xfe410858, 0, 32, 8, /* INT2PRI22 */ { HSPI, GPIO0,
+ GPIO1, Thermal } },
+ { 0xfe41085c, 0, 32, 8, /* INT2PRI23 */ { 0, 0, 0, 0 } },
+ { 0xfe410860, 0, 32, 8, /* INT2PRI24 */ { 0, 0, 0, 0 } },
+ { 0xfe410090, 0xfe4100a0, 32, 4, /* CnICIPRI / CnICIPRICLR */
+ { INTICI7, INTICI6, INTICI5, INTICI4,
+ INTICI3, INTICI2, INTICI1, INTICI0 }, INTC_SMP(4, 2) },
+};
+
+static struct intc_subgroup sh7786_subgroups[] __initdata = {
+ { 0xfe410c20, 32, SCIF1,
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TXI1, BRI1, RXI1, ERI1 } },
+};
+
+static struct intc_desc sh7786_intc_desc __initdata = {
+ .name = "sh7786",
+ .hw = {
+ .vectors = sh7786_vectors,
+ .nr_vectors = ARRAY_SIZE(sh7786_vectors),
+ .mask_regs = sh7786_mask_registers,
+ .nr_mask_regs = ARRAY_SIZE(sh7786_mask_registers),
+ .subgroups = sh7786_subgroups,
+ .nr_subgroups = ARRAY_SIZE(sh7786_subgroups),
+ .prio_regs = sh7786_prio_registers,
+ .nr_prio_regs = ARRAY_SIZE(sh7786_prio_registers),
+ },
+};
+
+/* Support for external interrupt pins in IRQ mode */
+static struct intc_vect vectors_irq0123[] __initdata = {
+ INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240),
+ INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0),
+};
+
+static struct intc_vect vectors_irq4567[] __initdata = {
+ INTC_VECT(IRQ4, 0x300), INTC_VECT(IRQ5, 0x340),
+ INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0),
+};
+
+static struct intc_sense_reg sh7786_sense_registers[] __initdata = {
+ { 0xfe41001c, 32, 2, /* ICR1 */ { IRQ0, IRQ1, IRQ2, IRQ3,
+ IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static struct intc_mask_reg sh7786_ack_registers[] __initdata = {
+ { 0xfe410024, 0, 32, /* INTREQ */
+ { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7786-irq0123",
+ vectors_irq0123, NULL, sh7786_mask_registers,
+ sh7786_prio_registers, sh7786_sense_registers,
+ sh7786_ack_registers);
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7786-irq4567",
+ vectors_irq4567, NULL, sh7786_mask_registers,
+ sh7786_prio_registers, sh7786_sense_registers,
+ sh7786_ack_registers);
+
+/* External interrupt pins in IRL mode */
+
+static struct intc_vect vectors_irl0123[] __initdata = {
+ INTC_VECT(IRL0_LLLL, 0x200), INTC_VECT(IRL0_LLLH, 0x220),
+ INTC_VECT(IRL0_LLHL, 0x240), INTC_VECT(IRL0_LLHH, 0x260),
+ INTC_VECT(IRL0_LHLL, 0x280), INTC_VECT(IRL0_LHLH, 0x2a0),
+ INTC_VECT(IRL0_LHHL, 0x2c0), INTC_VECT(IRL0_LHHH, 0x2e0),
+ INTC_VECT(IRL0_HLLL, 0x300), INTC_VECT(IRL0_HLLH, 0x320),
+ INTC_VECT(IRL0_HLHL, 0x340), INTC_VECT(IRL0_HLHH, 0x360),
+ INTC_VECT(IRL0_HHLL, 0x380), INTC_VECT(IRL0_HHLH, 0x3a0),
+ INTC_VECT(IRL0_HHHL, 0x3c0),
+};
+
+static struct intc_vect vectors_irl4567[] __initdata = {
+ INTC_VECT(IRL4_LLLL, 0x900), INTC_VECT(IRL4_LLLH, 0x920),
+ INTC_VECT(IRL4_LLHL, 0x940), INTC_VECT(IRL4_LLHH, 0x960),
+ INTC_VECT(IRL4_LHLL, 0x980), INTC_VECT(IRL4_LHLH, 0x9a0),
+ INTC_VECT(IRL4_LHHL, 0x9c0), INTC_VECT(IRL4_LHHH, 0x9e0),
+ INTC_VECT(IRL4_HLLL, 0xa00), INTC_VECT(IRL4_HLLH, 0xa20),
+ INTC_VECT(IRL4_HLHL, 0xa40), INTC_VECT(IRL4_HLHH, 0xa60),
+ INTC_VECT(IRL4_HHLL, 0xa80), INTC_VECT(IRL4_HHLH, 0xaa0),
+ INTC_VECT(IRL4_HHHL, 0xac0),
+};
+
+static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7786-irl0123", vectors_irl0123,
+ NULL, sh7786_mask_registers, NULL, NULL);
+
+static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567,
+ NULL, sh7786_mask_registers, NULL, NULL);
+
+#define INTC_ICR0 0xfe410000
+#define INTC_INTMSK0 CnINTMSK0
+#define INTC_INTMSK1 CnINTMSK1
+#define INTC_INTMSK2 INTMSK2
+#define INTC_INTMSKCLR1 CnINTMSKCLR1
+#define INTC_INTMSKCLR2 INTMSKCLR2
+
+void __init plat_irq_setup(void)
+{
+ /* disable IRQ3-0 + IRQ7-4 */
+ __raw_writel(0xff000000, INTC_INTMSK0);
+
+ /* disable IRL3-0 + IRL7-4 */
+ __raw_writel(0xc0000000, INTC_INTMSK1);
+ __raw_writel(0xfffefffe, INTC_INTMSK2);
+
+ /* select IRL mode for IRL3-0 + IRL7-4 */
+ __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
+
+ register_intc_controller(&sh7786_intc_desc);
+}
+
+void __init plat_irq_setup_pins(int mode)
+{
+ switch (mode) {
+ case IRQ_MODE_IRQ7654:
+ /* select IRQ mode for IRL7-4 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00400000, INTC_ICR0);
+ register_intc_controller(&intc_desc_irq4567);
+ break;
+ case IRQ_MODE_IRQ3210:
+ /* select IRQ mode for IRL3-0 */
+ __raw_writel(__raw_readl(INTC_ICR0) | 0x00800000, INTC_ICR0);
+ register_intc_controller(&intc_desc_irq0123);
+ break;
+ case IRQ_MODE_IRL7654:
+ /* enable IRL7-4 but don't provide any masking */
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ __raw_writel(0x0000fffe, INTC_INTMSKCLR2);
+ break;
+ case IRQ_MODE_IRL3210:
+ /* enable IRL0-3 but don't provide any masking */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ __raw_writel(0xfffe0000, INTC_INTMSKCLR2);
+ break;
+ case IRQ_MODE_IRL7654_MASK:
+ /* enable IRL7-4 and mask using cpu intc controller */
+ __raw_writel(0x40000000, INTC_INTMSKCLR1);
+ register_intc_controller(&intc_desc_irl4567);
+ break;
+ case IRQ_MODE_IRL3210_MASK:
+ /* enable IRL0-3 and mask using cpu intc controller */
+ __raw_writel(0x80000000, INTC_INTMSKCLR1);
+ register_intc_controller(&intc_desc_irl0123);
+ break;
+ default:
+ BUG();
+ }
+}
+
+void __init plat_mem_setup(void)
+{
+}
+
+static int __init sh7786_devices_setup(void)
+{
+ int ret, irq;
+
+ sh7786_usb_setup();
+
+ /*
+ * De-mux SCIF1 IRQs if possible
+ */
+ irq = intc_irq_lookup(sh7786_intc_desc.name, TXI1);
+ if (irq > 0) {
+ scif1_demux_resources[1].start =
+ intc_irq_lookup(sh7786_intc_desc.name, ERI1);
+ scif1_demux_resources[2].start =
+ intc_irq_lookup(sh7786_intc_desc.name, RXI1);
+ scif1_demux_resources[3].start = irq;
+ scif1_demux_resources[4].start =
+ intc_irq_lookup(sh7786_intc_desc.name, BRI1);
+
+ scif1_device.resource = scif1_demux_resources;
+ scif1_device.num_resources = ARRAY_SIZE(scif1_demux_resources);
+ }
+
+ ret = platform_add_devices(sh7786_early_devices,
+ ARRAY_SIZE(sh7786_early_devices));
+ if (unlikely(ret != 0))
+ return ret;
+
+ return platform_add_devices(sh7786_devices,
+ ARRAY_SIZE(sh7786_devices));
+}
+arch_initcall(sh7786_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh7786_early_devices,
+ ARRAY_SIZE(sh7786_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
index bd35f32534b..a78c5feb4e3 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c
@@ -1,7 +1,7 @@
/*
- * SH-X3 Setup
+ * SH-X3 Prototype Setup
*
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2010 Paul Mundt
*
* 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
@@ -12,52 +12,155 @@
#include <linux/serial.h>
#include <linux/serial_sci.h>
#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/sh_timer.h>
+#include <linux/sh_intc.h>
+#include <cpu/shx3.h>
#include <asm/mmzone.h>
-static struct plat_sci_port sci_platform_data[] = {
- {
- .mapbase = 0xffc30000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 40, 41, 43, 42 },
- }, {
- .mapbase = 0xffc40000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 44, 45, 47, 46 },
- }, {
- .mapbase = 0xffc50000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 48, 49, 51, 50 },
- }, {
- .mapbase = 0xffc60000,
- .flags = UPF_BOOT_AUTOCONF,
- .type = PORT_SCIF,
- .irqs = { 52, 53, 55, 54 },
- }, {
- .flags = 0,
- }
+/*
+ * This intentionally only registers SCIF ports 0, 1, and 3. SCIF 2
+ * INTEVT values overlap with the FPU EXPEVT ones, requiring special
+ * demuxing in the exception dispatch path.
+ *
+ * As this overlap is something that never should have made it in to
+ * silicon in the first place, we just refuse to deal with the port at
+ * all rather than adding infrastructure to hack around it.
+ */
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xffc30000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x700)),
+ DEFINE_RES_IRQ(evt2irq(0x720)),
+ DEFINE_RES_IRQ(evt2irq(0x760)),
+ DEFINE_RES_IRQ(evt2irq(0x740)),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct plat_sci_port scif1_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif1_resources[] = {
+ DEFINE_RES_MEM(0xffc40000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x780)),
+ DEFINE_RES_IRQ(evt2irq(0x7a0)),
+ DEFINE_RES_IRQ(evt2irq(0x7e0)),
+ DEFINE_RES_IRQ(evt2irq(0x7c0)),
+};
+
+static struct platform_device scif1_device = {
+ .name = "sh-sci",
+ .id = 1,
+ .resource = scif1_resources,
+ .num_resources = ARRAY_SIZE(scif1_resources),
+ .dev = {
+ .platform_data = &scif1_platform_data,
+ },
+};
+
+static struct plat_sci_port scif2_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xffc60000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
+ DEFINE_RES_IRQ(evt2irq(0x8a0)),
+ DEFINE_RES_IRQ(evt2irq(0x8e0)),
+ DEFINE_RES_IRQ(evt2irq(0x8c0)),
};
-static struct platform_device sci_device = {
+static struct platform_device scif2_device = {
.name = "sh-sci",
- .id = -1,
+ .id = 2,
+ .resource = scif2_resources,
+ .num_resources = ARRAY_SIZE(scif2_resources),
.dev = {
- .platform_data = sci_platform_data,
+ .platform_data = &scif2_platform_data,
},
};
-static struct platform_device *shx3_devices[] __initdata = {
- &sci_device,
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(0xffc10000, 0x30),
+ DEFINE_RES_IRQ(evt2irq(0x400)),
+ DEFINE_RES_IRQ(evt2irq(0x420)),
+ DEFINE_RES_IRQ(evt2irq(0x440)),
+};
+
+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 = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu1_resources[] = {
+ DEFINE_RES_MEM(0xffc20000, 0x2c),
+ DEFINE_RES_IRQ(evt2irq(0x460)),
+ DEFINE_RES_IRQ(evt2irq(0x480)),
+ DEFINE_RES_IRQ(evt2irq(0x4a0)),
+};
+
+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 platform_device *shx3_early_devices[] __initdata = {
+ &scif0_device,
+ &scif1_device,
+ &scif2_device,
+ &tmu0_device,
+ &tmu1_device,
};
static int __init shx3_devices_setup(void)
{
- return platform_add_devices(shx3_devices,
- ARRAY_SIZE(shx3_devices));
+ return platform_add_devices(shx3_early_devices,
+ ARRAY_SIZE(shx3_early_devices));
+}
+arch_initcall(shx3_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(shx3_early_devices,
+ ARRAY_SIZE(shx3_early_devices));
}
-__initcall(shx3_devices_setup);
enum {
UNUSED = 0,
@@ -82,10 +185,7 @@ enum {
DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8, DMAC1_DMINT9,
DMAC1_DMINT10, DMAC1_DMINT11, DMAC1_DMAE,
IIC, VIN0, VIN1, VCORE0, ATAPI,
- DTU0_TEND, DTU0_AE, DTU0_TMISS,
- DTU1_TEND, DTU1_AE, DTU1_TMISS,
- DTU2_TEND, DTU2_AE, DTU2_TMISS,
- DTU3_TEND, DTU3_AE, DTU3_TMISS,
+ DTU0, DTU1, DTU2, DTU3,
FE0, FE1,
GPIO0, GPIO1, GPIO2, GPIO3,
PAM, IRM,
@@ -94,7 +194,7 @@ enum {
/* interrupt groups */
IRL, PCII56789, SCIF0, SCIF1, SCIF2, SCIF3,
- DMAC0, DMAC1, DTU0, DTU1, DTU2, DTU3,
+ DMAC0, DMAC1,
};
static struct intc_vect vectors[] __initdata = {
@@ -111,8 +211,6 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(SCIF0_BRI, 0x740), INTC_VECT(SCIF0_TXI, 0x760),
INTC_VECT(SCIF1_ERI, 0x780), INTC_VECT(SCIF1_RXI, 0x7a0),
INTC_VECT(SCIF1_BRI, 0x7c0), INTC_VECT(SCIF1_TXI, 0x7e0),
- INTC_VECT(SCIF2_ERI, 0x800), INTC_VECT(SCIF2_RXI, 0x820),
- INTC_VECT(SCIF2_BRI, 0x840), INTC_VECT(SCIF2_TXI, 0x860),
INTC_VECT(SCIF3_ERI, 0x880), INTC_VECT(SCIF3_RXI, 0x8a0),
INTC_VECT(SCIF3_BRI, 0x8c0), INTC_VECT(SCIF3_TXI, 0x8e0),
INTC_VECT(DMAC0_DMINT0, 0x900), INTC_VECT(DMAC0_DMINT1, 0x920),
@@ -127,14 +225,14 @@ static struct intc_vect vectors[] __initdata = {
INTC_VECT(IIC, 0xae0),
INTC_VECT(VIN0, 0xb00), INTC_VECT(VIN1, 0xb20),
INTC_VECT(VCORE0, 0xb00), INTC_VECT(ATAPI, 0xb60),
- INTC_VECT(DTU0_TEND, 0xc00), INTC_VECT(DTU0_AE, 0xc20),
- INTC_VECT(DTU0_TMISS, 0xc40),
- INTC_VECT(DTU1_TEND, 0xc60), INTC_VECT(DTU1_AE, 0xc80),
- INTC_VECT(DTU1_TMISS, 0xca0),
- INTC_VECT(DTU2_TEND, 0xcc0), INTC_VECT(DTU2_AE, 0xce0),
- INTC_VECT(DTU2_TMISS, 0xd00),
- INTC_VECT(DTU3_TEND, 0xd20), INTC_VECT(DTU3_AE, 0xd40),
- INTC_VECT(DTU3_TMISS, 0xd60),
+ INTC_VECT(DTU0, 0xc00), INTC_VECT(DTU0, 0xc20),
+ INTC_VECT(DTU0, 0xc40),
+ INTC_VECT(DTU1, 0xc60), INTC_VECT(DTU1, 0xc80),
+ INTC_VECT(DTU1, 0xca0),
+ INTC_VECT(DTU2, 0xcc0), INTC_VECT(DTU2, 0xce0),
+ INTC_VECT(DTU2, 0xd00),
+ INTC_VECT(DTU3, 0xd20), INTC_VECT(DTU3, 0xd40),
+ INTC_VECT(DTU3, 0xd60),
INTC_VECT(FE0, 0xe00), INTC_VECT(FE1, 0xe20),
INTC_VECT(GPIO0, 0xe40), INTC_VECT(GPIO1, 0xe60),
INTC_VECT(GPIO2, 0xe80), INTC_VECT(GPIO3, 0xea0),
@@ -153,18 +251,17 @@ static struct intc_group groups[] __initdata = {
INTC_GROUP(PCII56789, PCII5, PCII6, PCII7, PCII8, PCII9),
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(SCIF3, SCIF3_ERI, SCIF3_RXI, SCIF3_BRI, SCIF3_TXI),
INTC_GROUP(DMAC0, DMAC0_DMINT0, DMAC0_DMINT1, DMAC0_DMINT2,
DMAC0_DMINT3, DMAC0_DMINT4, DMAC0_DMINT5, DMAC0_DMAE),
INTC_GROUP(DMAC1, DMAC1_DMINT6, DMAC1_DMINT7, DMAC1_DMINT8,
DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
- INTC_GROUP(DTU0, DTU0_TEND, DTU0_AE, DTU0_TMISS),
- INTC_GROUP(DTU1, DTU1_TEND, DTU1_AE, DTU1_TMISS),
- INTC_GROUP(DTU2, DTU2_TEND, DTU2_AE, DTU2_TMISS),
- INTC_GROUP(DTU3, DTU3_TEND, DTU3_AE, DTU3_TMISS),
};
+#define INT2DISTCR0 0xfe4108a0
+#define INT2DISTCR1 0xfe4108a4
+#define INT2DISTCR2 0xfe4108a8
+
static struct intc_mask_reg mask_registers[] __initdata = {
{ 0xfe410030, 0xfe410050, 32, /* CnINTMSK0 / CnINTMSKCLR0 */
{ IRQ0, IRQ1, IRQ2, IRQ3 } },
@@ -174,20 +271,23 @@ static struct intc_mask_reg mask_registers[] __initdata = {
{ FE1, FE0, 0, ATAPI, VCORE0, VIN1, VIN0, IIC,
DU, GPIO3, GPIO2, GPIO1, GPIO0, PAM, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, /* HUDI bits ignored */
- 0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, } },
+ 0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, },
+ INTC_SMP_BALANCING(INT2DISTCR0) },
{ 0xfe410830, 0xfe410860, 32, /* CnINT2MSK1 / CnINT2MSKCLR1 */
{ 0, 0, 0, 0, DTU3, DTU2, DTU1, DTU0, /* IRM bits ignored */
PCII9, PCII8, PCII7, PCII6, PCII5, PCII4, PCII3, PCII2,
PCII1, PCII0, DMAC1_DMAE, DMAC1_DMINT11,
DMAC1_DMINT10, DMAC1_DMINT9, DMAC1_DMINT8, DMAC1_DMINT7,
DMAC1_DMINT6, DMAC0_DMAE, DMAC0_DMINT5, DMAC0_DMINT4,
- DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 } },
+ DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 },
+ INTC_SMP_BALANCING(INT2DISTCR1) },
{ 0xfe410840, 0xfe410870, 32, /* CnINT2MSK2 / CnINT2MSKCLR2 */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
SCIF3_TXI, SCIF3_BRI, SCIF3_RXI, SCIF3_ERI,
SCIF2_TXI, SCIF2_BRI, SCIF2_RXI, SCIF2_ERI,
SCIF1_TXI, SCIF1_BRI, SCIF1_RXI, SCIF1_ERI,
- SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI } },
+ SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI },
+ INTC_SMP_BALANCING(INT2DISTCR2) },
};
static struct intc_prio_reg prio_registers[] __initdata = {
@@ -244,11 +344,33 @@ static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups,
void __init plat_irq_setup_pins(int mode)
{
+ int ret = 0;
+
switch (mode) {
case IRQ_MODE_IRQ:
+ ret |= gpio_request(GPIO_FN_IRQ3, intc_desc_irq.name);
+ ret |= gpio_request(GPIO_FN_IRQ2, intc_desc_irq.name);
+ ret |= gpio_request(GPIO_FN_IRQ1, intc_desc_irq.name);
+ ret |= gpio_request(GPIO_FN_IRQ0, intc_desc_irq.name);
+
+ if (unlikely(ret)) {
+ pr_err("Failed to set IRQ mode\n");
+ return;
+ }
+
register_intc_controller(&intc_desc_irq);
break;
case IRQ_MODE_IRL3210:
+ ret |= gpio_request(GPIO_FN_IRL3, intc_desc_irl.name);
+ ret |= gpio_request(GPIO_FN_IRL2, intc_desc_irl.name);
+ ret |= gpio_request(GPIO_FN_IRL1, intc_desc_irl.name);
+ ret |= gpio_request(GPIO_FN_IRL0, intc_desc_irl.name);
+
+ if (unlikely(ret)) {
+ pr_err("Failed to set IRL mode\n");
+ return;
+ }
+
register_intc_controller(&intc_desc_irl);
break;
default:
diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
index e5e06845fa4..4a298808789 100644
--- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c
+++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c
@@ -1,7 +1,7 @@
/*
* SH-X3 SMP
*
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2010 Paul Mundt
* Copyright (C) 2007 Magnus Damm
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -9,18 +9,49 @@
* for more details.
*/
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/cpumask.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/cpu.h>
+#include <asm/sections.h>
-void __init plat_smp_setup(void)
+#define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12))
+#define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12))
+
+#define STBCR_MSTP 0x00000001
+#define STBCR_RESET 0x00000002
+#define STBCR_SLEEP 0x00000004
+#define STBCR_LTSLP 0x80000000
+
+static irqreturn_t ipi_interrupt_handler(int irq, void *arg)
+{
+ unsigned int message = (unsigned int)(long)arg;
+ unsigned int cpu = hard_smp_processor_id();
+ unsigned int offs = 4 * cpu;
+ unsigned int x;
+
+ x = __raw_readl(0xfe410070 + offs); /* C0INITICI..CnINTICI */
+ x &= (1 << (message << 2));
+ __raw_writel(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */
+
+ smp_message_recv(message);
+
+ return IRQ_HANDLED;
+}
+
+static void shx3_smp_setup(void)
{
unsigned int cpu = 0;
int i, num;
- cpus_clear(cpu_possible_map);
- cpu_set(cpu, cpu_possible_map);
+ init_cpu_possible(cpumask_of(cpu));
+
+ /* Enable light sleep for the boot CPU */
+ __raw_writel(__raw_readl(STBCR_REG(cpu)) | STBCR_LTSLP, STBCR_REG(cpu));
__cpu_number_map[0] = 0;
__cpu_logical_map[0] = 0;
@@ -30,7 +61,7 @@ void __init plat_smp_setup(void)
* for the total number of cores.
*/
for (i = 1, num = 0; i < NR_CPUS; i++) {
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
__cpu_number_map[i] = ++num;
__cpu_logical_map[num] = i;
}
@@ -38,83 +69,98 @@ void __init plat_smp_setup(void)
printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
}
-void __init plat_prepare_cpus(unsigned int max_cpus)
+static void shx3_prepare_cpus(unsigned int max_cpus)
{
-}
+ int i;
-#define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12))
-#define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12))
+ local_timer_setup(0);
-#define STBCR_MSTP 0x00000001
-#define STBCR_RESET 0x00000002
-#define STBCR_LTSLP 0x80000000
+ BUILD_BUG_ON(SMP_MSG_NR >= 8);
-#define STBCR_AP_VAL (STBCR_RESET | STBCR_LTSLP)
+ for (i = 0; i < SMP_MSG_NR; i++)
+ request_irq(104 + i, ipi_interrupt_handler,
+ IRQF_PERCPU, "IPI", (void *)(long)i);
-void plat_start_cpu(unsigned int cpu, unsigned long entry_point)
+ for (i = 0; i < max_cpus; i++)
+ set_cpu_present(i, true);
+}
+
+static void shx3_start_cpu(unsigned int cpu, unsigned long entry_point)
{
- ctrl_outl(entry_point, RESET_REG(cpu));
+ if (__in_29bit_mode())
+ __raw_writel(entry_point, RESET_REG(cpu));
+ else
+ __raw_writel(virt_to_phys(entry_point), RESET_REG(cpu));
- if (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP))
- ctrl_outl(STBCR_MSTP, STBCR_REG(cpu));
+ if (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP))
+ __raw_writel(STBCR_MSTP, STBCR_REG(cpu));
- while (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP))
- ;
+ while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP))
+ cpu_relax();
/* Start up secondary processor by sending a reset */
- ctrl_outl(STBCR_AP_VAL, STBCR_REG(cpu));
+ __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu));
}
-int plat_smp_processor_id(void)
+static unsigned int shx3_smp_processor_id(void)
{
- return ctrl_inl(0xff000048); /* CPIDR */
+ return __raw_readl(0xff000048); /* CPIDR */
}
-void plat_send_ipi(unsigned int cpu, unsigned int message)
+static void shx3_send_ipi(unsigned int cpu, unsigned int message)
{
unsigned long addr = 0xfe410070 + (cpu * 4);
BUG_ON(cpu >= 4);
- BUG_ON(message >= SMP_MSG_NR);
- ctrl_outl(1 << (message << 2), addr); /* C0INTICI..CnINTICI */
+ __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */
}
-struct ipi_data {
- void (*handler)(void *);
- void *arg;
- unsigned int message;
-};
-
-static irqreturn_t ipi_interrupt_handler(int irq, void *arg)
+static void shx3_update_boot_vector(unsigned int cpu)
{
- struct ipi_data *id = arg;
- unsigned int cpu = hard_smp_processor_id();
- unsigned int offs = 4 * cpu;
- unsigned int x;
-
- x = ctrl_inl(0xfe410070 + offs); /* C0INITICI..CnINTICI */
- x &= (1 << (id->message << 2));
- ctrl_outl(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */
-
- id->handler(id->arg);
-
- return IRQ_HANDLED;
+ __raw_writel(STBCR_MSTP, STBCR_REG(cpu));
+ while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP))
+ cpu_relax();
+ __raw_writel(STBCR_RESET, STBCR_REG(cpu));
}
-static struct ipi_data ipi_handlers[SMP_MSG_NR];
-
-int plat_register_ipi_handler(unsigned int message,
- void (*handler)(void *), void *arg)
+static int
+shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
{
- struct ipi_data *id = &ipi_handlers[message];
+ unsigned int cpu = (unsigned int)hcpu;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ shx3_update_boot_vector(cpu);
+ break;
+ case CPU_ONLINE:
+ pr_info("CPU %u is now online\n", cpu);
+ break;
+ case CPU_DEAD:
+ break;
+ }
- BUG_ON(SMP_MSG_NR >= 8);
- BUG_ON(message >= SMP_MSG_NR);
+ return NOTIFY_OK;
+}
- id->handler = handler;
- id->arg = arg;
- id->message = message;
+static struct notifier_block shx3_cpu_notifier = {
+ .notifier_call = shx3_cpu_callback,
+};
- return request_irq(104 + message, ipi_interrupt_handler, 0, "IPI", id);
+static int register_shx3_cpu_notifier(void)
+{
+ register_hotcpu_notifier(&shx3_cpu_notifier);
+ return 0;
}
+late_initcall(register_shx3_cpu_notifier);
+
+struct plat_smp_ops shx3_smp_ops = {
+ .smp_setup = shx3_smp_setup,
+ .prepare_cpus = shx3_prepare_cpus,
+ .start_cpu = shx3_start_cpu,
+ .smp_processor_id = shx3_smp_processor_id,
+ .send_ipi = shx3_send_ipi,
+ .cpu_die = native_cpu_die,
+ .cpu_disable = native_cpu_disable,
+ .play_dead = native_play_dead,
+};
diff --git a/arch/sh/kernel/cpu/sh4a/ubc.c b/arch/sh/kernel/cpu/sh4a/ubc.c
new file mode 100644
index 00000000000..efb2745bcb3
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/ubc.c
@@ -0,0 +1,133 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/ubc.c
+ *
+ * On-chip UBC support for SH-4A CPUs.
+ *
+ * Copyright (C) 2009 - 2010 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/hw_breakpoint.h>
+
+#define UBC_CBR(idx) (0xff200000 + (0x20 * idx))
+#define UBC_CRR(idx) (0xff200004 + (0x20 * idx))
+#define UBC_CAR(idx) (0xff200008 + (0x20 * idx))
+#define UBC_CAMR(idx) (0xff20000c + (0x20 * idx))
+
+#define UBC_CCMFR 0xff200600
+#define UBC_CBCR 0xff200620
+
+/* CRR */
+#define UBC_CRR_PCB (1 << 1)
+#define UBC_CRR_BIE (1 << 0)
+
+/* CBR */
+#define UBC_CBR_CE (1 << 0)
+
+static struct sh_ubc sh4a_ubc;
+
+static void sh4a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
+{
+ __raw_writel(UBC_CBR_CE | info->len | info->type, UBC_CBR(idx));
+ __raw_writel(info->address, UBC_CAR(idx));
+}
+
+static void sh4a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
+{
+ __raw_writel(0, UBC_CBR(idx));
+ __raw_writel(0, UBC_CAR(idx));
+}
+
+static void sh4a_ubc_enable_all(unsigned long mask)
+{
+ int i;
+
+ for (i = 0; i < sh4a_ubc.num_events; i++)
+ if (mask & (1 << i))
+ __raw_writel(__raw_readl(UBC_CBR(i)) | UBC_CBR_CE,
+ UBC_CBR(i));
+}
+
+static void sh4a_ubc_disable_all(void)
+{
+ int i;
+
+ for (i = 0; i < sh4a_ubc.num_events; i++)
+ __raw_writel(__raw_readl(UBC_CBR(i)) & ~UBC_CBR_CE,
+ UBC_CBR(i));
+}
+
+static unsigned long sh4a_ubc_active_mask(void)
+{
+ unsigned long active = 0;
+ int i;
+
+ for (i = 0; i < sh4a_ubc.num_events; i++)
+ if (__raw_readl(UBC_CBR(i)) & UBC_CBR_CE)
+ active |= (1 << i);
+
+ return active;
+}
+
+static unsigned long sh4a_ubc_triggered_mask(void)
+{
+ return __raw_readl(UBC_CCMFR);
+}
+
+static void sh4a_ubc_clear_triggered_mask(unsigned long mask)
+{
+ __raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR);
+}
+
+static struct sh_ubc sh4a_ubc = {
+ .name = "SH-4A",
+ .num_events = 2,
+ .trap_nr = 0x1e0,
+ .enable = sh4a_ubc_enable,
+ .disable = sh4a_ubc_disable,
+ .enable_all = sh4a_ubc_enable_all,
+ .disable_all = sh4a_ubc_disable_all,
+ .active_mask = sh4a_ubc_active_mask,
+ .triggered_mask = sh4a_ubc_triggered_mask,
+ .clear_triggered_mask = sh4a_ubc_clear_triggered_mask,
+};
+
+static int __init sh4a_ubc_init(void)
+{
+ struct clk *ubc_iclk = clk_get(NULL, "ubc0");
+ int i;
+
+ /*
+ * The UBC MSTP bit is optional, as not all platforms will have
+ * it. Just ignore it if we can't find it.
+ */
+ if (IS_ERR(ubc_iclk))
+ ubc_iclk = NULL;
+
+ clk_enable(ubc_iclk);
+
+ __raw_writel(0, UBC_CBCR);
+
+ for (i = 0; i < sh4a_ubc.num_events; i++) {
+ __raw_writel(0, UBC_CAMR(i));
+ __raw_writel(0, UBC_CBR(i));
+
+ __raw_writel(UBC_CRR_BIE | UBC_CRR_PCB, UBC_CRR(i));
+
+ /* dummy read for write posting */
+ (void)__raw_readl(UBC_CRR(i));
+ }
+
+ clk_disable(ubc_iclk);
+
+ sh4a_ubc.clk = ubc_iclk;
+
+ return register_sh_ubc(&sh4a_ubc);
+}
+arch_initcall(sh4a_ubc_init);
diff --git a/arch/sh/kernel/cpu/sh5/Makefile b/arch/sh/kernel/cpu/sh5/Makefile
index 8646363e9de..a184a31e686 100644
--- a/arch/sh/kernel/cpu/sh5/Makefile
+++ b/arch/sh/kernel/cpu/sh5/Makefile
@@ -5,3 +5,11 @@ obj-y := entry.o probe.o switchto.o
obj-$(CONFIG_SH_FPU) += fpu.o
obj-$(CONFIG_KALLSYMS) += unwind.o
+
+# CPU subtype setup
+obj-$(CONFIG_CPU_SH5) += setup-sh5.o
+
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SH5) := clock-sh5.o
+
+obj-y += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c
new file mode 100644
index 00000000000..c48b93d4c08
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh5/clock-sh5.c
@@ -0,0 +1,79 @@
+/*
+ * arch/sh/kernel/cpu/sh5/clock-sh5.c
+ *
+ * SH-5 support for the clock framework
+ *
+ * Copyright (C) 2008 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/io.h>
+
+static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 };
+
+/* Clock, Power and Reset Controller */
+#define CPRC_BLOCK_OFF 0x01010000
+#define CPRC_BASE (PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF)
+
+static unsigned long cprc_base;
+
+static void master_clk_init(struct clk *clk)
+{
+ int idx = (__raw_readl(cprc_base + 0x00) >> 6) & 0x0007;
+ clk->rate *= ifc_table[idx];
+}
+
+static struct sh_clk_ops sh5_master_clk_ops = {
+ .init = master_clk_init,
+};
+
+static unsigned long module_clk_recalc(struct clk *clk)
+{
+ int idx = (__raw_readw(cprc_base) >> 12) & 0x0007;
+ return clk->parent->rate / ifc_table[idx];
+}
+
+static struct sh_clk_ops sh5_module_clk_ops = {
+ .recalc = module_clk_recalc,
+};
+
+static unsigned long bus_clk_recalc(struct clk *clk)
+{
+ int idx = (__raw_readw(cprc_base) >> 3) & 0x0007;
+ return clk->parent->rate / ifc_table[idx];
+}
+
+static struct sh_clk_ops sh5_bus_clk_ops = {
+ .recalc = bus_clk_recalc,
+};
+
+static unsigned long cpu_clk_recalc(struct clk *clk)
+{
+ int idx = (__raw_readw(cprc_base) & 0x0007);
+ return clk->parent->rate / ifc_table[idx];
+}
+
+static struct sh_clk_ops sh5_cpu_clk_ops = {
+ .recalc = cpu_clk_recalc,
+};
+
+static struct sh_clk_ops *sh5_clk_ops[] = {
+ &sh5_master_clk_ops,
+ &sh5_module_clk_ops,
+ &sh5_bus_clk_ops,
+ &sh5_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx)
+{
+ cprc_base = (unsigned long)ioremap_nocache(CPRC_BASE, 1024);
+ BUG_ON(!cprc_base);
+
+ if (idx < ARRAY_SIZE(sh5_clk_ops))
+ *ops = sh5_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S
index e640c63d581..0c8d0377d40 100644
--- a/arch/sh/kernel/cpu/sh5/entry.S
+++ b/arch/sh/kernel/cpu/sh5/entry.S
@@ -10,6 +10,7 @@
* for more details.
*/
#include <linux/errno.h>
+#include <linux/init.h>
#include <linux/sys.h>
#include <cpu/registers.h>
#include <asm/processor.h>
@@ -186,7 +187,7 @@ trap_jtable:
.rept 6
.long do_exception_error /* 0x880 - 0x920 */
.endr
- .long do_software_break_point /* 0x940 */
+ .long breakpoint_trap_handler /* 0x940 */
.long do_exception_error /* 0x960 */
.long do_single_step /* 0x980 */
@@ -334,7 +335,7 @@ tlb_miss:
/* If the fast path handler fixed the fault, just drop through quickly
to the restore code right away to return to the excepting context.
*/
- beqi/u r2, 0, tr1
+ bnei/u r2, 0, tr1
fast_tlb_miss_restore:
ld.q SP, SAVED_TR0, r2
@@ -811,27 +812,6 @@ no_underflow:
! exceptions
add SP, ZERO, r14
-#ifdef CONFIG_POOR_MANS_STRACE
- /* We've pushed all the registers now, so only r2-r4 hold anything
- * useful. Move them into callee save registers */
- or r2, ZERO, r28
- or r3, ZERO, r29
- or r4, ZERO, r30
-
- /* Preserve r2 as the event code */
- movi evt_debug, r3
- ori r3, 1, r3
- ptabs r3, tr0
-
- or SP, ZERO, r6
- getcon TRA, r5
- blink tr0, LINK
-
- or r28, ZERO, r2
- or r29, ZERO, r3
- or r30, ZERO, r4
-#endif
-
/* For syscall and debug race condition, get TRA now */
getcon TRA, r5
@@ -886,11 +866,6 @@ no_underflow:
*/
.global ret_from_irq
ret_from_irq:
-#ifdef CONFIG_POOR_MANS_STRACE
- pta evt_debug_ret_from_irq, tr0
- ori SP, 0, r2
- blink tr0, LINK
-#endif
ld.q SP, FRAME_S(FSSR), r6
shlri r6, 30, r6
andi r6, 1, r6
@@ -904,12 +879,6 @@ ret_from_irq:
ret_from_exception:
preempt_stop()
-#ifdef CONFIG_POOR_MANS_STRACE
- pta evt_debug_ret_from_exc, tr0
- ori SP, 0, r2
- blink tr0, LINK
-#endif
-
ld.q SP, FRAME_S(FSSR), r6
shlri r6, 30, r6
andi r6, 1, r6
@@ -964,7 +933,7 @@ ret_with_reschedule:
pta restore_all, tr1
- movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8
+ movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8
and r8, r7, r8
pta work_notifysig, tr0
bne r8, ZERO, tr0
@@ -1110,9 +1079,8 @@ restore_all:
*
* Kernel TLB fault handlers will get a slightly different interface.
* (r2) struct pt_regs *, original register's frame pointer
- * (r3) writeaccess, whether it's a store fault as opposed to load fault
- * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault
- * (r5) Effective Address of fault
+ * (r3) page fault error code (see asm/thread_info.h)
+ * (r4) Effective Address of fault
* (LINK) return address
* (SP) = r2
*
@@ -1123,26 +1091,25 @@ restore_all:
tlb_miss_load:
or SP, ZERO, r2
or ZERO, ZERO, r3 /* Read */
- or ZERO, ZERO, r4 /* Data */
- getcon TEA, r5
+ getcon TEA, r4
pta call_do_page_fault, tr0
beq ZERO, ZERO, tr0
tlb_miss_store:
or SP, ZERO, r2
- movi 1, r3 /* Write */
- or ZERO, ZERO, r4 /* Data */
- getcon TEA, r5
+ movi FAULT_CODE_WRITE, r3 /* Write */
+ getcon TEA, r4
pta call_do_page_fault, tr0
beq ZERO, ZERO, tr0
itlb_miss_or_IRQ:
pta its_IRQ, tr0
beqi/u r4, EVENT_INTERRUPT, tr0
+
+ /* ITLB miss */
or SP, ZERO, r2
- or ZERO, ZERO, r3 /* Read */
- movi 1, r4 /* Text */
- getcon TEA, r5
+ movi FAULT_CODE_ITLB, r3
+ getcon TEA, r4
/* Fall through */
call_do_page_fault:
@@ -1155,7 +1122,7 @@ fpu_error_or_IRQA:
pta its_IRQ, tr0
beqi/l r4, EVENT_INTERRUPT, tr0
#ifdef CONFIG_SH_FPU
- movi do_fpu_state_restore, r6
+ movi fpu_state_restore_trap_handler, r6
#else
movi do_exception_error, r6
#endif
@@ -1166,7 +1133,7 @@ fpu_error_or_IRQB:
pta its_IRQ, tr0
beqi/l r4, EVENT_INTERRUPT, tr0
#ifdef CONFIG_SH_FPU
- movi do_fpu_state_restore, r6
+ movi fpu_state_restore_trap_handler, r6
#else
movi do_exception_error, r6
#endif
@@ -1235,18 +1202,6 @@ syscall_bad:
.global syscall_ret
syscall_ret:
st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */
-
-#ifdef CONFIG_POOR_MANS_STRACE
- /* nothing useful in registers at this point */
-
- movi evt_debug2, r5
- ori r5, 1, r5
- ptabs r5, tr0
- ld.q SP, FRAME_R(9), r2
- or SP, ZERO, r3
- blink tr0, LINK
-#endif
-
ld.q SP, FRAME_S(FSPC), r2
addi r2, 4, r2 /* Move PC, being pre-execution event */
st.q SP, FRAME_S(FSPC), r2
@@ -1267,16 +1222,24 @@ ret_from_fork:
ptabs r5, tr0
blink tr0, LINK
-#ifdef CONFIG_POOR_MANS_STRACE
- /* nothing useful in registers at this point */
+ ld.q SP, FRAME_S(FSPC), r2
+ addi r2, 4, r2 /* Move PC, being pre-execution event */
+ st.q SP, FRAME_S(FSPC), r2
+ pta ret_from_syscall, tr0
+ blink tr0, ZERO
+
+.global ret_from_kernel_thread
+ret_from_kernel_thread:
- movi evt_debug2, r5
+ movi schedule_tail,r5
ori r5, 1, r5
ptabs r5, tr0
- ld.q SP, FRAME_R(9), r2
- or SP, ZERO, r3
blink tr0, LINK
-#endif
+
+ ld.q SP, FRAME_R(2), r2
+ ld.q SP, FRAME_R(3), r3
+ ptabs r3, tr0
+ blink tr0, LINK
ld.q SP, FRAME_S(FSPC), r2
addi r2, 4, r2 /* Move PC, being pre-execution event */
@@ -1284,8 +1247,6 @@ ret_from_fork:
pta ret_from_syscall, tr0
blink tr0, ZERO
-
-
syscall_allowed:
/* Use LINK to deflect the exit point, default is syscall_ret */
pta syscall_ret, tr0
@@ -1409,8 +1370,8 @@ peek_real_address_q:
r2(out) : result quadword
This is provided as a cheapskate way of manipulating device
- registers for debugging (to avoid the need to onchip_remap the debug
- module, and to avoid the need to onchip_remap the watchpoint
+ registers for debugging (to avoid the need to ioremap the debug
+ module, and to avoid the need to ioremap the watchpoint
controller in a way that identity maps sufficient bits to avoid the
SH5-101 cut2 silicon defect).
@@ -1458,8 +1419,8 @@ poke_real_address_q:
r3 : quadword value to write.
This is provided as a cheapskate way of manipulating device
- registers for debugging (to avoid the need to onchip_remap the debug
- module, and to avoid the need to onchip_remap the watchpoint
+ registers for debugging (to avoid the need to ioremap the debug
+ module, and to avoid the need to ioremap the watchpoint
controller in a way that identity maps sufficient bits to avoid the
SH5-101 cut2 silicon defect).
@@ -1627,86 +1588,6 @@ ___clear_user_exit:
#endif /* CONFIG_MMU */
/*
- * int __strncpy_from_user(unsigned long __dest, unsigned long __src,
- * int __count)
- *
- * Inputs:
- * (r2) target address
- * (r3) source address
- * (r4) maximum size in bytes
- *
- * Ouputs:
- * (*r2) copied data
- * (r2) -EFAULT (in case of faulting)
- * copied data (otherwise)
- */
- .global __strncpy_from_user
-__strncpy_from_user:
- pta ___strncpy_from_user1, tr0
- pta ___strncpy_from_user_done, tr1
- or r4, ZERO, r5 /* r5 = original count */
- beq/u r4, r63, tr1 /* early exit if r4==0 */
- movi -(EFAULT), r6 /* r6 = reply, no real fixup */
- or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
-
-___strncpy_from_user1:
- ld.b r3, 0, r7 /* Fault address: only in reading */
- st.b r2, 0, r7
- addi r2, 1, r2
- addi r3, 1, r3
- beq/u ZERO, r7, tr1
- addi r4, -1, r4 /* return real number of copied bytes */
- bne/l ZERO, r4, tr0
-
-___strncpy_from_user_done:
- sub r5, r4, r6 /* If done, return copied */
-
-___strncpy_from_user_exit:
- or r6, ZERO, r2
- ptabs LINK, tr0
- blink tr0, ZERO
-
-/*
- * extern long __strnlen_user(const char *__s, long __n)
- *
- * Inputs:
- * (r2) source address
- * (r3) source size in bytes
- *
- * Ouputs:
- * (r2) -EFAULT (in case of faulting)
- * string length (otherwise)
- */
- .global __strnlen_user
-__strnlen_user:
- pta ___strnlen_user_set_reply, tr0
- pta ___strnlen_user1, tr1
- or ZERO, ZERO, r5 /* r5 = counter */
- movi -(EFAULT), r6 /* r6 = reply, no real fixup */
- or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */
- beq r3, ZERO, tr0
-
-___strnlen_user1:
- ldx.b r2, r5, r7 /* Fault address: only in reading */
- addi r3, -1, r3 /* No real fixup */
- addi r5, 1, r5
- beq r3, ZERO, tr0
- bne r7, ZERO, tr1
-! The line below used to be active. This meant led to a junk byte lying between each pair
-! of entries in the argv & envp structures in memory. Whilst the program saw the right data
-! via the argv and envp arguments to main, it meant the 'flat' representation visible through
-! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example.
-! addi r5, 1, r5 /* Include '\0' */
-
-___strnlen_user_set_reply:
- or r5, ZERO, r6 /* If done, return counter */
-
-___strnlen_user_exit:
- or r6, ZERO, r2
- ptabs LINK, tr0
- blink tr0, ZERO
-
-/*
* extern long __get_user_asm_?(void *val, long addr)
*
* Inputs:
@@ -2040,8 +1921,6 @@ asm_uaccess_start:
.long ___copy_user2, ___copy_user_exit
.long ___clear_user1, ___clear_user_exit
#endif
- .long ___strncpy_from_user1, ___strncpy_from_user_exit
- .long ___strnlen_user1, ___strnlen_user_exit
.long ___get_user_asm_b1, ___get_user_asm_b_exit
.long ___get_user_asm_w1, ___get_user_asm_w_exit
.long ___get_user_asm_l1, ___get_user_asm_l_exit
@@ -2058,10 +1937,10 @@ asm_uaccess_end:
/*
- * --- .text.init Section
+ * --- .init.text Section
*/
- .section .text.init, "ax"
+ __INIT
/*
* void trap_init (void)
diff --git a/arch/sh/kernel/cpu/sh5/fpu.c b/arch/sh/kernel/cpu/sh5/fpu.c
index dd4f51ffb50..9f8713aa718 100644
--- a/arch/sh/kernel/cpu/sh5/fpu.c
+++ b/arch/sh/kernel/cpu/sh5/fpu.c
@@ -15,26 +15,8 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <asm/processor.h>
-#include <asm/user.h>
-#include <asm/io.h>
-#include <asm/fpu.h>
-/*
- * Initially load the FPU with signalling NANS. This bit pattern
- * has the property that no matter whether considered as single or as
- * double precision, it still represents a signalling NAN.
- */
-#define sNAN64 0xFFFFFFFFFFFFFFFFULL
-#define sNAN32 0xFFFFFFFFUL
-
-static union sh_fpu_union init_fpuregs = {
- .hard = {
- .fp_regs = { [0 ... 63] = sNAN32 },
- .fpscr = FPSCR_INIT
- }
-};
-
-void save_fpu(struct task_struct *tsk, struct pt_regs *regs)
+void save_fpu(struct task_struct *tsk)
{
asm volatile("fst.p %0, (0*8), fp0\n\t"
"fst.p %0, (1*8), fp2\n\t"
@@ -72,12 +54,11 @@ void save_fpu(struct task_struct *tsk, struct pt_regs *regs)
"fgetscr fr63\n\t"
"fst.s %0, (32*8), fr63\n\t"
: /* no output */
- : "r" (&tsk->thread.fpu.hard)
+ : "r" (&tsk->thread.xstate->hardfpu)
: "memory");
}
-static inline void
-fpload(struct sh_fpu_hard_struct *fpregs)
+void restore_fpu(struct task_struct *tsk)
{
asm volatile("fld.p %0, (0*8), fp0\n\t"
"fld.p %0, (1*8), fp2\n\t"
@@ -116,52 +97,15 @@ fpload(struct sh_fpu_hard_struct *fpregs)
"fld.p %0, (31*8), fp62\n\t"
: /* no output */
- : "r" (fpregs) );
-}
-
-void fpinit(struct sh_fpu_hard_struct *fpregs)
-{
- *fpregs = init_fpuregs.hard;
+ : "r" (&tsk->thread.xstate->hardfpu)
+ : "memory");
}
-asmlinkage void
-do_fpu_error(unsigned long ex, struct pt_regs *regs)
+asmlinkage void do_fpu_error(unsigned long ex, struct pt_regs *regs)
{
struct task_struct *tsk = current;
regs->pc += 4;
- tsk->thread.trap_no = 11;
- tsk->thread.error_code = 0;
force_sig(SIGFPE, tsk);
}
-
-
-asmlinkage void
-do_fpu_state_restore(unsigned long ex, struct pt_regs *regs)
-{
- void die(const char *str, struct pt_regs *regs, long err);
-
- if (! user_mode(regs))
- die("FPU used in kernel", regs, ex);
-
- regs->sr &= ~SR_FD;
-
- if (last_task_used_math == current)
- return;
-
- enable_fpu();
- if (last_task_used_math != NULL)
- /* Other processes fpu state, save away */
- save_fpu(last_task_used_math, regs);
-
- last_task_used_math = current;
- if (used_math()) {
- fpload(&current->thread.fpu.hard);
- } else {
- /* First time FPU user. */
- fpload(&init_fpuregs.hard);
- set_used_math();
- }
- disable_fpu();
-}
diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c
index 92ad844b5c1..eca427c2f2f 100644
--- a/arch/sh/kernel/cpu/sh5/probe.c
+++ b/arch/sh/kernel/cpu/sh5/probe.c
@@ -17,7 +17,7 @@
#include <asm/cache.h>
#include <asm/tlb.h>
-int __init detect_cpu_and_cache_system(void)
+void cpu_probe(void)
{
unsigned long long cir;
@@ -34,6 +34,8 @@ int __init detect_cpu_and_cache_system(void)
/* CPU.VCR aliased at CIR address on SH5-101 */
boot_cpu_data.type = CPU_SH5_101;
+ boot_cpu_data.family = CPU_FAMILY_SH5;
+
/*
* First, setup some sane values for the I-cache.
*/
@@ -70,6 +72,4 @@ int __init detect_cpu_and_cache_system(void)
/* Setup some I/D TLB defaults */
sh64_tlb_init();
-
- return 0;
}
diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c
new file mode 100644
index 00000000000..1bf0b2cf665
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c
@@ -0,0 +1,123 @@
+/*
+ * SH5-101/SH5-103 CPU Setup
+ *
+ * Copyright (C) 2009 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/serial_sci.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/sh_timer.h>
+#include <asm/addrspace.h>
+
+static struct plat_sci_port scif0_platform_data = {
+ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP,
+ .scscr = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+ .type = PORT_SCIF,
+};
+
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(PHYS_PERIPHERAL_BLOCK + 0x01030000, 0x100),
+ DEFINE_RES_IRQ(39),
+ DEFINE_RES_IRQ(40),
+ DEFINE_RES_IRQ(42),
+};
+
+static struct platform_device scif0_device = {
+ .name = "sh-sci",
+ .id = 0,
+ .resource = scif0_resources,
+ .num_resources = ARRAY_SIZE(scif0_resources),
+ .dev = {
+ .platform_data = &scif0_platform_data,
+ },
+};
+
+static struct resource rtc_resources[] = {
+ [0] = {
+ .start = PHYS_PERIPHERAL_BLOCK + 0x01040000,
+ .end = PHYS_PERIPHERAL_BLOCK + 0x01040000 + 0x58 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ /* Period IRQ */
+ .start = IRQ_PRI,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* Carry IRQ */
+ .start = IRQ_CUI,
+ .flags = IORESOURCE_IRQ,
+ },
+ [3] = {
+ /* Alarm IRQ */
+ .start = IRQ_ATI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtc_device = {
+ .name = "sh-rtc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+ .resource = rtc_resources,
+};
+
+#define TMU_BLOCK_OFF 0x01020000
+#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
+
+static struct sh_timer_config tmu0_platform_data = {
+ .channels_mask = 7,
+};
+
+static struct resource tmu0_resources[] = {
+ DEFINE_RES_MEM(TMU_BASE, 0x30),
+ DEFINE_RES_IRQ(IRQ_TUNI0),
+ DEFINE_RES_IRQ(IRQ_TUNI1),
+ DEFINE_RES_IRQ(IRQ_TUNI2),
+};
+
+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 platform_device *sh5_early_devices[] __initdata = {
+ &scif0_device,
+ &tmu0_device,
+};
+
+static struct platform_device *sh5_devices[] __initdata = {
+ &rtc_device,
+};
+
+static int __init sh5_devices_setup(void)
+{
+ int ret;
+
+ ret = platform_add_devices(sh5_early_devices,
+ ARRAY_SIZE(sh5_early_devices));
+ if (unlikely(ret != 0))
+ return ret;
+
+ return platform_add_devices(sh5_devices,
+ ARRAY_SIZE(sh5_devices));
+}
+arch_initcall(sh5_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+ early_platform_add_devices(sh5_early_devices,
+ ARRAY_SIZE(sh5_early_devices));
+}
diff --git a/arch/sh/kernel/cpu/sh5/unwind.c b/arch/sh/kernel/cpu/sh5/unwind.c
index b205b25eaf4..10aed41757f 100644
--- a/arch/sh/kernel/cpu/sh5/unwind.c
+++ b/arch/sh/kernel/cpu/sh5/unwind.c
@@ -16,6 +16,8 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/io.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
static u8 regcache[63];
@@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
return 0;
}
-/* Don't put this on the stack since we'll want to call sh64_unwind
- * when we're close to underflowing the stack anyway. */
+/*
+ * Don't put this on the stack since we'll want to call in to
+ * sh64_unwinder_dump() when we're close to underflowing the stack
+ * anyway.
+ */
static struct pt_regs here_regs;
extern const char syscall_ret;
@@ -208,17 +213,19 @@ extern const char ret_from_syscall;
extern const char ret_from_exception;
extern const char ret_from_irq;
-static void sh64_unwind_inner(struct pt_regs *regs);
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+ void *data, struct pt_regs *regs);
-static void unwind_nested (unsigned long pc, unsigned long fp)
+static inline void unwind_nested(const struct stacktrace_ops *ops, void *data,
+ unsigned long pc, unsigned long fp)
{
if ((fp >= __MEMORY_START) &&
- ((fp & 7) == 0)) {
- sh64_unwind_inner((struct pt_regs *) fp);
- }
+ ((fp & 7) == 0))
+ sh64_unwind_inner(ops, data, (struct pt_regs *)fp);
}
-static void sh64_unwind_inner(struct pt_regs *regs)
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+ void *data, struct pt_regs *regs)
{
unsigned long pc, fp;
int ofs = 0;
@@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs)
int cond;
unsigned long next_fp, next_pc;
- if (pc == ((unsigned long) &syscall_ret & ~1)) {
+ if (pc == ((unsigned long)&syscall_ret & ~1)) {
printk("SYSCALL\n");
- unwind_nested(pc,fp);
+ unwind_nested(ops, data, pc, fp);
return;
}
- if (pc == ((unsigned long) &ret_from_syscall & ~1)) {
+ if (pc == ((unsigned long)&ret_from_syscall & ~1)) {
printk("SYSCALL (PREEMPTED)\n");
- unwind_nested(pc,fp);
+ unwind_nested(ops, data, pc, fp);
return;
}
/* In this case, the PC is discovered by lookup_prev_stack_frame but
it has 4 taken off it to look like the 'caller' */
- if (pc == ((unsigned long) &ret_from_exception & ~1)) {
+ if (pc == ((unsigned long)&ret_from_exception & ~1)) {
printk("EXCEPTION\n");
- unwind_nested(pc,fp);
+ unwind_nested(ops, data, pc, fp);
return;
}
- if (pc == ((unsigned long) &ret_from_irq & ~1)) {
+ if (pc == ((unsigned long)&ret_from_irq & ~1)) {
printk("IRQ\n");
- unwind_nested(pc,fp);
+ unwind_nested(ops, data, pc, fp);
return;
}
@@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs)
pc -= ofs;
- printk("[<%08lx>] ", pc);
- print_symbol("%s\n", pc);
+ ops->address(data, pc, 1);
if (first_pass) {
/* If the innermost frame is a leaf function, it's
@@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
}
printk("\n");
-
}
-void sh64_unwind(struct pt_regs *regs)
+static void sh64_unwinder_dump(struct task_struct *task,
+ struct pt_regs *regs,
+ unsigned long *sp,
+ const struct stacktrace_ops *ops,
+ void *data)
{
if (!regs) {
/*
@@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs)
);
}
- printk("\nCall Trace:\n");
- sh64_unwind_inner(regs);
+ sh64_unwind_inner(ops, data, regs);
}
+static struct unwinder sh64_unwinder = {
+ .name = "sh64-unwinder",
+ .dump = sh64_unwinder_dump,
+ .rating = 150,
+};
+
+static int __init sh64_unwinder_init(void)
+{
+ return unwinder_register(&sh64_unwinder);
+}
+early_initcall(sh64_unwinder_init);
diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile
new file mode 100644
index 00000000000..e8a5111e848
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Linux/SuperH SH-Mobile backends.
+#
+
+# Power Management & Sleep mode
+obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
new file mode 100644
index 00000000000..e3abfd4277e
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -0,0 +1,101 @@
+/*
+ * arch/sh/kernel/cpu/shmobile/cpuidle.c
+ *
+ * Cpuidle support code for SuperH Mobile
+ *
+ * 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
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <linux/cpuidle.h>
+#include <linux/export.h>
+#include <asm/suspend.h>
+#include <asm/uaccess.h>
+
+static unsigned long cpuidle_mode[] = {
+ SUSP_SH_SLEEP, /* regular sleep mode */
+ SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */
+ SUSP_SH_STANDBY | SUSP_SH_SF, /* software standby mode + self refresh */
+};
+
+static int cpuidle_sleep_enter(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv,
+ int index)
+{
+ unsigned long allowed_mode = SUSP_SH_SLEEP;
+ int requested_state = index;
+ int allowed_state;
+ int k;
+
+ /* convert allowed mode to allowed state */
+ for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--)
+ if (cpuidle_mode[k] == allowed_mode)
+ break;
+
+ allowed_state = k;
+
+ /* take the following into account for sleep mode selection:
+ * - allowed_state: best mode allowed by hardware (clock deps)
+ * - requested_state: best mode allowed by software (latencies)
+ */
+ k = min_t(int, allowed_state, requested_state);
+
+ sh_mobile_call_standby(cpuidle_mode[k]);
+
+ return k;
+}
+
+static struct cpuidle_driver cpuidle_driver = {
+ .name = "sh_idle",
+ .owner = THIS_MODULE,
+ .states = {
+ {
+ .exit_latency = 1,
+ .target_residency = 1 * 2,
+ .power_usage = 3,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .enter = cpuidle_sleep_enter,
+ .name = "C1",
+ .desc = "SuperH Sleep Mode",
+ },
+ {
+ .exit_latency = 100,
+ .target_residency = 1 * 2,
+ .power_usage = 1,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .enter = cpuidle_sleep_enter,
+ .name = "C2",
+ .desc = "SuperH Sleep Mode [SF]",
+ .disabled = true,
+ },
+ {
+ .exit_latency = 2300,
+ .target_residency = 1 * 2,
+ .power_usage = 1,
+ .flags = CPUIDLE_FLAG_TIME_VALID,
+ .enter = cpuidle_sleep_enter,
+ .name = "C3",
+ .desc = "SuperH Mobile Standby Mode [SF]",
+ .disabled = true,
+ },
+ },
+ .safe_state_index = 0,
+ .state_count = 3,
+};
+
+int __init sh_mobile_setup_cpuidle(void)
+{
+ if (sh_mobile_sleep_supported & SUSP_SH_SF)
+ cpuidle_driver.states[1].disabled = false;
+
+ if (sh_mobile_sleep_supported & SUSP_SH_STANDBY)
+ cpuidle_driver.states[2].disabled = false;
+
+ return cpuidle_register(&cpuidle_driver, NULL);
+}
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
new file mode 100644
index 00000000000..ac37b7234f8
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -0,0 +1,156 @@
+/*
+ * arch/sh/kernel/cpu/shmobile/pm.c
+ *
+ * Power management support code for SuperH Mobile
+ *
+ * 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
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/suspend.h>
+#include <asm/suspend.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/bl_bit.h>
+
+/*
+ * Notifier lists for pre/post sleep notification
+ */
+ATOMIC_NOTIFIER_HEAD(sh_mobile_pre_sleep_notifier_list);
+ATOMIC_NOTIFIER_HEAD(sh_mobile_post_sleep_notifier_list);
+
+/*
+ * Sleep modes available on SuperH Mobile:
+ *
+ * Sleep mode is just plain "sleep" instruction
+ * Sleep Self-Refresh mode is above plus RAM put in Self-Refresh
+ * Standby Self-Refresh mode is above plus stopped clocks
+ */
+#define SUSP_MODE_SLEEP (SUSP_SH_SLEEP)
+#define SUSP_MODE_SLEEP_SF (SUSP_SH_SLEEP | SUSP_SH_SF)
+#define SUSP_MODE_STANDBY_SF (SUSP_SH_STANDBY | SUSP_SH_SF)
+#define SUSP_MODE_RSTANDBY_SF \
+ (SUSP_SH_RSTANDBY | SUSP_SH_MMU | SUSP_SH_REGS | SUSP_SH_SF)
+ /*
+ * U-standby mode is unsupported since it needs bootloader hacks
+ */
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7724
+#define RAM_BASE 0xfd800000 /* RSMEM */
+#else
+#define RAM_BASE 0xe5200000 /* ILRAM */
+#endif
+
+void sh_mobile_call_standby(unsigned long mode)
+{
+ void *onchip_mem = (void *)RAM_BASE;
+ struct sh_sleep_data *sdp = onchip_mem;
+ void (*standby_onchip_mem)(unsigned long, unsigned long);
+
+ /* code located directly after data structure */
+ standby_onchip_mem = (void *)(sdp + 1);
+
+ atomic_notifier_call_chain(&sh_mobile_pre_sleep_notifier_list,
+ mode, NULL);
+
+ /* flush the caches if MMU flag is set */
+ if (mode & SUSP_SH_MMU)
+ flush_cache_all();
+
+ /* Let assembly snippet in on-chip memory handle the rest */
+ standby_onchip_mem(mode, RAM_BASE);
+
+ atomic_notifier_call_chain(&sh_mobile_post_sleep_notifier_list,
+ mode, NULL);
+}
+
+extern char sh_mobile_sleep_enter_start;
+extern char sh_mobile_sleep_enter_end;
+
+extern char sh_mobile_sleep_resume_start;
+extern char sh_mobile_sleep_resume_end;
+
+unsigned long sh_mobile_sleep_supported = SUSP_SH_SLEEP;
+
+void sh_mobile_register_self_refresh(unsigned long flags,
+ void *pre_start, void *pre_end,
+ void *post_start, void *post_end)
+{
+ void *onchip_mem = (void *)RAM_BASE;
+ void *vp;
+ struct sh_sleep_data *sdp;
+ int n;
+
+ /* part 0: data area */
+ sdp = onchip_mem;
+ sdp->addr.stbcr = 0xa4150020; /* STBCR */
+ sdp->addr.bar = 0xa4150040; /* BAR */
+ sdp->addr.pteh = 0xff000000; /* PTEH */
+ sdp->addr.ptel = 0xff000004; /* PTEL */
+ sdp->addr.ttb = 0xff000008; /* TTB */
+ sdp->addr.tea = 0xff00000c; /* TEA */
+ sdp->addr.mmucr = 0xff000010; /* MMUCR */
+ sdp->addr.ptea = 0xff000034; /* PTEA */
+ sdp->addr.pascr = 0xff000070; /* PASCR */
+ sdp->addr.irmcr = 0xff000078; /* IRMCR */
+ sdp->addr.ccr = 0xff00001c; /* CCR */
+ sdp->addr.ramcr = 0xff000074; /* RAMCR */
+ vp = sdp + 1;
+
+ /* part 1: common code to enter sleep mode */
+ n = &sh_mobile_sleep_enter_end - &sh_mobile_sleep_enter_start;
+ memcpy(vp, &sh_mobile_sleep_enter_start, n);
+ vp += roundup(n, 4);
+
+ /* part 2: board specific code to enter self-refresh mode */
+ n = pre_end - pre_start;
+ memcpy(vp, pre_start, n);
+ sdp->sf_pre = (unsigned long)vp;
+ vp += roundup(n, 4);
+
+ /* part 3: board specific code to resume from self-refresh mode */
+ n = post_end - post_start;
+ memcpy(vp, post_start, n);
+ sdp->sf_post = (unsigned long)vp;
+ vp += roundup(n, 4);
+
+ /* part 4: common code to resume from sleep mode */
+ WARN_ON(vp > (onchip_mem + 0x600));
+ vp = onchip_mem + 0x600; /* located at interrupt vector */
+ n = &sh_mobile_sleep_resume_end - &sh_mobile_sleep_resume_start;
+ memcpy(vp, &sh_mobile_sleep_resume_start, n);
+ sdp->resume = (unsigned long)vp;
+
+ sh_mobile_sleep_supported |= flags;
+}
+
+static int sh_pm_enter(suspend_state_t state)
+{
+ if (!(sh_mobile_sleep_supported & SUSP_MODE_STANDBY_SF))
+ return -ENXIO;
+
+ local_irq_disable();
+ set_bl_bit();
+ sh_mobile_call_standby(SUSP_MODE_STANDBY_SF);
+ local_irq_disable();
+ clear_bl_bit();
+ return 0;
+}
+
+static const struct platform_suspend_ops sh_pm_ops = {
+ .enter = sh_pm_enter,
+ .valid = suspend_valid_only_mem,
+};
+
+static int __init sh_pm_init(void)
+{
+ suspend_set_ops(&sh_pm_ops);
+ return sh_mobile_setup_cpuidle();
+}
+
+late_initcall(sh_pm_init);
diff --git a/arch/sh/kernel/cpu/shmobile/sleep.S b/arch/sh/kernel/cpu/shmobile/sleep.S
new file mode 100644
index 00000000000..e6aac65f575
--- /dev/null
+++ b/arch/sh/kernel/cpu/shmobile/sleep.S
@@ -0,0 +1,405 @@
+/*
+ * arch/sh/kernel/cpu/sh4a/sleep-sh_mobile.S
+ *
+ * Sleep mode and Standby modes support for SuperH Mobile
+ *
+ * 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
+ * for more details.
+ */
+
+#include <linux/sys.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <asm/asm-offsets.h>
+#include <asm/suspend.h>
+
+/*
+ * Kernel mode register usage, see entry.S:
+ * k0 scratch
+ * k1 scratch
+ */
+#define k0 r0
+#define k1 r1
+
+/* manage self-refresh and enter standby mode. must be self-contained.
+ * this code will be copied to on-chip memory and executed from there.
+ */
+ .balign 4
+ENTRY(sh_mobile_sleep_enter_start)
+
+ /* save mode flags */
+ mov.l r4, @(SH_SLEEP_MODE, r5)
+
+ /* save original vbr */
+ stc vbr, r0
+ mov.l r0, @(SH_SLEEP_VBR, r5)
+
+ /* point vbr to our on-chip memory page */
+ ldc r5, vbr
+
+ /* save return address */
+ sts pr, r0
+ mov.l r0, @(SH_SLEEP_SPC, r5)
+
+ /* save sr */
+ stc sr, r0
+ mov.l r0, @(SH_SLEEP_SR, r5)
+
+ /* save general purpose registers to stack if needed */
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_REGS, r0
+ bt skip_regs_save
+
+ sts.l pr, @-r15
+ mov.l r14, @-r15
+ mov.l r13, @-r15
+ mov.l r12, @-r15
+ mov.l r11, @-r15
+ mov.l r10, @-r15
+ mov.l r9, @-r15
+ mov.l r8, @-r15
+
+ /* make sure bank0 is selected, save low registers */
+ mov.l rb_bit, r9
+ not r9, r9
+ bsr set_sr
+ mov #0, r10
+
+ bsr save_low_regs
+ nop
+
+ /* switch to bank 1, save low registers */
+ mov.l rb_bit, r10
+ bsr set_sr
+ mov #-1, r9
+
+ bsr save_low_regs
+ nop
+
+ /* switch back to bank 0 */
+ mov.l rb_bit, r9
+ not r9, r9
+ bsr set_sr
+ mov #0, r10
+
+skip_regs_save:
+
+ /* save sp, also set to internal ram */
+ mov.l r15, @(SH_SLEEP_SP, r5)
+ mov r5, r15
+
+ /* save stbcr */
+ bsr save_register
+ mov #SH_SLEEP_REG_STBCR, r0
+
+ /* save mmu and cache context if needed */
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_MMU, r0
+ bt skip_mmu_save_disable
+
+ /* save mmu state */
+ bsr save_register
+ mov #SH_SLEEP_REG_PTEH, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_PTEL, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_TTB, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_TEA, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_MMUCR, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_PTEA, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_PASCR, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_IRMCR, r0
+
+ /* invalidate TLBs and disable the MMU */
+ bsr get_register
+ mov #SH_SLEEP_REG_MMUCR, r0
+ mov #4, r1
+ mov.l r1, @r0
+ icbi @r0
+
+ /* save cache registers and disable caches */
+ bsr save_register
+ mov #SH_SLEEP_REG_CCR, r0
+
+ bsr save_register
+ mov #SH_SLEEP_REG_RAMCR, r0
+
+ bsr get_register
+ mov #SH_SLEEP_REG_CCR, r0
+ mov #0, r1
+ mov.l r1, @r0
+ icbi @r0
+
+skip_mmu_save_disable:
+ /* call self-refresh entering code if needed */
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_SF, r0
+ bt skip_set_sf
+
+ mov.l @(SH_SLEEP_SF_PRE, r5), r0
+ jsr @r0
+ nop
+
+skip_set_sf:
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_STANDBY, r0
+ bt test_rstandby
+
+ /* set mode to "software standby mode" */
+ bra do_sleep
+ mov #0x80, r1
+
+test_rstandby:
+ tst #SUSP_SH_RSTANDBY, r0
+ bt test_ustandby
+
+ /* setup BAR register */
+ bsr get_register
+ mov #SH_SLEEP_REG_BAR, r0
+ mov.l @(SH_SLEEP_RESUME, r5), r1
+ mov.l r1, @r0
+
+ /* set mode to "r-standby mode" */
+ bra do_sleep
+ mov #0x20, r1
+
+test_ustandby:
+ tst #SUSP_SH_USTANDBY, r0
+ bt force_sleep
+
+ /* set mode to "u-standby mode" */
+ bra do_sleep
+ mov #0x10, r1
+
+force_sleep:
+
+ /* set mode to "sleep mode" */
+ mov #0x00, r1
+
+do_sleep:
+ /* setup and enter selected standby mode */
+ bsr get_register
+ mov #SH_SLEEP_REG_STBCR, r0
+ mov.l r1, @r0
+again:
+ sleep
+ bra again
+ nop
+
+save_register:
+ add #SH_SLEEP_BASE_ADDR, r0
+ mov.l @(r0, r5), r1
+ add #-SH_SLEEP_BASE_ADDR, r0
+ mov.l @r1, r1
+ add #SH_SLEEP_BASE_DATA, r0
+ mov.l r1, @(r0, r5)
+ add #-SH_SLEEP_BASE_DATA, r0
+ rts
+ nop
+
+get_register:
+ add #SH_SLEEP_BASE_ADDR, r0
+ mov.l @(r0, r5), r0
+ rts
+ nop
+
+set_sr:
+ stc sr, r8
+ and r9, r8
+ or r10, r8
+ ldc r8, sr
+ rts
+ nop
+
+save_low_regs:
+ mov.l r7, @-r15
+ mov.l r6, @-r15
+ mov.l r5, @-r15
+ mov.l r4, @-r15
+ mov.l r3, @-r15
+ mov.l r2, @-r15
+ mov.l r1, @-r15
+ rts
+ mov.l r0, @-r15
+
+ .balign 4
+rb_bit: .long 0x20000000 ! RB=1
+
+ENTRY(sh_mobile_sleep_enter_end)
+
+ .balign 4
+ENTRY(sh_mobile_sleep_resume_start)
+
+ /* figure out start address */
+ bsr 0f
+ nop
+0:
+ sts pr, k1
+ mov.l 1f, k0
+ and k0, k1
+
+ /* store pointer to data area in VBR */
+ ldc k1, vbr
+
+ /* setup sr with saved sr */
+ mov.l @(SH_SLEEP_SR, k1), k0
+ ldc k0, sr
+
+ /* now: user register set! */
+ stc vbr, r5
+
+ /* setup spc with return address to c code */
+ mov.l @(SH_SLEEP_SPC, r5), r0
+ ldc r0, spc
+
+ /* restore vbr */
+ mov.l @(SH_SLEEP_VBR, r5), r0
+ ldc r0, vbr
+
+ /* setup ssr with saved sr */
+ mov.l @(SH_SLEEP_SR, r5), r0
+ ldc r0, ssr
+
+ /* restore sp */
+ mov.l @(SH_SLEEP_SP, r5), r15
+
+ /* restore sleep mode register */
+ bsr restore_register
+ mov #SH_SLEEP_REG_STBCR, r0
+
+ /* call self-refresh resume code if needed */
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_SF, r0
+ bt skip_restore_sf
+
+ mov.l @(SH_SLEEP_SF_POST, r5), r0
+ jsr @r0
+ nop
+
+skip_restore_sf:
+ /* restore mmu and cache state if needed */
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_MMU, r0
+ bt skip_restore_mmu
+
+ /* restore mmu state */
+ bsr restore_register
+ mov #SH_SLEEP_REG_PTEH, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_PTEL, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_TTB, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_TEA, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_PTEA, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_PASCR, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_IRMCR, r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_MMUCR, r0
+ icbi @r0
+
+ /* restore cache settings */
+ bsr restore_register
+ mov #SH_SLEEP_REG_RAMCR, r0
+ icbi @r0
+
+ bsr restore_register
+ mov #SH_SLEEP_REG_CCR, r0
+ icbi @r0
+
+skip_restore_mmu:
+
+ /* restore general purpose registers if needed */
+ mov.l @(SH_SLEEP_MODE, r5), r0
+ tst #SUSP_SH_REGS, r0
+ bt skip_restore_regs
+
+ /* switch to bank 1, restore low registers */
+ mov.l _rb_bit, r10
+ bsr _set_sr
+ mov #-1, r9
+
+ bsr restore_low_regs
+ nop
+
+ /* switch to bank0, restore low registers */
+ mov.l _rb_bit, r9
+ not r9, r9
+ bsr _set_sr
+ mov #0, r10
+
+ bsr restore_low_regs
+ nop
+
+ /* restore the rest of the registers */
+ mov.l @r15+, r8
+ mov.l @r15+, r9
+ mov.l @r15+, r10
+ mov.l @r15+, r11
+ mov.l @r15+, r12
+ mov.l @r15+, r13
+ mov.l @r15+, r14
+ lds.l @r15+, pr
+
+skip_restore_regs:
+ rte
+ nop
+
+restore_register:
+ add #SH_SLEEP_BASE_DATA, r0
+ mov.l @(r0, r5), r1
+ add #-SH_SLEEP_BASE_DATA, r0
+ add #SH_SLEEP_BASE_ADDR, r0
+ mov.l @(r0, r5), r0
+ mov.l r1, @r0
+ rts
+ nop
+
+_set_sr:
+ stc sr, r8
+ and r9, r8
+ or r10, r8
+ ldc r8, sr
+ rts
+ nop
+
+restore_low_regs:
+ mov.l @r15+, r0
+ mov.l @r15+, r1
+ mov.l @r15+, r2
+ mov.l @r15+, r3
+ mov.l @r15+, r4
+ mov.l @r15+, r5
+ mov.l @r15+, r6
+ rts
+ mov.l @r15+, r7
+
+ .balign 4
+_rb_bit: .long 0x20000000 ! RB=1
+1: .long ~0x7ff
+ENTRY(sh_mobile_sleep_resume_end)
diff --git a/arch/sh/kernel/cpu/ubc.S b/arch/sh/kernel/cpu/ubc.S
deleted file mode 100644
index 81923079fa1..00000000000
--- a/arch/sh/kernel/cpu/ubc.S
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * arch/sh/kernel/cpu/ubc.S
- *
- * Set of management routines for the User Break Controller (UBC)
- *
- * Copyright (C) 2002 Paul Mundt
- *
- * 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.
- */
-#include <linux/linkage.h>
-#include <asm/ubc.h>
-
-#define STBCR2 0xffc00010
-
-ENTRY(ubc_sleep)
- mov #0, r0
-
- mov.l 1f, r1 ! Zero out UBC_BBRA ..
- mov.w r0, @r1
-
- mov.l 2f, r1 ! .. same for BBRB ..
- mov.w r0, @r1
-
- mov.l 3f, r1 ! .. and again for BRCR.
- mov.w r0, @r1
-
- mov.w @r1, r0 ! Dummy read BRCR
-
- mov.l 4f, r1 ! Set MSTP5 in STBCR2
- mov.b @r1, r0
- or #0x01, r0
- mov.b r0, @r1
-
- mov.b @r1, r0 ! Two dummy reads ..
- mov.b @r1, r0
-
- rts
- nop
-
-ENTRY(ubc_wakeup)
- mov.l 4f, r1 ! Clear MSTP5
- mov.b @r1, r0
- and #0xfe, r0
- mov.b r0, @r1
-
- mov.b @r1, r0 ! Two more dummy reads ..
- mov.b @r1, r0
-
- rts
- nop
-
-1: .long UBC_BBRA
-2: .long UBC_BBRB
-3: .long UBC_BRCR
-4: .long STBCR2
-