diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-06 11:10:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-06 11:10:55 -0500 |
commit | dd6a7c19e4630f635467246a81b8e0cc818c05e6 (patch) | |
tree | 8fc93cdef4070183cbd3fa06019c84728380b389 /arch/sh/kernel/cpu | |
parent | dd8856bda5f1308beb113281b248683992998a9e (diff) | |
parent | ea0f8feaa041f3ccec3d6b8ee51325b177daef06 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: (43 commits)
sh: sh775x/titan fixes for irq header changes.
sh: update r7780rp defconfig.
sh: compile fixes for header cleanup.
sh: Fixup pte_mkhuge() build failure.
sh: set KBUILD_IMAGE to something sensible.
sh: show held locks in stack trace with lockdep.
sh: platform_pata support for R7780RP
sh: stacktrace/lockdep/irqflags tracing support.
sh: Fixup movli.l/movco.l atomic ops for gcc4.
sh: dyntick infrastructure.
sh: Clock framework tidying.
sh: Turn off IRQs around get_timer_offset() calls.
sh: Get the PGD right in oops case with 64-bit PTEs.
sh: Fix store queue bitmap end.
sh: More flexible + SH7780 earlyprintk SCIF support.
sh: Fixup various PAGE_SIZE == 4096 assumptions.
sh: Fixup 4K irq stacks.
sh: dma-api channel capability extensions.
sh: Drop name overload in dma-sh.
sh: Make dma-isa depend on ISA_DMA_API.
...
Diffstat (limited to 'arch/sh/kernel/cpu')
28 files changed, 1604 insertions, 161 deletions
diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index fb5dac069382..0582e6712b79 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile | |||
@@ -2,11 +2,12 @@ | |||
2 | # Makefile for the Linux/SuperH CPU-specifc backends. | 2 | # Makefile for the Linux/SuperH CPU-specifc backends. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += irq/ init.o clock.o | 5 | obj-$(CONFIG_CPU_SH2) = sh2/ |
6 | 6 | obj-$(CONFIG_CPU_SH2A) = sh2a/ | |
7 | obj-$(CONFIG_CPU_SH2) += sh2/ | 7 | obj-$(CONFIG_CPU_SH3) = sh3/ |
8 | obj-$(CONFIG_CPU_SH3) += sh3/ | 8 | obj-$(CONFIG_CPU_SH4) = sh4/ |
9 | obj-$(CONFIG_CPU_SH4) += sh4/ | ||
10 | 9 | ||
11 | obj-$(CONFIG_UBC_WAKEUP) += ubc.o | 10 | obj-$(CONFIG_UBC_WAKEUP) += ubc.o |
12 | obj-$(CONFIG_SH_ADC) += adc.o | 11 | obj-$(CONFIG_SH_ADC) += adc.o |
12 | |||
13 | obj-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 | ||
198 | struct 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 | */ | ||
205 | struct 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 | |||
231 | found: | ||
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 | # |
4 | obj-y += ipr.o imask.o | 4 | obj-y += imask.o |
5 | 5 | ||
6 | obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o | ||
6 | obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o | 7 | obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o |
7 | obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o | 8 | obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o |
8 | obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o | 9 | obj-$(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 74ca576a7ce5..74defe76a058 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c | |||
@@ -11,22 +11,29 @@ | |||
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/irq.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <asm/system.h> | 16 | |
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 | ||
17 | 26 | ||
18 | static void disable_intc2_irq(unsigned int irq) | 27 | static void disable_intc2_irq(unsigned int irq) |
19 | { | 28 | { |
20 | struct intc2_data *p = get_irq_chip_data(irq); | 29 | struct intc2_data *p = get_irq_chip_data(irq); |
21 | ctrl_outl(1 << p->msk_shift, | 30 | ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset); |
22 | INTC2_BASE + INTC2_INTMSK_OFFSET + p->msk_offset); | ||
23 | } | 31 | } |
24 | 32 | ||
25 | static void enable_intc2_irq(unsigned int irq) | 33 | static void enable_intc2_irq(unsigned int irq) |
26 | { | 34 | { |
27 | struct intc2_data *p = get_irq_chip_data(irq); | 35 | struct intc2_data *p = get_irq_chip_data(irq); |
28 | ctrl_outl(1 << p->msk_shift, | 36 | ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset); |
29 | INTC2_BASE + INTC2_INTMSKCLR_OFFSET + p->msk_offset); | ||
30 | } | 37 | } |
31 | 38 | ||
32 | static struct irq_chip intc2_irq_chip = { | 39 | static struct irq_chip intc2_irq_chip = { |
@@ -61,12 +68,10 @@ void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs) | |||
61 | /* Set the priority level */ | 68 | /* Set the priority level */ |
62 | local_irq_save(flags); | 69 | local_irq_save(flags); |
63 | 70 | ||
64 | ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + | 71 | ipr = ctrl_inl(INTC2_BASE + p->ipr_offset); |
65 | p->ipr_offset); | ||
66 | ipr &= ~(0xf << p->ipr_shift); | 72 | ipr &= ~(0xf << p->ipr_shift); |
67 | ipr |= p->priority << p->ipr_shift; | 73 | ipr |= p->priority << p->ipr_shift; |
68 | ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + | 74 | ctrl_outl(ipr, INTC2_BASE + p->ipr_offset); |
69 | p->ipr_offset); | ||
70 | 75 | ||
71 | local_irq_restore(flags); | 76 | local_irq_restore(flags); |
72 | 77 | ||
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index a0089563cbfc..35eb5751a3aa 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c | |||
@@ -19,25 +19,21 @@ | |||
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 | |||
26 | 24 | ||
27 | static void disable_ipr_irq(unsigned int irq) | 25 | static void disable_ipr_irq(unsigned int irq) |
28 | { | 26 | { |
29 | struct ipr_data *p = get_irq_chip_data(irq); | 27 | struct ipr_data *p = get_irq_chip_data(irq); |
30 | int shift = p->shift*4; | ||
31 | /* Set the priority in IPR to 0 */ | 28 | /* Set the priority in IPR to 0 */ |
32 | ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << shift)), p->addr); | 29 | ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); |
33 | } | 30 | } |
34 | 31 | ||
35 | static void enable_ipr_irq(unsigned int irq) | 32 | static void enable_ipr_irq(unsigned int irq) |
36 | { | 33 | { |
37 | struct ipr_data *p = get_irq_chip_data(irq); | 34 | struct ipr_data *p = get_irq_chip_data(irq); |
38 | int shift = p->shift*4; | ||
39 | /* Set priority in IPR back to original value */ | 35 | /* Set priority in IPR back to original value */ |
40 | ctrl_outw(ctrl_inw(p->addr) | (p->priority << shift), p->addr); | 36 | ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); |
41 | } | 37 | } |
42 | 38 | ||
43 | static struct irq_chip ipr_irq_chip = { | 39 | static struct irq_chip ipr_irq_chip = { |
@@ -53,6 +49,10 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) | |||
53 | 49 | ||
54 | for (i = 0; i < nr_irqs; i++) { | 50 | for (i = 0; i < nr_irqs; i++) { |
55 | unsigned int irq = table[i].irq; | 51 | unsigned int irq = table[i].irq; |
52 | table[i].addr = map_ipridx_to_addr(table[i].ipr_idx); | ||
53 | /* could the IPR index be mapped, if not we ignore this */ | ||
54 | if (table[i].addr == 0) | ||
55 | continue; | ||
56 | disable_irq_nosync(irq); | 56 | disable_irq_nosync(irq); |
57 | set_irq_chip_and_handler_name(irq, &ipr_irq_chip, | 57 | set_irq_chip_and_handler_name(irq, &ipr_irq_chip, |
58 | handle_level_irq, "level"); | 58 | handle_level_irq, "level"); |
@@ -62,83 +62,6 @@ void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) | |||
62 | } | 62 | } |
63 | EXPORT_SYMBOL(make_ipr_irq); | 63 | EXPORT_SYMBOL(make_ipr_irq); |
64 | 64 | ||
65 | static struct ipr_data sys_ipr_map[] = { | ||
66 | #ifndef CONFIG_CPU_SUBTYPE_SH7780 | ||
67 | { TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY }, | ||
68 | { TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY }, | ||
69 | #ifdef RTC_IRQ | ||
70 | { RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY }, | ||
71 | #endif | ||
72 | #ifdef SCI_ERI_IRQ | ||
73 | { SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, | ||
74 | { SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, | ||
75 | { SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY }, | ||
76 | #endif | ||
77 | #ifdef SCIF1_ERI_IRQ | ||
78 | { SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, | ||
79 | { SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, | ||
80 | { SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, | ||
81 | { SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY }, | ||
82 | #endif | ||
83 | #if defined(CONFIG_CPU_SUBTYPE_SH7300) | ||
84 | { SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY }, | ||
85 | { DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, | ||
86 | { DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY }, | ||
87 | { VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY }, | ||
88 | #endif | ||
89 | #ifdef SCIF_ERI_IRQ | ||
90 | { SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, | ||
91 | { SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, | ||
92 | { SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, | ||
93 | { SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY }, | ||
94 | #endif | ||
95 | #ifdef IRDA_ERI_IRQ | ||
96 | { IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, | ||
97 | { IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, | ||
98 | { IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, | ||
99 | { IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY }, | ||
100 | #endif | ||
101 | #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ | ||
102 | defined(CONFIG_CPU_SUBTYPE_SH7706) || \ | ||
103 | defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) | ||
104 | /* | ||
105 | * Initialize the Interrupt Controller (INTC) | ||
106 | * registers to their power on values | ||
107 | */ | ||
108 | |||
109 | /* | ||
110 | * Enable external irq (INTC IRQ mode). | ||
111 | * You should set corresponding bits of PFC to "00" | ||
112 | * to enable these interrupts. | ||
113 | */ | ||
114 | { IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY }, | ||
115 | { IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY }, | ||
116 | { IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY }, | ||
117 | { IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY }, | ||
118 | { IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY }, | ||
119 | { IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY }, | ||
120 | #endif | ||
121 | #endif | ||
122 | }; | ||
123 | |||
124 | void __init init_IRQ(void) | ||
125 | { | ||
126 | make_ipr_irq(sys_ipr_map, ARRAY_SIZE(sys_ipr_map)); | ||
127 | |||
128 | #ifdef CONFIG_CPU_HAS_PINT_IRQ | ||
129 | init_IRQ_pint(); | ||
130 | #endif | ||
131 | |||
132 | #ifdef CONFIG_CPU_HAS_INTC2_IRQ | ||
133 | init_IRQ_intc2(); | ||
134 | #endif | ||
135 | /* Perform the machine specific initialisation */ | ||
136 | if (sh_mv.mv_init_irq != NULL) | ||
137 | sh_mv.mv_init_irq(); | ||
138 | |||
139 | irq_ctx_init(smp_processor_id()); | ||
140 | } | ||
141 | |||
142 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) | 65 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) |
143 | int ipr_irq_demux(int irq) | 66 | int ipr_irq_demux(int irq) |
144 | { | 67 | { |
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 | ||
5 | obj-y := probe.o | 5 | obj-y := ex.o probe.o entry.o |
6 | 6 | ||
7 | obj-$(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 | |||
21 | const static int pll1rate[]={1,2}; | ||
22 | const 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 | |||
32 | static void master_clk_init(struct clk *clk) | ||
33 | { | ||
34 | clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; | ||
35 | } | ||
36 | |||
37 | static struct clk_ops sh7619_master_clk_ops = { | ||
38 | .init = master_clk_init, | ||
39 | }; | ||
40 | |||
41 | static 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 | |||
47 | static struct clk_ops sh7619_module_clk_ops = { | ||
48 | .recalc = module_clk_recalc, | ||
49 | }; | ||
50 | |||
51 | static void bus_clk_recalc(struct clk *clk) | ||
52 | { | ||
53 | clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 7]; | ||
54 | } | ||
55 | |||
56 | static struct clk_ops sh7619_bus_clk_ops = { | ||
57 | .recalc = bus_clk_recalc, | ||
58 | }; | ||
59 | |||
60 | static void cpu_clk_recalc(struct clk *clk) | ||
61 | { | ||
62 | clk->rate = clk->parent->rate; | ||
63 | } | ||
64 | |||
65 | static struct clk_ops sh7619_cpu_clk_ops = { | ||
66 | .recalc = cpu_clk_recalc, | ||
67 | }; | ||
68 | |||
69 | static 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 | |||
76 | void __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..34d51b3745ea --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/entry.S | |||
@@ -0,0 +1,341 @@ | |||
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 */ | ||
23 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | ||
24 | OFF_R1 = 4 /* New ABI: arg5 */ | ||
25 | OFF_R2 = 8 /* New ABI: arg6 */ | ||
26 | OFF_R3 = 12 /* New ABI: syscall_nr */ | ||
27 | OFF_R4 = 16 /* New ABI: arg0 */ | ||
28 | OFF_R5 = 20 /* New ABI: arg1 */ | ||
29 | OFF_R6 = 24 /* New ABI: arg2 */ | ||
30 | OFF_R7 = 28 /* New ABI: arg3 */ | ||
31 | OFF_SP = (15*4) | ||
32 | OFF_PC = (16*4) | ||
33 | OFF_SR = (16*4+2*4) | ||
34 | OFF_TRA = (16*4+6*4) | ||
35 | |||
36 | #include <asm/entry-macros.S> | ||
37 | |||
38 | ENTRY(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 | ||
101 | 1: | ||
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 | ||
142 | 2: | ||
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 | ||
161 | 3: | ||
162 | mov.l 5f,r10 | ||
163 | jmp @r8 | ||
164 | lds r10,pr | ||
165 | |||
166 | interrupt_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 | ||
174 | 4: .long exception_handling_table | ||
175 | 5: .long ret_from_exception | ||
176 | 6: .long ret_from_irq | ||
177 | 7: .long do_IRQ | ||
178 | 8: .long do_exception_error | ||
179 | |||
180 | trap_entry: | ||
181 | add #-0x10,r9 | ||
182 | shll2 r9 ! TRA | ||
183 | mov #OFF_TRA,r8 | ||
184 | add r15,r8 | ||
185 | mov.l r9,@r8 | ||
186 | mov r9,r8 | ||
187 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
188 | mov.l 5f, r9 | ||
189 | jsr @r9 | ||
190 | nop | ||
191 | #endif | ||
192 | sti | ||
193 | bra system_call | ||
194 | nop | ||
195 | |||
196 | .align 2 | ||
197 | 1: .long syscall_exit | ||
198 | 2: .long break_point_trap_software | ||
199 | 3: .long NR_syscalls | ||
200 | 4: .long sys_call_table | ||
201 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
202 | 5: .long trace_hardirqs_on | ||
203 | #endif | ||
204 | |||
205 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
206 | /* Unwind the stack and jmp to the debug entry */ | ||
207 | debug_kernel_fw: | ||
208 | mov r15,r0 | ||
209 | add #(22-4)*4-4,r0 | ||
210 | ldc.l @r0+,gbr | ||
211 | lds.l @r0+,mach | ||
212 | lds.l @r0+,macl | ||
213 | mov r15,r0 | ||
214 | mov.l @(OFF_SP,r0),r1 | ||
215 | mov #OFF_SR,r2 | ||
216 | mov.l @(r0,r2),r3 | ||
217 | mov.l r3,@-r1 | ||
218 | mov #OFF_SP,r2 | ||
219 | mov.l @(r0,r2),r3 | ||
220 | mov.l r3,@-r1 | ||
221 | mov r15,r0 | ||
222 | add #(22-4)*4-8,r0 | ||
223 | mov.l 1f,r2 | ||
224 | mov.l @r2,r2 | ||
225 | stc sr,r3 | ||
226 | mov.l r2,@r0 | ||
227 | mov.l r3,@r0 | ||
228 | mov.l r1,@(8,r0) | ||
229 | mov.l @r15+, r0 | ||
230 | mov.l @r15+, r1 | ||
231 | mov.l @r15+, r2 | ||
232 | mov.l @r15+, r3 | ||
233 | mov.l @r15+, r4 | ||
234 | mov.l @r15+, r5 | ||
235 | mov.l @r15+, r6 | ||
236 | mov.l @r15+, r7 | ||
237 | mov.l @r15+, r8 | ||
238 | mov.l @r15+, r9 | ||
239 | mov.l @r15+, r10 | ||
240 | mov.l @r15+, r11 | ||
241 | mov.l @r15+, r12 | ||
242 | mov.l @r15+, r13 | ||
243 | mov.l @r15+, r14 | ||
244 | add #8,r15 | ||
245 | lds.l @r15+, pr | ||
246 | rte | ||
247 | mov.l @r15+,r15 | ||
248 | .align 2 | ||
249 | 1: .long gdb_vbr_vector | ||
250 | #endif /* CONFIG_SH_STANDARD_BIOS */ | ||
251 | |||
252 | ENTRY(address_error_handler) | ||
253 | mov r15,r4 ! regs | ||
254 | add #4,r4 | ||
255 | mov #OFF_PC,r0 | ||
256 | mov.l @(r0,r15),r6 ! pc | ||
257 | mov.l 1f,r0 | ||
258 | jmp @r0 | ||
259 | mov #0,r5 ! writeaccess is unknown | ||
260 | .align 2 | ||
261 | |||
262 | 1: .long do_address_error | ||
263 | |||
264 | restore_all: | ||
265 | cli | ||
266 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
267 | mov.l 3f, r0 | ||
268 | jsr @r0 | ||
269 | nop | ||
270 | #endif | ||
271 | mov r15,r0 | ||
272 | mov.l $cpu_mode,r2 | ||
273 | mov #OFF_SR,r3 | ||
274 | mov.l @(r0,r3),r1 | ||
275 | mov.l r1,@r2 | ||
276 | shll2 r1 ! clear MD bit | ||
277 | shlr2 r1 | ||
278 | mov.l @(OFF_SP,r0),r2 | ||
279 | add #-8,r2 | ||
280 | mov.l r2,@(OFF_SP,r0) ! point exception frame top | ||
281 | mov.l r1,@(4,r2) ! set sr | ||
282 | mov #OFF_PC,r3 | ||
283 | mov.l @(r0,r3),r1 | ||
284 | mov.l r1,@r2 ! set pc | ||
285 | add #4*16+4,r0 | ||
286 | lds.l @r0+,pr | ||
287 | add #4,r0 ! skip sr | ||
288 | ldc.l @r0+,gbr | ||
289 | lds.l @r0+,mach | ||
290 | lds.l @r0+,macl | ||
291 | get_current_thread_info r0, r1 | ||
292 | mov.l $current_thread_info,r1 | ||
293 | mov.l r0,@r1 | ||
294 | mov.l @r15+,r0 | ||
295 | mov.l @r15+,r1 | ||
296 | mov.l @r15+,r2 | ||
297 | mov.l @r15+,r3 | ||
298 | mov.l @r15+,r4 | ||
299 | mov.l @r15+,r5 | ||
300 | mov.l @r15+,r6 | ||
301 | mov.l @r15+,r7 | ||
302 | mov.l @r15+,r8 | ||
303 | mov.l @r15+,r9 | ||
304 | mov.l @r15+,r10 | ||
305 | mov.l @r15+,r11 | ||
306 | mov.l @r15+,r12 | ||
307 | mov.l @r15+,r13 | ||
308 | mov.l @r15+,r14 | ||
309 | mov.l @r15,r15 | ||
310 | rte | ||
311 | nop | ||
312 | 2: | ||
313 | mov.l 1f,r8 | ||
314 | mov.l 2f,r9 | ||
315 | jmp @r9 | ||
316 | lds r8,pr | ||
317 | |||
318 | .align 2 | ||
319 | $current_thread_info: | ||
320 | .long __current_thread_info | ||
321 | $cpu_mode: | ||
322 | .long __cpu_mode | ||
323 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
324 | 3: .long trace_hardirqs_off | ||
325 | #endif | ||
326 | |||
327 | ! common exception handler | ||
328 | #include "../../entry-common.S" | ||
329 | |||
330 | .data | ||
331 | ! cpu operation mode | ||
332 | ! bit30 = MD (compatible SH3/4) | ||
333 | __cpu_mode: | ||
334 | .long 0x40000000 | ||
335 | |||
336 | .section .bss | ||
337 | __current_thread_info: | ||
338 | .long 0 | ||
339 | |||
340 | ENTRY(exception_handling_table) | ||
341 | .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 | ! | ||
18 | exception_entry: | ||
19 | no = 0 | ||
20 | .rept 256 | ||
21 | mov.l r0,@-sp | ||
22 | mov #no,r0 | ||
23 | bra exception_trampoline | ||
24 | and #0xff,r0 | ||
25 | no = no + 1 | ||
26 | .endr | ||
27 | exception_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 | ||
41 | ENTRY(vbr_base) | ||
42 | vector = 0 | ||
43 | .rept 256 | ||
44 | .long exception_entry + vector * 8 | ||
45 | vector = 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 | ||
18 | int __init detect_cpu_and_cache_system(void) | 18 | int __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..82c2d905152f --- /dev/null +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c | |||
@@ -0,0 +1,53 @@ | |||
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 | |||
15 | static 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 | |||
36 | static struct platform_device sci_device = { | ||
37 | .name = "sh-sci", | ||
38 | .id = -1, | ||
39 | .dev = { | ||
40 | .platform_data = sci_platform_data, | ||
41 | }, | ||
42 | }; | ||
43 | |||
44 | static struct platform_device *sh7619_devices[] __initdata = { | ||
45 | &sci_device, | ||
46 | }; | ||
47 | |||
48 | static 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); | ||
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 | |||
5 | obj-y := common.o probe.o | ||
6 | |||
7 | common-y += $(addprefix ../sh2/, ex.o) | ||
8 | common-y += $(addprefix ../sh2/, entry.o) | ||
9 | |||
10 | obj-$(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 | |||
21 | const static int pll1rate[]={1,2,3,4,6,8}; | ||
22 | const 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 | |||
35 | static void master_clk_init(struct clk *clk) | ||
36 | { | ||
37 | clk->rate *= PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | ||
38 | } | ||
39 | |||
40 | static struct clk_ops sh7206_master_clk_ops = { | ||
41 | .init = master_clk_init, | ||
42 | }; | ||
43 | |||
44 | static 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 | |||
50 | static struct clk_ops sh7206_module_clk_ops = { | ||
51 | .recalc = module_clk_recalc, | ||
52 | }; | ||
53 | |||
54 | static void bus_clk_recalc(struct clk *clk) | ||
55 | { | ||
56 | clk->rate = clk->parent->rate / pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | ||
57 | } | ||
58 | |||
59 | static struct clk_ops sh7206_bus_clk_ops = { | ||
60 | .recalc = bus_clk_recalc, | ||
61 | }; | ||
62 | |||
63 | static 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 | |||
69 | static struct clk_ops sh7206_cpu_clk_ops = { | ||
70 | .recalc = cpu_clk_recalc, | ||
71 | }; | ||
72 | |||
73 | static 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 | |||
80 | void __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 | |||
17 | int __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..cdfeef49e62e --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c | |||
@@ -0,0 +1,58 @@ | |||
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 | |||
15 | static struct plat_sci_port sci_platform_data[] = { | ||
16 | { | ||
17 | .mapbase = 0xfffe8000, | ||
18 | .flags = UPF_BOOT_AUTOCONF, | ||
19 | .type = PORT_SCIF, | ||
20 | .irqs = { 240, 241, 242, 243}, | ||
21 | }, { | ||
22 | .mapbase = 0xfffe8800, | ||
23 | .flags = UPF_BOOT_AUTOCONF, | ||
24 | .type = PORT_SCIF, | ||
25 | .irqs = { 244, 245, 246, 247}, | ||
26 | }, { | ||
27 | .mapbase = 0xfffe9000, | ||
28 | .flags = UPF_BOOT_AUTOCONF, | ||
29 | .type = PORT_SCIF, | ||
30 | .irqs = { 248, 249, 250, 251}, | ||
31 | }, { | ||
32 | .mapbase = 0xfffe9800, | ||
33 | .flags = UPF_BOOT_AUTOCONF, | ||
34 | .type = PORT_SCIF, | ||
35 | .irqs = { 252, 253, 254, 255}, | ||
36 | }, { | ||
37 | .flags = 0, | ||
38 | } | ||
39 | }; | ||
40 | |||
41 | static struct platform_device sci_device = { | ||
42 | .name = "sh-sci", | ||
43 | .id = -1, | ||
44 | .dev = { | ||
45 | .platform_data = sci_platform_data, | ||
46 | }, | ||
47 | }; | ||
48 | |||
49 | static struct platform_device *sh7206_devices[] __initdata = { | ||
50 | &sci_device, | ||
51 | }; | ||
52 | |||
53 | static 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); | ||
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 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o entry.o |
6 | 6 | ||
7 | # CPU subtype setup | 7 | # CPU subtype setup |
8 | obj-$(CONFIG_CPU_SUBTYPE_SH7705) += setup-sh7705.o | 8 | obj-$(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 | ||
25 | static void set_bus_parent(struct clk *clk) | 25 | static 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/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S new file mode 100644 index 000000000000..8c0dc2700c69 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -0,0 +1,693 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/entry.S | ||
3 | * | ||
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | ||
5 | * Copyright (C) 2003 - 2006 Paul Mundt | ||
6 | * | ||
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 | ||
9 | * for more details. | ||
10 | */ | ||
11 | #include <linux/sys.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/linkage.h> | ||
14 | #include <asm/asm-offsets.h> | ||
15 | #include <asm/thread_info.h> | ||
16 | #include <asm/unistd.h> | ||
17 | #include <asm/cpu/mmu_context.h> | ||
18 | #include <asm/pgtable.h> | ||
19 | #include <asm/page.h> | ||
20 | |||
21 | ! NOTE: | ||
22 | ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address | ||
23 | ! to be jumped is too far, but it causes illegal slot exception. | ||
24 | |||
25 | /* | ||
26 | * entry.S contains the system-call and fault low-level handling routines. | ||
27 | * This also contains the timer-interrupt handler, as well as all interrupts | ||
28 | * and faults that can result in a task-switch. | ||
29 | * | ||
30 | * NOTE: This code handles signal-recognition, which happens every time | ||
31 | * after a timer-interrupt and after each system call. | ||
32 | * | ||
33 | * NOTE: This code uses a convention that instructions in the delay slot | ||
34 | * of a transfer-control instruction are indented by an extra space, thus: | ||
35 | * | ||
36 | * jmp @k0 ! control-transfer instruction | ||
37 | * ldc k1, ssr ! delay slot | ||
38 | * | ||
39 | * Stack layout in 'ret_from_syscall': | ||
40 | * ptrace needs to have all regs on the stack. | ||
41 | * if the order here is changed, it needs to be | ||
42 | * updated in ptrace.c and ptrace.h | ||
43 | * | ||
44 | * r0 | ||
45 | * ... | ||
46 | * r15 = stack pointer | ||
47 | * spc | ||
48 | * pr | ||
49 | * ssr | ||
50 | * gbr | ||
51 | * mach | ||
52 | * macl | ||
53 | * syscall # | ||
54 | * | ||
55 | */ | ||
56 | #if defined(CONFIG_KGDB_NMI) | ||
57 | NMI_VEC = 0x1c0 ! Must catch early for debounce | ||
58 | #endif | ||
59 | |||
60 | /* Offsets to the stack */ | ||
61 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | ||
62 | OFF_R1 = 4 /* New ABI: arg5 */ | ||
63 | OFF_R2 = 8 /* New ABI: arg6 */ | ||
64 | OFF_R3 = 12 /* New ABI: syscall_nr */ | ||
65 | OFF_R4 = 16 /* New ABI: arg0 */ | ||
66 | OFF_R5 = 20 /* New ABI: arg1 */ | ||
67 | OFF_R6 = 24 /* New ABI: arg2 */ | ||
68 | OFF_R7 = 28 /* New ABI: arg3 */ | ||
69 | OFF_SP = (15*4) | ||
70 | OFF_PC = (16*4) | ||
71 | OFF_SR = (16*4+8) | ||
72 | OFF_TRA = (16*4+6*4) | ||
73 | |||
74 | |||
75 | #define k0 r0 | ||
76 | #define k1 r1 | ||
77 | #define k2 r2 | ||
78 | #define k3 r3 | ||
79 | #define k4 r4 | ||
80 | |||
81 | #define g_imask r6 /* r6_bank1 */ | ||
82 | #define k_g_imask r6_bank /* r6_bank1 */ | ||
83 | #define current r7 /* r7_bank1 */ | ||
84 | |||
85 | #include <asm/entry-macros.S> | ||
86 | |||
87 | /* | ||
88 | * Kernel mode register usage: | ||
89 | * k0 scratch | ||
90 | * k1 scratch | ||
91 | * k2 scratch (Exception code) | ||
92 | * k3 scratch (Return address) | ||
93 | * k4 scratch | ||
94 | * k5 reserved | ||
95 | * k6 Global Interrupt Mask (0--15 << 4) | ||
96 | * k7 CURRENT_THREAD_INFO (pointer to current thread info) | ||
97 | */ | ||
98 | |||
99 | ! | ||
100 | ! TLB Miss / Initial Page write exception handling | ||
101 | ! _and_ | ||
102 | ! TLB hits, but the access violate the protection. | ||
103 | ! It can be valid access, such as stack grow and/or C-O-W. | ||
104 | ! | ||
105 | ! | ||
106 | ! Find the pmd/pte entry and loadtlb | ||
107 | ! If it's not found, cause address error (SEGV) | ||
108 | ! | ||
109 | ! Although this could be written in assembly language (and it'd be faster), | ||
110 | ! this first version depends *much* on C implementation. | ||
111 | ! | ||
112 | |||
113 | #if defined(CONFIG_MMU) | ||
114 | .align 2 | ||
115 | ENTRY(tlb_miss_load) | ||
116 | bra call_dpf | ||
117 | mov #0, r5 | ||
118 | |||
119 | .align 2 | ||
120 | ENTRY(tlb_miss_store) | ||
121 | bra call_dpf | ||
122 | mov #1, r5 | ||
123 | |||
124 | .align 2 | ||
125 | ENTRY(initial_page_write) | ||
126 | bra call_dpf | ||
127 | mov #1, r5 | ||
128 | |||
129 | .align 2 | ||
130 | ENTRY(tlb_protection_violation_load) | ||
131 | bra call_dpf | ||
132 | mov #0, r5 | ||
133 | |||
134 | .align 2 | ||
135 | ENTRY(tlb_protection_violation_store) | ||
136 | bra call_dpf | ||
137 | mov #1, r5 | ||
138 | |||
139 | call_dpf: | ||
140 | mov.l 1f, r0 | ||
141 | mov.l @r0, r6 ! address | ||
142 | mov.l 3f, r0 | ||
143 | |||
144 | jmp @r0 | ||
145 | mov r15, r4 ! regs | ||
146 | |||
147 | .align 2 | ||
148 | 1: .long MMU_TEA | ||
149 | 3: .long do_page_fault | ||
150 | |||
151 | .align 2 | ||
152 | ENTRY(address_error_load) | ||
153 | bra call_dae | ||
154 | mov #0,r5 ! writeaccess = 0 | ||
155 | |||
156 | .align 2 | ||
157 | ENTRY(address_error_store) | ||
158 | bra call_dae | ||
159 | mov #1,r5 ! writeaccess = 1 | ||
160 | |||
161 | .align 2 | ||
162 | call_dae: | ||
163 | mov.l 1f, r0 | ||
164 | mov.l @r0, r6 ! address | ||
165 | mov.l 2f, r0 | ||
166 | jmp @r0 | ||
167 | mov r15, r4 ! regs | ||
168 | |||
169 | .align 2 | ||
170 | 1: .long MMU_TEA | ||
171 | 2: .long do_address_error | ||
172 | #endif /* CONFIG_MMU */ | ||
173 | |||
174 | #if defined(CONFIG_SH_STANDARD_BIOS) | ||
175 | /* Unwind the stack and jmp to the debug entry */ | ||
176 | debug_kernel_fw: | ||
177 | mov.l @r15+, r0 | ||
178 | mov.l @r15+, r1 | ||
179 | mov.l @r15+, r2 | ||
180 | mov.l @r15+, r3 | ||
181 | mov.l @r15+, r4 | ||
182 | mov.l @r15+, r5 | ||
183 | mov.l @r15+, r6 | ||
184 | mov.l @r15+, r7 | ||
185 | stc sr, r8 | ||
186 | mov.l 1f, r9 ! BL =1, RB=1, IMASK=0x0F | ||
187 | or r9, r8 | ||
188 | ldc r8, sr ! here, change the register bank | ||
189 | mov.l @r15+, r8 | ||
190 | mov.l @r15+, r9 | ||
191 | mov.l @r15+, r10 | ||
192 | mov.l @r15+, r11 | ||
193 | mov.l @r15+, r12 | ||
194 | mov.l @r15+, r13 | ||
195 | mov.l @r15+, r14 | ||
196 | mov.l @r15+, k0 | ||
197 | ldc.l @r15+, spc | ||
198 | lds.l @r15+, pr | ||
199 | mov.l @r15+, k1 | ||
200 | ldc.l @r15+, gbr | ||
201 | lds.l @r15+, mach | ||
202 | lds.l @r15+, macl | ||
203 | mov k0, r15 | ||
204 | ! | ||
205 | mov.l 2f, k0 | ||
206 | mov.l @k0, k0 | ||
207 | jmp @k0 | ||
208 | ldc k1, ssr | ||
209 | .align 2 | ||
210 | 1: .long 0x300000f0 | ||
211 | 2: .long gdb_vbr_vector | ||
212 | #endif /* CONFIG_SH_STANDARD_BIOS */ | ||
213 | |||
214 | restore_all: | ||
215 | mov.l @r15+, r0 | ||
216 | mov.l @r15+, r1 | ||
217 | mov.l @r15+, r2 | ||
218 | mov.l @r15+, r3 | ||
219 | mov.l @r15+, r4 | ||
220 | mov.l @r15+, r5 | ||
221 | mov.l @r15+, r6 | ||
222 | mov.l @r15+, r7 | ||
223 | ! | ||
224 | stc sr, r8 | ||
225 | mov.l 7f, r9 | ||
226 | or r9, r8 ! BL =1, RB=1 | ||
227 | ldc r8, sr ! here, change the register bank | ||
228 | ! | ||
229 | mov.l @r15+, r8 | ||
230 | mov.l @r15+, r9 | ||
231 | mov.l @r15+, r10 | ||
232 | mov.l @r15+, r11 | ||
233 | mov.l @r15+, r12 | ||
234 | mov.l @r15+, r13 | ||
235 | mov.l @r15+, r14 | ||
236 | mov.l @r15+, k4 ! original stack pointer | ||
237 | ldc.l @r15+, spc | ||
238 | lds.l @r15+, pr | ||
239 | mov.l @r15+, k3 ! original SR | ||
240 | ldc.l @r15+, gbr | ||
241 | lds.l @r15+, mach | ||
242 | lds.l @r15+, macl | ||
243 | add #4, r15 ! Skip syscall number | ||
244 | ! | ||
245 | #ifdef CONFIG_SH_DSP | ||
246 | mov.l @r15+, k0 ! DSP mode marker | ||
247 | mov.l 5f, k1 | ||
248 | cmp/eq k0, k1 ! Do we have a DSP stack frame? | ||
249 | bf skip_restore | ||
250 | |||
251 | stc sr, k0 ! Enable CPU DSP mode | ||
252 | or k1, k0 ! (within kernel it may be disabled) | ||
253 | ldc k0, sr | ||
254 | mov r2, k0 ! Backup r2 | ||
255 | |||
256 | ! Restore DSP registers from stack | ||
257 | mov r15, r2 | ||
258 | movs.l @r2+, a1 | ||
259 | movs.l @r2+, a0g | ||
260 | movs.l @r2+, a1g | ||
261 | movs.l @r2+, m0 | ||
262 | movs.l @r2+, m1 | ||
263 | mov r2, r15 | ||
264 | |||
265 | lds.l @r15+, a0 | ||
266 | lds.l @r15+, x0 | ||
267 | lds.l @r15+, x1 | ||
268 | lds.l @r15+, y0 | ||
269 | lds.l @r15+, y1 | ||
270 | lds.l @r15+, dsr | ||
271 | ldc.l @r15+, rs | ||
272 | ldc.l @r15+, re | ||
273 | ldc.l @r15+, mod | ||
274 | |||
275 | mov k0, r2 ! Restore r2 | ||
276 | skip_restore: | ||
277 | #endif | ||
278 | ! | ||
279 | ! Calculate new SR value | ||
280 | mov k3, k2 ! original SR value | ||
281 | mov #0xf0, k1 | ||
282 | extu.b k1, k1 | ||
283 | not k1, k1 | ||
284 | and k1, k2 ! Mask orignal SR value | ||
285 | ! | ||
286 | mov k3, k0 ! Calculate IMASK-bits | ||
287 | shlr2 k0 | ||
288 | and #0x3c, k0 | ||
289 | cmp/eq #0x3c, k0 | ||
290 | bt/s 6f | ||
291 | shll2 k0 | ||
292 | mov g_imask, k0 | ||
293 | ! | ||
294 | 6: or k0, k2 ! Set the IMASK-bits | ||
295 | ldc k2, ssr | ||
296 | ! | ||
297 | #if defined(CONFIG_KGDB_NMI) | ||
298 | ! Clear in_nmi | ||
299 | mov.l 6f, k0 | ||
300 | mov #0, k1 | ||
301 | mov.b k1, @k0 | ||
302 | #endif | ||
303 | mov.l @r15+, k2 ! restore EXPEVT | ||
304 | mov k4, r15 | ||
305 | rte | ||
306 | nop | ||
307 | |||
308 | .align 2 | ||
309 | 5: .long 0x00001000 ! DSP | ||
310 | 7: .long 0x30000000 | ||
311 | |||
312 | ! common exception handler | ||
313 | #include "../../entry-common.S" | ||
314 | |||
315 | ! Exception Vector Base | ||
316 | ! | ||
317 | ! Should be aligned page boundary. | ||
318 | ! | ||
319 | .balign 4096,0,4096 | ||
320 | ENTRY(vbr_base) | ||
321 | .long 0 | ||
322 | ! | ||
323 | .balign 256,0,256 | ||
324 | general_exception: | ||
325 | mov.l 1f, k2 | ||
326 | mov.l 2f, k3 | ||
327 | bra handle_exception | ||
328 | mov.l @k2, k2 | ||
329 | .align 2 | ||
330 | 1: .long EXPEVT | ||
331 | 2: .long ret_from_exception | ||
332 | ! | ||
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 | |||
358 | .balign 1024,0,1024 | ||
359 | tlb_miss: | ||
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 | |||
477 | 10: 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... | ||
493 | 1: .long swapper_pg_dir | ||
494 | 4: .short (PTRS_PER_PGD-1) << 2 | ||
495 | 5: .short _PAGE_PRESENT | ||
496 | 7: .long _PAGE_FLAGS_HARDWARE_MASK | ||
497 | 8: .long MMU_PTEH | ||
498 | #ifdef COUNT_EXCEPTIONS | ||
499 | 9: .long exception_count_miss | ||
500 | #endif | ||
501 | |||
502 | ! Either pgd or pte not present | ||
503 | 20: mov.l 1f, k2 | ||
504 | mov.l 4f, k3 | ||
505 | bra handle_exception | ||
506 | mov.l @k2, k2 | ||
507 | ! | ||
508 | .balign 512,0,512 | ||
509 | interrupt: | ||
510 | mov.l 2f, k2 | ||
511 | mov.l 3f, k3 | ||
512 | #if defined(CONFIG_KGDB_NMI) | ||
513 | ! Debounce (filter nested NMI) | ||
514 | mov.l @k2, k0 | ||
515 | mov.l 5f, k1 | ||
516 | cmp/eq k1, k0 | ||
517 | bf 0f | ||
518 | mov.l 6f, k1 | ||
519 | tas.b @k1 | ||
520 | bt 0f | ||
521 | rte | ||
522 | nop | ||
523 | .align 2 | ||
524 | 5: .long NMI_VEC | ||
525 | 6: .long in_nmi | ||
526 | 0: | ||
527 | #endif /* defined(CONFIG_KGDB_NMI) */ | ||
528 | bra handle_exception | ||
529 | mov #-1, k2 ! interrupt exception marker | ||
530 | |||
531 | .align 2 | ||
532 | 1: .long EXPEVT | ||
533 | 2: .long INTEVT | ||
534 | 3: .long ret_from_irq | ||
535 | 4: .long ret_from_exception | ||
536 | |||
537 | ! | ||
538 | ! | ||
539 | .align 2 | ||
540 | ENTRY(handle_exception) | ||
541 | ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), | ||
542 | ! save all registers onto stack. | ||
543 | ! | ||
544 | stc ssr, k0 ! Is it from kernel space? | ||
545 | shll k0 ! Check MD bit (bit30) by shifting it into... | ||
546 | shll k0 ! ...the T bit | ||
547 | bt/s 1f ! It's a kernel to kernel transition. | ||
548 | mov r15, k0 ! save original stack to k0 | ||
549 | /* User space to kernel */ | ||
550 | mov #(THREAD_SIZE >> 10), k1 | ||
551 | shll8 k1 ! k1 := THREAD_SIZE | ||
552 | shll2 k1 | ||
553 | add current, k1 | ||
554 | mov k1, r15 ! change to kernel stack | ||
555 | ! | ||
556 | 1: mov.l 2f, k1 | ||
557 | ! | ||
558 | #ifdef CONFIG_SH_DSP | ||
559 | mov.l r2, @-r15 ! Save r2, we need another reg | ||
560 | stc sr, k4 | ||
561 | mov.l 1f, r2 | ||
562 | tst r2, k4 ! Check if in DSP mode | ||
563 | mov.l @r15+, r2 ! Restore r2 now | ||
564 | bt/s skip_save | ||
565 | mov #0, k4 ! Set marker for no stack frame | ||
566 | |||
567 | mov r2, k4 ! Backup r2 (in k4) for later | ||
568 | |||
569 | ! Save DSP registers on stack | ||
570 | stc.l mod, @-r15 | ||
571 | stc.l re, @-r15 | ||
572 | stc.l rs, @-r15 | ||
573 | sts.l dsr, @-r15 | ||
574 | sts.l y1, @-r15 | ||
575 | sts.l y0, @-r15 | ||
576 | sts.l x1, @-r15 | ||
577 | sts.l x0, @-r15 | ||
578 | sts.l a0, @-r15 | ||
579 | |||
580 | ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr. | ||
581 | |||
582 | ! FIXME: Make sure that this is still the case with newer toolchains, | ||
583 | ! as we're not at all interested in supporting ancient toolchains at | ||
584 | ! this point. -- PFM. | ||
585 | |||
586 | mov r15, r2 | ||
587 | .word 0xf653 ! movs.l a1, @-r2 | ||
588 | .word 0xf6f3 ! movs.l a0g, @-r2 | ||
589 | .word 0xf6d3 ! movs.l a1g, @-r2 | ||
590 | .word 0xf6c3 ! movs.l m0, @-r2 | ||
591 | .word 0xf6e3 ! movs.l m1, @-r2 | ||
592 | mov r2, r15 | ||
593 | |||
594 | mov k4, r2 ! Restore r2 | ||
595 | mov.l 1f, k4 ! Force DSP stack frame | ||
596 | skip_save: | ||
597 | mov.l k4, @-r15 ! Push DSP mode marker onto stack | ||
598 | #endif | ||
599 | ! Save the user registers on the stack. | ||
600 | mov.l k2, @-r15 ! EXPEVT | ||
601 | |||
602 | mov #-1, k4 | ||
603 | mov.l k4, @-r15 ! set TRA (default: -1) | ||
604 | ! | ||
605 | sts.l macl, @-r15 | ||
606 | sts.l mach, @-r15 | ||
607 | stc.l gbr, @-r15 | ||
608 | stc.l ssr, @-r15 | ||
609 | sts.l pr, @-r15 | ||
610 | stc.l spc, @-r15 | ||
611 | ! | ||
612 | lds k3, pr ! Set the return address to pr | ||
613 | ! | ||
614 | mov.l k0, @-r15 ! save orignal stack | ||
615 | mov.l r14, @-r15 | ||
616 | mov.l r13, @-r15 | ||
617 | mov.l r12, @-r15 | ||
618 | mov.l r11, @-r15 | ||
619 | mov.l r10, @-r15 | ||
620 | mov.l r9, @-r15 | ||
621 | mov.l r8, @-r15 | ||
622 | ! | ||
623 | stc sr, r8 ! Back to normal register bank, and | ||
624 | or k1, r8 ! Block all interrupts | ||
625 | mov.l 3f, k1 | ||
626 | and k1, r8 ! ... | ||
627 | ldc r8, sr ! ...changed here. | ||
628 | ! | ||
629 | mov.l r7, @-r15 | ||
630 | mov.l r6, @-r15 | ||
631 | mov.l r5, @-r15 | ||
632 | mov.l r4, @-r15 | ||
633 | mov.l r3, @-r15 | ||
634 | mov.l r2, @-r15 | ||
635 | mov.l r1, @-r15 | ||
636 | mov.l r0, @-r15 | ||
637 | |||
638 | /* | ||
639 | * This gets a bit tricky.. in the INTEVT case we don't want to use | ||
640 | * the VBR offset as a destination in the jump call table, since all | ||
641 | * of the destinations are the same. In this case, (interrupt) sets | ||
642 | * a marker in r2 (now r2_bank since SR.RB changed), which we check | ||
643 | * to determine the exception type. For all other exceptions, we | ||
644 | * forcibly read EXPEVT from memory and fix up the jump address, in | ||
645 | * the interrupt exception case we jump to do_IRQ() and defer the | ||
646 | * INTEVT read until there. As a bonus, we can also clean up the SR.RB | ||
647 | * checks that do_IRQ() was doing.. | ||
648 | */ | ||
649 | stc r2_bank, r8 | ||
650 | cmp/pz r8 | ||
651 | bf interrupt_exception | ||
652 | shlr2 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 | |||
663 | mov.l 4f, r9 | ||
664 | add r8, r9 | ||
665 | mov.l @r9, r9 | ||
666 | jmp @r9 | ||
667 | nop | ||
668 | rts | ||
669 | nop | ||
670 | |||
671 | .align 2 | ||
672 | 1: .long 0x00001000 ! DSP=1 | ||
673 | 2: .long 0x000080f0 ! FD=1, IMASK=15 | ||
674 | 3: .long 0xcfffffff ! RB=0, BL=0 | ||
675 | 4: .long exception_handling_table | ||
676 | #ifdef COUNT_EXCEPTIONS | ||
677 | 5: .long exception_count_table | ||
678 | #endif | ||
679 | |||
680 | interrupt_exception: | ||
681 | mov.l 1f, r9 | ||
682 | jmp @r9 | ||
683 | nop | ||
684 | rts | ||
685 | nop | ||
686 | |||
687 | .align 2 | ||
688 | 1: .long do_IRQ | ||
689 | |||
690 | .align 2 | ||
691 | ENTRY(exception_none) | ||
692 | rts | ||
693 | nop | ||
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 8dbf3895ece7..6e415baf04b4 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 | ||
5 | obj-y := ex.o probe.o | 5 | obj-y := ex.o probe.o common.o |
6 | common-y += $(addprefix ../sh3/, entry.o) | ||
6 | 7 | ||
7 | obj-$(CONFIG_SH_FPU) += fpu.o | 8 | obj-$(CONFIG_SH_FPU) += fpu.o |
8 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | 9 | obj-$(CONFIG_SH_STORE_QUEUES) += sq.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 | ||
98 | static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) | 98 | static 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 | ||
152 | static int __init sh4202_clk_init(void) | 152 | static 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/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c index 93ad367342c9..9e6a216750c8 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh7780.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c | |||
@@ -98,7 +98,7 @@ static struct clk *sh7780_onchip_clocks[] = { | |||
98 | 98 | ||
99 | static int __init sh7780_clk_init(void) | 99 | static 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/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 | ||
298 | asmlinkage void | 295 | asmlinkage void |
299 | do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, | 296 | do_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 (®s)) | 302 | if (ieee_fpe_handler(regs)) |
305 | return; | 303 | return; |
306 | 304 | ||
307 | regs.pc += 2; | 305 | regs->pc += 2; |
308 | save_fpu(tsk, ®s); | 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 | ||
314 | asmlinkage void | 310 | asmlinkage void |
315 | do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, | 311 | do_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(®s); | 317 | grab_fpu(regs); |
321 | if (!user_mode(®s)) { | 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..afe0f1b1c030 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; |
@@ -126,23 +126,22 @@ int __init detect_cpu_and_cache_system(void) | |||
126 | break; | 126 | break; |
127 | case 0x8000: | 127 | case 0x8000: |
128 | cpu_data->type = CPU_ST40RA; | 128 | cpu_data->type = CPU_ST40RA; |
129 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | 129 | cpu_data->flags |= CPU_HAS_FPU; |
130 | break; | 130 | break; |
131 | case 0x8100: | 131 | case 0x8100: |
132 | cpu_data->type = CPU_ST40GX1; | 132 | cpu_data->type = CPU_ST40GX1; |
133 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | 133 | cpu_data->flags |= CPU_HAS_FPU; |
134 | break; | 134 | break; |
135 | case 0x700: | 135 | case 0x700: |
136 | cpu_data->type = CPU_SH4_501; | 136 | cpu_data->type = CPU_SH4_501; |
137 | cpu_data->icache.ways = 2; | 137 | cpu_data->icache.ways = 2; |
138 | cpu_data->dcache.ways = 2; | 138 | cpu_data->dcache.ways = 2; |
139 | cpu_data->flags |= CPU_HAS_PTEA; | ||
140 | break; | 139 | break; |
141 | case 0x600: | 140 | case 0x600: |
142 | cpu_data->type = CPU_SH4_202; | 141 | cpu_data->type = CPU_SH4_202; |
143 | cpu_data->icache.ways = 2; | 142 | cpu_data->icache.ways = 2; |
144 | cpu_data->dcache.ways = 2; | 143 | cpu_data->dcache.ways = 2; |
145 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | 144 | cpu_data->flags |= CPU_HAS_FPU; |
146 | break; | 145 | break; |
147 | case 0x500 ... 0x501: | 146 | case 0x500 ... 0x501: |
148 | switch (prr) { | 147 | switch (prr) { |
@@ -160,7 +159,7 @@ int __init detect_cpu_and_cache_system(void) | |||
160 | cpu_data->icache.ways = 2; | 159 | cpu_data->icache.ways = 2; |
161 | cpu_data->dcache.ways = 2; | 160 | cpu_data->dcache.ways = 2; |
162 | 161 | ||
163 | cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA; | 162 | cpu_data->flags |= CPU_HAS_FPU; |
164 | 163 | ||
165 | break; | 164 | break; |
166 | default: | 165 | default: |
@@ -173,6 +172,10 @@ int __init detect_cpu_and_cache_system(void) | |||
173 | cpu_data->dcache.ways = 1; | 172 | cpu_data->dcache.ways = 1; |
174 | #endif | 173 | #endif |
175 | 174 | ||
175 | #ifdef CONFIG_CPU_HAS_PTEA | ||
176 | cpu_data->flags |= CPU_HAS_PTEA; | ||
177 | #endif | ||
178 | |||
176 | /* | 179 | /* |
177 | * On anything that's not a direct-mapped cache, look to the CVR | 180 | * On anything that's not a direct-mapped cache, look to the CVR |
178 | * for I/D-cache specifics. | 181 | * 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..bbcb06f18b04 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,6 +11,7 @@ | |||
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 | ||
15 | static struct plat_sci_port sci_platform_data[] = { | 17 | static struct plat_sci_port sci_platform_data[] = { |
@@ -46,3 +48,71 @@ static int __init sh7750_devices_setup(void) | |||
46 | ARRAY_SIZE(sh7750_devices)); | 48 | ARRAY_SIZE(sh7750_devices)); |
47 | } | 49 | } |
48 | __initcall(sh7750_devices_setup); | 50 | __initcall(sh7750_devices_setup); |
51 | |||
52 | static struct ipr_data sh7750_ipr_map[] = { | ||
53 | /* IRQ, IPR-idx, shift, priority */ | ||
54 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ | ||
55 | { 17, 0, 12, 2 }, /* TMU1 TUNI */ | ||
56 | { 18, 0, 4, 2 }, /* TMU2 TUNI */ | ||
57 | { 19, 0, 4, 2 }, /* TMU2 TIPCI */ | ||
58 | { 27, 1, 12, 2 }, /* WDT ITI */ | ||
59 | { 20, 0, 0, 2 }, /* RTC ATI (alarm) */ | ||
60 | { 21, 0, 0, 2 }, /* RTC PRI (period) */ | ||
61 | { 22, 0, 0, 2 }, /* RTC CUI (carry) */ | ||
62 | { 23, 1, 4, 3 }, /* SCI ERI */ | ||
63 | { 24, 1, 4, 3 }, /* SCI RXI */ | ||
64 | { 25, 1, 4, 3 }, /* SCI TXI */ | ||
65 | { 40, 2, 4, 3 }, /* SCIF ERI */ | ||
66 | { 41, 2, 4, 3 }, /* SCIF RXI */ | ||
67 | { 42, 2, 4, 3 }, /* SCIF BRI */ | ||
68 | { 43, 2, 4, 3 }, /* SCIF TXI */ | ||
69 | { 34, 2, 8, 7 }, /* DMAC DMTE0 */ | ||
70 | { 35, 2, 8, 7 }, /* DMAC DMTE1 */ | ||
71 | { 36, 2, 8, 7 }, /* DMAC DMTE2 */ | ||
72 | { 37, 2, 8, 7 }, /* DMAC DMTE3 */ | ||
73 | { 28, 2, 8, 7 }, /* DMAC DMAE */ | ||
74 | }; | ||
75 | |||
76 | static struct ipr_data sh7751_ipr_map[] = { | ||
77 | { 44, 2, 8, 7 }, /* DMAC DMTE4 */ | ||
78 | { 45, 2, 8, 7 }, /* DMAC DMTE5 */ | ||
79 | { 46, 2, 8, 7 }, /* DMAC DMTE6 */ | ||
80 | { 47, 2, 8, 7 }, /* DMAC DMTE7 */ | ||
81 | /* The following use INTC_INPRI00 for masking, which is a 32-bit | ||
82 | register, not a 16-bit register like the IPRx registers, so it | ||
83 | would need special support */ | ||
84 | /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ | ||
85 | /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ | ||
86 | }; | ||
87 | |||
88 | static unsigned long ipr_offsets[] = { | ||
89 | 0xffd00004UL, /* 0: IPRA */ | ||
90 | 0xffd00008UL, /* 1: IPRB */ | ||
91 | 0xffd0000cUL, /* 2: IPRC */ | ||
92 | 0xffd00010UL, /* 3: IPRD */ | ||
93 | }; | ||
94 | |||
95 | /* given the IPR index return the address of the IPR register */ | ||
96 | unsigned int map_ipridx_to_addr(int idx) | ||
97 | { | ||
98 | if (idx >= ARRAY_SIZE(ipr_offsets)) | ||
99 | return 0; | ||
100 | return ipr_offsets[idx]; | ||
101 | } | ||
102 | |||
103 | #define INTC_ICR 0xffd00000UL | ||
104 | #define INTC_ICR_IRLM (1<<7) | ||
105 | |||
106 | /* enable individual interrupt mode for external interupts */ | ||
107 | void ipr_irq_enable_irlm(void) | ||
108 | { | ||
109 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | ||
110 | } | ||
111 | |||
112 | void __init init_IRQ_ipr() | ||
113 | { | ||
114 | make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map)); | ||
115 | #ifdef CONFIG_CPU_SUBTYPE_SH7751 | ||
116 | make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map)); | ||
117 | #endif | ||
118 | } | ||
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c index 814ddb226531..9aeaa2ddaa28 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7780.c | |||
@@ -79,25 +79,27 @@ static int __init sh7780_devices_setup(void) | |||
79 | __initcall(sh7780_devices_setup); | 79 | __initcall(sh7780_devices_setup); |
80 | 80 | ||
81 | static struct intc2_data intc2_irq_table[] = { | 81 | static struct intc2_data intc2_irq_table[] = { |
82 | { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2 }, | 82 | { 28, 0, 24, 0, 0, 2 }, /* TMU0 */ |
83 | { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, | ||
84 | { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY }, | ||
85 | { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY }, | ||
86 | { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | ||
87 | { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | ||
88 | { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | ||
89 | { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, | ||
90 | 83 | ||
91 | { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, | 84 | { 21, 1, 0, 0, 2, 2 }, |
92 | { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, | 85 | { 22, 1, 1, 0, 2, 2 }, |
93 | { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, | 86 | { 23, 1, 2, 0, 2, 2 }, |
94 | { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, | ||
95 | 87 | ||
96 | { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, | 88 | { 40, 8, 24, 0, 3, 3 }, /* SCIF0 ERI */ |
97 | { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, | 89 | { 41, 8, 24, 0, 3, 3 }, /* SCIF0 RXI */ |
98 | { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, | 90 | { 42, 8, 24, 0, 3, 3 }, /* SCIF0 BRI */ |
99 | { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, | 91 | { 43, 8, 24, 0, 3, 3 }, /* SCIF0 TXI */ |
100 | { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, | 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 */ | ||
101 | }; | 103 | }; |
102 | 104 | ||
103 | void __init init_IRQ_intc2(void) | 105 | void __init init_IRQ_intc2(void) |
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index 7bcc73f9b8df..55f43506995a 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> |
@@ -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 | } |
70 | EXPORT_SYMBOL(sq_flush_range); | ||
70 | 71 | ||
71 | static inline void sq_mapping_list_add(struct sq_mapping *map) | 72 | static inline void sq_mapping_list_add(struct sq_mapping *map) |
72 | { | 73 | { |
@@ -166,7 +167,7 @@ unsigned long sq_remap(unsigned long phys, unsigned int size, | |||
166 | map->size = size; | 167 | map->size = size; |
167 | map->name = name; | 168 | map->name = name; |
168 | 169 | ||
169 | page = bitmap_find_free_region(sq_bitmap, 0x04000000, | 170 | page = bitmap_find_free_region(sq_bitmap, 0x04000000 >> PAGE_SHIFT, |
170 | get_order(map->size)); | 171 | get_order(map->size)); |
171 | if (unlikely(page < 0)) { | 172 | if (unlikely(page < 0)) { |
172 | ret = -ENOSPC; | 173 | ret = -ENOSPC; |
@@ -193,6 +194,7 @@ out: | |||
193 | kmem_cache_free(sq_cache, map); | 194 | kmem_cache_free(sq_cache, map); |
194 | return ret; | 195 | return ret; |
195 | } | 196 | } |
197 | EXPORT_SYMBOL(sq_remap); | ||
196 | 198 | ||
197 | /** | 199 | /** |
198 | * sq_unmap - Unmap a Store Queue allocation | 200 | * sq_unmap - Unmap a Store Queue allocation |
@@ -234,6 +236,7 @@ void sq_unmap(unsigned long vaddr) | |||
234 | 236 | ||
235 | kmem_cache_free(sq_cache, map); | 237 | kmem_cache_free(sq_cache, map); |
236 | } | 238 | } |
239 | EXPORT_SYMBOL(sq_unmap); | ||
237 | 240 | ||
238 | /* | 241 | /* |
239 | * Needlessly complex sysfs interface. Unfortunately it doesn't seem like | 242 | * Needlessly complex sysfs interface. Unfortunately it doesn't seem like |
@@ -402,7 +405,3 @@ module_exit(sq_api_exit); | |||
402 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); | 405 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); |
403 | MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); | 406 | MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); |
404 | MODULE_LICENSE("GPL"); | 407 | MODULE_LICENSE("GPL"); |
405 | |||
406 | EXPORT_SYMBOL(sq_remap); | ||
407 | EXPORT_SYMBOL(sq_unmap); | ||
408 | EXPORT_SYMBOL(sq_flush_range); | ||