aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2006-12-12 17:41:41 -0500
committerDave Jones <davej@redhat.com>2006-12-12 17:41:41 -0500
commitc4366889dda8110247be59ca41fddb82951a8c26 (patch)
tree705c1a996bed8fd48ce94ff33ec9fd00f9b94875 /arch/sh/kernel
parentdb2fb9db5735cc532fd4fc55e94b9a3c3750378e (diff)
parente1036502e5263851259d147771226161e5ccc85a (diff)
Merge ../linus
Conflicts: drivers/cpufreq/cpufreq.c
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/Makefile3
-rw-r--r--arch/sh/kernel/cpu/Makefile12
-rw-r--r--arch/sh/kernel/cpu/clock.c27
-rw-r--r--arch/sh/kernel/cpu/init.c2
-rw-r--r--arch/sh/kernel/cpu/irq/Makefile3
-rw-r--r--arch/sh/kernel/cpu/irq/imask.c5
-rw-r--r--arch/sh/kernel/cpu/irq/intc2.c182
-rw-r--r--arch/sh/kernel/cpu/irq/ipr.c124
-rw-r--r--arch/sh/kernel/cpu/irq/pint.c8
-rw-r--r--arch/sh/kernel/cpu/sh2/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh2/clock-sh7619.c81
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S337
-rw-r--r--arch/sh/kernel/cpu/sh2/ex.S46
-rw-r--r--arch/sh/kernel/cpu/sh2/probe.c16
-rw-r--r--arch/sh/kernel/cpu/sh2/setup-sh7619.c94
-rw-r--r--arch/sh/kernel/cpu/sh2a/Makefile10
-rw-r--r--arch/sh/kernel/cpu/sh2a/clock-sh7206.c85
-rw-r--r--arch/sh/kernel/cpu/sh2a/probe.c39
-rw-r--r--arch/sh/kernel/cpu/sh2a/setup-sh7206.c112
-rw-r--r--arch/sh/kernel/cpu/sh3/Makefile2
-rw-r--r--arch/sh/kernel/cpu/sh3/clock-sh7709.c2
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S (renamed from arch/sh/kernel/entry.S)546
-rw-r--r--arch/sh/kernel/cpu/sh3/ex.S9
-rw-r--r--arch/sh/kernel/cpu/sh4/Makefile12
-rw-r--r--arch/sh/kernel/cpu/sh4/clock-sh4-202.c4
-rw-r--r--arch/sh/kernel/cpu/sh4/ex.S9
-rw-r--r--arch/sh/kernel/cpu/sh4/fpu.c25
-rw-r--r--arch/sh/kernel/cpu/sh4/probe.c28
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7750.c101
-rw-r--r--arch/sh/kernel/cpu/sh4/setup-sh7760.c63
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c20
-rw-r--r--arch/sh/kernel/cpu/sh4a/Makefile19
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh73180.c (renamed from arch/sh/kernel/cpu/sh4/clock-sh73180.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7343.c99
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7770.c (renamed from arch/sh/kernel/cpu/sh4/clock-sh7770.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/clock-sh7780.c (renamed from arch/sh/kernel/cpu/sh4/clock-sh7780.c)2
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh73180.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh73180.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh7343.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c80
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7770.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh7770.c)0
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c (renamed from arch/sh/kernel/cpu/sh4/setup-sh7780.c)29
-rw-r--r--arch/sh/kernel/early_printk.c64
-rw-r--r--arch/sh/kernel/entry-common.S444
-rw-r--r--arch/sh/kernel/head.S18
-rw-r--r--arch/sh/kernel/irq.c57
-rw-r--r--arch/sh/kernel/process.c59
-rw-r--r--arch/sh/kernel/relocate_kernel.S14
-rw-r--r--arch/sh/kernel/setup.c42
-rw-r--r--arch/sh/kernel/sh_ksyms.c22
-rw-r--r--arch/sh/kernel/signal.c37
-rw-r--r--arch/sh/kernel/stacktrace.c43
-rw-r--r--arch/sh/kernel/sys_sh.c15
-rw-r--r--arch/sh/kernel/syscalls.S3
-rw-r--r--arch/sh/kernel/time.c139
-rw-r--r--arch/sh/kernel/timers/Makefile2
-rw-r--r--arch/sh/kernel/timers/timer-cmt.c196
-rw-r--r--arch/sh/kernel/timers/timer-mtu2.c200
-rw-r--r--arch/sh/kernel/timers/timer-tmu.c13
-rw-r--r--arch/sh/kernel/timers/timer.c6
-rw-r--r--arch/sh/kernel/traps.c396
-rw-r--r--arch/sh/kernel/vmlinux.lds.S10
-rw-r--r--arch/sh/kernel/vsyscall/vsyscall.c2
62 files changed, 3076 insertions, 945 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 5da88a43d350..99c7e5249f7a 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -4,7 +4,7 @@
4 4
5extra-y := head.o init_task.o vmlinux.lds 5extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y := process.o signal.o entry.o traps.o irq.o \ 7obj-y := process.o signal.o traps.o irq.o \
8 ptrace.o setup.o time.o sys_sh.o semaphore.o \ 8 ptrace.o setup.o time.o sys_sh.o semaphore.o \
9 io.o io_generic.o sh_ksyms.o syscalls.o 9 io.o io_generic.o sh_ksyms.o syscalls.o
10 10
@@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
21obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 21obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
22obj-$(CONFIG_APM) += apm.o 22obj-$(CONFIG_APM) += apm.o
23obj-$(CONFIG_PM) += pm.o 23obj-$(CONFIG_PM) += pm.o
24obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
index fb5dac069382..d055a3ea6b4b 100644
--- a/arch/sh/kernel/cpu/Makefile
+++ b/arch/sh/kernel/cpu/Makefile
@@ -2,11 +2,13 @@
2# Makefile for the Linux/SuperH CPU-specifc backends. 2# Makefile for the Linux/SuperH CPU-specifc backends.
3# 3#
4 4
5obj-y += irq/ init.o clock.o 5obj-$(CONFIG_CPU_SH2) = sh2/
6 6obj-$(CONFIG_CPU_SH2A) = sh2a/
7obj-$(CONFIG_CPU_SH2) += sh2/ 7obj-$(CONFIG_CPU_SH3) = sh3/
8obj-$(CONFIG_CPU_SH3) += sh3/ 8obj-$(CONFIG_CPU_SH4) = sh4/
9obj-$(CONFIG_CPU_SH4) += sh4/ 9obj-$(CONFIG_CPU_SH4A) += sh4a/
10 10
11obj-$(CONFIG_UBC_WAKEUP) += ubc.o 11obj-$(CONFIG_UBC_WAKEUP) += ubc.o
12obj-$(CONFIG_SH_ADC) += adc.o 12obj-$(CONFIG_SH_ADC) += adc.o
13
14obj-y += irq/ init.o clock.o
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c
index 51ec64cdf348..abb586b12565 100644
--- a/arch/sh/kernel/cpu/clock.c
+++ b/arch/sh/kernel/cpu/clock.c
@@ -5,9 +5,11 @@
5 * 5 *
6 * This clock framework is derived from the OMAP version by: 6 * This clock framework is derived from the OMAP version by:
7 * 7 *
8 * Copyright (C) 2004 Nokia Corporation 8 * Copyright (C) 2004 - 2005 Nokia Corporation
9 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> 9 * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
10 * 10 *
11 * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
12 *
11 * This file is subject to the terms and conditions of the GNU General Public 13 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive 14 * License. See the file "COPYING" in the main directory of this archive
13 * for more details. 15 * for more details.
@@ -20,6 +22,7 @@
20#include <linux/kref.h> 22#include <linux/kref.h>
21#include <linux/seq_file.h> 23#include <linux/seq_file.h>
22#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/platform_device.h>
23#include <asm/clock.h> 26#include <asm/clock.h>
24#include <asm/timer.h> 27#include <asm/timer.h>
25 28
@@ -195,17 +198,37 @@ void clk_recalc_rate(struct clk *clk)
195 propagate_rate(clk); 198 propagate_rate(clk);
196} 199}
197 200
198struct clk *clk_get(const char *id) 201/*
202 * Returns a clock. Note that we first try to use device id on the bus
203 * and clock name. If this fails, we try to use clock name only.
204 */
205struct clk *clk_get(struct device *dev, const char *id)
199{ 206{
200 struct clk *p, *clk = ERR_PTR(-ENOENT); 207 struct clk *p, *clk = ERR_PTR(-ENOENT);
208 int idno;
209
210 if (dev == NULL || dev->bus != &platform_bus_type)
211 idno = -1;
212 else
213 idno = to_platform_device(dev)->id;
201 214
202 mutex_lock(&clock_list_sem); 215 mutex_lock(&clock_list_sem);
203 list_for_each_entry(p, &clock_list, node) { 216 list_for_each_entry(p, &clock_list, node) {
217 if (p->id == idno &&
218 strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
219 clk = p;
220 goto found;
221 }
222 }
223
224 list_for_each_entry(p, &clock_list, node) {
204 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { 225 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
205 clk = p; 226 clk = p;
206 break; 227 break;
207 } 228 }
208 } 229 }
230
231found:
209 mutex_unlock(&clock_list_sem); 232 mutex_unlock(&clock_list_sem);
210 233
211 return clk; 234 return clk;
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c
index bfb90eb0b7a6..48121766e8d2 100644
--- a/arch/sh/kernel/cpu/init.c
+++ b/arch/sh/kernel/cpu/init.c
@@ -68,12 +68,14 @@ static void __init cache_init(void)
68 68
69 waysize = cpu_data->dcache.sets; 69 waysize = cpu_data->dcache.sets;
70 70
71#ifdef CCR_CACHE_ORA
71 /* 72 /*
72 * If the OC is already in RAM mode, we only have 73 * If the OC is already in RAM mode, we only have
73 * half of the entries to flush.. 74 * half of the entries to flush..
74 */ 75 */
75 if (ccr & CCR_CACHE_ORA) 76 if (ccr & CCR_CACHE_ORA)
76 waysize >>= 1; 77 waysize >>= 1;
78#endif
77 79
78 waysize <<= cpu_data->dcache.entry_shift; 80 waysize <<= cpu_data->dcache.entry_shift;
79 81
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile
index 1c034c283f59..0049d217561a 100644
--- a/arch/sh/kernel/cpu/irq/Makefile
+++ b/arch/sh/kernel/cpu/irq/Makefile
@@ -1,8 +1,9 @@
1# 1#
2# Makefile for the Linux/SuperH CPU-specifc IRQ handlers. 2# Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
3# 3#
4obj-y += ipr.o imask.o 4obj-y += imask.o
5 5
6obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o
6obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o 7obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
7obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o 8obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o
8obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o 9obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o
diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c
index a33ae3e0a5a5..301b505c4278 100644
--- a/arch/sh/kernel/cpu/irq/imask.c
+++ b/arch/sh/kernel/cpu/irq/imask.c
@@ -53,7 +53,10 @@ void static inline set_interrupt_registers(int ip)
53{ 53{
54 unsigned long __dummy; 54 unsigned long __dummy;
55 55
56 asm volatile("ldc %2, r6_bank\n\t" 56 asm volatile(
57#ifdef CONFIG_CPU_HAS_SR_RB
58 "ldc %2, r6_bank\n\t"
59#endif
57 "stc sr, %0\n\t" 60 "stc sr, %0\n\t"
58 "and #0xf0, %0\n\t" 61 "and #0xf0, %0\n\t"
59 "shlr2 %0\n\t" 62 "shlr2 %0\n\t"
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c
index d4b2bb7e08c7..74defe76a058 100644
--- a/arch/sh/kernel/cpu/irq/intc2.c
+++ b/arch/sh/kernel/cpu/irq/intc2.c
@@ -11,27 +11,33 @@
11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. 11 * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780.
12 */ 12 */
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/init.h> 14#include <linux/interrupt.h>
15#include <linux/irq.h> 15#include <linux/io.h>
16#include <asm/system.h> 16
17#include <asm/io.h> 17#if defined(CONFIG_CPU_SUBTYPE_SH7760)
18#define INTC2_BASE 0xfe080000
19#define INTC2_INTMSK (INTC2_BASE + 0x40)
20#define INTC2_INTMSKCLR (INTC2_BASE + 0x60)
21#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
22#define INTC2_BASE 0xffd40000
23#define INTC2_INTMSK (INTC2_BASE + 0x38)
24#define INTC2_INTMSKCLR (INTC2_BASE + 0x3c)
25#endif
18 26
19static void disable_intc2_irq(unsigned int irq) 27static void disable_intc2_irq(unsigned int irq)
20{ 28{
21 struct intc2_data *p = get_irq_chip_data(irq); 29 struct intc2_data *p = get_irq_chip_data(irq);
22 ctrl_outl(1 << p->msk_shift, 30 ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset);
23 INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset);
24} 31}
25 32
26static void enable_intc2_irq(unsigned int irq) 33static void enable_intc2_irq(unsigned int irq)
27{ 34{
28 struct intc2_data *p = get_irq_chip_data(irq); 35 struct intc2_data *p = get_irq_chip_data(irq);
29 ctrl_outl(1 << p->msk_shift, 36 ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset);
30 INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset);
31} 37}
32 38
33static struct irq_chip intc2_irq_chip = { 39static struct irq_chip intc2_irq_chip = {
34 .typename = "intc2", 40 .name = "INTC2",
35 .mask = disable_intc2_irq, 41 .mask = disable_intc2_irq,
36 .unmask = enable_intc2_irq, 42 .unmask = enable_intc2_irq,
37 .mask_ack = disable_intc2_irq, 43 .mask_ack = disable_intc2_irq,
@@ -45,150 +51,34 @@ static struct irq_chip intc2_irq_chip = {
45 * PIO1 which is INTPRI00[19,16] and INTMSK00[13] 51 * PIO1 which is INTPRI00[19,16] and INTMSK00[13]
46 * would be: ^ ^ ^ ^ 52 * would be: ^ ^ ^ ^
47 * | | | | 53 * | | | |
48 * make_intc2_irq(84, 0, 16, 0, 13); 54 * { 84, 0, 16, 0, 13 },
55 *
56 * in the intc2_data table.
49 */ 57 */
50void make_intc2_irq(struct intc2_data *p) 58void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs)
51{ 59{
52 unsigned int flags; 60 int i;
53 unsigned long ipr;
54
55 disable_irq_nosync(p->irq);
56
57 /* Set the priority level */
58 local_irq_save(flags);
59
60 ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset);
61 ipr &= ~(0xf << p->ipr_shift);
62 ipr |= p->priority << p->ipr_shift;
63 ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + p->ipr_offset);
64
65 local_irq_restore(flags);
66 61
67 set_irq_chip_and_handler(p->irq, &intc2_irq_chip, handle_level_irq); 62 for (i = 0; i < nr_irqs; i++) {
68 set_irq_chip_data(p->irq, p); 63 unsigned long ipr, flags;
64 struct intc2_data *p = table + i;
69 65
70 enable_intc2_irq(p->irq); 66 disable_irq_nosync(p->irq);
71}
72 67
73static struct intc2_data intc2_irq_table[] = { 68 /* Set the priority level */
74#if defined(CONFIG_CPU_SUBTYPE_ST40) 69 local_irq_save(flags);
75 {64, 0, 0, 0, 0, 13}, /* PCI serr */
76 {65, 0, 4, 0, 1, 13}, /* PCI err */
77 {66, 0, 4, 0, 2, 13}, /* PCI ad */
78 {67, 0, 4, 0, 3, 13}, /* PCI pwd down */
79 {72, 0, 8, 0, 5, 13}, /* DMAC INT0 */
80 {73, 0, 8, 0, 6, 13}, /* DMAC INT1 */
81 {74, 0, 8, 0, 7, 13}, /* DMAC INT2 */
82 {75, 0, 8, 0, 8, 13}, /* DMAC INT3 */
83 {76, 0, 8, 0, 9, 13}, /* DMAC INT4 */
84 {78, 0, 8, 0, 11, 13}, /* DMAC ERR */
85 {80, 0, 12, 0, 12, 13}, /* PIO0 */
86 {84, 0, 16, 0, 13, 13}, /* PIO1 */
87 {88, 0, 20, 0, 14, 13}, /* PIO2 */
88 {112, 4, 0, 4, 0, 13}, /* Mailbox */
89 #ifdef CONFIG_CPU_SUBTYPE_ST40GX1
90 {116, 4, 4, 4, 4, 13}, /* SSC0 */
91 {120, 4, 8, 4, 8, 13}, /* IR Blaster */
92 {124, 4, 12, 4, 12, 13}, /* USB host */
93 {128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */
94 {132, 4, 20, 4, 20, 13}, /* UART0 */
95 {134, 4, 20, 4, 22, 13}, /* UART2 */
96 {136, 4, 24, 4, 24, 13}, /* IO_PIO0 */
97 {140, 4, 28, 4, 28, 13}, /* EMPI */
98 {144, 8, 0, 8, 0, 13}, /* MAFE */
99 {148, 8, 4, 8, 4, 13}, /* PWM */
100 {152, 8, 8, 8, 8, 13}, /* SSC1 */
101 {156, 8, 12, 8, 12, 13}, /* IO_PIO1 */
102 {160, 8, 16, 8, 16, 13}, /* USB target */
103 {164, 8, 20, 8, 20, 13}, /* UART1 */
104 {168, 8, 24, 8, 24, 13}, /* Teletext */
105 {172, 8, 28, 8, 28, 13}, /* VideoSync VTG */
106 {173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */
107 {174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */
108#endif
109#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
110/*
111 * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
112 */
113 /* INTPRIO0 | INTMSK0 */
114 {48, 0, 28, 0, 31, 3}, /* IRQ 4 */
115 {49, 0, 24, 0, 30, 3}, /* IRQ 3 */
116 {50, 0, 20, 0, 29, 3}, /* IRQ 2 */
117 {51, 0, 16, 0, 28, 3}, /* IRQ 1 */
118 /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
119 /* INTPRIO4 | INTMSK0 */
120 {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */
121 {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */
122 {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */
123 {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */
124 {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */
125 {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */
126 {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */
127 {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */
128 /* INTPRIO8 | INTMSK0 */
129 {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */
130 {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */
131 {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */
132 {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */
133 {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */
134 {65, 8, 24, 0, 16, 3}, /* LCDC */
135 /* 66, 67 unused */
136 {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */
137 {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */
138 {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */
139 /* 71 unused */
140 {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */
141 {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */
142 {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */
143 {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */
144 {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */
145 {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */
146 {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */
147 {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */
148 /* | INTMSK4 */
149 {80, 8, 4, 4, 23, 3}, /* SIM_ERI */
150 {81, 8, 4, 4, 22, 3}, /* SIM_RXI */
151 {82, 8, 4, 4, 21, 3}, /* SIM_TXI */
152 {83, 8, 4, 4, 20, 3}, /* SIM_TEI */
153 {84, 8, 0, 4, 19, 3}, /* HSPII */
154 /* INTPRIOC | INTMSK4 */
155 /* 85-87 unused/reserved */
156 {88, 12, 20, 4, 18, 3}, /* MMCI0 */
157 {89, 12, 20, 4, 17, 3}, /* MMCI1 */
158 {90, 12, 20, 4, 16, 3}, /* MMCI2 */
159 {91, 12, 20, 4, 15, 3}, /* MMCI3 */
160 {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/
161 /* 93-107 reserved/undocumented */
162 {108,12, 4, 4, 1, 3}, /* ADC */
163 {109,12, 0, 4, 0, 3}, /* CMTI */
164 /* 110-111 reserved/unused */
165#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
166 { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
167 { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
168 { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
169 { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
170 { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
171 { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
172 { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
173 { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
174 70
175 { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 71 ipr = ctrl_inl(INTC2_BASE + p->ipr_offset);
176 { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 72 ipr &= ~(0xf << p->ipr_shift);
177 { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 73 ipr |= p->priority << p->ipr_shift;
178 { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, 74 ctrl_outl(ipr, INTC2_BASE + p->ipr_offset);
179 75
180 { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, 76 local_irq_restore(flags);
181 { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY },
182 { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY },
183 { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY },
184 { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY },
185#endif
186};
187 77
188void __init init_IRQ_intc2(void) 78 set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip,
189{ 79 handle_level_irq, "level");
190 int i; 80 set_irq_chip_data(p->irq, p);
191 81
192 for (i = 0; i < ARRAY_SIZE(intc2_irq_table); i++) 82 enable_intc2_irq(p->irq);
193 make_intc2_irq(intc2_irq_table + i); 83 }
194} 84}
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c
index 8944abdf6e1c..35eb5751a3aa 100644
--- a/arch/sh/kernel/cpu/irq/ipr.c
+++ b/arch/sh/kernel/cpu/irq/ipr.c
@@ -19,15 +19,8 @@
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/module.h> 21#include <linux/module.h>
22#include <asm/system.h> 22#include <linux/io.h>
23#include <asm/io.h> 23#include <linux/interrupt.h>
24#include <asm/machvec.h>
25
26struct ipr_data {
27 unsigned int addr; /* Address of Interrupt Priority Register */
28 int shift; /* Shifts of the 16-bit data */
29 int priority; /* The priority */
30};
31 24
32static void disable_ipr_irq(unsigned int irq) 25static void disable_ipr_irq(unsigned int irq)
33{ 26{
@@ -44,107 +37,30 @@ static void enable_ipr_irq(unsigned int irq)
44} 37}
45 38
46static struct irq_chip ipr_irq_chip = { 39static struct irq_chip ipr_irq_chip = {
47 .name = "ipr", 40 .name = "IPR",
48 .mask = disable_ipr_irq, 41 .mask = disable_ipr_irq,
49 .unmask = enable_ipr_irq, 42 .unmask = enable_ipr_irq,
50 .mask_ack = disable_ipr_irq, 43 .mask_ack = disable_ipr_irq,
51}; 44};
52 45
53void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) 46void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs)
54{
55 struct ipr_data ipr_data;
56
57 disable_irq_nosync(irq);
58
59 ipr_data.addr = addr;
60 ipr_data.shift = pos*4; /* POSition (0-3) x 4 means shift */
61 ipr_data.priority = priority;
62
63 set_irq_chip_and_handler(irq, &ipr_irq_chip, handle_level_irq);
64 set_irq_chip_data(irq, &ipr_data);
65
66 enable_ipr_irq(irq);
67}
68
69/* XXX: This needs to die a horrible death.. */
70void __init init_IRQ(void)
71{ 47{
72#ifndef CONFIG_CPU_SUBTYPE_SH7780 48 int i;
73 make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); 49
74 make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); 50 for (i = 0; i < nr_irqs; i++) {
75#ifdef RTC_IRQ 51 unsigned int irq = table[i].irq;
76 make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); 52 table[i].addr = map_ipridx_to_addr(table[i].ipr_idx);
77#endif 53 /* could the IPR index be mapped, if not we ignore this */
78 54 if (table[i].addr == 0)
79#ifdef SCI_ERI_IRQ 55 continue;
80 make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); 56 disable_irq_nosync(irq);
81 make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); 57 set_irq_chip_and_handler_name(irq, &ipr_irq_chip,
82 make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); 58 handle_level_irq, "level");
83#endif 59 set_irq_chip_data(irq, &table[i]);
84 60 enable_ipr_irq(irq);
85#ifdef SCIF1_ERI_IRQ 61 }
86 make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
87 make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
88 make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
89 make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY);
90#endif
91
92#if defined(CONFIG_CPU_SUBTYPE_SH7300)
93 make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY);
94 make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
95 make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
96 make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
97#endif
98
99#ifdef SCIF_ERI_IRQ
100 make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
101 make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
102 make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
103 make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY);
104#endif
105
106#ifdef IRDA_ERI_IRQ
107 make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
108 make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
109 make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
110 make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY);
111#endif
112
113#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
114 defined(CONFIG_CPU_SUBTYPE_SH7706) || \
115 defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
116 /*
117 * Initialize the Interrupt Controller (INTC)
118 * registers to their power on values
119 */
120
121 /*
122 * Enable external irq (INTC IRQ mode).
123 * You should set corresponding bits of PFC to "00"
124 * to enable these interrupts.
125 */
126 make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY);
127 make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
128 make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
129 make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY);
130 make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY);
131 make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY);
132#endif
133#endif
134
135#ifdef CONFIG_CPU_HAS_PINT_IRQ
136 init_IRQ_pint();
137#endif
138
139#ifdef CONFIG_CPU_HAS_INTC2_IRQ
140 init_IRQ_intc2();
141#endif
142 /* Perform the machine specific initialisation */
143 if (sh_mv.mv_init_irq != NULL)
144 sh_mv.mv_init_irq();
145
146 irq_ctx_init(smp_processor_id());
147} 62}
63EXPORT_SYMBOL(make_ipr_irq);
148 64
149#if !defined(CONFIG_CPU_HAS_PINT_IRQ) 65#if !defined(CONFIG_CPU_HAS_PINT_IRQ)
150int ipr_irq_demux(int irq) 66int ipr_irq_demux(int irq)
@@ -152,5 +68,3 @@ int ipr_irq_demux(int irq)
152 return irq; 68 return irq;
153} 69}
154#endif 70#endif
155
156EXPORT_SYMBOL(make_ipr_irq);
diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c
index 17f47b373d6e..f60007783a21 100644
--- a/arch/sh/kernel/cpu/irq/pint.c
+++ b/arch/sh/kernel/cpu/irq/pint.c
@@ -84,12 +84,16 @@ void make_pint_irq(unsigned int irq)
84 disable_pint_irq(irq); 84 disable_pint_irq(irq);
85} 85}
86 86
87static struct ipr_data pint_ipr_map[] = {
88 { PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY },
89 { PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY },
90};
91
87void __init init_IRQ_pint(void) 92void __init init_IRQ_pint(void)
88{ 93{
89 int i; 94 int i;
90 95
91 make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); 96 make_ipr_irq(pint_ipr_map, ARRAY_SIZE(pint_ipr_map));
92 make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY);
93 97
94 enable_irq(PINT0_IRQ); 98 enable_irq(PINT0_IRQ);
95 enable_irq(PINT8_IRQ); 99 enable_irq(PINT8_IRQ);
diff --git a/arch/sh/kernel/cpu/sh2/Makefile b/arch/sh/kernel/cpu/sh2/Makefile
index 389353fba608..f0f059acfcfb 100644
--- a/arch/sh/kernel/cpu/sh2/Makefile
+++ b/arch/sh/kernel/cpu/sh2/Makefile
@@ -2,5 +2,6 @@
2# Makefile for the Linux/SuperH SH-2 backends. 2# Makefile for the Linux/SuperH SH-2 backends.
3# 3#
4 4
5obj-y := probe.o 5obj-y := ex.o probe.o entry.o
6 6
7obj-$(CONFIG_CPU_SUBTYPE_SH7619) += setup-sh7619.o clock-sh7619.o
diff --git a/arch/sh/kernel/cpu/sh2/clock-sh7619.c b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
new file mode 100644
index 000000000000..d0440b269702
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/clock-sh7619.c
@@ -0,0 +1,81 @@
1/*
2 * arch/sh/kernel/cpu/sh2/clock-sh7619.c
3 *
4 * SH7619 support for the clock framework
5 *
6 * Copyright (C) 2006 Yoshinori Sato
7 *
8 * Based on clock-sh4.c
9 * Copyright (C) 2005 Paul Mundt
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 */
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <asm/clock.h>
18#include <asm/freq.h>
19#include <asm/io.h>
20
21const static int pll1rate[]={1,2};
22const static int pfc_divisors[]={1,2,0,4};
23
24#if (CONFIG_SH_CLK_MD == 1) || (CONFIG_SH_CLK_MD == 2)
25#define PLL2 (4)
26#elif (CONFIG_SH_CLK_MD == 5) || (CONFIG_SH_CLK_MD == 6)
27#define PLL2 (2)
28#else
29#error "Illigal Clock Mode!"
30#endif
31
32static void master_clk_init(struct clk *clk)
33{
34 clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
35}
36
37static struct clk_ops sh7619_master_clk_ops = {
38 .init = master_clk_init,
39};
40
41static void module_clk_recalc(struct clk *clk)
42{
43 int idx = (ctrl_inw(FREQCR) & 0x0007);
44 clk->rate = clk->parent->rate / pfc_divisors[idx];
45}
46
47static struct clk_ops sh7619_module_clk_ops = {
48 .recalc = module_clk_recalc,
49};
50
51static void bus_clk_recalc(struct clk *clk)
52{
53 clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7];
54}
55
56static struct clk_ops sh7619_bus_clk_ops = {
57 .recalc = bus_clk_recalc,
58};
59
60static void cpu_clk_recalc(struct clk *clk)
61{
62 clk->rate = clk->parent->rate;
63}
64
65static struct clk_ops sh7619_cpu_clk_ops = {
66 .recalc = cpu_clk_recalc,
67};
68
69static struct clk_ops *sh7619_clk_ops[] = {
70 &sh7619_master_clk_ops,
71 &sh7619_module_clk_ops,
72 &sh7619_bus_clk_ops,
73 &sh7619_cpu_clk_ops,
74};
75
76void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
77{
78 if (idx < ARRAY_SIZE(sh7619_clk_ops))
79 *ops = sh7619_clk_ops[idx];
80}
81
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
new file mode 100644
index 000000000000..d51fa5e9904a
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -0,0 +1,337 @@
1/*
2 * arch/sh/kernel/cpu/sh2/entry.S
3 *
4 * The SH-2 exception entry
5 *
6 * Copyright (C) 2005,2006 Yoshinori Sato
7 * Copyright (C) 2005 AXE,Inc.
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 */
13
14#include <linux/linkage.h>
15#include <asm/asm-offsets.h>
16#include <asm/thread_info.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/unistd.h>
19#include <asm/errno.h>
20#include <asm/page.h>
21
22/* Offsets to the stack */
23OFF_R0 = 0 /* Return value. New ABI also arg4 */
24OFF_R1 = 4 /* New ABI: arg5 */
25OFF_R2 = 8 /* New ABI: arg6 */
26OFF_R3 = 12 /* New ABI: syscall_nr */
27OFF_R4 = 16 /* New ABI: arg0 */
28OFF_R5 = 20 /* New ABI: arg1 */
29OFF_R6 = 24 /* New ABI: arg2 */
30OFF_R7 = 28 /* New ABI: arg3 */
31OFF_SP = (15*4)
32OFF_PC = (16*4)
33OFF_SR = (16*4+2*4)
34OFF_TRA = (16*4+6*4)
35
36#include <asm/entry-macros.S>
37
38ENTRY(exception_handler)
39 ! already saved r0/r1
40 mov.l r2,@-sp
41 mov.l r3,@-sp
42 mov r0,r1
43 cli
44 mov.l $cpu_mode,r2
45 mov.l @r2,r0
46 mov.l @(5*4,r15),r3 ! previous SR
47 shll2 r3 ! set "S" flag
48 rotl r0 ! T <- "S" flag
49 rotl r0 ! "S" flag is LSB
50 rotcr r3 ! T -> r3:b30
51 shlr r3
52 shlr r0
53 bt/s 1f
54 mov.l r3,@(5*4,r15) ! copy cpu mode to SR
55 ! switch to kernel mode
56 mov #1,r0
57 rotr r0
58 rotr r0
59 mov.l r0,@r2 ! enter kernel mode
60 mov.l $current_thread_info,r2
61 mov.l @r2,r2
62 mov #0x20,r0
63 shll8 r0
64 add r2,r0
65 mov r15,r2 ! r2 = user stack top
66 mov r0,r15 ! switch kernel stack
67 add #-4,r15 ! dummy
68 mov.l r1,@-r15 ! TRA
69 sts.l macl, @-r15
70 sts.l mach, @-r15
71 stc.l gbr, @-r15
72 mov.l @(4*4,r2),r0
73 mov.l @(5*4,r2),r1
74 mov.l r1,@-r15 ! original SR
75 sts.l pr,@-r15
76 mov.l r0,@-r15 ! original PC
77 mov r2,r3
78 add #(4+2)*4,r3 ! rewind r0 - r3 + exception frame
79 mov.l r3,@-r15 ! original SP
80 mov.l r14,@-r15
81 mov.l r13,@-r15
82 mov.l r12,@-r15
83 mov.l r11,@-r15
84 mov.l r10,@-r15
85 mov.l r9,@-r15
86 mov.l r8,@-r15
87 mov.l r7,@-r15
88 mov.l r6,@-r15
89 mov.l r5,@-r15
90 mov.l r4,@-r15
91 mov r2,r8 ! copy user -> kernel stack
92 mov.l @r8+,r3
93 mov.l r3,@-r15
94 mov.l @r8+,r2
95 mov.l r2,@-r15
96 mov.l @r8+,r1
97 mov.l r1,@-r15
98 mov.l @r8+,r0
99 bra 2f
100 mov.l r0,@-r15
1011:
102 ! in kernel exception
103 mov #(22-4-4-1)*4+4,r0
104 mov r15,r2
105 sub r0,r15
106 mov.l @r2+,r0 ! old R3
107 mov.l r0,@-r15
108 mov.l @r2+,r0 ! old R2
109 mov.l r0,@-r15
110 mov.l @r2+,r0 ! old R1
111 mov.l r0,@-r15
112 mov.l @r2+,r0 ! old R0
113 mov.l r0,@-r15
114 mov.l @r2+,r3 ! old PC
115 mov.l @r2+,r0 ! old SR
116 add #-4,r2 ! exception frame stub (sr)
117 mov.l r1,@-r2 ! TRA
118 sts.l macl, @-r2
119 sts.l mach, @-r2
120 stc.l gbr, @-r2
121 mov.l r0,@-r2 ! save old SR
122 sts.l pr,@-r2
123 mov.l r3,@-r2 ! save old PC
124 mov r2,r0
125 add #8*4,r0
126 mov.l r0,@-r2 ! save old SP
127 mov.l r14,@-r2
128 mov.l r13,@-r2
129 mov.l r12,@-r2
130 mov.l r11,@-r2
131 mov.l r10,@-r2
132 mov.l r9,@-r2
133 mov.l r8,@-r2
134 mov.l r7,@-r2
135 mov.l r6,@-r2
136 mov.l r5,@-r2
137 mov.l r4,@-r2
138 mov.l @(OFF_R0,r15),r0
139 mov.l @(OFF_R1,r15),r1
140 mov.l @(OFF_R2,r15),r2
141 mov.l @(OFF_R3,r15),r3
1422:
143 mov #OFF_TRA,r8
144 add r15,r8
145 mov.l @r8,r9
146 mov #64,r8
147 cmp/hs r8,r9
148 bt interrupt_entry ! vec >= 64 is interrupt
149 mov #32,r8
150 cmp/hs r8,r9
151 bt trap_entry ! 64 > vec >= 32 is trap
152 mov.l 4f,r8
153 mov r9,r4
154 shll2 r9
155 add r9,r8
156 mov.l @r8,r8
157 mov #0,r9
158 cmp/eq r9,r8
159 bf 3f
160 mov.l 8f,r8 ! unhandled exception
1613:
162 mov.l 5f,r10
163 jmp @r8
164 lds r10,pr
165
166interrupt_entry:
167 mov r9,r4
168 mov.l 6f,r9
169 mov.l 7f,r8
170 jmp @r8
171 lds r9,pr
172
173 .align 2
1744: .long exception_handling_table
1755: .long ret_from_exception
1766: .long ret_from_irq
1777: .long do_IRQ
1788: .long do_exception_error
179
180trap_entry:
181 /* verbose BUG trapa entry check */
182 mov #0x3e,r8
183 cmp/ge r8,r9
184 bf/s 1f
185 add #-0x10,r9
186 add #0x10,r9
1871:
188 shll2 r9 ! TRA
189 mov #OFF_TRA,r8
190 add r15,r8
191 mov.l r9,@r8
192 mov r9,r8
193#ifdef CONFIG_TRACE_IRQFLAGS
194 mov.l 2f, r9
195 jsr @r9
196 nop
197#endif
198 sti
199 bra system_call
200 nop
201
202 .align 2
203#ifdef CONFIG_TRACE_IRQFLAGS
2042: .long trace_hardirqs_on
205#endif
206
207#if defined(CONFIG_SH_STANDARD_BIOS)
208 /* Unwind the stack and jmp to the debug entry */
209debug_kernel_fw:
210 mov r15,r0
211 add #(22-4)*4-4,r0
212 ldc.l @r0+,gbr
213 lds.l @r0+,mach
214 lds.l @r0+,macl
215 mov r15,r0
216 mov.l @(OFF_SP,r0),r1
217 mov #OFF_SR,r2
218 mov.l @(r0,r2),r3
219 mov.l r3,@-r1
220 mov #OFF_SP,r2
221 mov.l @(r0,r2),r3
222 mov.l r3,@-r1
223 mov r15,r0
224 add #(22-4)*4-8,r0
225 mov.l 1f,r2
226 mov.l @r2,r2
227 stc sr,r3
228 mov.l r2,@r0
229 mov.l r3,@r0
230 mov.l r1,@(8,r0)
231 mov.l @r15+, r0
232 mov.l @r15+, r1
233 mov.l @r15+, r2
234 mov.l @r15+, r3
235 mov.l @r15+, r4
236 mov.l @r15+, r5
237 mov.l @r15+, r6
238 mov.l @r15+, r7
239 mov.l @r15+, r8
240 mov.l @r15+, r9
241 mov.l @r15+, r10
242 mov.l @r15+, r11
243 mov.l @r15+, r12
244 mov.l @r15+, r13
245 mov.l @r15+, r14
246 add #8,r15
247 lds.l @r15+, pr
248 rte
249 mov.l @r15+,r15
250 .align 2
2511: .long gdb_vbr_vector
252#endif /* CONFIG_SH_STANDARD_BIOS */
253
254ENTRY(address_error_handler)
255 mov r15,r4 ! regs
256 add #4,r4
257 mov #OFF_PC,r0
258 mov.l @(r0,r15),r6 ! pc
259 mov.l 1f,r0
260 jmp @r0
261 mov #0,r5 ! writeaccess is unknown
262 .align 2
263
2641: .long do_address_error
265
266restore_all:
267 cli
268#ifdef CONFIG_TRACE_IRQFLAGS
269 mov.l 1f, r0
270 jsr @r0
271 nop
272#endif
273 mov r15,r0
274 mov.l $cpu_mode,r2
275 mov #OFF_SR,r3
276 mov.l @(r0,r3),r1
277 mov.l r1,@r2
278 shll2 r1 ! clear MD bit
279 shlr2 r1
280 mov.l @(OFF_SP,r0),r2
281 add #-8,r2
282 mov.l r2,@(OFF_SP,r0) ! point exception frame top
283 mov.l r1,@(4,r2) ! set sr
284 mov #OFF_PC,r3
285 mov.l @(r0,r3),r1
286 mov.l r1,@r2 ! set pc
287 add #4*16+4,r0
288 lds.l @r0+,pr
289 add #4,r0 ! skip sr
290 ldc.l @r0+,gbr
291 lds.l @r0+,mach
292 lds.l @r0+,macl
293 get_current_thread_info r0, r1
294 mov.l $current_thread_info,r1
295 mov.l r0,@r1
296 mov.l @r15+,r0
297 mov.l @r15+,r1
298 mov.l @r15+,r2
299 mov.l @r15+,r3
300 mov.l @r15+,r4
301 mov.l @r15+,r5
302 mov.l @r15+,r6
303 mov.l @r15+,r7
304 mov.l @r15+,r8
305 mov.l @r15+,r9
306 mov.l @r15+,r10
307 mov.l @r15+,r11
308 mov.l @r15+,r12
309 mov.l @r15+,r13
310 mov.l @r15+,r14
311 mov.l @r15,r15
312 rte
313 nop
314
315#ifdef CONFIG_TRACE_IRQFLAGS
3161: .long trace_hardirqs_off
317#endif
318$current_thread_info:
319 .long __current_thread_info
320$cpu_mode:
321 .long __cpu_mode
322
323! common exception handler
324#include "../../entry-common.S"
325
326 .data
327! cpu operation mode
328! bit30 = MD (compatible SH3/4)
329__cpu_mode:
330 .long 0x40000000
331
332 .section .bss
333__current_thread_info:
334 .long 0
335
336ENTRY(exception_handling_table)
337 .space 4*32
diff --git a/arch/sh/kernel/cpu/sh2/ex.S b/arch/sh/kernel/cpu/sh2/ex.S
new file mode 100644
index 000000000000..6d285af7846c
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/ex.S
@@ -0,0 +1,46 @@
1/*
2 * arch/sh/kernel/cpu/sh2/ex.S
3 *
4 * The SH-2 exception vector table
5 *
6 * Copyright (C) 2005 Yoshinori Sato
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/linkage.h>
14
15!
16! convert Exception Vector to Exception Number
17!
18exception_entry:
19no = 0
20 .rept 256
21 mov.l r0,@-sp
22 mov #no,r0
23 bra exception_trampoline
24 and #0xff,r0
25no = no + 1
26 .endr
27exception_trampoline:
28 mov.l r1,@-sp
29 mov.l $exception_handler,r1
30 jmp @r1
31
32 .align 2
33$exception_entry:
34 .long exception_entry
35$exception_handler:
36 .long exception_handler
37!
38! Exception Vector Base
39!
40 .align 2
41ENTRY(vbr_base)
42vector = 0
43 .rept 256
44 .long exception_entry + vector * 8
45vector = vector + 1
46 .endr
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c
index f17a2a0d588e..ba527d9b5024 100644
--- a/arch/sh/kernel/cpu/sh2/probe.c
+++ b/arch/sh/kernel/cpu/sh2/probe.c
@@ -17,17 +17,23 @@
17 17
18int __init detect_cpu_and_cache_system(void) 18int __init detect_cpu_and_cache_system(void)
19{ 19{
20 /* 20#if defined(CONFIG_CPU_SUBTYPE_SH7604)
21 * For now, assume SH7604 .. fix this later.
22 */
23 cpu_data->type = CPU_SH7604; 21 cpu_data->type = CPU_SH7604;
24 cpu_data->dcache.ways = 4; 22 cpu_data->dcache.ways = 4;
25 cpu_data->dcache.way_shift = 6; 23 cpu_data->dcache.way_incr = (1<<10);
26 cpu_data->dcache.sets = 64; 24 cpu_data->dcache.sets = 64;
27 cpu_data->dcache.entry_shift = 4; 25 cpu_data->dcache.entry_shift = 4;
28 cpu_data->dcache.linesz = L1_CACHE_BYTES; 26 cpu_data->dcache.linesz = L1_CACHE_BYTES;
29 cpu_data->dcache.flags = 0; 27 cpu_data->dcache.flags = 0;
30 28#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
29 cpu_data->type = CPU_SH7619;
30 cpu_data->dcache.ways = 4;
31 cpu_data->dcache.way_incr = (1<<12);
32 cpu_data->dcache.sets = 256;
33 cpu_data->dcache.entry_shift = 4;
34 cpu_data->dcache.linesz = L1_CACHE_BYTES;
35 cpu_data->dcache.flags = 0;
36#endif
31 /* 37 /*
32 * SH-2 doesn't have separate caches 38 * SH-2 doesn't have separate caches
33 */ 39 */
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
new file mode 100644
index 000000000000..79283e6c1d8f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c
@@ -0,0 +1,94 @@
1/*
2 * SH7619 Setup
3 *
4 * Copyright (C) 2006 Yoshinori Sato
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/platform_device.h>
11#include <linux/init.h>
12#include <linux/serial.h>
13#include <asm/sci.h>
14
15static struct plat_sci_port sci_platform_data[] = {
16 {
17 .mapbase = 0xf8400000,
18 .flags = UPF_BOOT_AUTOCONF,
19 .type = PORT_SCIF,
20 .irqs = { 88, 89, 91, 90},
21 }, {
22 .mapbase = 0xf8410000,
23 .flags = UPF_BOOT_AUTOCONF,
24 .type = PORT_SCIF,
25 .irqs = { 92, 93, 95, 94},
26 }, {
27 .mapbase = 0xf8420000,
28 .flags = UPF_BOOT_AUTOCONF,
29 .type = PORT_SCIF,
30 .irqs = { 96, 97, 99, 98},
31 }, {
32 .flags = 0,
33 }
34};
35
36static struct platform_device sci_device = {
37 .name = "sh-sci",
38 .id = -1,
39 .dev = {
40 .platform_data = sci_platform_data,
41 },
42};
43
44static struct platform_device *sh7619_devices[] __initdata = {
45 &sci_device,
46};
47
48static int __init sh7619_devices_setup(void)
49{
50 return platform_add_devices(sh7619_devices,
51 ARRAY_SIZE(sh7619_devices));
52}
53__initcall(sh7619_devices_setup);
54
55#define INTC_IPRC 0xf8080000UL
56#define INTC_IPRD 0xf8080002UL
57
58#define CMI0_IRQ 86
59
60#define SCIF0_ERI_IRQ 88
61#define SCIF0_RXI_IRQ 89
62#define SCIF0_BRI_IRQ 90
63#define SCIF0_TXI_IRQ 91
64
65#define SCIF1_ERI_IRQ 92
66#define SCIF1_RXI_IRQ 93
67#define SCIF1_BRI_IRQ 94
68#define SCIF1_TXI_IRQ 95
69
70#define SCIF2_BRI_IRQ 96
71#define SCIF2_ERI_IRQ 97
72#define SCIF2_RXI_IRQ 98
73#define SCIF2_TXI_IRQ 99
74
75static struct ipr_data sh7619_ipr_map[] = {
76 { CMI0_IRQ, INTC_IPRC, 1, 2 },
77 { SCIF0_ERI_IRQ, INTC_IPRD, 3, 3 },
78 { SCIF0_RXI_IRQ, INTC_IPRD, 3, 3 },
79 { SCIF0_BRI_IRQ, INTC_IPRD, 3, 3 },
80 { SCIF0_TXI_IRQ, INTC_IPRD, 3, 3 },
81 { SCIF1_ERI_IRQ, INTC_IPRD, 2, 3 },
82 { SCIF1_RXI_IRQ, INTC_IPRD, 2, 3 },
83 { SCIF1_BRI_IRQ, INTC_IPRD, 2, 3 },
84 { SCIF1_TXI_IRQ, INTC_IPRD, 2, 3 },
85 { SCIF2_ERI_IRQ, INTC_IPRD, 1, 3 },
86 { SCIF2_RXI_IRQ, INTC_IPRD, 1, 3 },
87 { SCIF2_BRI_IRQ, INTC_IPRD, 1, 3 },
88 { SCIF2_TXI_IRQ, INTC_IPRD, 1, 3 },
89};
90
91void __init init_IRQ_ipr(void)
92{
93 make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map));
94}
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile
new file mode 100644
index 000000000000..350972ae9410
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for the Linux/SuperH SH-2A backends.
3#
4
5obj-y := common.o probe.o
6
7common-y += $(addprefix ../sh2/, ex.o)
8common-y += $(addprefix ../sh2/, entry.o)
9
10obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7206.c b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
new file mode 100644
index 000000000000..a9ad309c6a33
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/clock-sh7206.c
@@ -0,0 +1,85 @@
1/*
2 * arch/sh/kernel/cpu/sh2a/clock-sh7206.c
3 *
4 * SH7206 support for the clock framework
5 *
6 * Copyright (C) 2006 Yoshinori Sato
7 *
8 * Based on clock-sh4.c
9 * Copyright (C) 2005 Paul Mundt
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
13 * for more details.
14 */
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <asm/clock.h>
18#include <asm/freq.h>
19#include <asm/io.h>
20
21const static int pll1rate[]={1,2,3,4,6,8};
22const static int pfc_divisors[]={1,2,3,4,6,8,12};
23#define ifc_divisors pfc_divisors
24
25#if (CONFIG_SH_CLK_MD == 2)
26#define PLL2 (4)
27#elif (CONFIG_SH_CLK_MD == 6)
28#define PLL2 (2)
29#elif (CONFIG_SH_CLK_MD == 7)
30#define PLL2 (1)
31#else
32#error "Illigal Clock Mode!"
33#endif
34
35static void master_clk_init(struct clk *clk)
36{
37 clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
38}
39
40static struct clk_ops sh7206_master_clk_ops = {
41 .init = master_clk_init,
42};
43
44static void module_clk_recalc(struct clk *clk)
45{
46 int idx = (ctrl_inw(FREQCR) & 0x0007);
47 clk->rate = clk->parent->rate / pfc_divisors[idx];
48}
49
50static struct clk_ops sh7206_module_clk_ops = {
51 .recalc = module_clk_recalc,
52};
53
54static void bus_clk_recalc(struct clk *clk)
55{
56 clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007];
57}
58
59static struct clk_ops sh7206_bus_clk_ops = {
60 .recalc = bus_clk_recalc,
61};
62
63static void cpu_clk_recalc(struct clk *clk)
64{
65 int idx = (ctrl_inw(FREQCR) & 0x0007);
66 clk->rate = clk->parent->rate / ifc_divisors[idx];
67}
68
69static struct clk_ops sh7206_cpu_clk_ops = {
70 .recalc = cpu_clk_recalc,
71};
72
73static struct clk_ops *sh7206_clk_ops[] = {
74 &sh7206_master_clk_ops,
75 &sh7206_module_clk_ops,
76 &sh7206_bus_clk_ops,
77 &sh7206_cpu_clk_ops,
78};
79
80void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
81{
82 if (idx < ARRAY_SIZE(sh7206_clk_ops))
83 *ops = sh7206_clk_ops[idx];
84}
85
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c
new file mode 100644
index 000000000000..87c6c0542089
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/probe.c
@@ -0,0 +1,39 @@
1/*
2 * arch/sh/kernel/cpu/sh2a/probe.c
3 *
4 * CPU Subtype Probing for SH-2A.
5 *
6 * Copyright (C) 2004, 2005 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12
13#include <linux/init.h>
14#include <asm/processor.h>
15#include <asm/cache.h>
16
17int __init detect_cpu_and_cache_system(void)
18{
19 /* Just SH7206 for now .. */
20 cpu_data->type = CPU_SH7206;
21
22 cpu_data->dcache.ways = 4;
23 cpu_data->dcache.way_incr = (1 << 11);
24 cpu_data->dcache.sets = 128;
25 cpu_data->dcache.entry_shift = 4;
26 cpu_data->dcache.linesz = L1_CACHE_BYTES;
27 cpu_data->dcache.flags = 0;
28
29 /*
30 * The icache is the same as the dcache as far as this setup is
31 * concerned. The only real difference in hardware is that the icache
32 * lacks the U bit that the dcache has, none of this has any bearing
33 * on the cache info.
34 */
35 cpu_data->icache = cpu_data->dcache;
36
37 return 0;
38}
39
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
new file mode 100644
index 000000000000..4b60fcc7d667
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c
@@ -0,0 +1,112 @@
1/*
2 * SH7206 Setup
3 *
4 * Copyright (C) 2006 Yoshinori Sato
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/platform_device.h>
11#include <linux/init.h>
12#include <linux/serial.h>
13#include <asm/sci.h>
14
15static struct plat_sci_port sci_platform_data[] = {
16 {
17 .mapbase = 0xfffe8000,
18 .flags = UPF_BOOT_AUTOCONF,
19 .type = PORT_SCIF,
20 .irqs = { 241, 242, 243, 240},
21 }, {
22 .mapbase = 0xfffe8800,
23 .flags = UPF_BOOT_AUTOCONF,
24 .type = PORT_SCIF,
25 .irqs = { 247, 244, 245, 246},
26 }, {
27 .mapbase = 0xfffe9000,
28 .flags = UPF_BOOT_AUTOCONF,
29 .type = PORT_SCIF,
30 .irqs = { 249, 250, 251, 248},
31 }, {
32 .mapbase = 0xfffe9800,
33 .flags = UPF_BOOT_AUTOCONF,
34 .type = PORT_SCIF,
35 .irqs = { 253, 254, 255, 252},
36 }, {
37 .flags = 0,
38 }
39};
40
41static struct platform_device sci_device = {
42 .name = "sh-sci",
43 .id = -1,
44 .dev = {
45 .platform_data = sci_platform_data,
46 },
47};
48
49static struct platform_device *sh7206_devices[] __initdata = {
50 &sci_device,
51};
52
53static int __init sh7206_devices_setup(void)
54{
55 return platform_add_devices(sh7206_devices,
56 ARRAY_SIZE(sh7206_devices));
57}
58__initcall(sh7206_devices_setup);
59
60#define INTC_IPR08 0xfffe0c04UL
61#define INTC_IPR09 0xfffe0c06UL
62#define INTC_IPR14 0xfffe0c10UL
63
64#define CMI0_IRQ 140
65
66#define MTU1_TGI1A 164
67
68#define SCIF0_BRI_IRQ 240
69#define SCIF0_ERI_IRQ 241
70#define SCIF0_RXI_IRQ 242
71#define SCIF0_TXI_IRQ 243
72
73#define SCIF1_BRI_IRQ 244
74#define SCIF1_ERI_IRQ 245
75#define SCIF1_RXI_IRQ 246
76#define SCIF1_TXI_IRQ 247
77
78#define SCIF2_BRI_IRQ 248
79#define SCIF2_ERI_IRQ 249
80#define SCIF2_RXI_IRQ 250
81#define SCIF2_TXI_IRQ 251
82
83#define SCIF3_BRI_IRQ 252
84#define SCIF3_ERI_IRQ 253
85#define SCIF3_RXI_IRQ 254
86#define SCIF3_TXI_IRQ 255
87
88static struct ipr_data sh7206_ipr_map[] = {
89 { CMI0_IRQ, INTC_IPR08, 3, 2 },
90 { MTU2_TGI1A, INTC_IPR09, 1, 2 },
91 { SCIF0_ERI_IRQ, INTC_IPR14, 3, 3 },
92 { SCIF0_RXI_IRQ, INTC_IPR14, 3, 3 },
93 { SCIF0_BRI_IRQ, INTC_IPR14, 3, 3 },
94 { SCIF0_TXI_IRQ, INTC_IPR14, 3, 3 },
95 { SCIF1_ERI_IRQ, INTC_IPR14, 2, 3 },
96 { SCIF1_RXI_IRQ, INTC_IPR14, 2, 3 },
97 { SCIF1_BRI_IRQ, INTC_IPR14, 2, 3 },
98 { SCIF1_TXI_IRQ, INTC_IPR14, 2, 3 },
99 { SCIF2_ERI_IRQ, INTC_IPR14, 1, 3 },
100 { SCIF2_RXI_IRQ, INTC_IPR14, 1, 3 },
101 { SCIF2_BRI_IRQ, INTC_IPR14, 1, 3 },
102 { SCIF2_TXI_IRQ, INTC_IPR14, 1, 3 },
103 { SCIF3_ERI_IRQ, INTC_IPR14, 0, 3 },
104 { SCIF3_RXI_IRQ, INTC_IPR14, 0, 3 },
105 { SCIF3_BRI_IRQ, INTC_IPR14, 0, 3 },
106 { SCIF3_TXI_IRQ, INTC_IPR14, 0, 3 },
107};
108
109void __init init_IRQ_ipr(void)
110{
111 make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map));
112}
diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile
index 58d3815695ff..83905e4e4387 100644
--- a/arch/sh/kernel/cpu/sh3/Makefile
+++ b/arch/sh/kernel/cpu/sh3/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the Linux/SuperH SH-3 backends. 2# Makefile for the Linux/SuperH SH-3 backends.
3# 3#
4 4
5obj-y := ex.o probe.o 5obj-y := ex.o probe.o entry.o
6 6
7# CPU subtype setup 7# CPU subtype setup
8obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o 8obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
index 10461a745e5f..b791a29fdb62 100644
--- a/arch/sh/kernel/cpu/sh3/clock-sh7709.c
+++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c
@@ -24,7 +24,7 @@ static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
24 24
25static void set_bus_parent(struct clk *clk) 25static void set_bus_parent(struct clk *clk)
26{ 26{
27 struct clk *bus_clk = clk_get("bus_clk"); 27 struct clk *bus_clk = clk_get(NULL, "bus_clk");
28 clk->parent = bus_clk; 28 clk->parent = bus_clk;
29 clk_put(bus_clk); 29 clk_put(bus_clk);
30} 30}
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 39aaefb2d83f..8c0dc2700c69 100644
--- a/arch/sh/kernel/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/arch/sh/entry.S 2 * arch/sh/kernel/entry.S
3 * 3 *
4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 4 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
5 * Copyright (C) 2003 - 2006 Paul Mundt 5 * Copyright (C) 2003 - 2006 Paul Mundt
@@ -7,15 +7,16 @@
7 * This file is subject to the terms and conditions of the GNU General Public 7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive 8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details. 9 * for more details.
10 *
11 */ 10 */
12#include <linux/sys.h> 11#include <linux/sys.h>
13#include <linux/errno.h> 12#include <linux/errno.h>
14#include <linux/linkage.h> 13#include <linux/linkage.h>
15#include <asm/asm-offsets.h> 14#include <asm/asm-offsets.h>
16#include <asm/thread_info.h> 15#include <asm/thread_info.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/unistd.h> 16#include <asm/unistd.h>
17#include <asm/cpu/mmu_context.h>
18#include <asm/pgtable.h>
19#include <asm/page.h>
19 20
20! NOTE: 21! NOTE:
21! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address 22! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
@@ -81,6 +82,8 @@ OFF_TRA = (16*4+6*4)
81#define k_g_imask r6_bank /* r6_bank1 */ 82#define k_g_imask r6_bank /* r6_bank1 */
82#define current r7 /* r7_bank1 */ 83#define current r7 /* r7_bank1 */
83 84
85#include <asm/entry-macros.S>
86
84/* 87/*
85 * Kernel mode register usage: 88 * Kernel mode register usage:
86 * k0 scratch 89 * k0 scratch
@@ -107,26 +110,6 @@ OFF_TRA = (16*4+6*4)
107! this first version depends *much* on C implementation. 110! this first version depends *much* on C implementation.
108! 111!
109 112
110#define CLI() \
111 stc sr, r0; \
112 or #0xf0, r0; \
113 ldc r0, sr
114
115#define STI() \
116 mov.l __INV_IMASK, r11; \
117 stc sr, r10; \
118 and r11, r10; \
119 stc k_g_imask, r11; \
120 or r11, r10; \
121 ldc r10, sr
122
123#if defined(CONFIG_PREEMPT)
124# define preempt_stop() CLI()
125#else
126# define preempt_stop()
127# define resume_kernel restore_all
128#endif
129
130#if defined(CONFIG_MMU) 113#if defined(CONFIG_MMU)
131 .align 2 114 .align 2
132ENTRY(tlb_miss_load) 115ENTRY(tlb_miss_load)
@@ -155,29 +138,14 @@ ENTRY(tlb_protection_violation_store)
155 138
156call_dpf: 139call_dpf:
157 mov.l 1f, r0 140 mov.l 1f, r0
158 mov r5, r8 141 mov.l @r0, r6 ! address
159 mov.l @r0, r6
160 mov r6, r9
161 mov.l 2f, r0
162 sts pr, r10
163 jsr @r0
164 mov r15, r4
165 !
166 tst r0, r0
167 bf/s 0f
168 lds r10, pr
169 rts
170 nop
1710: STI()
172 mov.l 3f, r0 142 mov.l 3f, r0
173 mov r9, r6 143
174 mov r8, r5
175 jmp @r0 144 jmp @r0
176 mov r15, r4 145 mov r15, r4 ! regs
177 146
178 .align 2 147 .align 2
1791: .long MMU_TEA 1481: .long MMU_TEA
1802: .long __do_page_fault
1813: .long do_page_fault 1493: .long do_page_fault
182 150
183 .align 2 151 .align 2
@@ -203,32 +171,6 @@ call_dae:
2032: .long do_address_error 1712: .long do_address_error
204#endif /* CONFIG_MMU */ 172#endif /* CONFIG_MMU */
205 173
206#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
207! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
208! If both are configured, handle the debug traps (breakpoints) in SW,
209! but still allow BIOS traps to FW.
210
211 .align 2
212debug_kernel:
213#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
214 /* Force BIOS call to FW (debug_trap put TRA in r8) */
215 mov r8,r0
216 shlr2 r0
217 cmp/eq #0x3f,r0
218 bt debug_kernel_fw
219#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
220
221debug_enter:
222#if defined(CONFIG_SH_KGDB)
223 /* Jump to kgdb, pass stacked regs as arg */
224debug_kernel_sw:
225 mov.l 3f, r0
226 jmp @r0
227 mov r15, r4
228 .align 2
2293: .long kgdb_handle_exception
230#endif /* CONFIG_SH_KGDB */
231
232#if defined(CONFIG_SH_STANDARD_BIOS) 174#if defined(CONFIG_SH_STANDARD_BIOS)
233 /* Unwind the stack and jmp to the debug entry */ 175 /* Unwind the stack and jmp to the debug entry */
234debug_kernel_fw: 176debug_kernel_fw:
@@ -269,276 +211,6 @@ debug_kernel_fw:
2692: .long gdb_vbr_vector 2112: .long gdb_vbr_vector
270#endif /* CONFIG_SH_STANDARD_BIOS */ 212#endif /* CONFIG_SH_STANDARD_BIOS */
271 213
272#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
273
274
275 .align 2
276debug_trap:
277#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
278 mov #OFF_SR, r0
279 mov.l @(r0,r15), r0 ! get status register
280 shll r0
281 shll r0 ! kernel space?
282 bt/s debug_kernel
283#endif
284 mov.l @r15, r0 ! Restore R0 value
285 mov.l 1f, r8
286 jmp @r8
287 nop
288
289 .align 2
290ENTRY(exception_error)
291 !
292 STI()
293 mov.l 2f, r0
294 jmp @r0
295 nop
296
297!
298 .align 2
2991: .long break_point_trap_software
3002: .long do_exception_error
301
302 .align 2
303ret_from_exception:
304 preempt_stop()
305ENTRY(ret_from_irq)
306 !
307 mov #OFF_SR, r0
308 mov.l @(r0,r15), r0 ! get status register
309 shll r0
310 shll r0 ! kernel space?
311 bt/s resume_kernel ! Yes, it's from kernel, go back soon
312 GET_THREAD_INFO(r8)
313
314#ifdef CONFIG_PREEMPT
315 bra resume_userspace
316 nop
317ENTRY(resume_kernel)
318 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
319 tst r0, r0
320 bf noresched
321need_resched:
322 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
323 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
324 bt noresched
325
326 mov #OFF_SR, r0
327 mov.l @(r0,r15), r0 ! get status register
328 and #0xf0, r0 ! interrupts off (exception path)?
329 cmp/eq #0xf0, r0
330 bt noresched
331
332 mov.l 1f, r0
333 mov.l r0, @(TI_PRE_COUNT,r8)
334
335 STI()
336 mov.l 2f, r0
337 jsr @r0
338 nop
339 mov #0, r0
340 mov.l r0, @(TI_PRE_COUNT,r8)
341 CLI()
342
343 bra need_resched
344 nop
345noresched:
346 bra restore_all
347 nop
348
349 .align 2
3501: .long PREEMPT_ACTIVE
3512: .long schedule
352#endif
353
354ENTRY(resume_userspace)
355 ! r8: current_thread_info
356 CLI()
357 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
358 tst #_TIF_WORK_MASK, r0
359 bt/s restore_all
360 tst #_TIF_NEED_RESCHED, r0
361
362 .align 2
363work_pending:
364 ! r0: current_thread_info->flags
365 ! r8: current_thread_info
366 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
367 bf/s work_resched
368 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
369work_notifysig:
370 bt/s restore_all
371 mov r15, r4
372 mov r12, r5 ! set arg1(save_r0)
373 mov r0, r6
374 mov.l 2f, r1
375 mova restore_all, r0
376 jmp @r1
377 lds r0, pr
378work_resched:
379#ifndef CONFIG_PREEMPT
380 ! gUSA handling
381 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
382 mov r0, r1
383 shll r0
384 bf/s 1f
385 shll r0
386 bf/s 1f
387 mov #OFF_PC, r0
388 ! SP >= 0xc0000000 : gUSA mark
389 mov.l @(r0,r15), r2 ! get user space PC (program counter)
390 mov.l @(OFF_R0,r15), r3 ! end point
391 cmp/hs r3, r2 ! r2 >= r3?
392 bt 1f
393 add r3, r1 ! rewind point #2
394 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
395 !
3961:
397#endif
398 mov.l 1f, r1
399 jsr @r1 ! schedule
400 nop
401 CLI()
402 !
403 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
404 tst #_TIF_WORK_MASK, r0
405 bt restore_all
406 bra work_pending
407 tst #_TIF_NEED_RESCHED, r0
408
409 .align 2
4101: .long schedule
4112: .long do_notify_resume
412
413 .align 2
414syscall_exit_work:
415 ! r0: current_thread_info->flags
416 ! r8: current_thread_info
417 tst #_TIF_SYSCALL_TRACE, r0
418 bt/s work_pending
419 tst #_TIF_NEED_RESCHED, r0
420 STI()
421 ! XXX setup arguments...
422 mov.l 4f, r0 ! do_syscall_trace
423 jsr @r0
424 nop
425 bra resume_userspace
426 nop
427
428 .align 2
429syscall_trace_entry:
430 ! Yes it is traced.
431 ! XXX setup arguments...
432 mov.l 4f, r11 ! Call do_syscall_trace which notifies
433 jsr @r11 ! superior (will chomp R[0-7])
434 nop
435 ! Reload R0-R4 from kernel stack, where the
436 ! parent may have modified them using
437 ! ptrace(POKEUSR). (Note that R0-R2 are
438 ! used by the system call handler directly
439 ! from the kernel stack anyway, so don't need
440 ! to be reloaded here.) This allows the parent
441 ! to rewrite system calls and args on the fly.
442 mov.l @(OFF_R4,r15), r4 ! arg0
443 mov.l @(OFF_R5,r15), r5
444 mov.l @(OFF_R6,r15), r6
445 mov.l @(OFF_R7,r15), r7 ! arg3
446 mov.l @(OFF_R3,r15), r3 ! syscall_nr
447 ! Arrange for do_syscall_trace to be called
448 ! again as the system call returns.
449 mov.l 2f, r10 ! Number of syscalls
450 cmp/hs r10, r3
451 bf syscall_call
452 mov #-ENOSYS, r0
453 bra syscall_exit
454 mov.l r0, @(OFF_R0,r15) ! Return value
455
456/*
457 * Syscall interface:
458 *
459 * Syscall #: R3
460 * Arguments #0 to #3: R4--R7
461 * Arguments #4 to #6: R0, R1, R2
462 * TRA: (number of arguments + 0x10) x 4
463 *
464 * This code also handles delegating other traps to the BIOS/gdb stub
465 * according to:
466 *
467 * Trap number
468 * (TRA>>2) Purpose
469 * -------- -------
470 * 0x0-0xf old syscall ABI
471 * 0x10-0x1f new syscall ABI
472 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
473 *
474 * Note: When we're first called, the TRA value must be shifted
475 * right 2 bits in order to get the value that was used as the "trapa"
476 * argument.
477 */
478
479 .align 2
480 .globl ret_from_fork
481ret_from_fork:
482 mov.l 1f, r8
483 jsr @r8
484 mov r0, r4
485 bra syscall_exit
486 nop
487 .align 2
4881: .long schedule_tail
489 !
490ENTRY(system_call)
491 mov.l 1f, r9
492 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
493 !
494 ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
495 mov #0x7f, r9
496 cmp/hi r9, r8
497 bt/s 0f
498 mov #OFF_TRA, r9
499 add r15, r9
500 !
501 mov.l r8, @r9 ! set TRA value to tra
502 STI()
503 ! Call the system call handler through the table.
504 ! First check for bad syscall number
505 mov r3, r9
506 mov.l 2f, r8 ! Number of syscalls
507 cmp/hs r8, r9
508 bf/s good_system_call
509 GET_THREAD_INFO(r8)
510syscall_badsys: ! Bad syscall number
511 mov #-ENOSYS, r0
512 bra resume_userspace
513 mov.l r0, @(OFF_R0,r15) ! Return value
514 !
5150:
516 bra debug_trap
517 nop
518 !
519good_system_call: ! Good syscall number
520 mov.l @(TI_FLAGS,r8), r8
521 mov #_TIF_SYSCALL_TRACE, r10
522 tst r10, r8
523 bf syscall_trace_entry
524 !
525syscall_call:
526 shll2 r9 ! x4
527 mov.l 3f, r8 ! Load the address of sys_call_table
528 add r8, r9
529 mov.l @r9, r8
530 jsr @r8 ! jump to specific syscall handler
531 nop
532 mov.l @(OFF_R0,r15), r12 ! save r0
533 mov.l r0, @(OFF_R0,r15) ! save the return value
534 !
535syscall_exit:
536 CLI()
537 !
538 GET_THREAD_INFO(r8)
539 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
540 tst #_TIF_ALLWORK_MASK, r0
541 bf syscall_exit_work
542restore_all: 214restore_all:
543 mov.l @r15+, r0 215 mov.l @r15+, r0
544 mov.l @r15+, r1 216 mov.l @r15+, r1
@@ -606,7 +278,9 @@ skip_restore:
606 ! 278 !
607 ! Calculate new SR value 279 ! Calculate new SR value
608 mov k3, k2 ! original SR value 280 mov k3, k2 ! original SR value
609 mov.l 9f, k1 281 mov #0xf0, k1
282 extu.b k1, k1
283 not k1, k1
610 and k1, k2 ! Mask orignal SR value 284 and k1, k2 ! Mask orignal SR value
611 ! 285 !
612 mov k3, k0 ! Calculate IMASK-bits 286 mov k3, k0 ! Calculate IMASK-bits
@@ -632,16 +306,12 @@ skip_restore:
632 nop 306 nop
633 307
634 .align 2 308 .align 2
6351: .long TRA
6362: .long NR_syscalls
6373: .long sys_call_table
6384: .long do_syscall_trace
6395: .long 0x00001000 ! DSP 3095: .long 0x00001000 ! DSP
6407: .long 0x30000000 3107: .long 0x30000000
6419:
642__INV_IMASK:
643 .long 0xffffff0f ! ~(IMASK)
644 311
312! common exception handler
313#include "../../entry-common.S"
314
645! Exception Vector Base 315! Exception Vector Base
646! 316!
647! Should be aligned page boundary. 317! Should be aligned page boundary.
@@ -661,9 +331,176 @@ general_exception:
6612: .long ret_from_exception 3312: .long ret_from_exception
662! 332!
663! 333!
334
335/* This code makes some assumptions to improve performance.
336 * Make sure they are stil true. */
337#if PTRS_PER_PGD != PTRS_PER_PTE
338#error PGD and PTE sizes don't match
339#endif
340
341/* gas doesn't flag impossible values for mov #immediate as an error */
342#if (_PAGE_PRESENT >> 2) > 0x7f
343#error cannot load PAGE_PRESENT as an immediate
344#endif
345#if _PAGE_DIRTY > 0x7f
346#error cannot load PAGE_DIRTY as an immediate
347#endif
348#if (_PAGE_PRESENT << 2) != _PAGE_ACCESSED
349#error cannot derive PAGE_ACCESSED from PAGE_PRESENT
350#endif
351
352#if defined(CONFIG_CPU_SH4)
353#define ldmmupteh(r) mov.l 8f, r
354#else
355#define ldmmupteh(r) mov #MMU_PTEH, r
356#endif
357
664 .balign 1024,0,1024 358 .balign 1024,0,1024
665tlb_miss: 359tlb_miss:
666 mov.l 1f, k2 360#ifdef COUNT_EXCEPTIONS
361 ! Increment the counts
362 mov.l 9f, k1
363 mov.l @k1, k2
364 add #1, k2
365 mov.l k2, @k1
366#endif
367
368 ! k0 scratch
369 ! k1 pgd and pte pointers
370 ! k2 faulting address
371 ! k3 pgd and pte index masks
372 ! k4 shift
373
374 ! Load up the pgd entry (k1)
375
376 ldmmupteh(k0) ! 9 LS (latency=2) MMU_PTEH
377
378 mov.w 4f, k3 ! 8 LS (latency=2) (PTRS_PER_PGD-1) << 2
379 mov #-(PGDIR_SHIFT-2), k4 ! 6 EX
380
381 mov.l @(MMU_TEA-MMU_PTEH,k0), k2 ! 18 LS (latency=2)
382
383 mov.l @(MMU_TTB-MMU_PTEH,k0), k1 ! 18 LS (latency=2)
384
385 mov k2, k0 ! 5 MT (latency=0)
386 shld k4, k0 ! 99 EX
387
388 and k3, k0 ! 78 EX
389
390 mov.l @(k0, k1), k1 ! 21 LS (latency=2)
391 mov #-(PAGE_SHIFT-2), k4 ! 6 EX
392
393 ! Load up the pte entry (k2)
394
395 mov k2, k0 ! 5 MT (latency=0)
396 shld k4, k0 ! 99 EX
397
398 tst k1, k1 ! 86 MT
399
400 bt 20f ! 110 BR
401
402 and k3, k0 ! 78 EX
403 mov.w 5f, k4 ! 8 LS (latency=2) _PAGE_PRESENT
404
405 mov.l @(k0, k1), k2 ! 21 LS (latency=2)
406 add k0, k1 ! 49 EX
407
408#ifdef CONFIG_CPU_HAS_PTEA
409 ! Test the entry for present and _PAGE_ACCESSED
410
411 mov #-28, k3 ! 6 EX
412 mov k2, k0 ! 5 MT (latency=0)
413
414 tst k4, k2 ! 68 MT
415 shld k3, k0 ! 99 EX
416
417 bt 20f ! 110 BR
418
419 ! Set PTEA register
420 ! MMU_PTEA = ((pteval >> 28) & 0xe) | (pteval & 0x1)
421 !
422 ! k0=pte>>28, k1=pte*, k2=pte, k3=<unused>, k4=_PAGE_PRESENT
423
424 and #0xe, k0 ! 79 EX
425
426 mov k0, k3 ! 5 MT (latency=0)
427 mov k2, k0 ! 5 MT (latency=0)
428
429 and #1, k0 ! 79 EX
430
431 or k0, k3 ! 82 EX
432
433 ldmmupteh(k0) ! 9 LS (latency=2)
434 shll2 k4 ! 101 EX _PAGE_ACCESSED
435
436 tst k4, k2 ! 68 MT
437
438 mov.l k3, @(MMU_PTEA-MMU_PTEH,k0) ! 27 LS
439
440 mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK
441
442 ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
443#else
444
445 ! Test the entry for present and _PAGE_ACCESSED
446
447 mov.l 7f, k3 ! 9 LS (latency=2) _PAGE_FLAGS_HARDWARE_MASK
448 tst k4, k2 ! 68 MT
449
450 shll2 k4 ! 101 EX _PAGE_ACCESSED
451 ldmmupteh(k0) ! 9 LS (latency=2)
452
453 bt 20f ! 110 BR
454 tst k4, k2 ! 68 MT
455
456 ! k0=MMU_PTEH, k1=pte*, k2=pte, k3=_PAGE_FLAGS_HARDWARE, k4=_PAGE_ACCESSED
457
458#endif
459
460 ! Set up the entry
461
462 and k2, k3 ! 78 EX
463 bt/s 10f ! 108 BR
464
465 mov.l k3, @(MMU_PTEL-MMU_PTEH,k0) ! 27 LS
466
467 ldtlb ! 128 CO
468
469 ! At least one instruction between ldtlb and rte
470 nop ! 119 NOP
471
472 rte ! 126 CO
473
474 nop ! 119 NOP
475
476
47710: or k4, k2 ! 82 EX
478
479 ldtlb ! 128 CO
480
481 ! At least one instruction between ldtlb and rte
482 mov.l k2, @k1 ! 27 LS
483
484 rte ! 126 CO
485
486 ! Note we cannot execute mov here, because it is executed after
487 ! restoring SSR, so would be executed in user space.
488 nop ! 119 NOP
489
490
491 .align 5
492 ! Once cache line if possible...
4931: .long swapper_pg_dir
4944: .short (PTRS_PER_PGD-1) << 2
4955: .short _PAGE_PRESENT
4967: .long _PAGE_FLAGS_HARDWARE_MASK
4978: .long MMU_PTEH
498#ifdef COUNT_EXCEPTIONS
4999: .long exception_count_miss
500#endif
501
502 ! Either pgd or pte not present
50320: mov.l 1f, k2
667 mov.l 4f, k3 504 mov.l 4f, k3
668 bra handle_exception 505 bra handle_exception
669 mov.l @k2, k2 506 mov.l @k2, k2
@@ -710,8 +547,9 @@ ENTRY(handle_exception)
710 bt/s 1f ! It's a kernel to kernel transition. 547 bt/s 1f ! It's a kernel to kernel transition.
711 mov r15, k0 ! save original stack to k0 548 mov r15, k0 ! save original stack to k0
712 /* User space to kernel */ 549 /* User space to kernel */
713 mov #(THREAD_SIZE >> 8), k1 550 mov #(THREAD_SIZE >> 10), k1
714 shll8 k1 ! k1 := THREAD_SIZE 551 shll8 k1 ! k1 := THREAD_SIZE
552 shll2 k1
715 add current, k1 553 add current, k1
716 mov k1, r15 ! change to kernel stack 554 mov k1, r15 ! change to kernel stack
717 ! 555 !
@@ -761,7 +599,7 @@ skip_save:
761 ! Save the user registers on the stack. 599 ! Save the user registers on the stack.
762 mov.l k2, @-r15 ! EXPEVT 600 mov.l k2, @-r15 ! EXPEVT
763 601
764 mov #-1, k4 602 mov #-1, k4
765 mov.l k4, @-r15 ! set TRA (default: -1) 603 mov.l k4, @-r15 ! set TRA (default: -1)
766 ! 604 !
767 sts.l macl, @-r15 605 sts.l macl, @-r15
@@ -813,6 +651,15 @@ skip_save:
813 bf interrupt_exception 651 bf interrupt_exception
814 shlr2 r8 652 shlr2 r8
815 shlr r8 653 shlr r8
654
655#ifdef COUNT_EXCEPTIONS
656 mov.l 5f, r9
657 add r8, r9
658 mov.l @r9, r10
659 add #1, r10
660 mov.l r10, @r9
661#endif
662
816 mov.l 4f, r9 663 mov.l 4f, r9
817 add r8, r9 664 add r8, r9
818 mov.l @r9, r9 665 mov.l @r9, r9
@@ -826,6 +673,9 @@ skip_save:
8262: .long 0x000080f0 ! FD=1, IMASK=15 6732: .long 0x000080f0 ! FD=1, IMASK=15
8273: .long 0xcfffffff ! RB=0, BL=0 6743: .long 0xcfffffff ! RB=0, BL=0
8284: .long exception_handling_table 6754: .long exception_handling_table
676#ifdef COUNT_EXCEPTIONS
6775: .long exception_count_table
678#endif
829 679
830interrupt_exception: 680interrupt_exception:
831 mov.l 1f, r9 681 mov.l 1f, r9
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S
index 6be46f0686b7..ba3082d640b5 100644
--- a/arch/sh/kernel/cpu/sh3/ex.S
+++ b/arch/sh/kernel/cpu/sh3/ex.S
@@ -4,7 +4,7 @@
4 * The SH-3 exception vector table. 4 * The SH-3 exception vector table.
5 5
6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
7 * Copyright (C) 2003 Paul Mundt 7 * Copyright (C) 2003 - 2006 Paul Mundt
8 * 8 *
9 * This file is subject to the terms and conditions of the GNU General Public 9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive 10 * License. See the file "COPYING" in the main directory of this archive
@@ -49,3 +49,10 @@ ENTRY(nmi_slot)
49#endif 49#endif
50ENTRY(user_break_point_trap) 50ENTRY(user_break_point_trap)
51 .long break_point_trap /* 1E0 */ 51 .long break_point_trap /* 1E0 */
52
53 /*
54 * Pad the remainder of the table out, exceptions residing in far
55 * away offsets can be manually inserted in to their appropriate
56 * location via set_exception_table_{evt,vec}().
57 */
58 .balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile
index 8dbf3895ece7..19ca68c71884 100644
--- a/arch/sh/kernel/cpu/sh4/Makefile
+++ b/arch/sh/kernel/cpu/sh4/Makefile
@@ -2,7 +2,8 @@
2# Makefile for the Linux/SuperH SH-4 backends. 2# Makefile for the Linux/SuperH SH-4 backends.
3# 3#
4 4
5obj-y := ex.o probe.o 5obj-y := ex.o probe.o common.o
6common-y += $(addprefix ../sh3/, entry.o)
6 7
7obj-$(CONFIG_SH_FPU) += fpu.o 8obj-$(CONFIG_SH_FPU) += fpu.o
8obj-$(CONFIG_SH_STORE_QUEUES) += sq.o 9obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
@@ -11,17 +12,12 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o
11obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o 12obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o
12obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o 13obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o
13obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o 14obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o
14obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
15obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
16obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
17obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
18obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o 15obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o
19 16
20# Primary on-chip clocks (common) 17# Primary on-chip clocks (common)
18ifndef CONFIG_CPU_SH4A
21clock-$(CONFIG_CPU_SH4) := clock-sh4.o 19clock-$(CONFIG_CPU_SH4) := clock-sh4.o
22clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o 20endif
23clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
24clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
25 21
26# Additional clocks by subtype 22# Additional clocks by subtype
27clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o 23clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
index bfdf5fe8d948..fa2019aabd74 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
+++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c
@@ -97,7 +97,7 @@ static void shoc_clk_recalc(struct clk *clk)
97 97
98static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) 98static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate)
99{ 99{
100 struct clk *bclk = clk_get("bus_clk"); 100 struct clk *bclk = clk_get(NULL, "bus_clk");
101 unsigned long bclk_rate = clk_get_rate(bclk); 101 unsigned long bclk_rate = clk_get_rate(bclk);
102 102
103 clk_put(bclk); 103 clk_put(bclk);
@@ -151,7 +151,7 @@ static struct clk *sh4202_onchip_clocks[] = {
151 151
152static int __init sh4202_clk_init(void) 152static int __init sh4202_clk_init(void)
153{ 153{
154 struct clk *clk = clk_get("master_clk"); 154 struct clk *clk = clk_get(NULL, "master_clk");
155 int i; 155 int i;
156 156
157 for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { 157 for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) {
diff --git a/arch/sh/kernel/cpu/sh4/ex.S b/arch/sh/kernel/cpu/sh4/ex.S
index 3f4cd043e900..ac8ab57413cc 100644
--- a/arch/sh/kernel/cpu/sh4/ex.S
+++ b/arch/sh/kernel/cpu/sh4/ex.S
@@ -4,7 +4,7 @@
4 * The SH-4 exception vector table. 4 * The SH-4 exception vector table.
5 5
6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka 6 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
7 * Copyright (C) 2003 Paul Mundt 7 * Copyright (C) 2003 - 2006 Paul Mundt
8 * 8 *
9 * This file is subject to the terms and conditions of the GNU General Public 9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive 10 * License. See the file "COPYING" in the main directory of this archive
@@ -53,3 +53,10 @@ ENTRY(nmi_slot)
53#endif 53#endif
54ENTRY(user_break_point_trap) 54ENTRY(user_break_point_trap)
55 .long break_point_trap /* 1E0 */ 55 .long break_point_trap /* 1E0 */
56
57 /*
58 * Pad the remainder of the table out, exceptions residing in far
59 * away offsets can be manually inserted in to their appropriate
60 * location via set_exception_table_{evt,vec}().
61 */
62 .balign 4096,0,4096
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index f486c07e10e2..7624677f6628 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -282,11 +282,8 @@ ieee_fpe_handler (struct pt_regs *regs)
282 grab_fpu(regs); 282 grab_fpu(regs);
283 restore_fpu(tsk); 283 restore_fpu(tsk);
284 set_tsk_thread_flag(tsk, TIF_USEDFPU); 284 set_tsk_thread_flag(tsk, TIF_USEDFPU);
285 } else { 285 } else
286 tsk->thread.trap_no = 11;
287 tsk->thread.error_code = 0;
288 force_sig(SIGFPE, tsk); 286 force_sig(SIGFPE, tsk);
289 }
290 287
291 regs->pc = nextpc; 288 regs->pc = nextpc;
292 return 1; 289 return 1;
@@ -296,29 +293,29 @@ ieee_fpe_handler (struct pt_regs *regs)
296} 293}
297 294
298asmlinkage void 295asmlinkage void
299do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, 296do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6,
300 struct pt_regs regs) 297 unsigned long r7, struct pt_regs __regs)
301{ 298{
299 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
302 struct task_struct *tsk = current; 300 struct task_struct *tsk = current;
303 301
304 if (ieee_fpe_handler (&regs)) 302 if (ieee_fpe_handler(regs))
305 return; 303 return;
306 304
307 regs.pc += 2; 305 regs->pc += 2;
308 save_fpu(tsk, &regs); 306 save_fpu(tsk, regs);
309 tsk->thread.trap_no = 11;
310 tsk->thread.error_code = 0;
311 force_sig(SIGFPE, tsk); 307 force_sig(SIGFPE, tsk);
312} 308}
313 309
314asmlinkage void 310asmlinkage void
315do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, 311do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6,
316 unsigned long r7, struct pt_regs regs) 312 unsigned long r7, struct pt_regs __regs)
317{ 313{
314 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
318 struct task_struct *tsk = current; 315 struct task_struct *tsk = current;
319 316
320 grab_fpu(&regs); 317 grab_fpu(regs);
321 if (!user_mode(&regs)) { 318 if (!user_mode(regs)) {
322 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); 319 printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
323 return; 320 return;
324 } 321 }
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c
index c294de1e14a3..9031a22a2ce7 100644
--- a/arch/sh/kernel/cpu/sh4/probe.c
+++ b/arch/sh/kernel/cpu/sh4/probe.c
@@ -79,16 +79,16 @@ int __init detect_cpu_and_cache_system(void)
79 case 0x205: 79 case 0x205:
80 cpu_data->type = CPU_SH7750; 80 cpu_data->type = CPU_SH7750;
81 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 81 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
82 CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; 82 CPU_HAS_PERF_COUNTER;
83 break; 83 break;
84 case 0x206: 84 case 0x206:
85 cpu_data->type = CPU_SH7750S; 85 cpu_data->type = CPU_SH7750S;
86 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU | 86 cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
87 CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA; 87 CPU_HAS_PERF_COUNTER;
88 break; 88 break;
89 case 0x1100: 89 case 0x1100:
90 cpu_data->type = CPU_SH7751; 90 cpu_data->type = CPU_SH7751;
91 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 91 cpu_data->flags |= CPU_HAS_FPU;
92 break; 92 break;
93 case 0x2000: 93 case 0x2000:
94 cpu_data->type = CPU_SH73180; 94 cpu_data->type = CPU_SH73180;
@@ -119,30 +119,38 @@ int __init detect_cpu_and_cache_system(void)
119 break; 119 break;
120 case 0x3000: 120 case 0x3000:
121 case 0x3003: 121 case 0x3003:
122 case 0x3009:
122 cpu_data->type = CPU_SH7343; 123 cpu_data->type = CPU_SH7343;
123 cpu_data->icache.ways = 4; 124 cpu_data->icache.ways = 4;
124 cpu_data->dcache.ways = 4; 125 cpu_data->dcache.ways = 4;
125 cpu_data->flags |= CPU_HAS_LLSC; 126 cpu_data->flags |= CPU_HAS_LLSC;
126 break; 127 break;
128 case 0x3008:
129 if (prr == 0xa0) {
130 cpu_data->type = CPU_SH7722;
131 cpu_data->icache.ways = 4;
132 cpu_data->dcache.ways = 4;
133 cpu_data->flags |= CPU_HAS_LLSC;
134 }
135 break;
127 case 0x8000: 136 case 0x8000:
128 cpu_data->type = CPU_ST40RA; 137 cpu_data->type = CPU_ST40RA;
129 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 138 cpu_data->flags |= CPU_HAS_FPU;
130 break; 139 break;
131 case 0x8100: 140 case 0x8100:
132 cpu_data->type = CPU_ST40GX1; 141 cpu_data->type = CPU_ST40GX1;
133 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 142 cpu_data->flags |= CPU_HAS_FPU;
134 break; 143 break;
135 case 0x700: 144 case 0x700:
136 cpu_data->type = CPU_SH4_501; 145 cpu_data->type = CPU_SH4_501;
137 cpu_data->icache.ways = 2; 146 cpu_data->icache.ways = 2;
138 cpu_data->dcache.ways = 2; 147 cpu_data->dcache.ways = 2;
139 cpu_data->flags |= CPU_HAS_PTEA;
140 break; 148 break;
141 case 0x600: 149 case 0x600:
142 cpu_data->type = CPU_SH4_202; 150 cpu_data->type = CPU_SH4_202;
143 cpu_data->icache.ways = 2; 151 cpu_data->icache.ways = 2;
144 cpu_data->dcache.ways = 2; 152 cpu_data->dcache.ways = 2;
145 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 153 cpu_data->flags |= CPU_HAS_FPU;
146 break; 154 break;
147 case 0x500 ... 0x501: 155 case 0x500 ... 0x501:
148 switch (prr) { 156 switch (prr) {
@@ -160,7 +168,7 @@ int __init detect_cpu_and_cache_system(void)
160 cpu_data->icache.ways = 2; 168 cpu_data->icache.ways = 2;
161 cpu_data->dcache.ways = 2; 169 cpu_data->dcache.ways = 2;
162 170
163 cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; 171 cpu_data->flags |= CPU_HAS_FPU;
164 172
165 break; 173 break;
166 default: 174 default:
@@ -173,6 +181,10 @@ int __init detect_cpu_and_cache_system(void)
173 cpu_data->dcache.ways = 1; 181 cpu_data->dcache.ways = 1;
174#endif 182#endif
175 183
184#ifdef CONFIG_CPU_HAS_PTEA
185 cpu_data->flags |= CPU_HAS_PTEA;
186#endif
187
176 /* 188 /*
177 * On anything that's not a direct-mapped cache, look to the CVR 189 * On anything that's not a direct-mapped cache, look to the CVR
178 * for I/D-cache specifics. 190 * for I/D-cache specifics.
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
index 50812d57c1c1..cbac27634c0b 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
@@ -2,6 +2,7 @@
2 * SH7750/SH7751 Setup 2 * SH7750/SH7751 Setup
3 * 3 *
4 * Copyright (C) 2006 Paul Mundt 4 * Copyright (C) 2006 Paul Mundt
5 * Copyright (C) 2006 Jamie Lenehan
5 * 6 *
6 * This file is subject to the terms and conditions of the GNU General Public 7 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive 8 * License. See the file "COPYING" in the main directory of this archive
@@ -10,8 +11,39 @@
10#include <linux/platform_device.h> 11#include <linux/platform_device.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/serial.h> 13#include <linux/serial.h>
14#include <linux/io.h>
13#include <asm/sci.h> 15#include <asm/sci.h>
14 16
17static struct resource rtc_resources[] = {
18 [0] = {
19 .start = 0xffc80000,
20 .end = 0xffc80000 + 0x58 - 1,
21 .flags = IORESOURCE_IO,
22 },
23 [1] = {
24 /* Period IRQ */
25 .start = 21,
26 .flags = IORESOURCE_IRQ,
27 },
28 [2] = {
29 /* Carry IRQ */
30 .start = 22,
31 .flags = IORESOURCE_IRQ,
32 },
33 [3] = {
34 /* Alarm IRQ */
35 .start = 20,
36 .flags = IORESOURCE_IRQ,
37 },
38};
39
40static struct platform_device rtc_device = {
41 .name = "sh-rtc",
42 .id = -1,
43 .num_resources = ARRAY_SIZE(rtc_resources),
44 .resource = rtc_resources,
45};
46
15static struct plat_sci_port sci_platform_data[] = { 47static struct plat_sci_port sci_platform_data[] = {
16 { 48 {
17 .mapbase = 0xffe00000, 49 .mapbase = 0xffe00000,
@@ -37,6 +69,7 @@ static struct platform_device sci_device = {
37}; 69};
38 70
39static struct platform_device *sh7750_devices[] __initdata = { 71static struct platform_device *sh7750_devices[] __initdata = {
72 &rtc_device,
40 &sci_device, 73 &sci_device,
41}; 74};
42 75
@@ -46,3 +79,71 @@ static int __init sh7750_devices_setup(void)
46 ARRAY_SIZE(sh7750_devices)); 79 ARRAY_SIZE(sh7750_devices));
47} 80}
48__initcall(sh7750_devices_setup); 81__initcall(sh7750_devices_setup);
82
83static struct ipr_data sh7750_ipr_map[] = {
84 /* IRQ, IPR-idx, shift, priority */
85 { 16, 0, 12, 2 }, /* TMU0 TUNI*/
86 { 17, 0, 12, 2 }, /* TMU1 TUNI */
87 { 18, 0, 4, 2 }, /* TMU2 TUNI */
88 { 19, 0, 4, 2 }, /* TMU2 TIPCI */
89 { 27, 1, 12, 2 }, /* WDT ITI */
90 { 20, 0, 0, 2 }, /* RTC ATI (alarm) */
91 { 21, 0, 0, 2 }, /* RTC PRI (period) */
92 { 22, 0, 0, 2 }, /* RTC CUI (carry) */
93 { 23, 1, 4, 3 }, /* SCI ERI */
94 { 24, 1, 4, 3 }, /* SCI RXI */
95 { 25, 1, 4, 3 }, /* SCI TXI */
96 { 40, 2, 4, 3 }, /* SCIF ERI */
97 { 41, 2, 4, 3 }, /* SCIF RXI */
98 { 42, 2, 4, 3 }, /* SCIF BRI */
99 { 43, 2, 4, 3 }, /* SCIF TXI */
100 { 34, 2, 8, 7 }, /* DMAC DMTE0 */
101 { 35, 2, 8, 7 }, /* DMAC DMTE1 */
102 { 36, 2, 8, 7 }, /* DMAC DMTE2 */
103 { 37, 2, 8, 7 }, /* DMAC DMTE3 */
104 { 28, 2, 8, 7 }, /* DMAC DMAE */
105};
106
107static struct ipr_data sh7751_ipr_map[] = {
108 { 44, 2, 8, 7 }, /* DMAC DMTE4 */
109 { 45, 2, 8, 7 }, /* DMAC DMTE5 */
110 { 46, 2, 8, 7 }, /* DMAC DMTE6 */
111 { 47, 2, 8, 7 }, /* DMAC DMTE7 */
112 /* The following use INTC_INPRI00 for masking, which is a 32-bit
113 register, not a 16-bit register like the IPRx registers, so it
114 would need special support */
115 /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */
116 /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */
117};
118
119static unsigned long ipr_offsets[] = {
120 0xffd00004UL, /* 0: IPRA */
121 0xffd00008UL, /* 1: IPRB */
122 0xffd0000cUL, /* 2: IPRC */
123 0xffd00010UL, /* 3: IPRD */
124};
125
126/* given the IPR index return the address of the IPR register */
127unsigned int map_ipridx_to_addr(int idx)
128{
129 if (idx >= ARRAY_SIZE(ipr_offsets))
130 return 0;
131 return ipr_offsets[idx];
132}
133
134#define INTC_ICR 0xffd00000UL
135#define INTC_ICR_IRLM (1<<7)
136
137/* enable individual interrupt mode for external interupts */
138void ipr_irq_enable_irlm(void)
139{
140 ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
141}
142
143void __init init_IRQ_ipr()
144{
145 make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map));
146#ifdef CONFIG_CPU_SUBTYPE_SH7751
147 make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map));
148#endif
149}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
index 97f1c9af35d6..07e5377bf550 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c
+++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
@@ -51,3 +51,66 @@ static int __init sh7760_devices_setup(void)
51 ARRAY_SIZE(sh7760_devices)); 51 ARRAY_SIZE(sh7760_devices));
52} 52}
53__initcall(sh7760_devices_setup); 53__initcall(sh7760_devices_setup);
54
55/*
56 * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0
57 */
58static struct intc2_data intc2_irq_table[] = {
59 /* INTPRIO0 | INTMSK0 */
60 {48, 0, 28, 0, 31, 3}, /* IRQ 4 */
61 {49, 0, 24, 0, 30, 3}, /* IRQ 3 */
62 {50, 0, 20, 0, 29, 3}, /* IRQ 2 */
63 {51, 0, 16, 0, 28, 3}, /* IRQ 1 */
64 /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */
65 /* INTPRIO4 | INTMSK0 */
66 {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */
67 {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */
68 {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */
69 {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */
70 {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */
71 {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */
72 {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */
73 {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */
74 /* INTPRIO8 | INTMSK0 */
75 {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */
76 {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */
77 {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */
78 {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */
79 {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */
80 {65, 8, 24, 0, 16, 3}, /* LCDC */
81 /* 66, 67 unused */
82 {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */
83 {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */
84 {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */
85 /* 71 unused */
86 {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */
87 {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */
88 {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */
89 {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */
90 {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */
91 {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */
92 {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */
93 {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */
94 /* | INTMSK4 */
95 {80, 8, 4, 4, 23, 3}, /* SIM_ERI */
96 {81, 8, 4, 4, 22, 3}, /* SIM_RXI */
97 {82, 8, 4, 4, 21, 3}, /* SIM_TXI */
98 {83, 8, 4, 4, 20, 3}, /* SIM_TEI */
99 {84, 8, 0, 4, 19, 3}, /* HSPII */
100 /* INTPRIOC | INTMSK4 */
101 /* 85-87 unused/reserved */
102 {88, 12, 20, 4, 18, 3}, /* MMCI0 */
103 {89, 12, 20, 4, 17, 3}, /* MMCI1 */
104 {90, 12, 20, 4, 16, 3}, /* MMCI2 */
105 {91, 12, 20, 4, 15, 3}, /* MMCI3 */
106 {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/
107 /* 93-107 reserved/undocumented */
108 {108,12, 4, 4, 1, 3}, /* ADC */
109 {109,12, 0, 4, 0, 3}, /* CMTI */
110 /* 110-111 reserved/unused */
111};
112
113void __init init_IRQ_intc2(void)
114{
115 make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
116}
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 7bcc73f9b8df..d7fff752e569 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -19,7 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/vmalloc.h> 20#include <linux/vmalloc.h>
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <asm/io.h> 22#include <linux/io.h>
23#include <asm/page.h> 23#include <asm/page.h>
24#include <asm/cacheflush.h> 24#include <asm/cacheflush.h>
25#include <asm/cpu/sq.h> 25#include <asm/cpu/sq.h>
@@ -38,7 +38,7 @@ struct sq_mapping {
38 38
39static struct sq_mapping *sq_mapping_list; 39static struct sq_mapping *sq_mapping_list;
40static DEFINE_SPINLOCK(sq_mapping_lock); 40static DEFINE_SPINLOCK(sq_mapping_lock);
41static kmem_cache_t *sq_cache; 41static struct kmem_cache *sq_cache;
42static unsigned long *sq_bitmap; 42static unsigned long *sq_bitmap;
43 43
44#define store_queue_barrier() \ 44#define store_queue_barrier() \
@@ -67,6 +67,7 @@ void sq_flush_range(unsigned long start, unsigned int len)
67 /* Wait for completion */ 67 /* Wait for completion */
68 store_queue_barrier(); 68 store_queue_barrier();
69} 69}
70EXPORT_SYMBOL(sq_flush_range);
70 71
71static inline void sq_mapping_list_add(struct sq_mapping *map) 72static inline void sq_mapping_list_add(struct sq_mapping *map)
72{ 73{
@@ -110,8 +111,9 @@ static int __sq_remap(struct sq_mapping *map, unsigned long flags)
110 111
111 vma->phys_addr = map->addr; 112 vma->phys_addr = map->addr;
112 113
113 if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr, 114 if (ioremap_page_range((unsigned long)vma->addr,
114 map->size, flags)) { 115 (unsigned long)vma->addr + map->size,
116 vma->phys_addr, __pgprot(flags))) {
115 vunmap(vma->addr); 117 vunmap(vma->addr);
116 return -EAGAIN; 118 return -EAGAIN;
117 } 119 }
@@ -166,7 +168,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
166 map->size = size; 168 map->size = size;
167 map->name = name; 169 map->name = name;
168 170
169 page = bitmap_find_free_region(sq_bitmap, 0x04000000, 171 page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT,
170 get_order(map->size)); 172 get_order(map->size));
171 if (unlikely(page < 0)) { 173 if (unlikely(page < 0)) {
172 ret = -ENOSPC; 174 ret = -ENOSPC;
@@ -175,7 +177,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size,
175 177
176 map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT); 178 map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
177 179
178 ret = __sq_remap(map, flags); 180 ret = __sq_remap(map, pgprot_val(PAGE_KERNEL_NOCACHE) | flags);
179 if (unlikely(ret != 0)) 181 if (unlikely(ret != 0))
180 goto out; 182 goto out;
181 183
@@ -193,6 +195,7 @@ out:
193 kmem_cache_free(sq_cache, map); 195 kmem_cache_free(sq_cache, map);
194 return ret; 196 return ret;
195} 197}
198EXPORT_SYMBOL(sq_remap);
196 199
197/** 200/**
198 * sq_unmap - Unmap a Store Queue allocation 201 * sq_unmap - Unmap a Store Queue allocation
@@ -234,6 +237,7 @@ void sq_unmap(unsigned long vaddr)
234 237
235 kmem_cache_free(sq_cache, map); 238 kmem_cache_free(sq_cache, map);
236} 239}
240EXPORT_SYMBOL(sq_unmap);
237 241
238/* 242/*
239 * Needlessly complex sysfs interface. Unfortunately it doesn't seem like 243 * Needlessly complex sysfs interface. Unfortunately it doesn't seem like
@@ -402,7 +406,3 @@ module_exit(sq_api_exit);
402MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); 406MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
403MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); 407MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
404MODULE_LICENSE("GPL"); 408MODULE_LICENSE("GPL");
405
406EXPORT_SYMBOL(sq_remap);
407EXPORT_SYMBOL(sq_unmap);
408EXPORT_SYMBOL(sq_flush_range);
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
new file mode 100644
index 000000000000..a8f493f2f21f
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/Makefile
@@ -0,0 +1,19 @@
1#
2# Makefile for the Linux/SuperH SH-4 backends.
3#
4
5# CPU subtype setup
6obj-$(CONFIG_CPU_SUBTYPE_SH7770) += setup-sh7770.o
7obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o
8obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o
9obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o
10obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o
11
12# Primary on-chip clocks (common)
13clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o
14clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o
15clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o
16clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o
17clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7343.o
18
19obj-y += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
index 2fa5cb2ae68d..2fa5cb2ae68d 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh73180.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh73180.c
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 000000000000..1707a213f0cf
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
@@ -0,0 +1,99 @@
1/*
2 * arch/sh/kernel/cpu/sh4/clock-sh7343.c
3 *
4 * SH7343/SH7722 support for the clock framework
5 *
6 * Copyright (C) 2006 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/io.h>
15#include <asm/clock.h>
16#include <asm/freq.h>
17
18/*
19 * SH7343/SH7722 uses a common set of multipliers and divisors, so this
20 * is quite simple..
21 */
22static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
23static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
24
25#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
26
27static void master_clk_init(struct clk *clk)
28{
29 clk->parent = clk_get(NULL, "cpu_clk");
30}
31
32static void master_clk_recalc(struct clk *clk)
33{
34 int idx = (ctrl_inl(FRQCR) & 0x000f);
35 clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
36}
37
38static struct clk_ops sh7343_master_clk_ops = {
39 .init = master_clk_init,
40 .recalc = master_clk_recalc,
41};
42
43static void module_clk_init(struct clk *clk)
44{
45 clk->parent = NULL;
46 clk->rate = CONFIG_SH_PCLK_FREQ;
47}
48
49static struct clk_ops sh7343_module_clk_ops = {
50 .init = module_clk_init,
51};
52
53static void bus_clk_init(struct clk *clk)
54{
55 clk->parent = clk_get(NULL, "cpu_clk");
56}
57
58static void bus_clk_recalc(struct clk *clk)
59{
60 int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
61 clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
62}
63
64static struct clk_ops sh7343_bus_clk_ops = {
65 .init = bus_clk_init,
66 .recalc = bus_clk_recalc,
67};
68
69static void cpu_clk_init(struct clk *clk)
70{
71 clk->parent = clk_get(NULL, "module_clk");
72 clk->flags |= CLK_RATE_PROPAGATES;
73 clk_set_rate(clk, clk_get_rate(clk));
74}
75
76static void cpu_clk_recalc(struct clk *clk)
77{
78 int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
79 clk->rate = clk->parent->rate * pll_calc() *
80 multipliers[idx] / divisors[idx];
81}
82
83static struct clk_ops sh7343_cpu_clk_ops = {
84 .init = cpu_clk_init,
85 .recalc = cpu_clk_recalc,
86};
87
88static struct clk_ops *sh7343_clk_ops[] = {
89 &sh7343_master_clk_ops,
90 &sh7343_module_clk_ops,
91 &sh7343_bus_clk_ops,
92 &sh7343_cpu_clk_ops,
93};
94
95void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
96{
97 if (idx < ARRAY_SIZE(sh7343_clk_ops))
98 *ops = sh7343_clk_ops[idx];
99}
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
index c8694bac6477..c8694bac6477 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
index 93ad367342c9..9e6a216750c8 100644
--- a/arch/sh/kernel/cpu/sh4/clock-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c
@@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = {
98 98
99static int __init sh7780_clk_init(void) 99static int __init sh7780_clk_init(void)
100{ 100{
101 struct clk *clk = clk_get("master_clk"); 101 struct clk *clk = clk_get(NULL, "master_clk");
102 int i; 102 int i;
103 103
104 for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { 104 for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) {
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4a/setup-sh73180.c
index cc9ea1e2e5df..cc9ea1e2e5df 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh73180.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh73180.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 91d61cf91ba1..91d61cf91ba1 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
new file mode 100644
index 000000000000..1143fbf65faf
--- /dev/null
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -0,0 +1,80 @@
1/*
2 * SH7722 Setup
3 *
4 * Copyright (C) 2006 Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/platform_device.h>
11#include <linux/init.h>
12#include <linux/serial.h>
13#include <asm/sci.h>
14
15static struct plat_sci_port sci_platform_data[] = {
16 {
17 .mapbase = 0xffe00000,
18 .flags = UPF_BOOT_AUTOCONF,
19 .type = PORT_SCIF,
20 .irqs = { 80, 81, 83, 82 },
21 }, {
22 .flags = 0,
23 }
24};
25
26static struct platform_device sci_device = {
27 .name = "sh-sci",
28 .id = -1,
29 .dev = {
30 .platform_data = sci_platform_data,
31 },
32};
33
34static struct platform_device *sh7722_devices[] __initdata = {
35 &sci_device,
36};
37
38static int __init sh7722_devices_setup(void)
39{
40 return platform_add_devices(sh7722_devices,
41 ARRAY_SIZE(sh7722_devices));
42}
43__initcall(sh7722_devices_setup);
44
45static struct ipr_data sh7722_ipr_map[] = {
46 /* IRQ, IPR-idx, shift, prio */
47 { 16, 0, 12, 2 }, /* TMU0 */
48 { 17, 0, 8, 2 }, /* TMU1 */
49 { 80, 6, 12, 3 }, /* SCIF ERI */
50 { 81, 6, 12, 3 }, /* SCIF RXI */
51 { 82, 6, 12, 3 }, /* SCIF BRI */
52 { 83, 6, 12, 3 }, /* SCIF TXI */
53};
54
55static unsigned long ipr_offsets[] = {
56 0xa4080000, /* 0: IPRA */
57 0xa4080004, /* 1: IPRB */
58 0xa4080008, /* 2: IPRC */
59 0xa408000c, /* 3: IPRD */
60 0xa4080010, /* 4: IPRE */
61 0xa4080014, /* 5: IPRF */
62 0xa4080018, /* 6: IPRG */
63 0xa408001c, /* 7: IPRH */
64 0xa4080020, /* 8: IPRI */
65 0xa4080024, /* 9: IPRJ */
66 0xa4080028, /* 10: IPRK */
67 0xa408002c, /* 11: IPRL */
68};
69
70unsigned int map_ipridx_to_addr(int idx)
71{
72 if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
73 return 0;
74 return ipr_offsets[idx];
75}
76
77void __init init_IRQ_ipr(void)
78{
79 make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
80}
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
index 6a04cc5f5aca..6a04cc5f5aca 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7770.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index 72493f259edc..9aeaa2ddaa28 100644
--- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -77,3 +77,32 @@ static int __init sh7780_devices_setup(void)
77 ARRAY_SIZE(sh7780_devices)); 77 ARRAY_SIZE(sh7780_devices));
78} 78}
79__initcall(sh7780_devices_setup); 79__initcall(sh7780_devices_setup);
80
81static struct intc2_data intc2_irq_table[] = {
82 { 28, 0, 24, 0, 0, 2 }, /* TMU0 */
83
84 { 21, 1, 0, 0, 2, 2 },
85 { 22, 1, 1, 0, 2, 2 },
86 { 23, 1, 2, 0, 2, 2 },
87
88 { 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */
89 { 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */
90 { 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */
91 { 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */
92
93 { 76, 8, 16, 0, 4, 3 }, /* SCIF1 ERI */
94 { 77, 8, 16, 0, 4, 3 }, /* SCIF1 RXI */
95 { 78, 8, 16, 0, 4, 3 }, /* SCIF1 BRI */
96 { 79, 8, 16, 0, 4, 3 }, /* SCIF1 TXI */
97
98 { 64, 0x10, 8, 0, 14, 2 }, /* PCIC0 */
99 { 65, 0x10, 0, 0, 15, 2 }, /* PCIC1 */
100 { 66, 0x14, 24, 0, 16, 2 }, /* PCIC2 */
101 { 67, 0x14, 16, 0, 17, 2 }, /* PCIC3 */
102 { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */
103};
104
105void __init init_IRQ_intc2(void)
106{
107 make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table));
108}
diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c
index a00022722e9e..560b91cdd15c 100644
--- a/arch/sh/kernel/early_printk.c
+++ b/arch/sh/kernel/early_printk.c
@@ -12,7 +12,7 @@
12#include <linux/console.h> 12#include <linux/console.h>
13#include <linux/tty.h> 13#include <linux/tty.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <asm/io.h> 15#include <linux/io.h>
16 16
17#ifdef CONFIG_SH_STANDARD_BIOS 17#ifdef CONFIG_SH_STANDARD_BIOS
18#include <asm/sh_bios.h> 18#include <asm/sh_bios.h>
@@ -62,17 +62,9 @@ static struct console bios_console = {
62#include <linux/serial_core.h> 62#include <linux/serial_core.h>
63#include "../../../drivers/serial/sh-sci.h" 63#include "../../../drivers/serial/sh-sci.h"
64 64
65#ifdef CONFIG_CPU_SH4
66#define SCIF_REG 0xffe80000
67#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
68#define SCIF_REG 0xfffe9800
69#else
70#error "Undefined SCIF for this subtype"
71#endif
72
73static struct uart_port scif_port = { 65static struct uart_port scif_port = {
74 .mapbase = SCIF_REG, 66 .mapbase = CONFIG_EARLY_SCIF_CONSOLE_PORT,
75 .membase = (char __iomem *)SCIF_REG, 67 .membase = (char __iomem *)CONFIG_EARLY_SCIF_CONSOLE_PORT,
76}; 68};
77 69
78static void scif_sercon_putc(int c) 70static void scif_sercon_putc(int c)
@@ -113,23 +105,29 @@ static struct console scif_console = {
113 .index = -1, 105 .index = -1,
114}; 106};
115 107
108#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
109/*
110 * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4
111 * devices that aren't using sh-ipl+g.
112 */
116static void scif_sercon_init(int baud) 113static void scif_sercon_init(int baud)
117{ 114{
118 ctrl_outw(0, SCIF_REG + 8); 115 ctrl_outw(0, scif_port.mapbase + 8);
119 ctrl_outw(0, SCIF_REG); 116 ctrl_outw(0, scif_port.mapbase);
120 117
121 /* Set baud rate */ 118 /* Set baud rate */
122 ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) / 119 ctrl_outb((CONFIG_SH_PCLK_FREQ + 16 * baud) /
123 (32 * baud) - 1, SCIF_REG + 4); 120 (32 * baud) - 1, scif_port.mapbase + 4);
124 121
125 ctrl_outw(12, SCIF_REG + 24); 122 ctrl_outw(12, scif_port.mapbase + 24);
126 ctrl_outw(8, SCIF_REG + 24); 123 ctrl_outw(8, scif_port.mapbase + 24);
127 ctrl_outw(0, SCIF_REG + 32); 124 ctrl_outw(0, scif_port.mapbase + 32);
128 ctrl_outw(0x60, SCIF_REG + 16); 125 ctrl_outw(0x60, scif_port.mapbase + 16);
129 ctrl_outw(0, SCIF_REG + 36); 126 ctrl_outw(0, scif_port.mapbase + 36);
130 ctrl_outw(0x30, SCIF_REG + 8); 127 ctrl_outw(0x30, scif_port.mapbase + 8);
131} 128}
132#endif 129#endif /* CONFIG_CPU_SH4 && !CONFIG_SH_STANDARD_BIOS */
130#endif /* CONFIG_EARLY_SCIF_CONSOLE */
133 131
134/* 132/*
135 * Setup a default console, if more than one is compiled in, rely on the 133 * Setup a default console, if more than one is compiled in, rely on the
@@ -146,16 +144,16 @@ static struct console *early_console =
146 ; 144 ;
147 145
148static int __initdata keep_early; 146static int __initdata keep_early;
147static int early_console_initialized;
149 148
150int __init setup_early_printk(char *opt) 149int __init setup_early_printk(char *buf)
151{ 150{
152 char *space; 151 if (!buf)
153 char buf[256]; 152 return 0;
154 153
155 strlcpy(buf, opt, sizeof(buf)); 154 if (early_console_initialized)
156 space = strchr(buf, ' '); 155 return 0;
157 if (space) 156 early_console_initialized = 1;
158 *space = 0;
159 157
160 if (strstr(buf, "keep")) 158 if (strstr(buf, "keep"))
161 keep_early = 1; 159 keep_early = 1;
@@ -168,7 +166,7 @@ int __init setup_early_printk(char *opt)
168 if (!strncmp(buf, "serial", 6)) { 166 if (!strncmp(buf, "serial", 6)) {
169 early_console = &scif_console; 167 early_console = &scif_console;
170 168
171#ifdef CONFIG_CPU_SH4 169#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_STANDARD_BIOS)
172 scif_sercon_init(115200); 170 scif_sercon_init(115200);
173#endif 171#endif
174 } 172 }
@@ -177,12 +175,14 @@ int __init setup_early_printk(char *opt)
177 if (likely(early_console)) 175 if (likely(early_console))
178 register_console(early_console); 176 register_console(early_console);
179 177
180 return 1; 178 return 0;
181} 179}
182__setup("earlyprintk=", setup_early_printk); 180early_param("earlyprintk", setup_early_printk);
183 181
184void __init disable_early_printk(void) 182void __init disable_early_printk(void)
185{ 183{
184 if (!early_console_initialized || !early_console)
185 return;
186 if (!keep_early) { 186 if (!keep_early) {
187 printk("disabling early console\n"); 187 printk("disabling early console\n");
188 unregister_console(early_console); 188 unregister_console(early_console);
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
new file mode 100644
index 000000000000..fc279aeb73ab
--- /dev/null
+++ b/arch/sh/kernel/entry-common.S
@@ -0,0 +1,444 @@
1/* $Id: entry.S,v 1.37 2004/06/11 13:02:46 doyu Exp $
2 *
3 * linux/arch/sh/entry.S
4 *
5 * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
6 * Copyright (C) 2003 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 *
12 */
13
14! NOTE:
15! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
16! to be jumped is too far, but it causes illegal slot exception.
17
18/*
19 * entry.S contains the system-call and fault low-level handling routines.
20 * This also contains the timer-interrupt handler, as well as all interrupts
21 * and faults that can result in a task-switch.
22 *
23 * NOTE: This code handles signal-recognition, which happens every time
24 * after a timer-interrupt and after each system call.
25 *
26 * NOTE: This code uses a convention that instructions in the delay slot
27 * of a transfer-control instruction are indented by an extra space, thus:
28 *
29 * jmp @k0 ! control-transfer instruction
30 * ldc k1, ssr ! delay slot
31 *
32 * Stack layout in 'ret_from_syscall':
33 * ptrace needs to have all regs on the stack.
34 * if the order here is changed, it needs to be
35 * updated in ptrace.c and ptrace.h
36 *
37 * r0
38 * ...
39 * r15 = stack pointer
40 * spc
41 * pr
42 * ssr
43 * gbr
44 * mach
45 * macl
46 * syscall #
47 *
48 */
49
50#if defined(CONFIG_PREEMPT)
51# define preempt_stop() cli
52#else
53# define preempt_stop()
54# define resume_kernel __restore_all
55#endif
56
57#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
58! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
59! If both are configured, handle the debug traps (breakpoints) in SW,
60! but still allow BIOS traps to FW.
61
62 .align 2
63debug_kernel:
64#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
65 /* Force BIOS call to FW (debug_trap put TRA in r8) */
66 mov r8,r0
67 shlr2 r0
68 cmp/eq #0x3f,r0
69 bt debug_kernel_fw
70#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
71
72debug_enter:
73#if defined(CONFIG_SH_KGDB)
74 /* Jump to kgdb, pass stacked regs as arg */
75debug_kernel_sw:
76 mov.l 3f, r0
77 jmp @r0
78 mov r15, r4
79 .align 2
803: .long kgdb_handle_exception
81#endif /* CONFIG_SH_KGDB */
82#ifdef CONFIG_SH_STANDARD_BIOS
83 bra debug_kernel_fw
84 nop
85#endif
86#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
87
88 .align 2
89debug_trap:
90#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
91 mov r8, r0
92 shlr2 r0
93 cmp/eq #0x3f, r0 ! sh_bios() trap
94 bf 1f
95#ifdef CONFIG_SH_KGDB
96 cmp/eq #0xff, r0 ! XXX: KGDB trap, fix for SH-2.
97 bf 1f
98#endif
99 mov #OFF_SR, r0
100 mov.l @(r0,r15), r0 ! get status register
101 shll r0
102 shll r0 ! kernel space?
103 bt/s debug_kernel
1041:
105#endif
106 mov.l @r15, r0 ! Restore R0 value
107 mov.l 1f, r8
108 jmp @r8
109 nop
110
111 .align 2
112ENTRY(exception_error)
113 !
114#ifdef CONFIG_TRACE_IRQFLAGS
115 mov.l 3f, r0
116 jsr @r0
117 nop
118#endif
119 sti
120 mov.l 2f, r0
121 jmp @r0
122 nop
123
124!
125 .align 2
1261: .long break_point_trap_software
1272: .long do_exception_error
128#ifdef CONFIG_TRACE_IRQFLAGS
1293: .long trace_hardirqs_on
130#endif
131
132 .align 2
133ret_from_exception:
134 preempt_stop()
135#ifdef CONFIG_TRACE_IRQFLAGS
136 mov.l 4f, r0
137 jsr @r0
138 nop
139#endif
140ENTRY(ret_from_irq)
141 !
142 mov #OFF_SR, r0
143 mov.l @(r0,r15), r0 ! get status register
144 shll r0
145 shll r0 ! kernel space?
146 get_current_thread_info r8, r0
147 bt resume_kernel ! Yes, it's from kernel, go back soon
148
149#ifdef CONFIG_PREEMPT
150 bra resume_userspace
151 nop
152ENTRY(resume_kernel)
153 mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count
154 tst r0, r0
155 bf noresched
156need_resched:
157 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
158 tst #_TIF_NEED_RESCHED, r0 ! need_resched set?
159 bt noresched
160
161 mov #OFF_SR, r0
162 mov.l @(r0,r15), r0 ! get status register
163 and #0xf0, r0 ! interrupts off (exception path)?
164 cmp/eq #0xf0, r0
165 bt noresched
166
167 mov.l 1f, r0
168 mov.l r0, @(TI_PRE_COUNT,r8)
169
170#ifdef CONFIG_TRACE_IRQFLAGS
171 mov.l 3f, r0
172 jsr @r0
173 nop
174#endif
175 sti
176 mov.l 2f, r0
177 jsr @r0
178 nop
179 mov #0, r0
180 mov.l r0, @(TI_PRE_COUNT,r8)
181 cli
182#ifdef CONFIG_TRACE_IRQFLAGS
183 mov.l 4f, r0
184 jsr @r0
185 nop
186#endif
187
188 bra need_resched
189 nop
190
191noresched:
192 bra __restore_all
193 nop
194
195 .align 2
1961: .long PREEMPT_ACTIVE
1972: .long schedule
198#ifdef CONFIG_TRACE_IRQFLAGS
1993: .long trace_hardirqs_on
2004: .long trace_hardirqs_off
201#endif
202#endif
203
204ENTRY(resume_userspace)
205 ! r8: current_thread_info
206 cli
207#ifdef CONFIG_TRACE_IRQFLAGS
208 mov.l 5f, r0
209 jsr @r0
210 nop
211#endif
212 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
213 tst #_TIF_WORK_MASK, r0
214 bt/s __restore_all
215 tst #_TIF_NEED_RESCHED, r0
216
217 .align 2
218work_pending:
219 ! r0: current_thread_info->flags
220 ! r8: current_thread_info
221 ! t: result of "tst #_TIF_NEED_RESCHED, r0"
222 bf/s work_resched
223 tst #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
224work_notifysig:
225 bt/s __restore_all
226 mov r15, r4
227 mov r12, r5 ! set arg1(save_r0)
228 mov r0, r6
229 mov.l 2f, r1
230 mov.l 3f, r0
231 jmp @r1
232 lds r0, pr
233work_resched:
234#ifndef CONFIG_PREEMPT
235 ! gUSA handling
236 mov.l @(OFF_SP,r15), r0 ! get user space stack pointer
237 mov r0, r1
238 shll r0
239 bf/s 1f
240 shll r0
241 bf/s 1f
242 mov #OFF_PC, r0
243 ! SP >= 0xc0000000 : gUSA mark
244 mov.l @(r0,r15), r2 ! get user space PC (program counter)
245 mov.l @(OFF_R0,r15), r3 ! end point
246 cmp/hs r3, r2 ! r2 >= r3?
247 bt 1f
248 add r3, r1 ! rewind point #2
249 mov.l r1, @(r0,r15) ! reset PC to rewind point #2
250 !
2511:
252#endif
253 mov.l 1f, r1
254 jsr @r1 ! schedule
255 nop
256 cli
257#ifdef CONFIG_TRACE_IRQFLAGS
258 mov.l 5f, r0
259 jsr @r0
260 nop
261#endif
262 !
263 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
264 tst #_TIF_WORK_MASK, r0
265 bt __restore_all
266 bra work_pending
267 tst #_TIF_NEED_RESCHED, r0
268
269 .align 2
2701: .long schedule
2712: .long do_notify_resume
2723: .long restore_all
273#ifdef CONFIG_TRACE_IRQFLAGS
2744: .long trace_hardirqs_on
2755: .long trace_hardirqs_off
276#endif
277
278 .align 2
279syscall_exit_work:
280 ! r0: current_thread_info->flags
281 ! r8: current_thread_info
282 tst #_TIF_SYSCALL_TRACE, r0
283 bt/s work_pending
284 tst #_TIF_NEED_RESCHED, r0
285#ifdef CONFIG_TRACE_IRQFLAGS
286 mov.l 5f, r0
287 jsr @r0
288 nop
289#endif
290 sti
291 ! XXX setup arguments...
292 mov.l 4f, r0 ! do_syscall_trace
293 jsr @r0
294 nop
295 bra resume_userspace
296 nop
297
298 .align 2
299syscall_trace_entry:
300 ! Yes it is traced.
301 ! XXX setup arguments...
302 mov.l 4f, r11 ! Call do_syscall_trace which notifies
303 jsr @r11 ! superior (will chomp R[0-7])
304 nop
305 ! Reload R0-R4 from kernel stack, where the
306 ! parent may have modified them using
307 ! ptrace(POKEUSR). (Note that R0-R2 are
308 ! used by the system call handler directly
309 ! from the kernel stack anyway, so don't need
310 ! to be reloaded here.) This allows the parent
311 ! to rewrite system calls and args on the fly.
312 mov.l @(OFF_R4,r15), r4 ! arg0
313 mov.l @(OFF_R5,r15), r5
314 mov.l @(OFF_R6,r15), r6
315 mov.l @(OFF_R7,r15), r7 ! arg3
316 mov.l @(OFF_R3,r15), r3 ! syscall_nr
317 !
318 mov.l 2f, r10 ! Number of syscalls
319 cmp/hs r10, r3
320 bf syscall_call
321 mov #-ENOSYS, r0
322 bra syscall_exit
323 mov.l r0, @(OFF_R0,r15) ! Return value
324
325__restore_all:
326 mov.l 1f, r0
327 jmp @r0
328 nop
329
330 .align 2
3311: .long restore_all
332
333 .align 2
334not_syscall_tra:
335 bra debug_trap
336 nop
337
338 .align 2
339syscall_badsys: ! Bad syscall number
340 mov #-ENOSYS, r0
341 bra resume_userspace
342 mov.l r0, @(OFF_R0,r15) ! Return value
343
344
345/*
346 * Syscall interface:
347 *
348 * Syscall #: R3
349 * Arguments #0 to #3: R4--R7
350 * Arguments #4 to #6: R0, R1, R2
351 * TRA: (number of arguments + 0x10) x 4
352 *
353 * This code also handles delegating other traps to the BIOS/gdb stub
354 * according to:
355 *
356 * Trap number
357 * (TRA>>2) Purpose
358 * -------- -------
359 * 0x0-0xf old syscall ABI
360 * 0x10-0x1f new syscall ABI
361 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub.
362 *
363 * Note: When we're first called, the TRA value must be shifted
364 * right 2 bits in order to get the value that was used as the "trapa"
365 * argument.
366 */
367
368 .align 2
369 .globl ret_from_fork
370ret_from_fork:
371 mov.l 1f, r8
372 jsr @r8
373 mov r0, r4
374 bra syscall_exit
375 nop
376 .align 2
3771: .long schedule_tail
378 !
379ENTRY(system_call)
380#if !defined(CONFIG_CPU_SH2)
381 mov.l 1f, r9
382 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
383#endif
384 !
385 ! Is the trap argument >= 0x20? (TRA will be >= 0x80)
386 mov #0x7f, r9
387 cmp/hi r9, r8
388 bt/s not_syscall_tra
389 mov #OFF_TRA, r9
390 add r15, r9
391 mov.l r8, @r9 ! set TRA value to tra
392#ifdef CONFIG_TRACE_IRQFLAGS
393 mov.l 5f, r10
394 jsr @r10
395 nop
396#endif
397 sti
398
399 !
400 get_current_thread_info r8, r10
401 mov.l @(TI_FLAGS,r8), r8
402 mov #_TIF_SYSCALL_TRACE, r10
403 tst r10, r8
404 bf syscall_trace_entry
405 !
406 mov.l 2f, r8 ! Number of syscalls
407 cmp/hs r8, r3
408 bt syscall_badsys
409 !
410syscall_call:
411 shll2 r3 ! x4
412 mov.l 3f, r8 ! Load the address of sys_call_table
413 add r8, r3
414 mov.l @r3, r8
415 jsr @r8 ! jump to specific syscall handler
416 nop
417 mov.l @(OFF_R0,r15), r12 ! save r0
418 mov.l r0, @(OFF_R0,r15) ! save the return value
419 !
420syscall_exit:
421 cli
422#ifdef CONFIG_TRACE_IRQFLAGS
423 mov.l 6f, r0
424 jsr @r0
425 nop
426#endif
427 !
428 get_current_thread_info r8, r0
429 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
430 tst #_TIF_ALLWORK_MASK, r0
431 bf syscall_exit_work
432 bra __restore_all
433 nop
434 .align 2
435#if !defined(CONFIG_CPU_SH2)
4361: .long TRA
437#endif
4382: .long NR_syscalls
4393: .long sys_call_table
4404: .long do_syscall_trace
441#ifdef CONFIG_TRACE_IRQFLAGS
4425: .long trace_hardirqs_on
4436: .long trace_hardirqs_off
444#endif
diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S
index f5f53d14f245..71a3ad7d283e 100644
--- a/arch/sh/kernel/head.S
+++ b/arch/sh/kernel/head.S
@@ -33,7 +33,8 @@ ENTRY(empty_zero_page)
33 .long 0x00360000 /* INITRD_START */ 33 .long 0x00360000 /* INITRD_START */
34 .long 0x000a0000 /* INITRD_SIZE */ 34 .long 0x000a0000 /* INITRD_SIZE */
35 .long 0 35 .long 0
36 .balign 4096,0,4096 361:
37 .skip PAGE_SIZE - empty_zero_page - 1b
37 38
38 .text 39 .text
39/* 40/*
@@ -53,8 +54,10 @@ ENTRY(_stext)
53 ldc r0, sr 54 ldc r0, sr
54 ! Initialize global interrupt mask 55 ! Initialize global interrupt mask
55 mov #0, r0 56 mov #0, r0
57#ifdef CONFIG_CPU_HAS_SR_RB
56 ldc r0, r6_bank 58 ldc r0, r6_bank
57 59#endif
60
58 /* 61 /*
59 * Prefetch if possible to reduce cache miss penalty. 62 * Prefetch if possible to reduce cache miss penalty.
60 * 63 *
@@ -68,11 +71,14 @@ ENTRY(_stext)
68 ! 71 !
69 mov.l 2f, r0 72 mov.l 2f, r0
70 mov r0, r15 ! Set initial r15 (stack pointer) 73 mov r0, r15 ! Set initial r15 (stack pointer)
71 mov #(THREAD_SIZE >> 8), r1 74 mov #(THREAD_SIZE >> 10), r1
72 shll8 r1 ! r1 = THREAD_SIZE 75 shll8 r1 ! r1 = THREAD_SIZE
76 shll2 r1
73 sub r1, r0 ! 77 sub r1, r0 !
78#ifdef CONFIG_CPU_HAS_SR_RB
74 ldc r0, r7_bank ! ... and initial thread_info 79 ldc r0, r7_bank ! ... and initial thread_info
75 80#endif
81
76 ! Clear BSS area 82 ! Clear BSS area
77 mov.l 3f, r1 83 mov.l 3f, r1
78 add #4, r1 84 add #4, r1
@@ -95,7 +101,11 @@ ENTRY(_stext)
95 nop 101 nop
96 102
97 .balign 4 103 .balign 4
104#if defined(CONFIG_CPU_SH2)
1051: .long 0x000000F0 ! IMASK=0xF
106#else
981: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF 1071: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
108#endif
992: .long init_thread_union+THREAD_SIZE 1092: .long init_thread_union+THREAD_SIZE
1003: .long __bss_start 1103: .long __bss_start
1014: .long _end 1114: .long _end
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index acf2602569c4..67be2b6e8cd1 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -12,7 +12,7 @@
12#include <linux/kernel_stat.h> 12#include <linux/kernel_stat.h>
13#include <linux/seq_file.h> 13#include <linux/seq_file.h>
14#include <linux/io.h> 14#include <linux/io.h>
15#include <asm/irq.h> 15#include <linux/irq.h>
16#include <asm/processor.h> 16#include <asm/processor.h>
17#include <asm/uaccess.h> 17#include <asm/uaccess.h>
18#include <asm/thread_info.h> 18#include <asm/thread_info.h>
@@ -54,7 +54,7 @@ int show_interrupts(struct seq_file *p, void *v)
54 for_each_online_cpu(j) 54 for_each_online_cpu(j)
55 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); 55 seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
56 seq_printf(p, " %14s", irq_desc[i].chip->name); 56 seq_printf(p, " %14s", irq_desc[i].chip->name);
57 seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq)); 57 seq_printf(p, "-%-8s", irq_desc[i].name);
58 seq_printf(p, " %s", action->name); 58 seq_printf(p, " %s", action->name);
59 59
60 for (action=action->next; action; action = action->next) 60 for (action=action->next; action; action = action->next)
@@ -78,15 +78,16 @@ union irq_ctx {
78 u32 stack[THREAD_SIZE/sizeof(u32)]; 78 u32 stack[THREAD_SIZE/sizeof(u32)];
79}; 79};
80 80
81static union irq_ctx *hardirq_ctx[NR_CPUS]; 81static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
82static union irq_ctx *softirq_ctx[NR_CPUS]; 82static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
83#endif 83#endif
84 84
85asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, 85asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
86 unsigned long r6, unsigned long r7, 86 unsigned long r6, unsigned long r7,
87 struct pt_regs regs) 87 struct pt_regs __regs)
88{ 88{
89 struct pt_regs *old_regs = set_irq_regs(&regs); 89 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
90 struct pt_regs *old_regs = set_irq_regs(regs);
90 int irq; 91 int irq;
91#ifdef CONFIG_4KSTACKS 92#ifdef CONFIG_4KSTACKS
92 union irq_ctx *curctx, *irqctx; 93 union irq_ctx *curctx, *irqctx;
@@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
111#endif 112#endif
112 113
113#ifdef CONFIG_CPU_HAS_INTEVT 114#ifdef CONFIG_CPU_HAS_INTEVT
114 irq = (ctrl_inl(INTEVT) >> 5) - 16; 115 irq = evt2irq(ctrl_inl(INTEVT));
115#else 116#else
116 irq = r4; 117 irq = r4;
117#endif 118#endif
@@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
135 irqctx->tinfo.task = curctx->tinfo.task; 136 irqctx->tinfo.task = curctx->tinfo.task;
136 irqctx->tinfo.previous_sp = current_stack_pointer; 137 irqctx->tinfo.previous_sp = current_stack_pointer;
137 138
139 /*
140 * Copy the softirq bits in preempt_count so that the
141 * softirq checks work in the hardirq context.
142 */
143 irqctx->tinfo.preempt_count =
144 (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
145 (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
146
138 __asm__ __volatile__ ( 147 __asm__ __volatile__ (
139 "mov %0, r4 \n" 148 "mov %0, r4 \n"
140 "mov r15, r9 \n" 149 "mov r15, r8 \n"
141 "jsr @%1 \n" 150 "jsr @%1 \n"
142 /* swith to the irq stack */ 151 /* swith to the irq stack */
143 " mov %2, r15 \n" 152 " mov %2, r15 \n"
144 /* restore the stack (ring zero) */ 153 /* restore the stack (ring zero) */
145 "mov r9, r15 \n" 154 "mov r8, r15 \n"
146 : /* no outputs */ 155 : /* no outputs */
147 : "r" (irq), "r" (generic_handle_irq), "r" (isp) 156 : "r" (irq), "r" (generic_handle_irq), "r" (isp)
148 /* XXX: A somewhat excessive clobber list? -PFM */
149 : "memory", "r0", "r1", "r2", "r3", "r4", 157 : "memory", "r0", "r1", "r2", "r3", "r4",
150 "r5", "r6", "r7", "r8", "t", "pr" 158 "r5", "r6", "r7", "r8", "t", "pr"
151 ); 159 );
@@ -193,7 +201,7 @@ void irq_ctx_init(int cpu)
193 irqctx->tinfo.task = NULL; 201 irqctx->tinfo.task = NULL;
194 irqctx->tinfo.exec_domain = NULL; 202 irqctx->tinfo.exec_domain = NULL;
195 irqctx->tinfo.cpu = cpu; 203 irqctx->tinfo.cpu = cpu;
196 irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET; 204 irqctx->tinfo.preempt_count = 0;
197 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); 205 irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
198 206
199 softirq_ctx[cpu] = irqctx; 207 softirq_ctx[cpu] = irqctx;
@@ -239,13 +247,38 @@ asmlinkage void do_softirq(void)
239 "mov r9, r15 \n" 247 "mov r9, r15 \n"
240 : /* no outputs */ 248 : /* no outputs */
241 : "r" (__do_softirq), "r" (isp) 249 : "r" (__do_softirq), "r" (isp)
242 /* XXX: A somewhat excessive clobber list? -PFM */
243 : "memory", "r0", "r1", "r2", "r3", "r4", 250 : "memory", "r0", "r1", "r2", "r3", "r4",
244 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr" 251 "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
245 ); 252 );
253
254 /*
255 * Shouldnt happen, we returned above if in_interrupt():
256 */
257 WARN_ON_ONCE(softirq_count());
246 } 258 }
247 259
248 local_irq_restore(flags); 260 local_irq_restore(flags);
249} 261}
250EXPORT_SYMBOL(do_softirq); 262EXPORT_SYMBOL(do_softirq);
251#endif 263#endif
264
265void __init init_IRQ(void)
266{
267#ifdef CONFIG_CPU_HAS_PINT_IRQ
268 init_IRQ_pint();
269#endif
270
271#ifdef CONFIG_CPU_HAS_INTC2_IRQ
272 init_IRQ_intc2();
273#endif
274
275#ifdef CONFIG_CPU_HAS_IPR_IRQ
276 init_IRQ_ipr();
277#endif
278
279 /* Perform the machine specific initialisation */
280 if (sh_mv.mv_init_irq)
281 sh_mv.mv_init_irq();
282
283 irq_ctx_init(smp_processor_id());
284}
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 91516dca4a85..486c06e18033 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -105,7 +105,7 @@ void show_regs(struct pt_regs * regs)
105{ 105{
106 printk("\n"); 106 printk("\n");
107 printk("Pid : %d, Comm: %20s\n", current->pid, current->comm); 107 printk("Pid : %d, Comm: %20s\n", current->pid, current->comm);
108 print_symbol("PC is at %s\n", regs->pc); 108 print_symbol("PC is at %s\n", instruction_pointer(regs));
109 printk("PC : %08lx SP : %08lx SR : %08lx ", 109 printk("PC : %08lx SP : %08lx SR : %08lx ",
110 regs->pc, regs->regs[15], regs->sr); 110 regs->pc, regs->regs[15], regs->sr);
111#ifdef CONFIG_MMU 111#ifdef CONFIG_MMU
@@ -130,15 +130,7 @@ void show_regs(struct pt_regs * regs)
130 printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", 130 printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n",
131 regs->mach, regs->macl, regs->gbr, regs->pr); 131 regs->mach, regs->macl, regs->gbr, regs->pr);
132 132
133 /* 133 show_trace(NULL, (unsigned long *)regs->regs[15], regs);
134 * If we're in kernel mode, dump the stack too..
135 */
136 if (!user_mode(regs)) {
137 extern void show_task(unsigned long *sp);
138 unsigned long sp = regs->regs[15];
139
140 show_task((unsigned long *)sp);
141 }
142} 134}
143 135
144/* 136/*
@@ -393,10 +385,11 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
393 385
394asmlinkage int sys_fork(unsigned long r4, unsigned long r5, 386asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
395 unsigned long r6, unsigned long r7, 387 unsigned long r6, unsigned long r7,
396 struct pt_regs regs) 388 struct pt_regs __regs)
397{ 389{
390 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
398#ifdef CONFIG_MMU 391#ifdef CONFIG_MMU
399 return do_fork(SIGCHLD, regs.regs[15], &regs, 0, NULL, NULL); 392 return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL);
400#else 393#else
401 /* fork almost works, enough to trick you into looking elsewhere :-( */ 394 /* fork almost works, enough to trick you into looking elsewhere :-( */
402 return -EINVAL; 395 return -EINVAL;
@@ -406,11 +399,12 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
406asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, 399asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
407 unsigned long parent_tidptr, 400 unsigned long parent_tidptr,
408 unsigned long child_tidptr, 401 unsigned long child_tidptr,
409 struct pt_regs regs) 402 struct pt_regs __regs)
410{ 403{
404 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
411 if (!newsp) 405 if (!newsp)
412 newsp = regs.regs[15]; 406 newsp = regs->regs[15];
413 return do_fork(clone_flags, newsp, &regs, 0, 407 return do_fork(clone_flags, newsp, regs, 0,
414 (int __user *)parent_tidptr, (int __user *)child_tidptr); 408 (int __user *)parent_tidptr, (int __user *)child_tidptr);
415} 409}
416 410
@@ -426,9 +420,10 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
426 */ 420 */
427asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, 421asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
428 unsigned long r6, unsigned long r7, 422 unsigned long r6, unsigned long r7,
429 struct pt_regs regs) 423 struct pt_regs __regs)
430{ 424{
431 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.regs[15], &regs, 425 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
426 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs,
432 0, NULL, NULL); 427 0, NULL, NULL);
433} 428}
434 429
@@ -437,8 +432,9 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
437 */ 432 */
438asmlinkage int sys_execve(char *ufilename, char **uargv, 433asmlinkage int sys_execve(char *ufilename, char **uargv,
439 char **uenvp, unsigned long r7, 434 char **uenvp, unsigned long r7,
440 struct pt_regs regs) 435 struct pt_regs __regs)
441{ 436{
437 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
442 int error; 438 int error;
443 char *filename; 439 char *filename;
444 440
@@ -450,7 +446,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv,
450 error = do_execve(filename, 446 error = do_execve(filename,
451 (char __user * __user *)uargv, 447 (char __user * __user *)uargv,
452 (char __user * __user *)uenvp, 448 (char __user * __user *)uenvp,
453 &regs); 449 regs);
454 if (error == 0) { 450 if (error == 0) {
455 task_lock(current); 451 task_lock(current);
456 current->ptrace &= ~PT_DTRACE; 452 current->ptrace &= ~PT_DTRACE;
@@ -474,15 +470,14 @@ unsigned long get_wchan(struct task_struct *p)
474 */ 470 */
475 pc = thread_saved_pc(p); 471 pc = thread_saved_pc(p);
476 if (in_sched_functions(pc)) { 472 if (in_sched_functions(pc)) {
477 schedule_frame = ((unsigned long *)(long)p->thread.sp)[1]; 473 schedule_frame = (unsigned long)p->thread.sp;
478 return (unsigned long)((unsigned long *)schedule_frame)[1]; 474 return ((unsigned long *)schedule_frame)[21];
479 } 475 }
476
480 return pc; 477 return pc;
481} 478}
482 479
483asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, 480asmlinkage void break_point_trap(void)
484 unsigned long r6, unsigned long r7,
485 struct pt_regs regs)
486{ 481{
487 /* Clear tracing. */ 482 /* Clear tracing. */
488#if defined(CONFIG_CPU_SH4A) 483#if defined(CONFIG_CPU_SH4A)
@@ -500,8 +495,20 @@ asmlinkage void break_point_trap(unsigned long r4, unsigned long r5,
500 495
501asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, 496asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5,
502 unsigned long r6, unsigned long r7, 497 unsigned long r6, unsigned long r7,
503 struct pt_regs regs) 498 struct pt_regs __regs)
504{ 499{
505 regs.pc -= 2; 500 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
501
502 /* Rewind */
503 regs->pc -= 2;
504
505#ifdef CONFIG_BUG
506 if (__kernel_text_address(instruction_pointer(regs))) {
507 u16 insn = *(u16 *)instruction_pointer(regs);
508 if (insn == TRAPA_BUG_OPCODE)
509 handle_BUG(regs);
510 }
511#endif
512
506 force_sig(SIGTRAP, current); 513 force_sig(SIGTRAP, current);
507} 514}
diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S
index 8221b37c9773..c66cb3209db5 100644
--- a/arch/sh/kernel/relocate_kernel.S
+++ b/arch/sh/kernel/relocate_kernel.S
@@ -7,11 +7,9 @@
7 * This source code is licensed under the GNU General Public License, 7 * This source code is licensed under the GNU General Public License,
8 * Version 2. See the file COPYING for more details. 8 * Version 2. See the file COPYING for more details.
9 */ 9 */
10
11#include <linux/linkage.h> 10#include <linux/linkage.h>
12 11#include <asm/addrspace.h>
13#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */ 12#include <asm/page.h>
14
15 13
16 .globl relocate_new_kernel 14 .globl relocate_new_kernel
17relocate_new_kernel: 15relocate_new_kernel:
@@ -20,8 +18,8 @@ relocate_new_kernel:
20 /* r6 = start_address */ 18 /* r6 = start_address */
21 /* r7 = vbr_reg */ 19 /* r7 = vbr_reg */
22 20
23 mov.l 10f,r8 /* 4096 */ 21 mov.l 10f,r8 /* PAGE_SIZE */
24 mov.l 11f,r9 /* 0xa0000000 */ 22 mov.l 11f,r9 /* P2SEG */
25 23
26 /* stack setting */ 24 /* stack setting */
27 add r8,r5 25 add r8,r5
@@ -32,7 +30,7 @@ relocate_new_kernel:
320: 300:
33 mov.l @r4+,r0 /* cmd = *ind++ */ 31 mov.l @r4+,r0 /* cmd = *ind++ */
34 32
351: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ 331: /* addr = (cmd | P2SEG) & 0xfffffff0 */
36 mov r0,r2 34 mov r0,r2
37 or r9,r2 35 or r9,r2
38 mov #-16,r1 36 mov #-16,r1
@@ -92,7 +90,7 @@ relocate_new_kernel:
9210: 9010:
93 .long PAGE_SIZE 91 .long PAGE_SIZE
9411: 9211:
95 .long 0xa0000000 93 .long P2SEG
96 94
97relocate_new_kernel_end: 95relocate_new_kernel_end:
98 96
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 36d86f9ac38a..225f9ea5cdd7 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -84,8 +84,7 @@ unsigned long memory_start, memory_end;
84 84
85static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], 85static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
86 struct sh_machine_vector** mvp, 86 struct sh_machine_vector** mvp,
87 unsigned long *mv_io_base, 87 unsigned long *mv_io_base)
88 int *mv_mmio_enable)
89{ 88{
90 char c = ' ', *to = command_line, *from = COMMAND_LINE; 89 char c = ' ', *to = command_line, *from = COMMAND_LINE;
91 int len = 0; 90 int len = 0;
@@ -112,23 +111,6 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
112 } 111 }
113 } 112 }
114 113
115#ifdef CONFIG_EARLY_PRINTK
116 if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
117 char *ep_end;
118
119 if (to != command_line)
120 to--;
121
122 from += 12;
123 ep_end = strchr(from, ' ');
124
125 setup_early_printk(from);
126 printk("early console enabled\n");
127
128 from = ep_end;
129 }
130#endif
131
132 if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { 114 if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
133 char* mv_end; 115 char* mv_end;
134 char* mv_comma; 116 char* mv_comma;
@@ -145,7 +127,6 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
145 int ints[3]; 127 int ints[3];
146 get_options(mv_comma+1, ARRAY_SIZE(ints), ints); 128 get_options(mv_comma+1, ARRAY_SIZE(ints), ints);
147 *mv_io_base = ints[1]; 129 *mv_io_base = ints[1];
148 *mv_mmio_enable = ints[2];
149 mv_len = mv_comma - from; 130 mv_len = mv_comma - from;
150 } else { 131 } else {
151 mv_len = mv_end - from; 132 mv_len = mv_end - from;
@@ -158,6 +139,7 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
158 139
159 *mvp = get_mv_byname(mv_name); 140 *mvp = get_mv_byname(mv_name);
160 } 141 }
142
161 c = *(from++); 143 c = *(from++);
162 if (!c) 144 if (!c)
163 break; 145 break;
@@ -177,9 +159,8 @@ static int __init sh_mv_setup(char **cmdline_p)
177 struct sh_machine_vector *mv = NULL; 159 struct sh_machine_vector *mv = NULL;
178 char mv_name[MV_NAME_SIZE] = ""; 160 char mv_name[MV_NAME_SIZE] = "";
179 unsigned long mv_io_base = 0; 161 unsigned long mv_io_base = 0;
180 int mv_mmio_enable = 0;
181 162
182 parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable); 163 parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base);
183 164
184#ifdef CONFIG_SH_UNKNOWN 165#ifdef CONFIG_SH_UNKNOWN
185 if (mv == NULL) { 166 if (mv == NULL) {
@@ -258,6 +239,7 @@ void __init setup_arch(char **cmdline_p)
258 239
259 sh_mv_setup(cmdline_p); 240 sh_mv_setup(cmdline_p);
260 241
242
261 /* 243 /*
262 * Find the highest page frame number we have available 244 * Find the highest page frame number we have available
263 */ 245 */
@@ -305,6 +287,7 @@ void __init setup_arch(char **cmdline_p)
305 PFN_PHYS(pages)); 287 PFN_PHYS(pages));
306 } 288 }
307 289
290
308 /* 291 /*
309 * Reserve the kernel text and 292 * Reserve the kernel text and
310 * Reserve the bootmem bitmap. We do this in two steps (first step 293 * Reserve the bootmem bitmap. We do this in two steps (first step
@@ -325,15 +308,18 @@ void __init setup_arch(char **cmdline_p)
325 ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); 308 ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
326 if (&__rd_start != &__rd_end) { 309 if (&__rd_start != &__rd_end) {
327 LOADER_TYPE = 1; 310 LOADER_TYPE = 1;
328 INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START; 311 INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
329 INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start; 312 __MEMORY_START;
313 INITRD_SIZE = (unsigned long)&__rd_end -
314 (unsigned long)&__rd_start;
330 } 315 }
331 316
332 if (LOADER_TYPE && INITRD_START) { 317 if (LOADER_TYPE && INITRD_START) {
333 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { 318 if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
334 reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE); 319 reserve_bootmem_node(NODE_DATA(0), INITRD_START +
335 initrd_start = 320 __MEMORY_START, INITRD_SIZE);
336 INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; 321 initrd_start = INITRD_START + PAGE_OFFSET +
322 __MEMORY_START;
337 initrd_end = initrd_start + INITRD_SIZE; 323 initrd_end = initrd_start + INITRD_SIZE;
338 } else { 324 } else {
339 printk("initrd extends beyond end of memory " 325 printk("initrd extends beyond end of memory "
@@ -392,6 +378,7 @@ static int __init topology_init(void)
392subsys_initcall(topology_init); 378subsys_initcall(topology_init);
393 379
394static const char *cpu_name[] = { 380static const char *cpu_name[] = {
381 [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619",
395 [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", 382 [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300",
396 [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", 383 [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706",
397 [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", 384 [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708",
@@ -404,6 +391,7 @@ static const char *cpu_name[] = {
404 [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501", 391 [CPU_SH4_202] = "SH4-202", [CPU_SH4_501] = "SH4-501",
405 [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", 392 [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780",
406 [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", 393 [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343",
394 [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722",
407 [CPU_SH_NONE] = "Unknown" 395 [CPU_SH_NONE] = "Unknown"
408}; 396};
409 397
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
index 9daad70bc305..e6106239a0fe 100644
--- a/arch/sh/kernel/sh_ksyms.c
+++ b/arch/sh/kernel/sh_ksyms.c
@@ -18,7 +18,6 @@
18#include <asm/delay.h> 18#include <asm/delay.h>
19#include <asm/tlbflush.h> 19#include <asm/tlbflush.h>
20#include <asm/cacheflush.h> 20#include <asm/cacheflush.h>
21#include <asm/checksum.h>
22 21
23extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); 22extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
24extern struct hw_interrupt_type no_irq_type; 23extern struct hw_interrupt_type no_irq_type;
@@ -71,15 +70,26 @@ DECLARE_EXPORT(__sdivsi3);
71DECLARE_EXPORT(__ashrdi3); 70DECLARE_EXPORT(__ashrdi3);
72DECLARE_EXPORT(__ashldi3); 71DECLARE_EXPORT(__ashldi3);
73DECLARE_EXPORT(__lshrdi3); 72DECLARE_EXPORT(__lshrdi3);
74DECLARE_EXPORT(__movstr);
75DECLARE_EXPORT(__movstrSI16); 73DECLARE_EXPORT(__movstrSI16);
76 74#if __GNUC__ == 4
77EXPORT_SYMBOL(strcpy); 75DECLARE_EXPORT(__movmem);
76#else
77DECLARE_EXPORT(__movstr);
78#endif
78 79
79#ifdef CONFIG_CPU_SH4 80#ifdef CONFIG_CPU_SH4
81#if __GNUC__ == 4
82DECLARE_EXPORT(__movmem_i4_even);
83DECLARE_EXPORT(__movmem_i4_odd);
84DECLARE_EXPORT(__movmemSI12_i4);
85DECLARE_EXPORT(__sdivsi3_i4i);
86DECLARE_EXPORT(__udiv_qrnnd_16);
87DECLARE_EXPORT(__udivsi3_i4i);
88#else /* GCC 3.x */
80DECLARE_EXPORT(__movstr_i4_even); 89DECLARE_EXPORT(__movstr_i4_even);
81DECLARE_EXPORT(__movstr_i4_odd); 90DECLARE_EXPORT(__movstr_i4_odd);
82DECLARE_EXPORT(__movstrSI12_i4); 91DECLARE_EXPORT(__movstrSI12_i4);
92#endif /* __GNUC__ == 4 */
83#endif 93#endif
84 94
85#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) 95#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
@@ -102,10 +112,6 @@ EXPORT_SYMBOL(__down_trylock);
102EXPORT_SYMBOL(synchronize_irq); 112EXPORT_SYMBOL(synchronize_irq);
103#endif 113#endif
104 114
105#ifdef CONFIG_PM
106EXPORT_SYMBOL(pm_suspend);
107#endif
108
109EXPORT_SYMBOL(csum_partial); 115EXPORT_SYMBOL(csum_partial);
110#ifdef CONFIG_IPV6 116#ifdef CONFIG_IPV6
111EXPORT_SYMBOL(csum_ipv6_magic); 117EXPORT_SYMBOL(csum_ipv6_magic);
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index 5213f5bc6ce0..379c88bf5d9a 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -23,6 +23,7 @@
23#include <linux/elf.h> 23#include <linux/elf.h>
24#include <linux/personality.h> 24#include <linux/personality.h>
25#include <linux/binfmts.h> 25#include <linux/binfmts.h>
26#include <linux/freezer.h>
26 27
27#include <asm/ucontext.h> 28#include <asm/ucontext.h>
28#include <asm/uaccess.h> 29#include <asm/uaccess.h>
@@ -37,7 +38,7 @@
37asmlinkage int 38asmlinkage int
38sys_sigsuspend(old_sigset_t mask, 39sys_sigsuspend(old_sigset_t mask,
39 unsigned long r5, unsigned long r6, unsigned long r7, 40 unsigned long r5, unsigned long r6, unsigned long r7,
40 struct pt_regs regs) 41 struct pt_regs __regs)
41{ 42{
42 mask &= _BLOCKABLE; 43 mask &= _BLOCKABLE;
43 spin_lock_irq(&current->sighand->siglock); 44 spin_lock_irq(&current->sighand->siglock);
@@ -52,7 +53,7 @@ sys_sigsuspend(old_sigset_t mask,
52 return -ERESTARTNOHAND; 53 return -ERESTARTNOHAND;
53} 54}
54 55
55asmlinkage int 56asmlinkage int
56sys_sigaction(int sig, const struct old_sigaction __user *act, 57sys_sigaction(int sig, const struct old_sigaction __user *act,
57 struct old_sigaction __user *oact) 58 struct old_sigaction __user *oact)
58{ 59{
@@ -87,9 +88,11 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
87asmlinkage int 88asmlinkage int
88sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 89sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
89 unsigned long r6, unsigned long r7, 90 unsigned long r6, unsigned long r7,
90 struct pt_regs regs) 91 struct pt_regs __regs)
91{ 92{
92 return do_sigaltstack(uss, uoss, regs.regs[15]); 93 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
94
95 return do_sigaltstack(uss, uoss, regs->regs[15]);
93} 96}
94 97
95 98
@@ -98,7 +101,11 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
98 */ 101 */
99 102
100#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ 103#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */
101#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */ 104#if defined(CONFIG_CPU_SH2)
105#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */
106#else
107#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */
108#endif
102#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ 109#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */
103 110
104struct sigframe 111struct sigframe
@@ -194,9 +201,10 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
194 201
195asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, 202asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
196 unsigned long r6, unsigned long r7, 203 unsigned long r6, unsigned long r7,
197 struct pt_regs regs) 204 struct pt_regs __regs)
198{ 205{
199 struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15]; 206 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
207 struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15];
200 sigset_t set; 208 sigset_t set;
201 int r0; 209 int r0;
202 210
@@ -216,7 +224,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
216 recalc_sigpending(); 224 recalc_sigpending();
217 spin_unlock_irq(&current->sighand->siglock); 225 spin_unlock_irq(&current->sighand->siglock);
218 226
219 if (restore_sigcontext(&regs, &frame->sc, &r0)) 227 if (restore_sigcontext(regs, &frame->sc, &r0))
220 goto badframe; 228 goto badframe;
221 return r0; 229 return r0;
222 230
@@ -227,9 +235,10 @@ badframe:
227 235
228asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, 236asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
229 unsigned long r6, unsigned long r7, 237 unsigned long r6, unsigned long r7,
230 struct pt_regs regs) 238 struct pt_regs __regs)
231{ 239{
232 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15]; 240 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
241 struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
233 sigset_t set; 242 sigset_t set;
234 stack_t st; 243 stack_t st;
235 int r0; 244 int r0;
@@ -246,14 +255,14 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
246 recalc_sigpending(); 255 recalc_sigpending();
247 spin_unlock_irq(&current->sighand->siglock); 256 spin_unlock_irq(&current->sighand->siglock);
248 257
249 if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0)) 258 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
250 goto badframe; 259 goto badframe;
251 260
252 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) 261 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
253 goto badframe; 262 goto badframe;
254 /* It is more difficult to avoid calling this function than to 263 /* It is more difficult to avoid calling this function than to
255 call it and ignore errors. */ 264 call it and ignore errors. */
256 do_sigaltstack(&st, NULL, regs.regs[15]); 265 do_sigaltstack(&st, NULL, regs->regs[15]);
257 266
258 return r0; 267 return r0;
259 268
@@ -350,7 +359,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
350 } else { 359 } else {
351 /* Generate return code (system call to sigreturn) */ 360 /* Generate return code (system call to sigreturn) */
352 err |= __put_user(MOVW(7), &frame->retcode[0]); 361 err |= __put_user(MOVW(7), &frame->retcode[0]);
353 err |= __put_user(TRAP16, &frame->retcode[1]); 362 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
354 err |= __put_user(OR_R0_R0, &frame->retcode[2]); 363 err |= __put_user(OR_R0_R0, &frame->retcode[2]);
355 err |= __put_user(OR_R0_R0, &frame->retcode[3]); 364 err |= __put_user(OR_R0_R0, &frame->retcode[3]);
356 err |= __put_user(OR_R0_R0, &frame->retcode[4]); 365 err |= __put_user(OR_R0_R0, &frame->retcode[4]);
@@ -430,7 +439,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
430 } else { 439 } else {
431 /* Generate return code (system call to rt_sigreturn) */ 440 /* Generate return code (system call to rt_sigreturn) */
432 err |= __put_user(MOVW(7), &frame->retcode[0]); 441 err |= __put_user(MOVW(7), &frame->retcode[0]);
433 err |= __put_user(TRAP16, &frame->retcode[1]); 442 err |= __put_user(TRAP_NOARG, &frame->retcode[1]);
434 err |= __put_user(OR_R0_R0, &frame->retcode[2]); 443 err |= __put_user(OR_R0_R0, &frame->retcode[2]);
435 err |= __put_user(OR_R0_R0, &frame->retcode[3]); 444 err |= __put_user(OR_R0_R0, &frame->retcode[3]);
436 err |= __put_user(OR_R0_R0, &frame->retcode[4]); 445 err |= __put_user(OR_R0_R0, &frame->retcode[4]);
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
new file mode 100644
index 000000000000..0d5268afe80f
--- /dev/null
+++ b/arch/sh/kernel/stacktrace.c
@@ -0,0 +1,43 @@
1/*
2 * arch/sh/kernel/stacktrace.c
3 *
4 * Stack trace management functions
5 *
6 * Copyright (C) 2006 Paul Mundt
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/sched.h>
13#include <linux/stacktrace.h>
14#include <linux/thread_info.h>
15#include <asm/ptrace.h>
16
17/*
18 * Save stack-backtrace addresses into a stack_trace buffer.
19 */
20void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
21{
22 unsigned long *sp;
23
24 if (!task)
25 task = current;
26 if (task == current)
27 sp = (unsigned long *)current_stack_pointer;
28 else
29 sp = (unsigned long *)task->thread.sp;
30
31 while (!kstack_end(sp)) {
32 unsigned long addr = *sp++;
33
34 if (__kernel_text_address(addr)) {
35 if (trace->skip > 0)
36 trace->skip--;
37 else
38 trace->entries[trace->nr_entries++] = addr;
39 if (trace->nr_entries >= trace->max_entries)
40 break;
41 }
42 }
43}
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index 8fde95001c34..e18f183e1035 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -33,14 +33,15 @@
33 */ 33 */
34asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, 34asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
35 unsigned long r6, unsigned long r7, 35 unsigned long r6, unsigned long r7,
36 struct pt_regs regs) 36 struct pt_regs __regs)
37{ 37{
38 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
38 int fd[2]; 39 int fd[2];
39 int error; 40 int error;
40 41
41 error = do_pipe(fd); 42 error = do_pipe(fd);
42 if (!error) { 43 if (!error) {
43 regs.regs[1] = fd[1]; 44 regs->regs[1] = fd[1];
44 return fd[0]; 45 return fd[0];
45 } 46 }
46 return error; 47 return error;
@@ -50,6 +51,7 @@ unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */
50 51
51EXPORT_SYMBOL(shm_align_mask); 52EXPORT_SYMBOL(shm_align_mask);
52 53
54#ifdef CONFIG_MMU
53/* 55/*
54 * To avoid cache aliases, we map the shared page with same color. 56 * To avoid cache aliases, we map the shared page with same color.
55 */ 57 */
@@ -135,6 +137,7 @@ full_search:
135 addr = COLOUR_ALIGN(addr, pgoff); 137 addr = COLOUR_ALIGN(addr, pgoff);
136 } 138 }
137} 139}
140#endif /* CONFIG_MMU */
138 141
139static inline long 142static inline long
140do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 143do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
@@ -311,6 +314,12 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
311#endif 314#endif
312} 315}
313 316
317#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)
318#define SYSCALL_ARG3 "trapa #0x23"
319#else
320#define SYSCALL_ARG3 "trapa #0x13"
321#endif
322
314/* 323/*
315 * Do a system call from kernel instead of calling sys_execve so we 324 * Do a system call from kernel instead of calling sys_execve so we
316 * end up with proper pt_regs. 325 * end up with proper pt_regs.
@@ -321,7 +330,7 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[])
321 register long __sc4 __asm__ ("r4") = (long) filename; 330 register long __sc4 __asm__ ("r4") = (long) filename;
322 register long __sc5 __asm__ ("r5") = (long) argv; 331 register long __sc5 __asm__ ("r5") = (long) argv;
323 register long __sc6 __asm__ ("r6") = (long) envp; 332 register long __sc6 __asm__ ("r6") = (long) envp;
324 __asm__ __volatile__ ("trapa #0x13" : "=z" (__sc0) 333 __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)
325 : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) 334 : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
326 : "memory"); 335 : "memory");
327 return __sc0; 336 return __sc0;
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
index 768334e95075..ca81976e9e34 100644
--- a/arch/sh/kernel/syscalls.S
+++ b/arch/sh/kernel/syscalls.S
@@ -351,3 +351,6 @@ ENTRY(sys_call_table)
351 .long sys_sync_file_range 351 .long sys_sync_file_range
352 .long sys_tee /* 315 */ 352 .long sys_tee /* 315 */
353 .long sys_vmsplice 353 .long sys_vmsplice
354 .long sys_move_pages
355 .long sys_getcpu
356 .long sys_epoll_pwait
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 57e708d7b52d..c206c9504c4b 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -13,6 +13,8 @@
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/profile.h> 15#include <linux/profile.h>
16#include <linux/timex.h>
17#include <linux/sched.h>
16#include <asm/clock.h> 18#include <asm/clock.h>
17#include <asm/rtc.h> 19#include <asm/rtc.h>
18#include <asm/timer.h> 20#include <asm/timer.h>
@@ -50,15 +52,20 @@ unsigned long long __attribute__ ((weak)) sched_clock(void)
50#ifndef CONFIG_GENERIC_TIME 52#ifndef CONFIG_GENERIC_TIME
51void do_gettimeofday(struct timeval *tv) 53void do_gettimeofday(struct timeval *tv)
52{ 54{
55 unsigned long flags;
53 unsigned long seq; 56 unsigned long seq;
54 unsigned long usec, sec; 57 unsigned long usec, sec;
55 58
56 do { 59 do {
57 seq = read_seqbegin(&xtime_lock); 60 /*
61 * Turn off IRQs when grabbing xtime_lock, so that
62 * the sys_timer get_offset code doesn't have to handle it.
63 */
64 seq = read_seqbegin_irqsave(&xtime_lock, flags);
58 usec = get_timer_offset(); 65 usec = get_timer_offset();
59 sec = xtime.tv_sec; 66 sec = xtime.tv_sec;
60 usec += xtime.tv_nsec / 1000; 67 usec += xtime.tv_nsec / NSEC_PER_USEC;
61 } while (read_seqretry(&xtime_lock, seq)); 68 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
62 69
63 while (usec >= 1000000) { 70 while (usec >= 1000000) {
64 usec -= 1000000; 71 usec -= 1000000;
@@ -85,7 +92,7 @@ int do_settimeofday(struct timespec *tv)
85 * wall time. Discover what correction gettimeofday() would have 92 * wall time. Discover what correction gettimeofday() would have
86 * made, and then undo it! 93 * made, and then undo it!
87 */ 94 */
88 nsec -= 1000 * get_timer_offset(); 95 nsec -= get_timer_offset() * NSEC_PER_USEC;
89 96
90 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); 97 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
91 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); 98 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -169,6 +176,108 @@ static struct sysdev_class timer_sysclass = {
169 .resume = timer_resume, 176 .resume = timer_resume,
170}; 177};
171 178
179#ifdef CONFIG_NO_IDLE_HZ
180static int timer_dyn_tick_enable(void)
181{
182 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
183 unsigned long flags;
184 int ret = -ENODEV;
185
186 if (dyn_tick) {
187 spin_lock_irqsave(&dyn_tick->lock, flags);
188 ret = 0;
189 if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
190 ret = dyn_tick->enable();
191
192 if (ret == 0)
193 dyn_tick->state |= DYN_TICK_ENABLED;
194 }
195 spin_unlock_irqrestore(&dyn_tick->lock, flags);
196 }
197
198 return ret;
199}
200
201static int timer_dyn_tick_disable(void)
202{
203 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
204 unsigned long flags;
205 int ret = -ENODEV;
206
207 if (dyn_tick) {
208 spin_lock_irqsave(&dyn_tick->lock, flags);
209 ret = 0;
210 if (dyn_tick->state & DYN_TICK_ENABLED) {
211 ret = dyn_tick->disable();
212
213 if (ret == 0)
214 dyn_tick->state &= ~DYN_TICK_ENABLED;
215 }
216 spin_unlock_irqrestore(&dyn_tick->lock, flags);
217 }
218
219 return ret;
220}
221
222/*
223 * Reprogram the system timer for at least the calculated time interval.
224 * This function should be called from the idle thread with IRQs disabled,
225 * immediately before sleeping.
226 */
227void timer_dyn_reprogram(void)
228{
229 struct dyn_tick_timer *dyn_tick = sys_timer->dyn_tick;
230 unsigned long next, seq, flags;
231
232 if (!dyn_tick)
233 return;
234
235 spin_lock_irqsave(&dyn_tick->lock, flags);
236 if (dyn_tick->state & DYN_TICK_ENABLED) {
237 next = next_timer_interrupt();
238 do {
239 seq = read_seqbegin(&xtime_lock);
240 dyn_tick->reprogram(next - jiffies);
241 } while (read_seqretry(&xtime_lock, seq));
242 }
243 spin_unlock_irqrestore(&dyn_tick->lock, flags);
244}
245
246static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
247{
248 return sprintf(buf, "%i\n",
249 (sys_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
250}
251
252static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
253 size_t count)
254{
255 unsigned int enable = simple_strtoul(buf, NULL, 2);
256
257 if (enable)
258 timer_dyn_tick_enable();
259 else
260 timer_dyn_tick_disable();
261
262 return count;
263}
264static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
265
266/*
267 * dyntick=enable|disable
268 */
269static char dyntick_str[4] __initdata = "";
270
271static int __init dyntick_setup(char *str)
272{
273 if (str)
274 strlcpy(dyntick_str, str, sizeof(dyntick_str));
275 return 1;
276}
277
278__setup("dyntick=", dyntick_setup);
279#endif
280
172static int __init timer_init_sysfs(void) 281static int __init timer_init_sysfs(void)
173{ 282{
174 int ret = sysdev_class_register(&timer_sysclass); 283 int ret = sysdev_class_register(&timer_sysclass);
@@ -176,7 +285,22 @@ static int __init timer_init_sysfs(void)
176 return ret; 285 return ret;
177 286
178 sys_timer->dev.cls = &timer_sysclass; 287 sys_timer->dev.cls = &timer_sysclass;
179 return sysdev_register(&sys_timer->dev); 288 ret = sysdev_register(&sys_timer->dev);
289
290#ifdef CONFIG_NO_IDLE_HZ
291 if (ret == 0 && sys_timer->dyn_tick) {
292 ret = sysdev_create_file(&sys_timer->dev, &attr_dyn_tick);
293
294 /*
295 * Turn on dynamic tick after calibrate delay
296 * for correct bogomips
297 */
298 if (ret == 0 && dyntick_str[0] == 'e')
299 ret = timer_dyn_tick_enable();
300 }
301#endif
302
303 return ret;
180} 304}
181device_initcall(timer_init_sysfs); 305device_initcall(timer_init_sysfs);
182 306
@@ -200,6 +324,11 @@ void __init time_init(void)
200 sys_timer = get_sys_timer(); 324 sys_timer = get_sys_timer();
201 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); 325 printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
202 326
327#ifdef CONFIG_NO_IDLE_HZ
328 if (sys_timer->dyn_tick)
329 spin_lock_init(&sys_timer->dyn_tick->lock);
330#endif
331
203#if defined(CONFIG_SH_KGDB) 332#if defined(CONFIG_SH_KGDB)
204 /* 333 /*
205 * Set up kgdb as requested. We do it here because the serial 334 * Set up kgdb as requested. We do it here because the serial
diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile
index 151a6a304cec..bcf244ff6a12 100644
--- a/arch/sh/kernel/timers/Makefile
+++ b/arch/sh/kernel/timers/Makefile
@@ -5,4 +5,6 @@
5obj-y := timer.o 5obj-y := timer.o
6 6
7obj-$(CONFIG_SH_TMU) += timer-tmu.o 7obj-$(CONFIG_SH_TMU) += timer-tmu.o
8obj-$(CONFIG_SH_MTU2) += timer-mtu2.o
9obj-$(CONFIG_SH_CMT) += timer-cmt.o
8 10
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c
new file mode 100644
index 000000000000..a574b93a4e7b
--- /dev/null
+++ b/arch/sh/kernel/timers/timer-cmt.c
@@ -0,0 +1,196 @@
1/*
2 * arch/sh/kernel/timers/timer-cmt.c - CMT Timer Support
3 *
4 * Copyright (C) 2005 Yoshinori Sato
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/interrupt.h>
14#include <linux/seqlock.h>
15#include <asm/timer.h>
16#include <asm/rtc.h>
17#include <asm/io.h>
18#include <asm/irq.h>
19#include <asm/clock.h>
20
21#if defined(CONFIG_CPU_SUBTYPE_SH7619)
22#define CMT_CMSTR 0xf84a0070
23#define CMT_CMCSR_0 0xf84a0072
24#define CMT_CMCNT_0 0xf84a0074
25#define CMT_CMCOR_0 0xf84a0076
26#define CMT_CMCSR_1 0xf84a0078
27#define CMT_CMCNT_1 0xf84a007a
28#define CMT_CMCOR_1 0xf84a007c
29
30#define STBCR3 0xf80a0000
31#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0)
32#define CMT_CMCSR_INIT 0x0040
33#define CMT_CMCSR_CALIB 0x0000
34#elif defined(CONFIG_CPU_SUBTYPE_SH7206)
35#define CMT_CMSTR 0xfffec000
36#define CMT_CMCSR_0 0xfffec002
37#define CMT_CMCNT_0 0xfffec004
38#define CMT_CMCOR_0 0xfffec006
39
40#define STBCR4 0xfffe040c
41#define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR4) & ~0x04, STBCR4); } while(0)
42#define CMT_CMCSR_INIT 0x0040
43#define CMT_CMCSR_CALIB 0x0000
44#else
45#error "Unknown CPU SUBTYPE"
46#endif
47
48static unsigned long cmt_timer_get_offset(void)
49{
50 int count;
51 static unsigned short count_p = 0xffff; /* for the first call after boot */
52 static unsigned long jiffies_p = 0;
53
54 /*
55 * cache volatile jiffies temporarily; we have IRQs turned off.
56 */
57 unsigned long jiffies_t;
58
59 /* timer count may underflow right here */
60 count = ctrl_inw(CMT_CMCOR_0);
61 count -= ctrl_inw(CMT_CMCNT_0);
62
63 jiffies_t = jiffies;
64
65 /*
66 * avoiding timer inconsistencies (they are rare, but they happen)...
67 * there is one kind of problem that must be avoided here:
68 * 1. the timer counter underflows
69 */
70
71 if (jiffies_t == jiffies_p) {
72 if (count > count_p) {
73 /* the nutcase */
74 if (ctrl_inw(CMT_CMCSR_0) & 0x80) { /* Check CMF bit */
75 count -= LATCH;
76 } else {
77 printk("%s (): hardware timer problem?\n",
78 __FUNCTION__);
79 }
80 }
81 } else
82 jiffies_p = jiffies_t;
83
84 count_p = count;
85
86 count = ((LATCH-1) - count) * TICK_SIZE;
87 count = (count + LATCH/2) / LATCH;
88
89 return count;
90}
91
92static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id)
93{
94 unsigned long timer_status;
95
96 /* Clear CMF bit */
97 timer_status = ctrl_inw(CMT_CMCSR_0);
98 timer_status &= ~0x80;
99 ctrl_outw(timer_status, CMT_CMCSR_0);
100
101 /*
102 * Here we are in the timer irq handler. We just have irqs locally
103 * disabled but we don't know if the timer_bh is running on the other
104 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
105 * the irq version of write_lock because as just said we have irq
106 * locally disabled. -arca
107 */
108 write_seqlock(&xtime_lock);
109 handle_timer_tick();
110 write_sequnlock(&xtime_lock);
111
112 return IRQ_HANDLED;
113}
114
115static struct irqaction cmt_irq = {
116 .name = "timer",
117 .handler = cmt_timer_interrupt,
118 .flags = IRQF_DISABLED | IRQF_TIMER,
119 .mask = CPU_MASK_NONE,
120};
121
122static void cmt_clk_init(struct clk *clk)
123{
124 u8 divisor = CMT_CMCSR_INIT & 0x3;
125 ctrl_inw(CMT_CMCSR_0);
126 ctrl_outw(CMT_CMCSR_INIT, CMT_CMCSR_0);
127 clk->parent = clk_get(NULL, "module_clk");
128 clk->rate = clk->parent->rate / (8 << (divisor << 1));
129}
130
131static void cmt_clk_recalc(struct clk *clk)
132{
133 u8 divisor = ctrl_inw(CMT_CMCSR_0) & 0x3;
134 clk->rate = clk->parent->rate / (8 << (divisor << 1));
135}
136
137static struct clk_ops cmt_clk_ops = {
138 .init = cmt_clk_init,
139 .recalc = cmt_clk_recalc,
140};
141
142static struct clk cmt0_clk = {
143 .name = "cmt0_clk",
144 .ops = &cmt_clk_ops,
145};
146
147static int cmt_timer_start(void)
148{
149 ctrl_outw(ctrl_inw(CMT_CMSTR) | 0x01, CMT_CMSTR);
150 return 0;
151}
152
153static int cmt_timer_stop(void)
154{
155 ctrl_outw(ctrl_inw(CMT_CMSTR) & ~0x01, CMT_CMSTR);
156 return 0;
157}
158
159static int cmt_timer_init(void)
160{
161 unsigned long interval;
162
163 cmt_clock_enable();
164
165 setup_irq(CONFIG_SH_TIMER_IRQ, &cmt_irq);
166
167 cmt0_clk.parent = clk_get(NULL, "module_clk");
168
169 cmt_timer_stop();
170
171 interval = cmt0_clk.parent->rate / 8 / HZ;
172 printk(KERN_INFO "Interval = %ld\n", interval);
173
174 ctrl_outw(interval, CMT_CMCOR_0);
175
176 clk_register(&cmt0_clk);
177 clk_enable(&cmt0_clk);
178
179 cmt_timer_start();
180
181 return 0;
182}
183
184struct sys_timer_ops cmt_timer_ops = {
185 .init = cmt_timer_init,
186 .start = cmt_timer_start,
187 .stop = cmt_timer_stop,
188#ifndef CONFIG_GENERIC_TIME
189 .get_offset = cmt_timer_get_offset,
190#endif
191};
192
193struct sys_timer cmt_timer = {
194 .name = "cmt",
195 .ops = &cmt_timer_ops,
196};
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c
new file mode 100644
index 000000000000..fffcd1c09873
--- /dev/null
+++ b/arch/sh/kernel/timers/timer-mtu2.c
@@ -0,0 +1,200 @@
1/*
2 * arch/sh/kernel/timers/timer-mtu2.c - MTU2 Timer Support
3 *
4 * Copyright (C) 2005 Paul Mundt
5 *
6 * Based off of arch/sh/kernel/timers/timer-tmu.c
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/seqlock.h>
16#include <asm/timer.h>
17#include <asm/io.h>
18#include <asm/irq.h>
19#include <asm/clock.h>
20
21/*
22 * We use channel 1 for our lowly system timer. Channel 2 would be the other
23 * likely candidate, but we leave it alone as it has higher divisors that
24 * would be of more use to other more interesting applications.
25 *
26 * TODO: Presently we only implement a 16-bit single-channel system timer.
27 * However, we can implement channel cascade if we go the overflow route and
28 * get away with using 2 MTU2 channels as a 32-bit timer.
29 */
30#define MTU2_TSTR 0xfffe4280
31#define MTU2_TCR_1 0xfffe4380
32#define MTU2_TMDR_1 0xfffe4381
33#define MTU2_TIOR_1 0xfffe4382
34#define MTU2_TIER_1 0xfffe4384
35#define MTU2_TSR_1 0xfffe4385
36#define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */
37#define MTU2_TGRA_1 0xfffe438a
38
39#define STBCR3 0xfffe0408
40
41#define MTU2_TSTR_CST1 (1 << 1) /* Counter Start 1 */
42
43#define MTU2_TSR_TGFA (1 << 0) /* GRA compare match */
44
45#define MTU2_TIER_TGIEA (1 << 0) /* GRA compare match interrupt enable */
46
47#define MTU2_TCR_INIT 0x22
48
49#define MTU2_TCR_CALIB 0x00
50
51static unsigned long mtu2_timer_get_offset(void)
52{
53 int count;
54 static int count_p = 0x7fff; /* for the first call after boot */
55 static unsigned long jiffies_p = 0;
56
57 /*
58 * cache volatile jiffies temporarily; we have IRQs turned off.
59 */
60 unsigned long jiffies_t;
61
62 /* timer count may underflow right here */
63 count = ctrl_inw(MTU2_TCNT_1); /* read the latched count */
64
65 jiffies_t = jiffies;
66
67 /*
68 * avoiding timer inconsistencies (they are rare, but they happen)...
69 * there is one kind of problem that must be avoided here:
70 * 1. the timer counter underflows
71 */
72
73 if (jiffies_t == jiffies_p) {
74 if (count > count_p) {
75 if (ctrl_inb(MTU2_TSR_1) & MTU2_TSR_TGFA) {
76 count -= LATCH;
77 } else {
78 printk("%s (): hardware timer problem?\n",
79 __FUNCTION__);
80 }
81 }
82 } else
83 jiffies_p = jiffies_t;
84
85 count_p = count;
86
87 count = ((LATCH-1) - count) * TICK_SIZE;
88 count = (count + LATCH/2) / LATCH;
89
90 return count;
91}
92
93static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id)
94{
95 unsigned long timer_status;
96
97 /* Clear TGFA bit */
98 timer_status = ctrl_inb(MTU2_TSR_1);
99 timer_status &= ~MTU2_TSR_TGFA;
100 ctrl_outb(timer_status, MTU2_TSR_1);
101
102 /* Do timer tick */
103 write_seqlock(&xtime_lock);
104 handle_timer_tick();
105 write_sequnlock(&xtime_lock);
106
107 return IRQ_HANDLED;
108}
109
110static struct irqaction mtu2_irq = {
111 .name = "timer",
112 .handler = mtu2_timer_interrupt,
113 .flags = IRQF_DISABLED | IRQF_TIMER,
114 .mask = CPU_MASK_NONE,
115};
116
117static unsigned int divisors[] = { 1, 4, 16, 64, 1, 1, 256 };
118
119static void mtu2_clk_init(struct clk *clk)
120{
121 u8 idx = MTU2_TCR_INIT & 0x7;
122
123 clk->rate = clk->parent->rate / divisors[idx];
124 /* Start TCNT counting */
125 ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
126
127}
128
129static void mtu2_clk_recalc(struct clk *clk)
130{
131 u8 idx = ctrl_inb(MTU2_TCR_1) & 0x7;
132 clk->rate = clk->parent->rate / divisors[idx];
133}
134
135static struct clk_ops mtu2_clk_ops = {
136 .init = mtu2_clk_init,
137 .recalc = mtu2_clk_recalc,
138};
139
140static struct clk mtu2_clk1 = {
141 .name = "mtu2_clk1",
142 .ops = &mtu2_clk_ops,
143};
144
145static int mtu2_timer_start(void)
146{
147 ctrl_outb(ctrl_inb(MTU2_TSTR) | MTU2_TSTR_CST1, MTU2_TSTR);
148 return 0;
149}
150
151static int mtu2_timer_stop(void)
152{
153 ctrl_outb(ctrl_inb(MTU2_TSTR) & ~MTU2_TSTR_CST1, MTU2_TSTR);
154 return 0;
155}
156
157static int mtu2_timer_init(void)
158{
159 u8 tmp;
160 unsigned long interval;
161
162 setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq);
163
164 mtu2_clk1.parent = clk_get(NULL, "module_clk");
165
166 ctrl_outb(ctrl_inb(STBCR3) & (~0x20), STBCR3);
167
168 /* Normal operation */
169 ctrl_outb(0, MTU2_TMDR_1);
170 ctrl_outb(MTU2_TCR_INIT, MTU2_TCR_1);
171 ctrl_outb(0x01, MTU2_TIOR_1);
172
173 /* Enable underflow interrupt */
174 ctrl_outb(ctrl_inb(MTU2_TIER_1) | MTU2_TIER_TGIEA, MTU2_TIER_1);
175
176 interval = CONFIG_SH_PCLK_FREQ / 16 / HZ;
177 printk(KERN_INFO "Interval = %ld\n", interval);
178
179 ctrl_outw(interval, MTU2_TGRA_1);
180 ctrl_outw(0, MTU2_TCNT_1);
181
182 clk_register(&mtu2_clk1);
183 clk_enable(&mtu2_clk1);
184
185 return 0;
186}
187
188struct sys_timer_ops mtu2_timer_ops = {
189 .init = mtu2_timer_init,
190 .start = mtu2_timer_start,
191 .stop = mtu2_timer_stop,
192#ifndef CONFIG_GENERIC_TIME
193 .get_offset = mtu2_timer_get_offset,
194#endif
195};
196
197struct sys_timer mtu2_timer = {
198 .name = "mtu2",
199 .ops = &mtu2_timer_ops,
200};
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c
index 24927015dc31..e060e71d0785 100644
--- a/arch/sh/kernel/timers/timer-tmu.c
+++ b/arch/sh/kernel/timers/timer-tmu.c
@@ -17,7 +17,6 @@
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/spinlock.h>
21#include <linux/seqlock.h> 20#include <linux/seqlock.h>
22#include <asm/timer.h> 21#include <asm/timer.h>
23#include <asm/rtc.h> 22#include <asm/rtc.h>
@@ -31,13 +30,9 @@
31 30
32#define TMU0_TCR_CALIB 0x0000 31#define TMU0_TCR_CALIB 0x0000
33 32
34static DEFINE_SPINLOCK(tmu0_lock);
35
36static unsigned long tmu_timer_get_offset(void) 33static unsigned long tmu_timer_get_offset(void)
37{ 34{
38 int count; 35 int count;
39 unsigned long flags;
40
41 static int count_p = 0x7fffffff; /* for the first call after boot */ 36 static int count_p = 0x7fffffff; /* for the first call after boot */
42 static unsigned long jiffies_p = 0; 37 static unsigned long jiffies_p = 0;
43 38
@@ -46,7 +41,6 @@ static unsigned long tmu_timer_get_offset(void)
46 */ 41 */
47 unsigned long jiffies_t; 42 unsigned long jiffies_t;
48 43
49 spin_lock_irqsave(&tmu0_lock, flags);
50 /* timer count may underflow right here */ 44 /* timer count may underflow right here */
51 count = ctrl_inl(TMU0_TCNT); /* read the latched count */ 45 count = ctrl_inl(TMU0_TCNT); /* read the latched count */
52 46
@@ -72,7 +66,6 @@ static unsigned long tmu_timer_get_offset(void)
72 jiffies_p = jiffies_t; 66 jiffies_p = jiffies_t;
73 67
74 count_p = count; 68 count_p = count;
75 spin_unlock_irqrestore(&tmu0_lock, flags);
76 69
77 count = ((LATCH-1) - count) * TICK_SIZE; 70 count = ((LATCH-1) - count) * TICK_SIZE;
78 count = (count + LATCH/2) / LATCH; 71 count = (count + LATCH/2) / LATCH;
@@ -106,7 +99,7 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
106static struct irqaction tmu_irq = { 99static struct irqaction tmu_irq = {
107 .name = "timer", 100 .name = "timer",
108 .handler = tmu_timer_interrupt, 101 .handler = tmu_timer_interrupt,
109 .flags = IRQF_DISABLED, 102 .flags = IRQF_DISABLED | IRQF_TIMER,
110 .mask = CPU_MASK_NONE, 103 .mask = CPU_MASK_NONE,
111}; 104};
112 105
@@ -149,9 +142,9 @@ static int tmu_timer_init(void)
149{ 142{
150 unsigned long interval; 143 unsigned long interval;
151 144
152 setup_irq(TIMER_IRQ, &tmu_irq); 145 setup_irq(CONFIG_SH_TIMER_IRQ, &tmu_irq);
153 146
154 tmu0_clk.parent = clk_get("module_clk"); 147 tmu0_clk.parent = clk_get(NULL, "module_clk");
155 148
156 /* Start TMU0 */ 149 /* Start TMU0 */
157 tmu_timer_stop(); 150 tmu_timer_stop();
diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c
index dc1f631053a8..a6bcc913d25e 100644
--- a/arch/sh/kernel/timers/timer.c
+++ b/arch/sh/kernel/timers/timer.c
@@ -17,6 +17,12 @@ static struct sys_timer *sys_timers[] __initdata = {
17#ifdef CONFIG_SH_TMU 17#ifdef CONFIG_SH_TMU
18 &tmu_timer, 18 &tmu_timer,
19#endif 19#endif
20#ifdef CONFIG_SH_MTU2
21 &mtu2_timer,
22#endif
23#ifdef CONFIG_SH_CMT
24 &cmt_timer,
25#endif
20 NULL, 26 NULL,
21}; 27};
22 28
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index c2c597e09482..ec110157992d 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -1,43 +1,32 @@
1/* $Id: traps.c,v 1.17 2004/05/02 01:46:30 sugioka Exp $ 1/*
2 * 2 * 'traps.c' handles hardware traps and faults after we have saved some
3 * linux/arch/sh/traps.c 3 * state in 'entry.S'.
4 * 4 *
5 * SuperH version: Copyright (C) 1999 Niibe Yutaka 5 * SuperH version: Copyright (C) 1999 Niibe Yutaka
6 * Copyright (C) 2000 Philipp Rumpf 6 * Copyright (C) 2000 Philipp Rumpf
7 * Copyright (C) 2000 David Howells 7 * Copyright (C) 2000 David Howells
8 * Copyright (C) 2002, 2003 Paul Mundt 8 * Copyright (C) 2002 - 2006 Paul Mundt
9 */ 9 *
10 10 * This file is subject to the terms and conditions of the GNU General Public
11/* 11 * License. See the file "COPYING" in the main directory of this archive
12 * 'Traps.c' handles hardware traps and faults after we have saved some 12 * for more details.
13 * state in 'entry.S'.
14 */ 13 */
15#include <linux/sched.h>
16#include <linux/kernel.h> 14#include <linux/kernel.h>
17#include <linux/string.h>
18#include <linux/errno.h>
19#include <linux/ptrace.h> 15#include <linux/ptrace.h>
20#include <linux/timer.h>
21#include <linux/mm.h>
22#include <linux/smp.h>
23#include <linux/smp_lock.h>
24#include <linux/init.h> 16#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/spinlock.h> 17#include <linux/spinlock.h>
27#include <linux/module.h> 18#include <linux/module.h>
28#include <linux/kallsyms.h> 19#include <linux/kallsyms.h>
29 20#include <linux/io.h>
21#include <linux/debug_locks.h>
22#include <linux/limits.h>
30#include <asm/system.h> 23#include <asm/system.h>
31#include <asm/uaccess.h> 24#include <asm/uaccess.h>
32#include <asm/io.h>
33#include <asm/atomic.h>
34#include <asm/processor.h>
35#include <asm/sections.h>
36 25
37#ifdef CONFIG_SH_KGDB 26#ifdef CONFIG_SH_KGDB
38#include <asm/kgdb.h> 27#include <asm/kgdb.h>
39#define CHK_REMOTE_DEBUG(regs) \ 28#define CHK_REMOTE_DEBUG(regs) \
40{ \ 29{ \
41 if (kgdb_debug_hook && !user_mode(regs))\ 30 if (kgdb_debug_hook && !user_mode(regs))\
42 (*kgdb_debug_hook)(regs); \ 31 (*kgdb_debug_hook)(regs); \
43} 32}
@@ -46,20 +35,44 @@
46#endif 35#endif
47 36
48#ifdef CONFIG_CPU_SH2 37#ifdef CONFIG_CPU_SH2
49#define TRAP_RESERVED_INST 4 38# define TRAP_RESERVED_INST 4
50#define TRAP_ILLEGAL_SLOT_INST 6 39# define TRAP_ILLEGAL_SLOT_INST 6
40# define TRAP_ADDRESS_ERROR 9
41# ifdef CONFIG_CPU_SH2A
42# define TRAP_DIVZERO_ERROR 17
43# define TRAP_DIVOVF_ERROR 18
44# endif
51#else 45#else
52#define TRAP_RESERVED_INST 12 46#define TRAP_RESERVED_INST 12
53#define TRAP_ILLEGAL_SLOT_INST 13 47#define TRAP_ILLEGAL_SLOT_INST 13
54#endif 48#endif
55 49
56/* 50static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
57 * These constants are for searching for possible module text 51{
58 * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is 52 unsigned long p;
59 * a guess of how much space is likely to be vmalloced. 53 int i;
60 */ 54
61#define VMALLOC_OFFSET (8*1024*1024) 55 printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
62#define MODULE_RANGE (8*1024*1024) 56
57 for (p = bottom & ~31; p < top; ) {
58 printk("%04lx: ", p & 0xffff);
59
60 for (i = 0; i < 8; i++, p += 4) {
61 unsigned int val;
62
63 if (p < bottom || p >= top)
64 printk(" ");
65 else {
66 if (__get_user(val, (unsigned int __user *)p)) {
67 printk("\n");
68 return;
69 }
70 printk("%08x ", val);
71 }
72 }
73 printk("\n");
74 }
75}
63 76
64DEFINE_SPINLOCK(die_lock); 77DEFINE_SPINLOCK(die_lock);
65 78
@@ -69,21 +82,33 @@ void die(const char * str, struct pt_regs * regs, long err)
69 82
70 console_verbose(); 83 console_verbose();
71 spin_lock_irq(&die_lock); 84 spin_lock_irq(&die_lock);
85 bust_spinlocks(1);
86
72 printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); 87 printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
88
73 CHK_REMOTE_DEBUG(regs); 89 CHK_REMOTE_DEBUG(regs);
90 print_modules();
74 show_regs(regs); 91 show_regs(regs);
92
93 printk("Process: %s (pid: %d, stack limit = %p)\n",
94 current->comm, current->pid, task_stack_page(current) + 1);
95
96 if (!user_mode(regs) || in_interrupt())
97 dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
98 (unsigned long)task_stack_page(current));
99
100 bust_spinlocks(0);
75 spin_unlock_irq(&die_lock); 101 spin_unlock_irq(&die_lock);
76 do_exit(SIGSEGV); 102 do_exit(SIGSEGV);
77} 103}
78 104
79static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) 105static inline void die_if_kernel(const char *str, struct pt_regs *regs,
106 long err)
80{ 107{
81 if (!user_mode(regs)) 108 if (!user_mode(regs))
82 die(str, regs, err); 109 die(str, regs, err);
83} 110}
84 111
85static int handle_unaligned_notify_count = 10;
86
87/* 112/*
88 * try and fix up kernelspace address errors 113 * try and fix up kernelspace address errors
89 * - userspace errors just cause EFAULT to be returned, resulting in SEGV 114 * - userspace errors just cause EFAULT to be returned, resulting in SEGV
@@ -93,8 +118,7 @@ static int handle_unaligned_notify_count = 10;
93 */ 118 */
94static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) 119static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
95{ 120{
96 if (!user_mode(regs)) 121 if (!user_mode(regs)) {
97 {
98 const struct exception_table_entry *fixup; 122 const struct exception_table_entry *fixup;
99 fixup = search_exception_tables(regs->pc); 123 fixup = search_exception_tables(regs->pc);
100 if (fixup) { 124 if (fixup) {
@@ -106,6 +130,40 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
106 return -EFAULT; 130 return -EFAULT;
107} 131}
108 132
133#ifdef CONFIG_BUG
134#ifdef CONFIG_DEBUG_BUGVERBOSE
135static inline void do_bug_verbose(struct pt_regs *regs)
136{
137 struct bug_frame f;
138 long len;
139
140 if (__copy_from_user(&f, (const void __user *)regs->pc,
141 sizeof(struct bug_frame)))
142 return;
143
144 len = __strnlen_user(f.file, PATH_MAX) - 1;
145 if (unlikely(len < 0 || len >= PATH_MAX))
146 f.file = "<bad filename>";
147 len = __strnlen_user(f.func, PATH_MAX) - 1;
148 if (unlikely(len < 0 || len >= PATH_MAX))
149 f.func = "<bad function>";
150
151 printk(KERN_ALERT "kernel BUG in %s() at %s:%d!\n",
152 f.func, f.file, f.line);
153}
154#else
155static inline void do_bug_verbose(struct pt_regs *regs)
156{
157}
158#endif /* CONFIG_DEBUG_BUGVERBOSE */
159#endif /* CONFIG_BUG */
160
161void handle_BUG(struct pt_regs *regs)
162{
163 do_bug_verbose(regs);
164 die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff);
165}
166
109/* 167/*
110 * handle an instruction that does an unaligned memory access by emulating the 168 * handle an instruction that does an unaligned memory access by emulating the
111 * desired behaviour 169 * desired behaviour
@@ -179,7 +237,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
179 if (copy_to_user(dst,src,4)) 237 if (copy_to_user(dst,src,4))
180 goto fetch_fault; 238 goto fetch_fault;
181 ret = 0; 239 ret = 0;
182 break; 240 break;
183 241
184 case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ 242 case 2: /* mov.[bwl] to memory, possibly with pre-decrement */
185 if (instruction & 4) 243 if (instruction & 4)
@@ -203,7 +261,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
203 if (copy_from_user(dst,src,4)) 261 if (copy_from_user(dst,src,4))
204 goto fetch_fault; 262 goto fetch_fault;
205 ret = 0; 263 ret = 0;
206 break; 264 break;
207 265
208 case 6: /* mov.[bwl] from memory, possibly with post-increment */ 266 case 6: /* mov.[bwl] from memory, possibly with post-increment */
209 src = (unsigned char*) *rm; 267 src = (unsigned char*) *rm;
@@ -211,7 +269,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
211 *rm += count; 269 *rm += count;
212 dst = (unsigned char*) rn; 270 dst = (unsigned char*) rn;
213 *(unsigned long*)dst = 0; 271 *(unsigned long*)dst = 0;
214 272
215#ifdef __LITTLE_ENDIAN__ 273#ifdef __LITTLE_ENDIAN__
216 if (copy_from_user(dst, src, count)) 274 if (copy_from_user(dst, src, count))
217 goto fetch_fault; 275 goto fetch_fault;
@@ -222,7 +280,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs)
222 } 280 }
223#else 281#else
224 dst += 4-count; 282 dst += 4-count;
225 283
226 if (copy_from_user(dst, src, count)) 284 if (copy_from_user(dst, src, count))
227 goto fetch_fault; 285 goto fetch_fault;
228 286
@@ -301,7 +359,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
301 return -EFAULT; 359 return -EFAULT;
302 360
303 /* kernel */ 361 /* kernel */
304 die("delay-slot-insn faulting in handle_unaligned_delayslot", regs, 0); 362 die("delay-slot-insn faulting in handle_unaligned_delayslot",
363 regs, 0);
305 } 364 }
306 365
307 return handle_unaligned_ins(instruction,regs); 366 return handle_unaligned_ins(instruction,regs);
@@ -323,6 +382,13 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs)
323#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) 382#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
324#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) 383#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
325 384
385/*
386 * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit
387 * opcodes..
388 */
389#ifndef CONFIG_CPU_SH2A
390static int handle_unaligned_notify_count = 10;
391
326static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) 392static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
327{ 393{
328 u_int rm; 394 u_int rm;
@@ -335,7 +401,8 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
335 if (user_mode(regs) && handle_unaligned_notify_count>0) { 401 if (user_mode(regs) && handle_unaligned_notify_count>0) {
336 handle_unaligned_notify_count--; 402 handle_unaligned_notify_count--;
337 403
338 printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", 404 printk(KERN_NOTICE "Fixing up unaligned userspace access "
405 "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
339 current->comm,current->pid,(u16*)regs->pc,instruction); 406 current->comm,current->pid,(u16*)regs->pc,instruction);
340 } 407 }
341 408
@@ -459,32 +526,58 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
459 regs->pc += 2; 526 regs->pc += 2;
460 return ret; 527 return ret;
461} 528}
529#endif /* CONFIG_CPU_SH2A */
530
531#ifdef CONFIG_CPU_HAS_SR_RB
532#define lookup_exception_vector(x) \
533 __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x)))
534#else
535#define lookup_exception_vector(x) \
536 __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x)))
537#endif
462 538
463/* 539/*
464 * Handle various address error exceptions 540 * Handle various address error exceptions:
541 * - instruction address error:
542 * misaligned PC
543 * PC >= 0x80000000 in user mode
544 * - data address error (read and write)
545 * misaligned data access
546 * access to >= 0x80000000 is user mode
547 * Unfortuntaly we can't distinguish between instruction address error
548 * and data address errors caused by read acceses.
465 */ 549 */
466asmlinkage void do_address_error(struct pt_regs *regs, 550asmlinkage void do_address_error(struct pt_regs *regs,
467 unsigned long writeaccess, 551 unsigned long writeaccess,
468 unsigned long address) 552 unsigned long address)
469{ 553{
470 unsigned long error_code; 554 unsigned long error_code = 0;
471 mm_segment_t oldfs; 555 mm_segment_t oldfs;
556 siginfo_t info;
557#ifndef CONFIG_CPU_SH2A
472 u16 instruction; 558 u16 instruction;
473 int tmp; 559 int tmp;
560#endif
474 561
475 asm volatile("stc r2_bank,%0": "=r" (error_code)); 562 /* Intentional ifdef */
563#ifdef CONFIG_CPU_HAS_SR_RB
564 lookup_exception_vector(error_code);
565#endif
476 566
477 oldfs = get_fs(); 567 oldfs = get_fs();
478 568
479 if (user_mode(regs)) { 569 if (user_mode(regs)) {
570 int si_code = BUS_ADRERR;
571
480 local_irq_enable(); 572 local_irq_enable();
481 current->thread.error_code = error_code;
482 current->thread.trap_no = (writeaccess) ? 8 : 7;
483 573
484 /* bad PC is not something we can fix */ 574 /* bad PC is not something we can fix */
485 if (regs->pc & 1) 575 if (regs->pc & 1) {
576 si_code = BUS_ADRALN;
486 goto uspace_segv; 577 goto uspace_segv;
578 }
487 579
580#ifndef CONFIG_CPU_SH2A
488 set_fs(USER_DS); 581 set_fs(USER_DS);
489 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { 582 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
490 /* Argh. Fault on the instruction itself. 583 /* Argh. Fault on the instruction itself.
@@ -499,14 +592,23 @@ asmlinkage void do_address_error(struct pt_regs *regs,
499 592
500 if (tmp==0) 593 if (tmp==0)
501 return; /* sorted */ 594 return; /* sorted */
595#endif
502 596
503 uspace_segv: 597uspace_segv:
504 printk(KERN_NOTICE "Killing process \"%s\" due to unaligned access\n", current->comm); 598 printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned "
505 force_sig(SIGSEGV, current); 599 "access (PC %lx PR %lx)\n", current->comm, regs->pc,
600 regs->pr);
601
602 info.si_signo = SIGBUS;
603 info.si_errno = 0;
604 info.si_code = si_code;
605 info.si_addr = (void *) address;
606 force_sig_info(SIGBUS, &info, current);
506 } else { 607 } else {
507 if (regs->pc & 1) 608 if (regs->pc & 1)
508 die("unaligned program counter", regs, error_code); 609 die("unaligned program counter", regs, error_code);
509 610
611#ifndef CONFIG_CPU_SH2A
510 set_fs(KERNEL_DS); 612 set_fs(KERNEL_DS);
511 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { 613 if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) {
512 /* Argh. Fault on the instruction itself. 614 /* Argh. Fault on the instruction itself.
@@ -518,6 +620,12 @@ asmlinkage void do_address_error(struct pt_regs *regs,
518 620
519 handle_unaligned_access(instruction, regs); 621 handle_unaligned_access(instruction, regs);
520 set_fs(oldfs); 622 set_fs(oldfs);
623#else
624 printk(KERN_NOTICE "Killing process \"%s\" due to unaligned "
625 "access\n", current->comm);
626
627 force_sig(SIGSEGV, current);
628#endif
521 } 629 }
522} 630}
523 631
@@ -529,7 +637,7 @@ int is_dsp_inst(struct pt_regs *regs)
529{ 637{
530 unsigned short inst; 638 unsigned short inst;
531 639
532 /* 640 /*
533 * Safe guard if DSP mode is already enabled or we're lacking 641 * Safe guard if DSP mode is already enabled or we're lacking
534 * the DSP altogether. 642 * the DSP altogether.
535 */ 643 */
@@ -550,24 +658,49 @@ int is_dsp_inst(struct pt_regs *regs)
550#define is_dsp_inst(regs) (0) 658#define is_dsp_inst(regs) (0)
551#endif /* CONFIG_SH_DSP */ 659#endif /* CONFIG_SH_DSP */
552 660
553extern int do_fpu_inst(unsigned short, struct pt_regs*); 661#ifdef CONFIG_CPU_SH2A
662asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
663 unsigned long r6, unsigned long r7,
664 struct pt_regs __regs)
665{
666 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
667 siginfo_t info;
668
669 switch (r4) {
670 case TRAP_DIVZERO_ERROR:
671 info.si_code = FPE_INTDIV;
672 break;
673 case TRAP_DIVOVF_ERROR:
674 info.si_code = FPE_INTOVF;
675 break;
676 }
677
678 force_sig_info(SIGFPE, &info, current);
679}
680#endif
681
682/* arch/sh/kernel/cpu/sh4/fpu.c */
683extern int do_fpu_inst(unsigned short, struct pt_regs *);
684extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5,
685 unsigned long r6, unsigned long r7, struct pt_regs __regs);
554 686
555asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, 687asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
556 unsigned long r6, unsigned long r7, 688 unsigned long r6, unsigned long r7,
557 struct pt_regs regs) 689 struct pt_regs __regs)
558{ 690{
691 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
559 unsigned long error_code; 692 unsigned long error_code;
560 struct task_struct *tsk = current; 693 struct task_struct *tsk = current;
561 694
562#ifdef CONFIG_SH_FPU_EMU 695#ifdef CONFIG_SH_FPU_EMU
563 unsigned short inst; 696 unsigned short inst = 0;
564 int err; 697 int err;
565 698
566 get_user(inst, (unsigned short*)regs.pc); 699 get_user(inst, (unsigned short*)regs->pc);
567 700
568 err = do_fpu_inst(inst, &regs); 701 err = do_fpu_inst(inst, regs);
569 if (!err) { 702 if (!err) {
570 regs.pc += 2; 703 regs->pc += 2;
571 return; 704 return;
572 } 705 }
573 /* not a FPU inst. */ 706 /* not a FPU inst. */
@@ -575,20 +708,19 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
575 708
576#ifdef CONFIG_SH_DSP 709#ifdef CONFIG_SH_DSP
577 /* Check if it's a DSP instruction */ 710 /* Check if it's a DSP instruction */
578 if (is_dsp_inst(&regs)) { 711 if (is_dsp_inst(regs)) {
579 /* Enable DSP mode, and restart instruction. */ 712 /* Enable DSP mode, and restart instruction. */
580 regs.sr |= SR_DSP; 713 regs->sr |= SR_DSP;
581 return; 714 return;
582 } 715 }
583#endif 716#endif
584 717
585 asm volatile("stc r2_bank, %0": "=r" (error_code)); 718 lookup_exception_vector(error_code);
719
586 local_irq_enable(); 720 local_irq_enable();
587 tsk->thread.error_code = error_code; 721 CHK_REMOTE_DEBUG(regs);
588 tsk->thread.trap_no = TRAP_RESERVED_INST;
589 CHK_REMOTE_DEBUG(&regs);
590 force_sig(SIGILL, tsk); 722 force_sig(SIGILL, tsk);
591 die_if_no_fixup("reserved instruction", &regs, error_code); 723 die_if_no_fixup("reserved instruction", regs, error_code);
592} 724}
593 725
594#ifdef CONFIG_SH_FPU_EMU 726#ifdef CONFIG_SH_FPU_EMU
@@ -636,39 +768,41 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs)
636 768
637asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, 769asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
638 unsigned long r6, unsigned long r7, 770 unsigned long r6, unsigned long r7,
639 struct pt_regs regs) 771 struct pt_regs __regs)
640{ 772{
773 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
641 unsigned long error_code; 774 unsigned long error_code;
642 struct task_struct *tsk = current; 775 struct task_struct *tsk = current;
643#ifdef CONFIG_SH_FPU_EMU 776#ifdef CONFIG_SH_FPU_EMU
644 unsigned short inst; 777 unsigned short inst = 0;
645 778
646 get_user(inst, (unsigned short *)regs.pc + 1); 779 get_user(inst, (unsigned short *)regs->pc + 1);
647 if (!do_fpu_inst(inst, &regs)) { 780 if (!do_fpu_inst(inst, regs)) {
648 get_user(inst, (unsigned short *)regs.pc); 781 get_user(inst, (unsigned short *)regs->pc);
649 if (!emulate_branch(inst, &regs)) 782 if (!emulate_branch(inst, regs))
650 return; 783 return;
651 /* fault in branch.*/ 784 /* fault in branch.*/
652 } 785 }
653 /* not a FPU inst. */ 786 /* not a FPU inst. */
654#endif 787#endif
655 788
656 asm volatile("stc r2_bank, %0": "=r" (error_code)); 789 lookup_exception_vector(error_code);
790
657 local_irq_enable(); 791 local_irq_enable();
658 tsk->thread.error_code = error_code; 792 CHK_REMOTE_DEBUG(regs);
659 tsk->thread.trap_no = TRAP_RESERVED_INST;
660 CHK_REMOTE_DEBUG(&regs);
661 force_sig(SIGILL, tsk); 793 force_sig(SIGILL, tsk);
662 die_if_no_fixup("illegal slot instruction", &regs, error_code); 794 die_if_no_fixup("illegal slot instruction", regs, error_code);
663} 795}
664 796
665asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, 797asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
666 unsigned long r6, unsigned long r7, 798 unsigned long r6, unsigned long r7,
667 struct pt_regs regs) 799 struct pt_regs __regs)
668{ 800{
801 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
669 long ex; 802 long ex;
670 asm volatile("stc r2_bank, %0" : "=r" (ex)); 803
671 die_if_kernel("exception", &regs, ex); 804 lookup_exception_vector(ex);
805 die_if_kernel("exception", regs, ex);
672} 806}
673 807
674#if defined(CONFIG_SH_STANDARD_BIOS) 808#if defined(CONFIG_SH_STANDARD_BIOS)
@@ -709,14 +843,24 @@ void __init per_cpu_trap_init(void)
709 : "memory"); 843 : "memory");
710} 844}
711 845
712void __init trap_init(void) 846void *set_exception_table_vec(unsigned int vec, void *handler)
713{ 847{
714 extern void *exception_handling_table[]; 848 extern void *exception_handling_table[];
849 void *old_handler;
850
851 old_handler = exception_handling_table[vec];
852 exception_handling_table[vec] = handler;
853 return old_handler;
854}
715 855
716 exception_handling_table[TRAP_RESERVED_INST] 856extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5,
717 = (void *)do_reserved_inst; 857 unsigned long r6, unsigned long r7,
718 exception_handling_table[TRAP_ILLEGAL_SLOT_INST] 858 struct pt_regs __regs);
719 = (void *)do_illegal_slot_inst; 859
860void __init trap_init(void)
861{
862 set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst);
863 set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst);
720 864
721#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ 865#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
722 defined(CONFIG_SH_FPU_EMU) 866 defined(CONFIG_SH_FPU_EMU)
@@ -725,61 +869,67 @@ void __init trap_init(void)
725 * reserved. They'll be handled in the math-emu case, or faulted on 869 * reserved. They'll be handled in the math-emu case, or faulted on
726 * otherwise. 870 * otherwise.
727 */ 871 */
728 /* entry 64 corresponds to EXPEVT=0x800 */ 872 set_exception_table_evt(0x800, do_reserved_inst);
729 exception_handling_table[64] = (void *)do_reserved_inst; 873 set_exception_table_evt(0x820, do_illegal_slot_inst);
730 exception_handling_table[65] = (void *)do_illegal_slot_inst; 874#elif defined(CONFIG_SH_FPU)
875 set_exception_table_evt(0x800, do_fpu_state_restore);
876 set_exception_table_evt(0x820, do_fpu_state_restore);
731#endif 877#endif
732 878
879#ifdef CONFIG_CPU_SH2
880 set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler);
881#endif
882#ifdef CONFIG_CPU_SH2A
883 set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error);
884 set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error);
885#endif
886
733 /* Setup VBR for boot cpu */ 887 /* Setup VBR for boot cpu */
734 per_cpu_trap_init(); 888 per_cpu_trap_init();
735} 889}
736 890
737void show_stack(struct task_struct *tsk, unsigned long *sp) 891void show_trace(struct task_struct *tsk, unsigned long *sp,
892 struct pt_regs *regs)
738{ 893{
739 unsigned long *stack, addr; 894 unsigned long addr;
740 unsigned long module_start = VMALLOC_START;
741 unsigned long module_end = VMALLOC_END;
742 int i = 1;
743 895
744 if (!tsk) 896 if (regs && user_mode(regs))
745 tsk = current; 897 return;
746 if (tsk == current)
747 sp = (unsigned long *)current_stack_pointer;
748 else
749 sp = (unsigned long *)tsk->thread.sp;
750
751 stack = sp;
752 898
753 printk("\nCall trace: "); 899 printk("\nCall trace: ");
754#ifdef CONFIG_KALLSYMS 900#ifdef CONFIG_KALLSYMS
755 printk("\n"); 901 printk("\n");
756#endif 902#endif
757 903
758 while (!kstack_end(stack)) { 904 while (!kstack_end(sp)) {
759 addr = *stack++; 905 addr = *sp++;
760 if (((addr >= (unsigned long)_text) && 906 if (kernel_text_address(addr))
761 (addr <= (unsigned long)_etext)) || 907 print_ip_sym(addr);
762 ((addr >= module_start) && (addr <= module_end))) {
763 /*
764 * For 80-columns display, 6 entry is maximum.
765 * NOTE: '[<8c00abcd>] ' consumes 13 columns .
766 */
767#ifndef CONFIG_KALLSYMS
768 if (i && ((i % 6) == 0))
769 printk("\n ");
770#endif
771 printk("[<%08lx>] ", addr);
772 print_symbol("%s\n", addr);
773 i++;
774 }
775 } 908 }
776 909
777 printk("\n"); 910 printk("\n");
911
912 if (!tsk)
913 tsk = current;
914
915 debug_show_held_locks(tsk);
778} 916}
779 917
780void show_task(unsigned long *sp) 918void show_stack(struct task_struct *tsk, unsigned long *sp)
781{ 919{
782 show_stack(NULL, sp); 920 unsigned long stack;
921
922 if (!tsk)
923 tsk = current;
924 if (tsk == current)
925 sp = (unsigned long *)current_stack_pointer;
926 else
927 sp = (unsigned long *)tsk->thread.sp;
928
929 stack = (unsigned long)sp;
930 dump_mem("Stack: ", stack, THREAD_SIZE +
931 (unsigned long)task_stack_page(tsk));
932 show_trace(tsk, sp, NULL);
783} 933}
784 934
785void dump_stack(void) 935void dump_stack(void)
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5eb930918186..f34bdcc33a7d 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -51,7 +51,7 @@ SECTIONS
51 } 51 }
52 52
53 . = ALIGN(PAGE_SIZE); 53 . = ALIGN(PAGE_SIZE);
54 .data.page_aligned : { *(.data.idt) } 54 .data.page_aligned : { *(.data.page_aligned) }
55 55
56 . = ALIGN(32); 56 . = ALIGN(32);
57 __per_cpu_start = .; 57 __per_cpu_start = .;
@@ -76,13 +76,7 @@ SECTIONS
76 __setup_end = .; 76 __setup_end = .;
77 __initcall_start = .; 77 __initcall_start = .;
78 .initcall.init : { 78 .initcall.init : {
79 *(.initcall1.init) 79 INITCALLS
80 *(.initcall2.init)
81 *(.initcall3.init)
82 *(.initcall4.init)
83 *(.initcall5.init)
84 *(.initcall6.init)
85 *(.initcall7.init)
86 } 80 }
87 __initcall_end = .; 81 __initcall_end = .;
88 __con_initcall_start = .; 82 __con_initcall_start = .;
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
index 075d6cc1a2d7..deb46941f315 100644
--- a/arch/sh/kernel/vsyscall/vsyscall.c
+++ b/arch/sh/kernel/vsyscall/vsyscall.c
@@ -97,7 +97,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
97 goto up_fail; 97 goto up_fail;
98 } 98 }
99 99
100 vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); 100 vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
101 if (!vma) { 101 if (!vma) {
102 ret = -ENOMEM; 102 ret = -ENOMEM;
103 goto up_fail; 103 goto up_fail;