aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/cpu/sh3
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/cpu/sh3')
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile26
-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.S485
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S44
-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.c71
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7705.c172
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh770x.c231
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7710.c180
-rw-r--r--arch/sh/kernel/cpu/sh3/setup-sh7720.c240
-rw-r--r--arch/sh/kernel/cpu/sh3/swsusp.S147
20 files changed, 1158 insertions, 783 deletions
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index 3ae4d9111f1..d3634ae7b71 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -2,18 +2,20 @@
# Makefile for the Linux/SuperH SH-3 backends.
#
-obj-y := ex.o probe.o entry.o
+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 4004073f98c..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
@@ -14,8 +14,10 @@
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
#include <asm/unistd.h>
-#include <asm/cpu/mmu_context.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 11b6d9c6eda..99b4d020179 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -4,7 +4,7 @@
* The SH-3 and SH-4 exception vector table.
* Copyright (C) 1999, 2000, 2002 Niibe Yutaka
- * Copyright (C) 2003 - 2006 Paul Mundt
+ * Copyright (C) 2003 - 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
@@ -12,13 +12,30 @@
*/
#include <linux/linkage.h>
+#if !defined(CONFIG_MMU)
+#define tlb_miss_load exception_error
+#define tlb_miss_store exception_error
+#define initial_page_write exception_error
+#define tlb_protection_violation_load exception_error
+#define tlb_protection_violation_store exception_error
+#define address_error_load exception_error
+#define address_error_store exception_error
+#endif
+
+#if !defined(CONFIG_SH_FPU)
+#define fpu_error_trap_handler exception_error
+#endif
+
+#if !defined(CONFIG_KGDB)
+#define kgdb_handle_exception exception_error
+#endif
+
.align 2
.data
ENTRY(exception_handling_table)
.long exception_error /* 000 */
.long exception_error
-#if defined(CONFIG_MMU)
.long tlb_miss_load /* 040 */
.long tlb_miss_store
.long initial_page_write
@@ -26,32 +43,13 @@ ENTRY(exception_handling_table)
.long tlb_protection_violation_store
.long address_error_load
.long address_error_store /* 100 */
-#else
- .long exception_error ! tlb miss load /* 040 */
- .long exception_error ! tlb miss store
- .long exception_error ! initial page write
- .long exception_error ! tlb prot violation load
- .long exception_error ! tlb prot violation store
- .long exception_error ! address error load
- .long exception_error ! address error store /* 100 */
-#endif
-#if defined(CONFIG_SH_FPU)
.long fpu_error_trap_handler /* 120 */
-#else
- .long exception_error /* 120 */
-#endif
.long exception_error /* 140 */
.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)
-#if defined (CONFIG_KGDB_NMI)
- .long kgdb_handle_exception /* 1C0 */ ! Allow trap to debugger
-#else
- .long exception_none /* 1C0 */ ! Not implemented yet
-#endif
-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
new file mode 100644
index 00000000000..53be70b9811
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh3/setup-sh3.c
@@ -0,0 +1,71 @@
+/*
+ * Shared SH3 Setup code
+ *
+ * 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/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+/* All SH3 devices are equipped with IRQ0->5 (except sh7708) */
+
+enum {
+ UNUSED = 0,
+
+ /* interrupt sources */
+ IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5,
+};
+
+static struct intc_vect vectors_irq0123[] __initdata = {
+ INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
+ INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+};
+
+static struct intc_vect vectors_irq45[] __initdata = {
+ INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+};
+
+static struct intc_prio_reg prio_registers[] __initdata = {
+ { 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } },
+ { 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } },
+};
+
+static struct intc_mask_reg ack_registers[] __initdata = {
+ { 0xa4000004, 0, 8, /* IRR0 */
+ { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
+};
+
+static struct intc_sense_reg sense_registers[] __initdata = {
+ { 0xa4000010, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
+};
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh3-irq0123",
+ vectors_irq0123, NULL, NULL,
+ prio_registers, sense_registers, ack_registers);
+
+static DECLARE_INTC_DESC_ACK(intc_desc_irq45, "sh3-irq45",
+ vectors_irq45, NULL, NULL,
+ prio_registers, sense_registers, ack_registers);
+
+#define INTC_ICR1 0xa4000010UL
+#define INTC_ICR1_IRQLVL (1<<14)
+
+void __init plat_irq_setup_pins(int mode)
+{
+ if (mode == IRQ_MODE_IRQ) {
+ __raw_writew(__raw_readw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
+ register_intc_controller(&intc_desc_irq0123);
+ return;
+ }
+ BUG();
+}
+
+void __init plat_irq_setup_sh3(void)
+{
+ register_intc_controller(&intc_desc_irq45);
+}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
index f581534cb73..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 = {
- INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
+ /* 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(TPU3, 0xc80), INTC_VECT(TPU1, 0xca0),
+ 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,38 +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 intc_vect vectors_irq[] __initdata = {
- INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
- INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
+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 DECLARE_INTC_DESC(intc_desc_irq, "sh7705-irq", vectors_irq, NULL,
- NULL, prio_registers, NULL);
+static struct resource scif0_resources[] = {
+ DEFINE_RES_MEM(0xa4410000, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x900)),
+};
-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 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_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 = sci_platform_data,
+ .platform_data = &scif1_platform_data,
},
};
@@ -120,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 = {
@@ -147,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,
};
@@ -157,18 +175,22 @@ 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_irq_setup_pins(int mode)
+void __init plat_early_device_setup(void)
{
- if (mode == IRQ_MODE_IRQ) {
- register_intc_controller(&intc_desc_irq);
- return;
- }
- BUG();
+ early_platform_add_devices(sh7705_early_devices,
+ ARRAY_SIZE(sh7705_early_devices));
}
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
+ plat_irq_setup_sh3();
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c
index d3733b13ea5..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)
- INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
- INTC_VECT(DMAC_DEI0, 0x800), INTC_VECT(DMAC_DEI1, 0x820),
- INTC_VECT(DMAC_DEI2, 0x840), INTC_VECT(DMAC_DEI3, 0x860),
+ /* IRQ0->5 are handled in setup-sh3.c */
+ 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,21 +86,9 @@ 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);
-#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
- defined(CONFIG_CPU_SUBTYPE_SH7707) || \
- defined(CONFIG_CPU_SUBTYPE_SH7709)
-static struct intc_vect vectors_irq[] __initdata = {
- INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
- INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
-};
-
-static DECLARE_INTC_DESC(intc_desc_irq, "sh770x-irq", vectors_irq, NULL,
- NULL, prio_registers, NULL);
-#endif
-
static struct resource rtc_resources[] = {
[0] = {
.start = 0xfffffec0,
@@ -123,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,
},
};
@@ -143,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 platform_device sci_device = {
+static struct resource scif2_resources[] = {
+ DEFINE_RES_MEM(0xa4000140, 0x100),
+ DEFINE_RES_IRQ(evt2irq(0x880)),
+};
+
+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,
};
@@ -192,26 +225,34 @@ 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);
-#define INTC_ICR1 0xa4000010UL
-#define INTC_ICR1_IRQLVL (1<<14)
-
-void __init plat_irq_setup_pins(int mode)
-{
- if (mode == IRQ_MODE_IRQ) {
+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)
- ctrl_outw(ctrl_inw(INTC_ICR1) & ~INTC_ICR1_IRQLVL, INTC_ICR1);
- register_intc_controller(&intc_desc_irq);
- return;
+ &scif1_device,
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ &scif2_device,
#endif
- }
- BUG();
+ &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)
{
register_intc_controller(&intc_desc);
+#if defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7709)
+ plat_irq_setup_sh3();
+#endif
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
index 7406c9ad925..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,83 +22,53 @@ 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 = {
- INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0),
- 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),
+ /* IRQ0->5 are handled in setup-sh3.c */
+ 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 } },
{ 0xa4000016, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } },
{ 0xa4000018, 0, 16, 4, /* IPRD */ { 0, 0, IRQ5, IRQ4 } },
{ 0xa400001a, 0, 16, 4, /* IPRE */ { DMAC1, SCIF0, SCIF1 } },
- { 0xa4080000, 0, 16, 4, /* IPRF */ { 0, DMAC2 } },
-#ifdef CONFIG_CPU_SUBTYPE_SH7710
- { 0xa4080000, 0, 16, 4, /* IPRF */ { IPSEC } },
-#endif
+ { 0xa4080000, 0, 16, 4, /* IPRF */ { IPSEC, DMAC2 } },
{ 0xa4080002, 0, 16, 4, /* IPRG */ { EDMAC0, EDMAC1, EDMAC2 } },
{ 0xa4080004, 0, 16, 4, /* IPRH */ { 0, 0, 0, SIOF0 } },
{ 0xa4080006, 0, 16, 4, /* IPRI */ { 0, 0, SIOF1 } },
};
-static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, groups,
- NULL, prio_registers, NULL);
-
-static struct intc_vect vectors_irq[] __initdata = {
- INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620),
- INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660),
-};
-
-static DECLARE_INTC_DESC(intc_desc_irq, "sh7710-irq", vectors_irq, NULL,
+static DECLARE_INTC_DESC(intc_desc, "sh7710", vectors, NULL,
NULL, prio_registers, NULL);
static struct resource rtc_resources[] = {
@@ -106,17 +78,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 = {
@@ -133,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 = sci_platform_data,
+ .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 = &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,
};
@@ -168,18 +174,22 @@ 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_irq_setup_pins(int mode)
+void __init plat_early_device_setup(void)
{
- if (mode == IRQ_MODE_IRQ) {
- register_intc_controller(&intc_desc_irq);
- return;
- }
- BUG();
+ early_platform_add_devices(sh7710_early_devices,
+ ARRAY_SIZE(sh7710_early_devices));
}
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
+ plat_irq_setup_sh3();
}
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c
index 8028082527c..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,11 +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>
-
-#define INTC_ICR1 0xA4140010UL
-#define INTC_ICR_IRLM 0x4000
-#define INTC_ICR_IRQ (~INTC_ICR_IRLM)
+#include <cpu/serial.h>
static struct resource rtc_resources[] = {
[0] = {
@@ -30,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,
},
};
@@ -60,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,
},
};
@@ -92,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,
@@ -119,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,
},
};
@@ -136,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,
};
@@ -148,77 +207,74 @@ 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 } },
{ 0xA4140016UL, 0, 16, 4, /* IPRC */ { IRQ3, IRQ2, IRQ1, IRQ0 } },
{ 0xA4140018UL, 0, 16, 4, /* IPRD */ { USBF_SPD, TMU_SUNI, IRQ5, IRQ4 } },
-#if defined(CONFIG_CPU_SUBTYPE_SH7720)
{ 0xA414001AUL, 0, 16, 4, /* IPRE */ { DMAC1, 0, LCDC, SSL } },
-#else
- { 0xA414001AUL, 0, 16, 4, /* IPRE */ { DMAC1, 0, LCDC, 0 } },
-#endif
{ 0xA4080000UL, 0, 16, 4, /* IPRF */ { ADC, DMAC2, USBFI, CMT } },
{ 0xA4080002UL, 0, 16, 4, /* IPRG */ { SCIF0, SCIF1, 0, 0 } },
{ 0xA4080004UL, 0, 16, 4, /* IPRH */ { PINT07, PINT815, TPU, IIC } },
@@ -226,35 +282,11 @@ 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);
-static struct intc_sense_reg sense_registers[] __initdata = {
- { INTC_ICR1, 16, 2, { 0, 0, IRQ5, IRQ4, IRQ3, IRQ2, IRQ1, IRQ0 } },
-};
-
-static struct intc_vect vectors_irq[] __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),
-};
-
-static DECLARE_INTC_DESC(intc_irq_desc, "sh7720-irq", vectors_irq,
- NULL, NULL, prio_registers, sense_registers);
-
-void __init plat_irq_setup_pins(int mode)
-{
- switch (mode) {
- case IRQ_MODE_IRQ:
- ctrl_outw(ctrl_inw(INTC_ICR1) & INTC_ICR_IRQ, INTC_ICR1);
- register_intc_controller(&intc_irq_desc);
- break;
- default:
- BUG();
- }
-}
-
void __init plat_irq_setup(void)
{
register_intc_controller(&intc_desc);
+ plat_irq_setup_sh3();
}
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