diff options
Diffstat (limited to 'arch/sh/kernel')
35 files changed, 863 insertions, 435 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 9104b6257644..1f141a8ba17c 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -4,10 +4,9 @@ | |||
4 | 4 | ||
5 | extra-y := head.o init_task.o vmlinux.lds | 5 | extra-y := head.o init_task.o vmlinux.lds |
6 | 6 | ||
7 | obj-y := process.o signal.o traps.o irq.o \ | 7 | obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \ |
8 | ptrace.o setup.o time.o sys_sh.o semaphore.o \ | 8 | semaphore.o setup.o signal.o sys_sh.o syscalls.o \ |
9 | io.o io_generic.o sh_ksyms.o syscalls.o \ | 9 | time.o topology.o traps.o |
10 | debugtraps.o | ||
11 | 10 | ||
12 | obj-y += cpu/ timers/ | 11 | obj-y += cpu/ timers/ |
13 | obj-$(CONFIG_VSYSCALL) += vsyscall/ | 12 | obj-$(CONFIG_VSYSCALL) += vsyscall/ |
@@ -17,7 +16,7 @@ obj-$(CONFIG_CF_ENABLER) += cf-enabler.o | |||
17 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o | 16 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o |
18 | obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o | 17 | obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o |
19 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o | 18 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o |
20 | obj-$(CONFIG_MODULES) += module.o | 19 | obj-$(CONFIG_MODULES) += sh_ksyms.o module.o |
21 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 20 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
22 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 21 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
23 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 22 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c index ebc73b85094a..1c3b99642e1c 100644 --- a/arch/sh/kernel/cf-enabler.c +++ b/arch/sh/kernel/cf-enabler.c | |||
@@ -75,11 +75,7 @@ static int __init cf_init_default(void) | |||
75 | #if defined(CONFIG_CPU_SH4) | 75 | #if defined(CONFIG_CPU_SH4) |
76 | allocate_cf_area(); | 76 | allocate_cf_area(); |
77 | #endif | 77 | #endif |
78 | #if defined(CONFIG_SH_UNKNOWN) | 78 | |
79 | /* This should be done in each board's init_xxx_irq. */ | ||
80 | make_imask_irq(14); | ||
81 | disable_irq(14); | ||
82 | #endif | ||
83 | return 0; | 79 | return 0; |
84 | } | 80 | } |
85 | 81 | ||
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 6451ad630174..9172e97dc26a 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c | |||
@@ -21,8 +21,7 @@ | |||
21 | #include <asm/cacheflush.h> | 21 | #include <asm/cacheflush.h> |
22 | #include <asm/cache.h> | 22 | #include <asm/cache.h> |
23 | #include <asm/io.h> | 23 | #include <asm/io.h> |
24 | 24 | #include <asm/ubc.h> | |
25 | extern void detect_cpu_and_cache_system(void); | ||
26 | 25 | ||
27 | /* | 26 | /* |
28 | * Generic wrapper for command line arguments to disable on-chip | 27 | * Generic wrapper for command line arguments to disable on-chip |
@@ -152,15 +151,6 @@ static void __init cache_init(void) | |||
152 | flags |= CCR_CACHE_CB; | 151 | flags |= CCR_CACHE_CB; |
153 | #endif | 152 | #endif |
154 | 153 | ||
155 | #ifdef CONFIG_SH_OCRAM | ||
156 | /* Turn on OCRAM -- halve the OC */ | ||
157 | flags |= CCR_CACHE_ORA; | ||
158 | current_cpu_data.dcache.sets >>= 1; | ||
159 | |||
160 | current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets * | ||
161 | current_cpu_data.dcache.linesz; | ||
162 | #endif | ||
163 | |||
164 | ctrl_outl(flags, CCR); | 154 | ctrl_outl(flags, CCR); |
165 | back_to_P1(); | 155 | back_to_P1(); |
166 | } | 156 | } |
@@ -269,7 +259,6 @@ asmlinkage void __init sh_cpu_init(void) | |||
269 | } | 259 | } |
270 | #endif | 260 | #endif |
271 | 261 | ||
272 | #ifdef CONFIG_UBC_WAKEUP | ||
273 | /* | 262 | /* |
274 | * Some brain-damaged loaders decided it would be a good idea to put | 263 | * Some brain-damaged loaders decided it would be a good idea to put |
275 | * the UBC to sleep. This causes some issues when it comes to things | 264 | * the UBC to sleep. This causes some issues when it comes to things |
@@ -277,7 +266,5 @@ asmlinkage void __init sh_cpu_init(void) | |||
277 | * we wake it up and hope that all is well. | 266 | * we wake it up and hope that all is well. |
278 | */ | 267 | */ |
279 | ubc_wakeup(); | 268 | ubc_wakeup(); |
280 | #endif | ||
281 | |||
282 | speculative_execution_init(); | 269 | speculative_execution_init(); |
283 | } | 270 | } |
diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c index d8e22f4ff0f0..cc5221390e09 100644 --- a/arch/sh/kernel/cpu/irq/intc2.c +++ b/arch/sh/kernel/cpu/irq/intc2.c | |||
@@ -13,36 +13,31 @@ | |||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <asm/smp.h> | ||
16 | 17 | ||
17 | #if defined(CONFIG_CPU_SUBTYPE_SH7760) | 18 | static inline struct intc2_desc *get_intc2_desc(unsigned int irq) |
18 | #define INTC2_BASE 0xfe080000 | 19 | { |
19 | #define INTC2_INTMSK (INTC2_BASE + 0x40) | 20 | struct irq_chip *chip = get_irq_chip(irq); |
20 | #define INTC2_INTMSKCLR (INTC2_BASE + 0x60) | 21 | return (void *)((char *)chip - offsetof(struct intc2_desc, chip)); |
21 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | 22 | } |
22 | defined(CONFIG_CPU_SUBTYPE_SH7785) | ||
23 | #define INTC2_BASE 0xffd40000 | ||
24 | #define INTC2_INTMSK (INTC2_BASE + 0x38) | ||
25 | #define INTC2_INTMSKCLR (INTC2_BASE + 0x3c) | ||
26 | #endif | ||
27 | 23 | ||
28 | static void disable_intc2_irq(unsigned int irq) | 24 | static void disable_intc2_irq(unsigned int irq) |
29 | { | 25 | { |
30 | struct intc2_data *p = get_irq_chip_data(irq); | 26 | struct intc2_data *p = get_irq_chip_data(irq); |
31 | ctrl_outl(1 << p->msk_shift, INTC2_INTMSK + p->msk_offset); | 27 | struct intc2_desc *d = get_intc2_desc(irq); |
28 | |||
29 | ctrl_outl(1 << p->msk_shift, d->msk_base + p->msk_offset + | ||
30 | (hard_smp_processor_id() * 4)); | ||
32 | } | 31 | } |
33 | 32 | ||
34 | static void enable_intc2_irq(unsigned int irq) | 33 | static void enable_intc2_irq(unsigned int irq) |
35 | { | 34 | { |
36 | struct intc2_data *p = get_irq_chip_data(irq); | 35 | struct intc2_data *p = get_irq_chip_data(irq); |
37 | ctrl_outl(1 << p->msk_shift, INTC2_INTMSKCLR + p->msk_offset); | 36 | struct intc2_desc *d = get_intc2_desc(irq); |
38 | } | ||
39 | 37 | ||
40 | static struct irq_chip intc2_irq_chip = { | 38 | ctrl_outl(1 << p->msk_shift, d->mskclr_base + p->msk_offset + |
41 | .name = "INTC2", | 39 | (hard_smp_processor_id() * 4)); |
42 | .mask = disable_intc2_irq, | 40 | } |
43 | .unmask = enable_intc2_irq, | ||
44 | .mask_ack = disable_intc2_irq, | ||
45 | }; | ||
46 | 41 | ||
47 | /* | 42 | /* |
48 | * Setup an INTC2 style interrupt. | 43 | * Setup an INTC2 style interrupt. |
@@ -56,30 +51,36 @@ static struct irq_chip intc2_irq_chip = { | |||
56 | * | 51 | * |
57 | * in the intc2_data table. | 52 | * in the intc2_data table. |
58 | */ | 53 | */ |
59 | void make_intc2_irq(struct intc2_data *table, unsigned int nr_irqs) | 54 | void register_intc2_controller(struct intc2_desc *desc) |
60 | { | 55 | { |
61 | int i; | 56 | int i; |
62 | 57 | ||
63 | for (i = 0; i < nr_irqs; i++) { | 58 | desc->chip.mask = disable_intc2_irq; |
59 | desc->chip.unmask = enable_intc2_irq; | ||
60 | desc->chip.mask_ack = disable_intc2_irq; | ||
61 | |||
62 | for (i = 0; i < desc->nr_irqs; i++) { | ||
64 | unsigned long ipr, flags; | 63 | unsigned long ipr, flags; |
65 | struct intc2_data *p = table + i; | 64 | struct intc2_data *p = desc->intc2_data + i; |
66 | 65 | ||
67 | disable_irq_nosync(p->irq); | 66 | disable_irq_nosync(p->irq); |
68 | 67 | ||
69 | /* Set the priority level */ | 68 | if (desc->prio_base) { |
70 | local_irq_save(flags); | 69 | /* Set the priority level */ |
70 | local_irq_save(flags); | ||
71 | 71 | ||
72 | ipr = ctrl_inl(INTC2_BASE + p->ipr_offset); | 72 | ipr = ctrl_inl(desc->prio_base + p->ipr_offset); |
73 | ipr &= ~(0xf << p->ipr_shift); | 73 | ipr &= ~(0xf << p->ipr_shift); |
74 | ipr |= p->priority << p->ipr_shift; | 74 | ipr |= p->priority << p->ipr_shift; |
75 | ctrl_outl(ipr, INTC2_BASE + p->ipr_offset); | 75 | ctrl_outl(ipr, desc->prio_base + p->ipr_offset); |
76 | 76 | ||
77 | local_irq_restore(flags); | 77 | local_irq_restore(flags); |
78 | } | ||
78 | 79 | ||
79 | set_irq_chip_and_handler_name(p->irq, &intc2_irq_chip, | 80 | set_irq_chip_and_handler_name(p->irq, &desc->chip, |
80 | handle_level_irq, "level"); | 81 | handle_level_irq, "level"); |
81 | set_irq_chip_data(p->irq, p); | 82 | set_irq_chip_data(p->irq, p); |
82 | 83 | ||
83 | enable_intc2_irq(p->irq); | 84 | disable_intc2_irq(p->irq); |
84 | } | 85 | } |
85 | } | 86 | } |
diff --git a/arch/sh/kernel/cpu/irq/ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 210280b6fddf..98e84f40c713 100644 --- a/arch/sh/kernel/cpu/irq/ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c | |||
@@ -22,58 +22,57 @@ | |||
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | 24 | ||
25 | static inline struct ipr_desc *get_ipr_desc(unsigned int irq) | ||
26 | { | ||
27 | struct irq_chip *chip = get_irq_chip(irq); | ||
28 | return (void *)((char *)chip - offsetof(struct ipr_desc, chip)); | ||
29 | } | ||
30 | |||
25 | static void disable_ipr_irq(unsigned int irq) | 31 | static void disable_ipr_irq(unsigned int irq) |
26 | { | 32 | { |
27 | struct ipr_data *p = get_irq_chip_data(irq); | 33 | struct ipr_data *p = get_irq_chip_data(irq); |
34 | unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; | ||
28 | /* Set the priority in IPR to 0 */ | 35 | /* Set the priority in IPR to 0 */ |
29 | ctrl_outw(ctrl_inw(p->addr) & (0xffff ^ (0xf << p->shift)), p->addr); | 36 | ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr); |
30 | } | 37 | } |
31 | 38 | ||
32 | static void enable_ipr_irq(unsigned int irq) | 39 | static void enable_ipr_irq(unsigned int irq) |
33 | { | 40 | { |
34 | struct ipr_data *p = get_irq_chip_data(irq); | 41 | struct ipr_data *p = get_irq_chip_data(irq); |
42 | unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx]; | ||
35 | /* Set priority in IPR back to original value */ | 43 | /* Set priority in IPR back to original value */ |
36 | ctrl_outw(ctrl_inw(p->addr) | (p->priority << p->shift), p->addr); | 44 | ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr); |
37 | } | 45 | } |
38 | 46 | ||
39 | static struct irq_chip ipr_irq_chip = { | 47 | /* |
40 | .name = "IPR", | 48 | * The shift value is now the number of bits to shift, not the number of |
41 | .mask = disable_ipr_irq, | 49 | * bits/4. This is to make it easier to read the value directly from the |
42 | .unmask = enable_ipr_irq, | 50 | * datasheets. The IPR address is calculated using the ipr_offset table. |
43 | .mask_ack = disable_ipr_irq, | 51 | */ |
44 | }; | ||
45 | |||
46 | unsigned int map_ipridx_to_addr(int idx) __attribute__ ((weak)); | ||
47 | unsigned int map_ipridx_to_addr(int idx) | ||
48 | { | ||
49 | return 0; | ||
50 | } | ||
51 | 52 | ||
52 | void make_ipr_irq(struct ipr_data *table, unsigned int nr_irqs) | 53 | void register_ipr_controller(struct ipr_desc *desc) |
53 | { | 54 | { |
54 | int i; | 55 | int i; |
55 | 56 | ||
56 | for (i = 0; i < nr_irqs; i++) { | 57 | desc->chip.mask = disable_ipr_irq; |
57 | unsigned int irq = table[i].irq; | 58 | desc->chip.unmask = enable_ipr_irq; |
59 | desc->chip.mask_ack = disable_ipr_irq; | ||
58 | 60 | ||
59 | if (!irq) | 61 | for (i = 0; i < desc->nr_irqs; i++) { |
60 | irq = table[i].irq = i; | 62 | struct ipr_data *p = desc->ipr_data + i; |
61 | 63 | ||
62 | /* could the IPR index be mapped, if not we ignore this */ | 64 | BUG_ON(p->ipr_idx >= desc->nr_offsets); |
63 | if (!table[i].addr) { | 65 | BUG_ON(!desc->ipr_offsets[p->ipr_idx]); |
64 | table[i].addr = map_ipridx_to_addr(table[i].ipr_idx); | ||
65 | if (!table[i].addr) | ||
66 | continue; | ||
67 | } | ||
68 | 66 | ||
69 | disable_irq_nosync(irq); | 67 | disable_irq_nosync(p->irq); |
70 | set_irq_chip_and_handler_name(irq, &ipr_irq_chip, | 68 | set_irq_chip_and_handler_name(p->irq, &desc->chip, |
71 | handle_level_irq, "level"); | 69 | handle_level_irq, "level"); |
72 | set_irq_chip_data(irq, &table[i]); | 70 | set_irq_chip_data(p->irq, p); |
73 | enable_ipr_irq(irq); | 71 | disable_ipr_irq(p->irq); |
74 | } | 72 | } |
75 | } | 73 | } |
76 | EXPORT_SYMBOL(make_ipr_irq); | 74 | |
75 | EXPORT_SYMBOL(register_ipr_controller); | ||
77 | 76 | ||
78 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) | 77 | #if !defined(CONFIG_CPU_HAS_PINT_IRQ) |
79 | int ipr_irq_demux(int irq) | 78 | int ipr_irq_demux(int irq) |
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S index c16dc8fec489..ee8f1fe84b08 100644 --- a/arch/sh/kernel/cpu/sh2/entry.S +++ b/arch/sh/kernel/cpu/sh2/entry.S | |||
@@ -311,6 +311,7 @@ restore_all: | |||
311 | rte | 311 | rte |
312 | nop | 312 | nop |
313 | 313 | ||
314 | .align 2 | ||
314 | #ifdef CONFIG_TRACE_IRQFLAGS | 315 | #ifdef CONFIG_TRACE_IRQFLAGS |
315 | 1: .long trace_hardirqs_off | 316 | 1: .long trace_hardirqs_off |
316 | #endif | 317 | #endif |
diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index 108e81b682ed..abbf17427e52 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c | |||
@@ -9,23 +9,14 @@ | |||
9 | * License. See the file "COPYING" in the main directory of this archive | 9 | * License. See the file "COPYING" in the main directory of this archive |
10 | * for more details. | 10 | * for more details. |
11 | */ | 11 | */ |
12 | |||
13 | |||
14 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/smp.h> | ||
15 | #include <asm/processor.h> | 14 | #include <asm/processor.h> |
16 | #include <asm/cache.h> | 15 | #include <asm/cache.h> |
17 | 16 | ||
18 | int __init detect_cpu_and_cache_system(void) | 17 | int __init detect_cpu_and_cache_system(void) |
19 | { | 18 | { |
20 | #if defined(CONFIG_CPU_SUBTYPE_SH7604) | 19 | #if defined(CONFIG_CPU_SUBTYPE_SH7619) |
21 | current_cpu_data.type = CPU_SH7604; | ||
22 | current_cpu_data.dcache.ways = 4; | ||
23 | current_cpu_data.dcache.way_incr = (1<<10); | ||
24 | current_cpu_data.dcache.sets = 64; | ||
25 | current_cpu_data.dcache.entry_shift = 4; | ||
26 | current_cpu_data.dcache.linesz = L1_CACHE_BYTES; | ||
27 | current_cpu_data.dcache.flags = 0; | ||
28 | #elif defined(CONFIG_CPU_SUBTYPE_SH7619) | ||
29 | current_cpu_data.type = CPU_SH7619; | 20 | current_cpu_data.type = CPU_SH7619; |
30 | current_cpu_data.dcache.ways = 4; | 21 | current_cpu_data.dcache.ways = 4; |
31 | current_cpu_data.dcache.way_incr = (1<<12); | 22 | current_cpu_data.dcache.way_incr = (1<<12); |
diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index f83ff8a68f35..1a107fe22dde 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c | |||
@@ -52,7 +52,7 @@ static int __init sh7619_devices_setup(void) | |||
52 | } | 52 | } |
53 | __initcall(sh7619_devices_setup); | 53 | __initcall(sh7619_devices_setup); |
54 | 54 | ||
55 | static struct ipr_data sh7619_ipr_map[] = { | 55 | static struct ipr_data ipr_irq_table[] = { |
56 | { 86, 0, 4, 2 }, /* CMI0 */ | 56 | { 86, 0, 4, 2 }, /* CMI0 */ |
57 | { 88, 1, 12, 3 }, /* SCIF0_ERI */ | 57 | { 88, 1, 12, 3 }, /* SCIF0_ERI */ |
58 | { 89, 1, 12, 3 }, /* SCIF0_RXI */ | 58 | { 89, 1, 12, 3 }, /* SCIF0_RXI */ |
@@ -68,7 +68,7 @@ static struct ipr_data sh7619_ipr_map[] = { | |||
68 | { 99, 1, 4, 3 }, /* SCIF2_TXI */ | 68 | { 99, 1, 4, 3 }, /* SCIF2_TXI */ |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static unsigned int ipr_offsets[] = { | 71 | static unsigned long ipr_offsets[] = { |
72 | 0xf8080000, /* IPRC */ | 72 | 0xf8080000, /* IPRC */ |
73 | 0xf8080002, /* IPRD */ | 73 | 0xf8080002, /* IPRD */ |
74 | 0xf8080004, /* IPRE */ | 74 | 0xf8080004, /* IPRE */ |
@@ -76,15 +76,19 @@ static unsigned int ipr_offsets[] = { | |||
76 | 0xf8080008, /* IPRG */ | 76 | 0xf8080008, /* IPRG */ |
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* given the IPR index return the address of the IPR register */ | 79 | static struct ipr_desc ipr_irq_desc = { |
80 | unsigned int map_ipridx_to_addr(int idx) | 80 | .ipr_offsets = ipr_offsets, |
81 | { | 81 | .nr_offsets = ARRAY_SIZE(ipr_offsets), |
82 | if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) | 82 | |
83 | return 0; | 83 | .ipr_data = ipr_irq_table, |
84 | return ipr_offsets[idx]; | 84 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), |
85 | } | 85 | |
86 | .chip = { | ||
87 | .name = "IPR-sh7619", | ||
88 | }, | ||
89 | }; | ||
86 | 90 | ||
87 | void __init init_IRQ_ipr(void) | 91 | void __init init_IRQ_ipr(void) |
88 | { | 92 | { |
89 | make_ipr_irq(sh7619_ipr_map, ARRAY_SIZE(sh7619_ipr_map)); | 93 | register_ipr_controller(&ipr_irq_desc); |
90 | } | 94 | } |
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 4ed9110632bc..b6e3a6351fa6 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c | |||
@@ -57,7 +57,7 @@ static int __init sh7206_devices_setup(void) | |||
57 | } | 57 | } |
58 | __initcall(sh7206_devices_setup); | 58 | __initcall(sh7206_devices_setup); |
59 | 59 | ||
60 | static struct ipr_data sh7206_ipr_map[] = { | 60 | static struct ipr_data ipr_irq_table[] = { |
61 | { 140, 7, 12, 2 }, /* CMI0 */ | 61 | { 140, 7, 12, 2 }, /* CMI0 */ |
62 | { 164, 8, 4, 2 }, /* MTU2_TGI1A */ | 62 | { 164, 8, 4, 2 }, /* MTU2_TGI1A */ |
63 | { 240, 13, 12, 3 }, /* SCIF0_BRI */ | 63 | { 240, 13, 12, 3 }, /* SCIF0_BRI */ |
@@ -78,7 +78,7 @@ static struct ipr_data sh7206_ipr_map[] = { | |||
78 | { 255, 13, 0, 3 }, /* SCIF3_TXI */ | 78 | { 255, 13, 0, 3 }, /* SCIF3_TXI */ |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static unsigned int ipr_offsets[] = { | 81 | static unsigned long ipr_offsets[] = { |
82 | 0xfffe0818, /* IPR01 */ | 82 | 0xfffe0818, /* IPR01 */ |
83 | 0xfffe081a, /* IPR02 */ | 83 | 0xfffe081a, /* IPR02 */ |
84 | 0, /* unused */ | 84 | 0, /* unused */ |
@@ -95,15 +95,19 @@ static unsigned int ipr_offsets[] = { | |||
95 | 0xfffe0c10, /* IPR14 */ | 95 | 0xfffe0c10, /* IPR14 */ |
96 | }; | 96 | }; |
97 | 97 | ||
98 | /* given the IPR index return the address of the IPR register */ | 98 | static struct ipr_desc ipr_irq_desc = { |
99 | unsigned int map_ipridx_to_addr(int idx) | 99 | .ipr_offsets = ipr_offsets, |
100 | { | 100 | .nr_offsets = ARRAY_SIZE(ipr_offsets), |
101 | if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) | 101 | |
102 | return 0; | 102 | .ipr_data = ipr_irq_table, |
103 | return ipr_offsets[idx]; | 103 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), |
104 | } | 104 | |
105 | .chip = { | ||
106 | .name = "IPR-sh7206", | ||
107 | }, | ||
108 | }; | ||
105 | 109 | ||
106 | void __init init_IRQ_ipr(void) | 110 | void __init init_IRQ_ipr(void) |
107 | { | 111 | { |
108 | make_ipr_irq(sh7206_ipr_map, ARRAY_SIZE(sh7206_ipr_map)); | 112 | register_ipr_controller(&ipr_irq_desc); |
109 | } | 113 | } |
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index b0b59d4a33ca..d8e122971c3e 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -340,8 +340,27 @@ ENTRY(vbr_base) | |||
340 | general_exception: | 340 | general_exception: |
341 | mov.l 1f, k2 | 341 | mov.l 1f, k2 |
342 | mov.l 2f, k3 | 342 | mov.l 2f, k3 |
343 | #ifdef CONFIG_CPU_SUBTYPE_SHX3 | ||
344 | mov.l @k2, k2 | ||
345 | |||
346 | ! Is EXPEVT larger than 0x800? | ||
347 | mov #0x8, k0 | ||
348 | shll8 k0 | ||
349 | cmp/hs k0, k2 | ||
350 | bf 0f | ||
351 | |||
352 | ! then add 0x580 (k2 is 0xd80 or 0xda0) | ||
353 | mov #0x58, k0 | ||
354 | shll2 k0 | ||
355 | shll2 k0 | ||
356 | add k0, k2 | ||
357 | 0: | ||
358 | bra handle_exception | ||
359 | nop | ||
360 | #else | ||
343 | bra handle_exception | 361 | bra handle_exception |
344 | mov.l @k2, k2 | 362 | mov.l @k2, k2 |
363 | #endif | ||
345 | .align 2 | 364 | .align 2 |
346 | 1: .long EXPEVT | 365 | 1: .long EXPEVT |
347 | 2: .long ret_from_exception | 366 | 2: .long ret_from_exception |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index 1983fb7ad6ea..a55b8ce2c54c 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c | |||
@@ -48,7 +48,7 @@ static int __init sh7705_devices_setup(void) | |||
48 | } | 48 | } |
49 | __initcall(sh7705_devices_setup); | 49 | __initcall(sh7705_devices_setup); |
50 | 50 | ||
51 | static struct ipr_data sh7705_ipr_map[] = { | 51 | static struct ipr_data ipr_irq_table[] = { |
52 | /* IRQ, IPR-idx, shift, priority */ | 52 | /* IRQ, IPR-idx, shift, priority */ |
53 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ | 53 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ |
54 | { 17, 0, 8, 2 }, /* TMU1 TUNI */ | 54 | { 17, 0, 8, 2 }, /* TMU1 TUNI */ |
@@ -70,25 +70,29 @@ static struct ipr_data sh7705_ipr_map[] = { | |||
70 | }; | 70 | }; |
71 | 71 | ||
72 | static unsigned long ipr_offsets[] = { | 72 | static unsigned long ipr_offsets[] = { |
73 | 0xFFFFFEE2 /* 0: IPRA */ | 73 | 0xFFFFFEE2, /* 0: IPRA */ |
74 | , 0xFFFFFEE4 /* 1: IPRB */ | 74 | 0xFFFFFEE4, /* 1: IPRB */ |
75 | , 0xA4000016 /* 2: IPRC */ | 75 | 0xA4000016, /* 2: IPRC */ |
76 | , 0xA4000018 /* 3: IPRD */ | 76 | 0xA4000018, /* 3: IPRD */ |
77 | , 0xA400001A /* 4: IPRE */ | 77 | 0xA400001A, /* 4: IPRE */ |
78 | , 0xA4080000 /* 5: IPRF */ | 78 | 0xA4080000, /* 5: IPRF */ |
79 | , 0xA4080002 /* 6: IPRG */ | 79 | 0xA4080002, /* 6: IPRG */ |
80 | , 0xA4080004 /* 7: IPRH */ | 80 | 0xA4080004, /* 7: IPRH */ |
81 | }; | 81 | }; |
82 | 82 | ||
83 | /* given the IPR index return the address of the IPR register */ | 83 | static struct ipr_desc ipr_irq_desc = { |
84 | unsigned int map_ipridx_to_addr(int idx) | 84 | .ipr_offsets = ipr_offsets, |
85 | { | 85 | .nr_offsets = ARRAY_SIZE(ipr_offsets), |
86 | if (idx >= ARRAY_SIZE(ipr_offsets)) | 86 | |
87 | return 0; | 87 | .ipr_data = ipr_irq_table, |
88 | return ipr_offsets[idx]; | 88 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), |
89 | } | 89 | |
90 | .chip = { | ||
91 | .name = "IPR-sh7705", | ||
92 | }, | ||
93 | }; | ||
90 | 94 | ||
91 | void __init init_IRQ_ipr() | 95 | void __init init_IRQ_ipr(void) |
92 | { | 96 | { |
93 | make_ipr_irq(sh7705_ipr_map, ARRAY_SIZE(sh7705_ipr_map)); | 97 | register_ipr_controller(&ipr_irq_desc); |
94 | } | 98 | } |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c index c7d7c35fc834..d79ec0c0522f 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7709.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7709.c | |||
@@ -12,6 +12,26 @@ | |||
12 | #include <linux/serial.h> | 12 | #include <linux/serial.h> |
13 | #include <asm/sci.h> | 13 | #include <asm/sci.h> |
14 | 14 | ||
15 | static struct resource rtc_resources[] = { | ||
16 | [0] = { | ||
17 | .start = 0xfffffec0, | ||
18 | .end = 0xfffffec0 + 0x1e, | ||
19 | .flags = IORESOURCE_IO, | ||
20 | }, | ||
21 | [1] = { | ||
22 | .start = 20, | ||
23 | .flags = IORESOURCE_IRQ, | ||
24 | }, | ||
25 | [2] = { | ||
26 | .start = 21, | ||
27 | .flags = IORESOURCE_IRQ, | ||
28 | }, | ||
29 | [3] = { | ||
30 | .start = 22, | ||
31 | .flags = IORESOURCE_IRQ, | ||
32 | }, | ||
33 | }; | ||
34 | |||
15 | static struct plat_sci_port sci_platform_data[] = { | 35 | static struct plat_sci_port sci_platform_data[] = { |
16 | { | 36 | { |
17 | .mapbase = 0xfffffe80, | 37 | .mapbase = 0xfffffe80, |
@@ -41,8 +61,16 @@ static struct platform_device sci_device = { | |||
41 | }, | 61 | }, |
42 | }; | 62 | }; |
43 | 63 | ||
64 | static struct platform_device rtc_device = { | ||
65 | .name = "sh-rtc", | ||
66 | .id = -1, | ||
67 | .num_resources = ARRAY_SIZE(rtc_resources), | ||
68 | .resource = rtc_resources, | ||
69 | }; | ||
70 | |||
44 | static struct platform_device *sh7709_devices[] __initdata = { | 71 | static struct platform_device *sh7709_devices[] __initdata = { |
45 | &sci_device, | 72 | &sci_device, |
73 | &rtc_device, | ||
46 | }; | 74 | }; |
47 | 75 | ||
48 | static int __init sh7709_devices_setup(void) | 76 | static int __init sh7709_devices_setup(void) |
@@ -52,32 +80,66 @@ static int __init sh7709_devices_setup(void) | |||
52 | } | 80 | } |
53 | __initcall(sh7709_devices_setup); | 81 | __initcall(sh7709_devices_setup); |
54 | 82 | ||
55 | #define IPRx(A,N) .addr=A, .shift=N | 83 | static struct ipr_data ipr_irq_table[] = { |
56 | #define IPRA(N) IPRx(0xfffffee2UL,N) | 84 | { 16, 0, 12, 2 }, /* TMU TUNI0 */ |
57 | #define IPRB(N) IPRx(0xfffffee4UL,N) | 85 | { 17, 0, 8, 4 }, /* TMU TUNI1 */ |
58 | #define IPRC(N) IPRx(0xa4000016UL,N) | 86 | { 18, 0, 4, 1 }, /* TMU TUNI1 */ |
59 | #define IPRD(N) IPRx(0xa4000018UL,N) | 87 | { 19, 0, 4, 1 }, /* TMU TUNI1 */ |
60 | #define IPRE(N) IPRx(0xa400001aUL,N) | 88 | { 20, 0, 0, 2 }, /* RTC CUI */ |
61 | 89 | { 21, 0, 0, 2 }, /* RTC CUI */ | |
62 | static struct ipr_data sh7709_ipr_map[] = { | 90 | { 22, 0, 0, 2 }, /* RTC CUI */ |
63 | [16] = { IPRA(12), 2 }, /* TMU TUNI0 */ | 91 | |
64 | [17] = { IPRA(8), 4 }, /* TMU TUNI1 */ | 92 | { 23, 1, 4, 3 }, /* SCI */ |
65 | [18 ... 19] = { IPRA(4), 1 }, /* TMU TUNI1 */ | 93 | { 24, 1, 4, 3 }, /* SCI */ |
66 | [20 ... 22] = { IPRA(0), 2 }, /* RTC CUI */ | 94 | { 25, 1, 4, 3 }, /* SCI */ |
67 | [23 ... 26] = { IPRB(4), 3 }, /* SCI */ | 95 | { 26, 1, 4, 3 }, /* SCI */ |
68 | [27] = { IPRB(12), 2 }, /* WDT ITI */ | 96 | { 27, 1, 12, 3 }, /* WDT ITI */ |
69 | [32] = { IPRC(0), 1 }, /* IRQ 0 */ | 97 | |
70 | [33] = { IPRC(4), 1 }, /* IRQ 1 */ | 98 | { 32, 2, 0, 1 }, /* IRQ 0 */ |
71 | [34] = { IPRC(8), 1 }, /* IRQ 2 APM */ | 99 | { 33, 2, 4, 1 }, /* IRQ 1 */ |
72 | [35] = { IPRC(12), 1 }, /* IRQ 3 TOUCHSCREEN */ | 100 | { 34, 2, 8, 1 }, /* IRQ 2 APM */ |
73 | [36] = { IPRD(0), 1 }, /* IRQ 4 */ | 101 | { 35, 2, 12, 1 }, /* IRQ 3 TOUCHSCREEN */ |
74 | [37] = { IPRD(4), 1 }, /* IRQ 5 */ | 102 | |
75 | [48 ... 51] = { IPRE(12), 7 }, /* DMA */ | 103 | { 36, 3, 0, 1 }, /* IRQ 4 */ |
76 | [52 ... 55] = { IPRE(8), 3 }, /* IRDA */ | 104 | { 37, 3, 4, 1 }, /* IRQ 5 */ |
77 | [56 ... 59] = { IPRE(4), 3 }, /* SCIF */ | 105 | |
106 | { 48, 4, 12, 7 }, /* DMA */ | ||
107 | { 49, 4, 12, 7 }, /* DMA */ | ||
108 | { 50, 4, 12, 7 }, /* DMA */ | ||
109 | { 51, 4, 12, 7 }, /* DMA */ | ||
110 | |||
111 | { 52, 4, 8, 3 }, /* IRDA */ | ||
112 | { 53, 4, 8, 3 }, /* IRDA */ | ||
113 | { 54, 4, 8, 3 }, /* IRDA */ | ||
114 | { 55, 4, 8, 3 }, /* IRDA */ | ||
115 | |||
116 | { 56, 4, 4, 3 }, /* SCIF */ | ||
117 | { 57, 4, 4, 3 }, /* SCIF */ | ||
118 | { 58, 4, 4, 3 }, /* SCIF */ | ||
119 | { 59, 4, 4, 3 }, /* SCIF */ | ||
120 | }; | ||
121 | |||
122 | static unsigned long ipr_offsets[] = { | ||
123 | 0xfffffee2, /* 0: IPRA */ | ||
124 | 0xfffffee4, /* 1: IPRB */ | ||
125 | 0xa4000016, /* 2: IPRC */ | ||
126 | 0xa4000018, /* 3: IPRD */ | ||
127 | 0xa400001a, /* 4: IPRE */ | ||
128 | }; | ||
129 | |||
130 | static struct ipr_desc ipr_irq_desc = { | ||
131 | .ipr_offsets = ipr_offsets, | ||
132 | .nr_offsets = ARRAY_SIZE(ipr_offsets), | ||
133 | |||
134 | .ipr_data = ipr_irq_table, | ||
135 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), | ||
136 | |||
137 | .chip = { | ||
138 | .name = "IPR-sh7709", | ||
139 | }, | ||
78 | }; | 140 | }; |
79 | 141 | ||
80 | void __init init_IRQ_ipr() | 142 | void __init init_IRQ_ipr(void) |
81 | { | 143 | { |
82 | make_ipr_irq(sh7709_ipr_map, ARRAY_SIZE(sh7709_ipr_map)); | 144 | register_ipr_controller(&ipr_irq_desc); |
83 | } | 145 | } |
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 51760a7e7f1c..f40e6dac337d 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c | |||
@@ -49,7 +49,7 @@ static int __init sh7710_devices_setup(void) | |||
49 | } | 49 | } |
50 | __initcall(sh7710_devices_setup); | 50 | __initcall(sh7710_devices_setup); |
51 | 51 | ||
52 | static struct ipr_data sh7710_ipr_map[] = { | 52 | static struct ipr_data ipr_irq_table[] = { |
53 | /* IRQ, IPR-idx, shift, priority */ | 53 | /* IRQ, IPR-idx, shift, priority */ |
54 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ | 54 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ |
55 | { 17, 0, 8, 2 }, /* TMU1 TUNI */ | 55 | { 17, 0, 8, 2 }, /* TMU1 TUNI */ |
@@ -78,26 +78,30 @@ static struct ipr_data sh7710_ipr_map[] = { | |||
78 | }; | 78 | }; |
79 | 79 | ||
80 | static unsigned long ipr_offsets[] = { | 80 | static unsigned long ipr_offsets[] = { |
81 | 0xA414FEE2 /* 0: IPRA */ | 81 | 0xA414FEE2, /* 0: IPRA */ |
82 | , 0xA414FEE4 /* 1: IPRB */ | 82 | 0xA414FEE4, /* 1: IPRB */ |
83 | , 0xA4140016 /* 2: IPRC */ | 83 | 0xA4140016, /* 2: IPRC */ |
84 | , 0xA4140018 /* 3: IPRD */ | 84 | 0xA4140018, /* 3: IPRD */ |
85 | , 0xA414001A /* 4: IPRE */ | 85 | 0xA414001A, /* 4: IPRE */ |
86 | , 0xA4080000 /* 5: IPRF */ | 86 | 0xA4080000, /* 5: IPRF */ |
87 | , 0xA4080002 /* 6: IPRG */ | 87 | 0xA4080002, /* 6: IPRG */ |
88 | , 0xA4080004 /* 7: IPRH */ | 88 | 0xA4080004, /* 7: IPRH */ |
89 | , 0xA4080006 /* 8: IPRI */ | 89 | 0xA4080006, /* 8: IPRI */ |
90 | }; | 90 | }; |
91 | 91 | ||
92 | /* given the IPR index return the address of the IPR register */ | 92 | static struct ipr_desc ipr_irq_desc = { |
93 | unsigned int map_ipridx_to_addr(int idx) | 93 | .ipr_offsets = ipr_offsets, |
94 | { | 94 | .nr_offsets = ARRAY_SIZE(ipr_offsets), |
95 | if (idx >= ARRAY_SIZE(ipr_offsets)) | 95 | |
96 | return 0; | 96 | .ipr_data = ipr_irq_table, |
97 | return ipr_offsets[idx]; | 97 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), |
98 | } | 98 | |
99 | .chip = { | ||
100 | .name = "IPR-sh7710", | ||
101 | }, | ||
102 | }; | ||
99 | 103 | ||
100 | void __init init_IRQ_ipr() | 104 | void __init init_IRQ_ipr(void) |
101 | { | 105 | { |
102 | make_ipr_irq(sh7710_ipr_map, ARRAY_SIZE(sh7710_ipr_map)); | 106 | register_ipr_controller(&ipr_irq_desc); |
103 | } | 107 | } |
diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index 8add10bd8268..dadd6bffc128 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile | |||
@@ -10,7 +10,11 @@ obj-$(CONFIG_SH_STORE_QUEUES) += sq.o | |||
10 | 10 | ||
11 | # CPU subtype setup | 11 | # CPU subtype setup |
12 | obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o | 12 | obj-$(CONFIG_CPU_SUBTYPE_SH7750) += setup-sh7750.o |
13 | obj-$(CONFIG_CPU_SUBTYPE_SH7750R) += setup-sh7750.o | ||
14 | obj-$(CONFIG_CPU_SUBTYPE_SH7750S) += setup-sh7750.o | ||
15 | obj-$(CONFIG_CPU_SUBTYPE_SH7091) += setup-sh7750.o | ||
13 | obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o | 16 | obj-$(CONFIG_CPU_SUBTYPE_SH7751) += setup-sh7750.o |
17 | obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += setup-sh7750.o | ||
14 | obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o | 18 | obj-$(CONFIG_CPU_SUBTYPE_SH7760) += setup-sh7760.o |
15 | obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o | 19 | obj-$(CONFIG_CPU_SUBTYPE_SH4_202) += setup-sh4-202.o |
16 | 20 | ||
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index fab2eb07196b..66c3f75647b2 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c | |||
@@ -141,6 +141,14 @@ int __init detect_cpu_and_cache_system(void) | |||
141 | current_cpu_data.flags |= CPU_HAS_LLSC; | 141 | current_cpu_data.flags |= CPU_HAS_LLSC; |
142 | } | 142 | } |
143 | break; | 143 | break; |
144 | case 0x4000: /* 1st cut */ | ||
145 | case 0x4001: /* 2nd cut */ | ||
146 | current_cpu_data.type = CPU_SHX3; | ||
147 | current_cpu_data.icache.ways = 4; | ||
148 | current_cpu_data.dcache.ways = 4; | ||
149 | current_cpu_data.flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER | | ||
150 | CPU_HAS_LLSC; | ||
151 | break; | ||
144 | case 0x8000: | 152 | case 0x8000: |
145 | current_cpu_data.type = CPU_ST40RA; | 153 | current_cpu_data.type = CPU_ST40RA; |
146 | current_cpu_data.flags |= CPU_HAS_FPU; | 154 | current_cpu_data.flags |= CPU_HAS_FPU; |
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 03b14cf78ddf..da153bcdfeb2 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c | |||
@@ -82,7 +82,7 @@ static int __init sh7750_devices_setup(void) | |||
82 | } | 82 | } |
83 | __initcall(sh7750_devices_setup); | 83 | __initcall(sh7750_devices_setup); |
84 | 84 | ||
85 | static struct ipr_data sh7750_ipr_map[] = { | 85 | static struct ipr_data ipr_irq_table[] = { |
86 | /* IRQ, IPR-idx, shift, priority */ | 86 | /* IRQ, IPR-idx, shift, priority */ |
87 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ | 87 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ |
88 | { 17, 0, 12, 2 }, /* TMU1 TUNI */ | 88 | { 17, 0, 12, 2 }, /* TMU1 TUNI */ |
@@ -106,8 +106,27 @@ static struct ipr_data sh7750_ipr_map[] = { | |||
106 | { 38, 2, 8, 7 }, /* DMAC DMAE */ | 106 | { 38, 2, 8, 7 }, /* DMAC DMAE */ |
107 | }; | 107 | }; |
108 | 108 | ||
109 | static unsigned long ipr_offsets[] = { | ||
110 | 0xffd00004UL, /* 0: IPRA */ | ||
111 | 0xffd00008UL, /* 1: IPRB */ | ||
112 | 0xffd0000cUL, /* 2: IPRC */ | ||
113 | 0xffd00010UL, /* 3: IPRD */ | ||
114 | }; | ||
115 | |||
116 | static struct ipr_desc ipr_irq_desc = { | ||
117 | .ipr_offsets = ipr_offsets, | ||
118 | .nr_offsets = ARRAY_SIZE(ipr_offsets), | ||
119 | |||
120 | .ipr_data = ipr_irq_table, | ||
121 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), | ||
122 | |||
123 | .chip = { | ||
124 | .name = "IPR-sh7750", | ||
125 | }, | ||
126 | }; | ||
127 | |||
109 | #ifdef CONFIG_CPU_SUBTYPE_SH7751 | 128 | #ifdef CONFIG_CPU_SUBTYPE_SH7751 |
110 | static struct ipr_data sh7751_ipr_map[] = { | 129 | static struct ipr_data ipr_irq_table_sh7751[] = { |
111 | { 44, 2, 8, 7 }, /* DMAC DMTE4 */ | 130 | { 44, 2, 8, 7 }, /* DMAC DMTE4 */ |
112 | { 45, 2, 8, 7 }, /* DMAC DMTE5 */ | 131 | { 45, 2, 8, 7 }, /* DMAC DMTE5 */ |
113 | { 46, 2, 8, 7 }, /* DMAC DMTE6 */ | 132 | { 46, 2, 8, 7 }, /* DMAC DMTE6 */ |
@@ -118,21 +137,26 @@ static struct ipr_data sh7751_ipr_map[] = { | |||
118 | /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ | 137 | /*{ 72, INTPRI00, 8, ? },*/ /* TMU3 TUNI */ |
119 | /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ | 138 | /*{ 76, INTPRI00, 12, ? },*/ /* TMU4 TUNI */ |
120 | }; | 139 | }; |
121 | #endif | ||
122 | 140 | ||
123 | static unsigned long ipr_offsets[] = { | 141 | static struct ipr_desc ipr_irq_desc_sh7751 = { |
124 | 0xffd00004UL, /* 0: IPRA */ | 142 | .ipr_offsets = ipr_offsets, |
125 | 0xffd00008UL, /* 1: IPRB */ | 143 | .nr_offsets = ARRAY_SIZE(ipr_offsets), |
126 | 0xffd0000cUL, /* 2: IPRC */ | 144 | |
127 | 0xffd00010UL, /* 3: IPRD */ | 145 | .ipr_data = ipr_irq_table_sh7751, |
146 | .nr_irqs = ARRAY_SIZE(ipr_irq_table_sh7751), | ||
147 | |||
148 | .chip = { | ||
149 | .name = "IPR-sh7751", | ||
150 | }, | ||
128 | }; | 151 | }; |
152 | #endif | ||
129 | 153 | ||
130 | /* given the IPR index return the address of the IPR register */ | 154 | void __init init_IRQ_ipr(void) |
131 | unsigned int map_ipridx_to_addr(int idx) | ||
132 | { | 155 | { |
133 | if (idx >= ARRAY_SIZE(ipr_offsets)) | 156 | register_ipr_controller(&ipr_irq_desc); |
134 | return 0; | 157 | #ifdef CONFIG_CPU_SUBTYPE_SH7751 |
135 | return ipr_offsets[idx]; | 158 | register_ipr_controller(&ipr_irq_desc_sh7751); |
159 | #endif | ||
136 | } | 160 | } |
137 | 161 | ||
138 | #define INTC_ICR 0xffd00000UL | 162 | #define INTC_ICR 0xffd00000UL |
@@ -143,11 +167,3 @@ void ipr_irq_enable_irlm(void) | |||
143 | { | 167 | { |
144 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); | 168 | ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); |
145 | } | 169 | } |
146 | |||
147 | void __init init_IRQ_ipr() | ||
148 | { | ||
149 | make_ipr_irq(sh7750_ipr_map, ARRAY_SIZE(sh7750_ipr_map)); | ||
150 | #ifdef CONFIG_CPU_SUBTYPE_SH7751 | ||
151 | make_ipr_irq(sh7751_ipr_map, ARRAY_SIZE(sh7751_ipr_map)); | ||
152 | #endif | ||
153 | } | ||
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index b7c702821e6f..3df169755673 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c | |||
@@ -96,7 +96,25 @@ static struct intc2_data intc2_irq_table[] = { | |||
96 | {109,12, 0, 4, 0, 3}, /* CMTI */ | 96 | {109,12, 0, 4, 0, 3}, /* CMTI */ |
97 | }; | 97 | }; |
98 | 98 | ||
99 | static struct ipr_data sh7760_ipr_map[] = { | 99 | static struct intc2_desc intc2_irq_desc __read_mostly = { |
100 | .prio_base = 0xfe080000, | ||
101 | .msk_base = 0xfe080040, | ||
102 | .mskclr_base = 0xfe080060, | ||
103 | |||
104 | .intc2_data = intc2_irq_table, | ||
105 | .nr_irqs = ARRAY_SIZE(intc2_irq_table), | ||
106 | |||
107 | .chip = { | ||
108 | .name = "INTC2-sh7760", | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | void __init init_IRQ_intc2(void) | ||
113 | { | ||
114 | register_intc2_controller(&intc2_irq_desc); | ||
115 | } | ||
116 | |||
117 | static struct ipr_data ipr_irq_table[] = { | ||
100 | /* IRQ, IPR-idx, shift, priority */ | 118 | /* IRQ, IPR-idx, shift, priority */ |
101 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ | 119 | { 16, 0, 12, 2 }, /* TMU0 TUNI*/ |
102 | { 17, 0, 8, 2 }, /* TMU1 TUNI */ | 120 | { 17, 0, 8, 2 }, /* TMU1 TUNI */ |
@@ -133,20 +151,19 @@ static unsigned long ipr_offsets[] = { | |||
133 | 0xffd00010UL, /* 3: IPRD */ | 151 | 0xffd00010UL, /* 3: IPRD */ |
134 | }; | 152 | }; |
135 | 153 | ||
136 | /* given the IPR index return the address of the IPR register */ | 154 | static struct ipr_desc ipr_irq_desc = { |
137 | unsigned int map_ipridx_to_addr(int idx) | 155 | .ipr_offsets = ipr_offsets, |
138 | { | 156 | .nr_offsets = ARRAY_SIZE(ipr_offsets), |
139 | if (idx >= ARRAY_SIZE(ipr_offsets)) | ||
140 | return 0; | ||
141 | return ipr_offsets[idx]; | ||
142 | } | ||
143 | 157 | ||
144 | void __init init_IRQ_intc2(void) | 158 | .ipr_data = ipr_irq_table, |
145 | { | 159 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), |
146 | make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table)); | 160 | |
147 | } | 161 | .chip = { |
162 | .name = "IPR-sh7760", | ||
163 | }, | ||
164 | }; | ||
148 | 165 | ||
149 | void __init init_IRQ_ipr(void) | 166 | void __init init_IRQ_ipr(void) |
150 | { | 167 | { |
151 | make_ipr_irq(sh7760_ipr_map, ARRAY_SIZE(sh7760_ipr_map)); | 168 | register_ipr_controller(&ipr_irq_desc); |
152 | } | 169 | } |
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index ab7422f8f820..400623286487 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o | |||
9 | obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o | 9 | obj-$(CONFIG_CPU_SUBTYPE_SH73180) += setup-sh73180.o |
10 | obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o | 10 | obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o |
11 | obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o | 11 | obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o |
12 | obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o | ||
12 | 13 | ||
13 | # Primary on-chip clocks (common) | 14 | # Primary on-chip clocks (common) |
14 | clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o | 15 | clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o |
@@ -17,5 +18,6 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o | |||
17 | clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o | 18 | clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o |
18 | clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o | 19 | clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o |
19 | clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o | 20 | clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o |
21 | clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o | ||
20 | 22 | ||
21 | obj-y += $(clock-y) | 23 | obj-y += $(clock-y) |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c new file mode 100644 index 000000000000..c630b29e06a8 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh4/clock-shx3.c | ||
3 | * | ||
4 | * SH-X3 support for the clock framework | ||
5 | * | ||
6 | * Copyright (C) 2006-2007 Renesas Technology Corp. | ||
7 | * Copyright (C) 2006-2007 Renesas Solutions Corp. | ||
8 | * Copyright (C) 2006-2007 Paul Mundt | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file "COPYING" in the main directory of this archive | ||
12 | * for more details. | ||
13 | */ | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <asm/clock.h> | ||
17 | #include <asm/freq.h> | ||
18 | #include <asm/io.h> | ||
19 | |||
20 | static int ifc_divisors[] = { 1, 2, 4 ,6 }; | ||
21 | static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 }; | ||
22 | static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 }; | ||
23 | static int cfc_divisors[] = { 1, 1, 4, 6 }; | ||
24 | |||
25 | #define IFC_POS 28 | ||
26 | #define IFC_MSK 0x0003 | ||
27 | #define BFC_MSK 0x000f | ||
28 | #define PFC_MSK 0x000f | ||
29 | #define CFC_MSK 0x0003 | ||
30 | #define BFC_POS 16 | ||
31 | #define PFC_POS 0 | ||
32 | #define CFC_POS 20 | ||
33 | |||
34 | static void master_clk_init(struct clk *clk) | ||
35 | { | ||
36 | clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK]; | ||
37 | } | ||
38 | |||
39 | static struct clk_ops shx3_master_clk_ops = { | ||
40 | .init = master_clk_init, | ||
41 | }; | ||
42 | |||
43 | static void module_clk_recalc(struct clk *clk) | ||
44 | { | ||
45 | int idx = ((ctrl_inl(FRQCR) >> PFC_POS) & PFC_MSK); | ||
46 | clk->rate = clk->parent->rate / pfc_divisors[idx]; | ||
47 | } | ||
48 | |||
49 | static struct clk_ops shx3_module_clk_ops = { | ||
50 | .recalc = module_clk_recalc, | ||
51 | }; | ||
52 | |||
53 | static void bus_clk_recalc(struct clk *clk) | ||
54 | { | ||
55 | int idx = ((ctrl_inl(FRQCR) >> BFC_POS) & BFC_MSK); | ||
56 | clk->rate = clk->parent->rate / bfc_divisors[idx]; | ||
57 | } | ||
58 | |||
59 | static struct clk_ops shx3_bus_clk_ops = { | ||
60 | .recalc = bus_clk_recalc, | ||
61 | }; | ||
62 | |||
63 | static void cpu_clk_recalc(struct clk *clk) | ||
64 | { | ||
65 | int idx = ((ctrl_inl(FRQCR) >> IFC_POS) & IFC_MSK); | ||
66 | clk->rate = clk->parent->rate / ifc_divisors[idx]; | ||
67 | } | ||
68 | |||
69 | static struct clk_ops shx3_cpu_clk_ops = { | ||
70 | .recalc = cpu_clk_recalc, | ||
71 | }; | ||
72 | |||
73 | static struct clk_ops *shx3_clk_ops[] = { | ||
74 | &shx3_master_clk_ops, | ||
75 | &shx3_module_clk_ops, | ||
76 | &shx3_bus_clk_ops, | ||
77 | &shx3_cpu_clk_ops, | ||
78 | }; | ||
79 | |||
80 | void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | ||
81 | { | ||
82 | if (idx < ARRAY_SIZE(shx3_clk_ops)) | ||
83 | *ops = shx3_clk_ops[idx]; | ||
84 | } | ||
85 | |||
86 | static void shyway_clk_recalc(struct clk *clk) | ||
87 | { | ||
88 | int idx = ((ctrl_inl(FRQCR) >> CFC_POS) & CFC_MSK); | ||
89 | clk->rate = clk->parent->rate / cfc_divisors[idx]; | ||
90 | } | ||
91 | |||
92 | static struct clk_ops shx3_shyway_clk_ops = { | ||
93 | .recalc = shyway_clk_recalc, | ||
94 | }; | ||
95 | |||
96 | static struct clk shx3_shyway_clk = { | ||
97 | .name = "shyway_clk", | ||
98 | .flags = CLK_ALWAYS_ENABLED, | ||
99 | .ops = &shx3_shyway_clk_ops, | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * Additional SHx3-specific on-chip clocks that aren't already part of the | ||
104 | * clock framework | ||
105 | */ | ||
106 | static struct clk *shx3_onchip_clocks[] = { | ||
107 | &shx3_shyway_clk, | ||
108 | }; | ||
109 | |||
110 | static int __init shx3_clk_init(void) | ||
111 | { | ||
112 | struct clk *clk = clk_get(NULL, "master_clk"); | ||
113 | int i; | ||
114 | |||
115 | for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) { | ||
116 | struct clk *clkp = shx3_onchip_clocks[i]; | ||
117 | |||
118 | clkp->parent = clk; | ||
119 | clk_register(clkp); | ||
120 | clk_enable(clkp); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Now that we have the rest of the clocks registered, we need to | ||
125 | * force the parent clock to propagate so that these clocks will | ||
126 | * automatically figure out their rate. We cheat by handing the | ||
127 | * parent clock its current rate and forcing child propagation. | ||
128 | */ | ||
129 | clk_set_rate(clk, clk_get_rate(clk)); | ||
130 | |||
131 | clk_put(clk); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | arch_initcall(shx3_clk_init); | ||
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 1143fbf65faf..a3e159ef6dfe 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * SH7722 Setup | 2 | * SH7722 Setup |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Paul Mundt | 4 | * Copyright (C) 2006 - 2007 Paul Mundt |
5 | * | 5 | * |
6 | * This file is subject to the terms and conditions of the GNU General Public | 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 | 7 | * License. See the file "COPYING" in the main directory of this archive |
@@ -10,6 +10,8 @@ | |||
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/serial.h> | 12 | #include <linux/serial.h> |
13 | #include <linux/mm.h> | ||
14 | #include <asm/mmzone.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[] = { |
@@ -42,7 +44,7 @@ static int __init sh7722_devices_setup(void) | |||
42 | } | 44 | } |
43 | __initcall(sh7722_devices_setup); | 45 | __initcall(sh7722_devices_setup); |
44 | 46 | ||
45 | static struct ipr_data sh7722_ipr_map[] = { | 47 | static struct ipr_data ipr_irq_table[] = { |
46 | /* IRQ, IPR-idx, shift, prio */ | 48 | /* IRQ, IPR-idx, shift, prio */ |
47 | { 16, 0, 12, 2 }, /* TMU0 */ | 49 | { 16, 0, 12, 2 }, /* TMU0 */ |
48 | { 17, 0, 8, 2 }, /* TMU1 */ | 50 | { 17, 0, 8, 2 }, /* TMU1 */ |
@@ -67,14 +69,25 @@ static unsigned long ipr_offsets[] = { | |||
67 | 0xa408002c, /* 11: IPRL */ | 69 | 0xa408002c, /* 11: IPRL */ |
68 | }; | 70 | }; |
69 | 71 | ||
70 | unsigned int map_ipridx_to_addr(int idx) | 72 | static struct ipr_desc ipr_irq_desc = { |
73 | .ipr_offsets = ipr_offsets, | ||
74 | .nr_offsets = ARRAY_SIZE(ipr_offsets), | ||
75 | |||
76 | .ipr_data = ipr_irq_table, | ||
77 | .nr_irqs = ARRAY_SIZE(ipr_irq_table), | ||
78 | |||
79 | .chip = { | ||
80 | .name = "IPR-sh7722", | ||
81 | }, | ||
82 | }; | ||
83 | |||
84 | void __init init_IRQ_ipr(void) | ||
71 | { | 85 | { |
72 | if (unlikely(idx >= ARRAY_SIZE(ipr_offsets))) | 86 | register_ipr_controller(&ipr_irq_desc); |
73 | return 0; | ||
74 | return ipr_offsets[idx]; | ||
75 | } | 87 | } |
76 | 88 | ||
77 | void __init init_IRQ_ipr(void) | 89 | void __init plat_mem_setup(void) |
78 | { | 90 | { |
79 | make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map)); | 91 | /* Register the URAM space as Node 1 */ |
92 | setup_bootmem_node(1, 0x055f0000, 0x05610000); | ||
80 | } | 93 | } |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 9aeaa2ddaa28..b57c760bffde 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c | |||
@@ -102,7 +102,20 @@ static struct intc2_data intc2_irq_table[] = { | |||
102 | { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */ | 102 | { 68, 0x14, 8, 0, 18, 2 }, /* PCIC4 */ |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static struct intc2_desc intc2_irq_desc __read_mostly = { | ||
106 | .prio_base = 0xffd40000, | ||
107 | .msk_base = 0xffd40038, | ||
108 | .mskclr_base = 0xffd4003c, | ||
109 | |||
110 | .intc2_data = intc2_irq_table, | ||
111 | .nr_irqs = ARRAY_SIZE(intc2_irq_table), | ||
112 | |||
113 | .chip = { | ||
114 | .name = "INTC2-sh7780", | ||
115 | }, | ||
116 | }; | ||
117 | |||
105 | void __init init_IRQ_intc2(void) | 118 | void __init init_IRQ_intc2(void) |
106 | { | 119 | { |
107 | make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table)); | 120 | register_intc2_controller(&intc2_irq_desc); |
108 | } | 121 | } |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 07b0de82cfe6..ce10ec5d6914 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c | |||
@@ -97,7 +97,21 @@ static struct intc2_data intc2_irq_table[] = { | |||
97 | { 60, 12, 16, 0, 7, 3 }, /* SCIF5 ERI, RXI, BRI, TXI */ | 97 | { 60, 12, 16, 0, 7, 3 }, /* SCIF5 ERI, RXI, BRI, TXI */ |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static struct intc2_desc intc2_irq_desc __read_mostly = { | ||
101 | .prio_base = 0xffd40000, | ||
102 | .msk_base = 0xffd40038, | ||
103 | .mskclr_base = 0xffd4003c, | ||
104 | |||
105 | .intc2_data = intc2_irq_table, | ||
106 | .nr_irqs = ARRAY_SIZE(intc2_irq_table), | ||
107 | |||
108 | .chip = { | ||
109 | .name = "INTC2-sh7785", | ||
110 | }, | ||
111 | }; | ||
112 | |||
100 | void __init init_IRQ_intc2(void) | 113 | void __init init_IRQ_intc2(void) |
101 | { | 114 | { |
102 | make_intc2_irq(intc2_irq_table, ARRAY_SIZE(intc2_irq_table)); | 115 | register_intc2_controller(&intc2_irq_desc); |
103 | } | 116 | } |
117 | |||
diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c new file mode 100644 index 000000000000..70683ea12b83 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * SH-X3 Setup | ||
3 | * | ||
4 | * Copyright (C) 2007 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 <linux/io.h> | ||
14 | #include <asm/sci.h> | ||
15 | |||
16 | static struct plat_sci_port sci_platform_data[] = { | ||
17 | { | ||
18 | .mapbase = 0xffc30000, | ||
19 | .flags = UPF_BOOT_AUTOCONF, | ||
20 | .type = PORT_SCIF, | ||
21 | .irqs = { 40, 41, 43, 42 }, | ||
22 | }, { | ||
23 | .mapbase = 0xffc40000, | ||
24 | .flags = UPF_BOOT_AUTOCONF, | ||
25 | .type = PORT_SCIF, | ||
26 | .irqs = { 44, 45, 47, 46 }, | ||
27 | }, { | ||
28 | .mapbase = 0xffc50000, | ||
29 | .flags = UPF_BOOT_AUTOCONF, | ||
30 | .type = PORT_SCIF, | ||
31 | .irqs = { 48, 49, 51, 50 }, | ||
32 | }, { | ||
33 | .mapbase = 0xffc60000, | ||
34 | .flags = UPF_BOOT_AUTOCONF, | ||
35 | .type = PORT_SCIF, | ||
36 | .irqs = { 52, 53, 55, 54 }, | ||
37 | }, { | ||
38 | .flags = 0, | ||
39 | } | ||
40 | }; | ||
41 | |||
42 | static struct platform_device sci_device = { | ||
43 | .name = "sh-sci", | ||
44 | .id = -1, | ||
45 | .dev = { | ||
46 | .platform_data = sci_platform_data, | ||
47 | }, | ||
48 | }; | ||
49 | |||
50 | static struct platform_device *shx3_devices[] __initdata = { | ||
51 | &sci_device, | ||
52 | }; | ||
53 | |||
54 | static int __init shx3_devices_setup(void) | ||
55 | { | ||
56 | return platform_add_devices(shx3_devices, | ||
57 | ARRAY_SIZE(shx3_devices)); | ||
58 | } | ||
59 | __initcall(shx3_devices_setup); | ||
60 | |||
61 | static struct intc2_data intc2_irq_table[] = { | ||
62 | { 16, 0, 0, 0, 1, 2 }, /* TMU0 */ | ||
63 | { 40, 4, 0, 0x20, 0, 3 }, /* SCIF0 ERI */ | ||
64 | { 41, 4, 0, 0x20, 1, 3 }, /* SCIF0 RXI */ | ||
65 | { 42, 4, 0, 0x20, 2, 3 }, /* SCIF0 BRI */ | ||
66 | { 43, 4, 0, 0x20, 3, 3 }, /* SCIF0 TXI */ | ||
67 | }; | ||
68 | |||
69 | static struct intc2_desc intc2_irq_desc __read_mostly = { | ||
70 | .prio_base = 0xfe410000, | ||
71 | .msk_base = 0xfe410820, | ||
72 | .mskclr_base = 0xfe410850, | ||
73 | |||
74 | .intc2_data = intc2_irq_table, | ||
75 | .nr_irqs = ARRAY_SIZE(intc2_irq_table), | ||
76 | |||
77 | .chip = { | ||
78 | .name = "INTC2-SHX3", | ||
79 | }, | ||
80 | }; | ||
81 | |||
82 | void __init init_IRQ_intc2(void) | ||
83 | { | ||
84 | register_intc2_controller(&intc2_irq_desc); | ||
85 | } | ||
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 27b923c45b3d..27897798867a 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
@@ -158,15 +158,11 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs) | |||
158 | } | 158 | } |
159 | 159 | ||
160 | #ifdef CONFIG_4KSTACKS | 160 | #ifdef CONFIG_4KSTACKS |
161 | /* | ||
162 | * These should really be __section__(".bss.page_aligned") as well, but | ||
163 | * gcc's 3.0 and earlier don't handle that correctly. | ||
164 | */ | ||
165 | static char softirq_stack[NR_CPUS * THREAD_SIZE] | 161 | static char softirq_stack[NR_CPUS * THREAD_SIZE] |
166 | __attribute__((__aligned__(THREAD_SIZE))); | 162 | __attribute__((__section__(".bss.page_aligned"))); |
167 | 163 | ||
168 | static char hardirq_stack[NR_CPUS * THREAD_SIZE] | 164 | static char hardirq_stack[NR_CPUS * THREAD_SIZE] |
169 | __attribute__((__aligned__(THREAD_SIZE))); | 165 | __attribute__((__section__(".bss.page_aligned"))); |
170 | 166 | ||
171 | /* | 167 | /* |
172 | * allocate per-cpu stacks for hardirq and for softirq processing | 168 | * allocate per-cpu stacks for hardirq and for softirq processing |
diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c new file mode 100644 index 000000000000..23c5948f0124 --- /dev/null +++ b/arch/sh/kernel/machvec.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/machvec.c | ||
3 | * | ||
4 | * The SuperH machine vector setup handlers, yanked from setup.c | ||
5 | * | ||
6 | * Copyright (C) 1999 Niibe Yutaka | ||
7 | * Copyright (C) 2002 - 2007 Paul Mundt | ||
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 | #include <linux/init.h> | ||
14 | #include <linux/string.h> | ||
15 | #include <asm/machvec.h> | ||
16 | #include <asm/sections.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/irq.h> | ||
19 | |||
20 | #define MV_NAME_SIZE 32 | ||
21 | |||
22 | #define for_each_mv(mv) \ | ||
23 | for ((mv) = (struct sh_machine_vector *)&__machvec_start; \ | ||
24 | (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \ | ||
25 | (mv)++) | ||
26 | |||
27 | static struct sh_machine_vector * __init get_mv_byname(const char *name) | ||
28 | { | ||
29 | struct sh_machine_vector *mv; | ||
30 | |||
31 | for_each_mv(mv) | ||
32 | if (strcasecmp(name, mv->mv_name) == 0) | ||
33 | return mv; | ||
34 | |||
35 | return NULL; | ||
36 | } | ||
37 | |||
38 | static unsigned int __initdata machvec_selected; | ||
39 | |||
40 | static int __init early_parse_mv(char *from) | ||
41 | { | ||
42 | char mv_name[MV_NAME_SIZE] = ""; | ||
43 | char *mv_end; | ||
44 | char *mv_comma; | ||
45 | int mv_len; | ||
46 | struct sh_machine_vector *mvp; | ||
47 | |||
48 | mv_end = strchr(from, ' '); | ||
49 | if (mv_end == NULL) | ||
50 | mv_end = from + strlen(from); | ||
51 | |||
52 | mv_comma = strchr(from, ','); | ||
53 | mv_len = mv_end - from; | ||
54 | if (mv_len > (MV_NAME_SIZE-1)) | ||
55 | mv_len = MV_NAME_SIZE-1; | ||
56 | memcpy(mv_name, from, mv_len); | ||
57 | mv_name[mv_len] = '\0'; | ||
58 | from = mv_end; | ||
59 | |||
60 | machvec_selected = 1; | ||
61 | |||
62 | /* Boot with the generic vector */ | ||
63 | if (strcmp(mv_name, "generic") == 0) | ||
64 | return 0; | ||
65 | |||
66 | mvp = get_mv_byname(mv_name); | ||
67 | if (unlikely(!mvp)) { | ||
68 | printk("Available vectors:\n\n\t'%s', ", sh_mv.mv_name); | ||
69 | for_each_mv(mvp) | ||
70 | printk("'%s', ", mvp->mv_name); | ||
71 | printk("\n\n"); | ||
72 | panic("Failed to select machvec '%s' -- halting.\n", | ||
73 | mv_name); | ||
74 | } else | ||
75 | sh_mv = *mvp; | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | early_param("sh_mv", early_parse_mv); | ||
80 | |||
81 | void __init sh_mv_setup(void) | ||
82 | { | ||
83 | /* | ||
84 | * Only overload the machvec if one hasn't been selected on | ||
85 | * the command line with sh_mv= | ||
86 | */ | ||
87 | if (!machvec_selected) { | ||
88 | unsigned long machvec_size; | ||
89 | |||
90 | machvec_size = ((unsigned long)&__machvec_end - | ||
91 | (unsigned long)&__machvec_start); | ||
92 | |||
93 | /* | ||
94 | * If the machvec hasn't been preselected, use the first | ||
95 | * vector (usually the only one) from .machvec.init. | ||
96 | */ | ||
97 | if (machvec_size >= sizeof(struct sh_machine_vector)) | ||
98 | sh_mv = *(struct sh_machine_vector *)&__machvec_start; | ||
99 | } | ||
100 | |||
101 | printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type()); | ||
102 | |||
103 | /* | ||
104 | * Manually walk the vec, fill in anything that the board hasn't yet | ||
105 | * by hand, wrapping to the generic implementation. | ||
106 | */ | ||
107 | #define mv_set(elem) do { \ | ||
108 | if (!sh_mv.mv_##elem) \ | ||
109 | sh_mv.mv_##elem = generic_##elem; \ | ||
110 | } while (0) | ||
111 | |||
112 | mv_set(inb); mv_set(inw); mv_set(inl); | ||
113 | mv_set(outb); mv_set(outw); mv_set(outl); | ||
114 | |||
115 | mv_set(inb_p); mv_set(inw_p); mv_set(inl_p); | ||
116 | mv_set(outb_p); mv_set(outw_p); mv_set(outl_p); | ||
117 | |||
118 | mv_set(insb); mv_set(insw); mv_set(insl); | ||
119 | mv_set(outsb); mv_set(outsw); mv_set(outsl); | ||
120 | |||
121 | mv_set(readb); mv_set(readw); mv_set(readl); | ||
122 | mv_set(writeb); mv_set(writew); mv_set(writel); | ||
123 | |||
124 | mv_set(ioport_map); | ||
125 | mv_set(ioport_unmap); | ||
126 | mv_set(irq_demux); | ||
127 | |||
128 | if (!sh_mv.mv_nr_irqs) | ||
129 | sh_mv.mv_nr_irqs = NR_IRQS; | ||
130 | } | ||
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index a11e2aa73cbc..6334a4c54c7c 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/kexec.h> | 17 | #include <linux/kexec.h> |
18 | #include <linux/kdebug.h> | 18 | #include <linux/kdebug.h> |
19 | #include <linux/tick.h> | 19 | #include <linux/tick.h> |
20 | #include <linux/reboot.h> | ||
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | #include <asm/mmu_context.h> | 22 | #include <asm/mmu_context.h> |
22 | #include <asm/pgalloc.h> | 23 | #include <asm/pgalloc.h> |
@@ -319,9 +320,7 @@ static void ubc_set_tracing(int asid, unsigned long pc) | |||
319 | ctrl_outl(pc, UBC_BARA); | 320 | ctrl_outl(pc, UBC_BARA); |
320 | 321 | ||
321 | #ifdef CONFIG_MMU | 322 | #ifdef CONFIG_MMU |
322 | /* We don't have any ASID settings for the SH-2! */ | 323 | ctrl_outb(asid, UBC_BASRA); |
323 | if (current_cpu_data.type != CPU_SH7604) | ||
324 | ctrl_outb(asid, UBC_BASRA); | ||
325 | #endif | 324 | #endif |
326 | 325 | ||
327 | ctrl_outl(0, UBC_BAMRA); | 326 | ctrl_outl(0, UBC_BAMRA); |
@@ -405,8 +404,8 @@ asmlinkage int sys_fork(unsigned long r4, unsigned long r5, | |||
405 | unsigned long r6, unsigned long r7, | 404 | unsigned long r6, unsigned long r7, |
406 | struct pt_regs __regs) | 405 | struct pt_regs __regs) |
407 | { | 406 | { |
408 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
409 | #ifdef CONFIG_MMU | 407 | #ifdef CONFIG_MMU |
408 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
410 | return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); | 409 | return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); |
411 | #else | 410 | #else |
412 | /* fork almost works, enough to trick you into looking elsewhere :-( */ | 411 | /* fork almost works, enough to trick you into looking elsewhere :-( */ |
@@ -449,23 +448,20 @@ asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, | |||
449 | /* | 448 | /* |
450 | * sys_execve() executes a new program. | 449 | * sys_execve() executes a new program. |
451 | */ | 450 | */ |
452 | asmlinkage int sys_execve(char *ufilename, char **uargv, | 451 | asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, |
453 | char **uenvp, unsigned long r7, | 452 | char __user * __user *uenvp, unsigned long r7, |
454 | struct pt_regs __regs) | 453 | struct pt_regs __regs) |
455 | { | 454 | { |
456 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | 455 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); |
457 | int error; | 456 | int error; |
458 | char *filename; | 457 | char *filename; |
459 | 458 | ||
460 | filename = getname((char __user *)ufilename); | 459 | filename = getname(ufilename); |
461 | error = PTR_ERR(filename); | 460 | error = PTR_ERR(filename); |
462 | if (IS_ERR(filename)) | 461 | if (IS_ERR(filename)) |
463 | goto out; | 462 | goto out; |
464 | 463 | ||
465 | error = do_execve(filename, | 464 | error = do_execve(filename, uargv, uenvp, regs); |
466 | (char __user * __user *)uargv, | ||
467 | (char __user * __user *)uenvp, | ||
468 | regs); | ||
469 | if (error == 0) { | 465 | if (error == 0) { |
470 | task_lock(current); | 466 | task_lock(current); |
471 | current->ptrace &= ~PT_DTRACE; | 467 | current->ptrace &= ~PT_DTRACE; |
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 3fb5fc0b550d..f2eaa485d04d 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c | |||
@@ -99,7 +99,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
99 | ret = -EIO; | 99 | ret = -EIO; |
100 | if (copied != sizeof(tmp)) | 100 | if (copied != sizeof(tmp)) |
101 | break; | 101 | break; |
102 | ret = put_user(tmp,(unsigned long *) data); | 102 | ret = put_user(tmp,(unsigned long __user *) data); |
103 | break; | 103 | break; |
104 | } | 104 | } |
105 | 105 | ||
@@ -128,7 +128,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
128 | tmp = !!tsk_used_math(child); | 128 | tmp = !!tsk_used_math(child); |
129 | else | 129 | else |
130 | tmp = 0; | 130 | tmp = 0; |
131 | ret = put_user(tmp, (unsigned long *)data); | 131 | ret = put_user(tmp, (unsigned long __user *)data); |
132 | break; | 132 | break; |
133 | } | 133 | } |
134 | 134 | ||
@@ -196,7 +196,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
196 | 196 | ||
197 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | 197 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ |
198 | long pc; | 198 | long pc; |
199 | struct pt_regs *dummy = NULL; | 199 | struct pt_regs *regs = NULL; |
200 | 200 | ||
201 | ret = -EIO; | 201 | ret = -EIO; |
202 | if (!valid_signal(data)) | 202 | if (!valid_signal(data)) |
@@ -207,7 +207,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
207 | child->ptrace |= PT_DTRACE; | 207 | child->ptrace |= PT_DTRACE; |
208 | } | 208 | } |
209 | 209 | ||
210 | pc = get_stack_long(child, (long)&dummy->pc); | 210 | pc = get_stack_long(child, (long)®s->pc); |
211 | 211 | ||
212 | /* Next scheduling will set up UBC */ | 212 | /* Next scheduling will set up UBC */ |
213 | if (child->thread.ubc_pc == 0) | 213 | if (child->thread.ubc_pc == 0) |
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index c27729135935..de8e6e2f2c87 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/kexec.h> | 23 | #include <linux/kexec.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/io.h> | 25 | #include <asm/io.h> |
26 | #include <asm/page.h> | ||
26 | #include <asm/sections.h> | 27 | #include <asm/sections.h> |
27 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
28 | #include <asm/setup.h> | 29 | #include <asm/setup.h> |
@@ -41,20 +42,19 @@ extern void * __rd_start, * __rd_end; | |||
41 | * The bigger value means no problem. | 42 | * The bigger value means no problem. |
42 | */ | 43 | */ |
43 | struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, }; | 44 | struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, }; |
45 | |||
46 | /* | ||
47 | * The machine vector. First entry in .machvec.init, or clobbered by | ||
48 | * sh_mv= on the command line, prior to .machvec.init teardown. | ||
49 | */ | ||
50 | struct sh_machine_vector sh_mv = { .mv_name = "generic", }; | ||
51 | |||
44 | #ifdef CONFIG_VT | 52 | #ifdef CONFIG_VT |
45 | struct screen_info screen_info; | 53 | struct screen_info screen_info; |
46 | #endif | 54 | #endif |
47 | 55 | ||
48 | #if defined(CONFIG_SH_UNKNOWN) | ||
49 | struct sh_machine_vector sh_mv; | ||
50 | #endif | ||
51 | |||
52 | extern int root_mountflags; | 56 | extern int root_mountflags; |
53 | 57 | ||
54 | #define MV_NAME_SIZE 32 | ||
55 | |||
56 | static struct sh_machine_vector* __init get_mv_byname(const char* name); | ||
57 | |||
58 | /* | 58 | /* |
59 | * This is set up by the setup-routine at boot-time | 59 | * This is set up by the setup-routine at boot-time |
60 | */ | 60 | */ |
@@ -80,131 +80,17 @@ static struct resource data_resource = { .name = "Kernel data", }; | |||
80 | 80 | ||
81 | unsigned long memory_start, memory_end; | 81 | unsigned long memory_start, memory_end; |
82 | 82 | ||
83 | static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE], | 83 | static int __init early_parse_mem(char *p) |
84 | struct sh_machine_vector** mvp, | ||
85 | unsigned long *mv_io_base) | ||
86 | { | 84 | { |
87 | char c = ' ', *to = command_line, *from = COMMAND_LINE; | 85 | unsigned long size; |
88 | int len = 0; | ||
89 | |||
90 | /* Save unparsed command line copy for /proc/cmdline */ | ||
91 | memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); | ||
92 | boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; | ||
93 | 86 | ||
94 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; | 87 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; |
95 | memory_end = memory_start + __MEMORY_SIZE; | 88 | size = memparse(p, &p); |
96 | 89 | memory_end = memory_start + size; | |
97 | for (;;) { | ||
98 | /* | ||
99 | * "mem=XXX[kKmM]" defines a size of memory. | ||
100 | */ | ||
101 | if (c == ' ' && !memcmp(from, "mem=", 4)) { | ||
102 | if (to != command_line) | ||
103 | to--; | ||
104 | { | ||
105 | unsigned long mem_size; | ||
106 | |||
107 | mem_size = memparse(from+4, &from); | ||
108 | memory_end = memory_start + mem_size; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | if (c == ' ' && !memcmp(from, "sh_mv=", 6)) { | ||
113 | char* mv_end; | ||
114 | char* mv_comma; | ||
115 | int mv_len; | ||
116 | if (to != command_line) | ||
117 | to--; | ||
118 | from += 6; | ||
119 | mv_end = strchr(from, ' '); | ||
120 | if (mv_end == NULL) | ||
121 | mv_end = from + strlen(from); | ||
122 | |||
123 | mv_comma = strchr(from, ','); | ||
124 | if ((mv_comma != NULL) && (mv_comma < mv_end)) { | ||
125 | int ints[3]; | ||
126 | get_options(mv_comma+1, ARRAY_SIZE(ints), ints); | ||
127 | *mv_io_base = ints[1]; | ||
128 | mv_len = mv_comma - from; | ||
129 | } else { | ||
130 | mv_len = mv_end - from; | ||
131 | } | ||
132 | if (mv_len > (MV_NAME_SIZE-1)) | ||
133 | mv_len = MV_NAME_SIZE-1; | ||
134 | memcpy(mv_name, from, mv_len); | ||
135 | mv_name[mv_len] = '\0'; | ||
136 | from = mv_end; | ||
137 | |||
138 | *mvp = get_mv_byname(mv_name); | ||
139 | } | ||
140 | |||
141 | c = *(from++); | ||
142 | if (!c) | ||
143 | break; | ||
144 | if (COMMAND_LINE_SIZE <= ++len) | ||
145 | break; | ||
146 | *(to++) = c; | ||
147 | } | ||
148 | *to = '\0'; | ||
149 | *cmdline_p = command_line; | ||
150 | } | ||
151 | |||
152 | static int __init sh_mv_setup(char **cmdline_p) | ||
153 | { | ||
154 | #ifdef CONFIG_SH_UNKNOWN | ||
155 | extern struct sh_machine_vector mv_unknown; | ||
156 | #endif | ||
157 | struct sh_machine_vector *mv = NULL; | ||
158 | char mv_name[MV_NAME_SIZE] = ""; | ||
159 | unsigned long mv_io_base = 0; | ||
160 | |||
161 | parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base); | ||
162 | |||
163 | #ifdef CONFIG_SH_UNKNOWN | ||
164 | if (mv == NULL) { | ||
165 | mv = &mv_unknown; | ||
166 | if (*mv_name != '\0') { | ||
167 | printk("Warning: Unsupported machine %s, using unknown\n", | ||
168 | mv_name); | ||
169 | } | ||
170 | } | ||
171 | sh_mv = *mv; | ||
172 | #endif | ||
173 | |||
174 | /* | ||
175 | * Manually walk the vec, fill in anything that the board hasn't yet | ||
176 | * by hand, wrapping to the generic implementation. | ||
177 | */ | ||
178 | #define mv_set(elem) do { \ | ||
179 | if (!sh_mv.mv_##elem) \ | ||
180 | sh_mv.mv_##elem = generic_##elem; \ | ||
181 | } while (0) | ||
182 | |||
183 | mv_set(inb); mv_set(inw); mv_set(inl); | ||
184 | mv_set(outb); mv_set(outw); mv_set(outl); | ||
185 | |||
186 | mv_set(inb_p); mv_set(inw_p); mv_set(inl_p); | ||
187 | mv_set(outb_p); mv_set(outw_p); mv_set(outl_p); | ||
188 | |||
189 | mv_set(insb); mv_set(insw); mv_set(insl); | ||
190 | mv_set(outsb); mv_set(outsw); mv_set(outsl); | ||
191 | |||
192 | mv_set(readb); mv_set(readw); mv_set(readl); | ||
193 | mv_set(writeb); mv_set(writew); mv_set(writel); | ||
194 | |||
195 | mv_set(ioport_map); | ||
196 | mv_set(ioport_unmap); | ||
197 | mv_set(irq_demux); | ||
198 | |||
199 | #ifdef CONFIG_SH_UNKNOWN | ||
200 | __set_io_port_base(mv_io_base); | ||
201 | #endif | ||
202 | |||
203 | if (!sh_mv.mv_nr_irqs) | ||
204 | sh_mv.mv_nr_irqs = NR_IRQS; | ||
205 | 90 | ||
206 | return 0; | 91 | return 0; |
207 | } | 92 | } |
93 | early_param("mem", early_parse_mem); | ||
208 | 94 | ||
209 | /* | 95 | /* |
210 | * Register fully available low RAM pages with the bootmem allocator. | 96 | * Register fully available low RAM pages with the bootmem allocator. |
@@ -230,7 +116,7 @@ static void __init register_bootmem_low_pages(void) | |||
230 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); | 116 | free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); |
231 | } | 117 | } |
232 | 118 | ||
233 | void __init setup_bootmem_allocator(unsigned long start_pfn) | 119 | void __init setup_bootmem_allocator(unsigned long free_pfn) |
234 | { | 120 | { |
235 | unsigned long bootmap_size; | 121 | unsigned long bootmap_size; |
236 | 122 | ||
@@ -239,9 +125,10 @@ void __init setup_bootmem_allocator(unsigned long start_pfn) | |||
239 | * bootstrap step all allocations (until the page allocator | 125 | * bootstrap step all allocations (until the page allocator |
240 | * is intact) must be done via bootmem_alloc(). | 126 | * is intact) must be done via bootmem_alloc(). |
241 | */ | 127 | */ |
242 | bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, | 128 | bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn, |
243 | min_low_pfn, max_low_pfn); | 129 | min_low_pfn, max_low_pfn); |
244 | 130 | ||
131 | add_active_range(0, min_low_pfn, max_low_pfn); | ||
245 | register_bootmem_low_pages(); | 132 | register_bootmem_low_pages(); |
246 | 133 | ||
247 | node_set_online(0); | 134 | node_set_online(0); |
@@ -254,7 +141,7 @@ void __init setup_bootmem_allocator(unsigned long start_pfn) | |||
254 | * an invalid RAM area. | 141 | * an invalid RAM area. |
255 | */ | 142 | */ |
256 | reserve_bootmem(__MEMORY_START+PAGE_SIZE, | 143 | reserve_bootmem(__MEMORY_START+PAGE_SIZE, |
257 | (PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); | 144 | (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START); |
258 | 145 | ||
259 | /* | 146 | /* |
260 | * reserve physical page 0 - it's a special BIOS page on many boxes, | 147 | * reserve physical page 0 - it's a special BIOS page on many boxes, |
@@ -262,6 +149,8 @@ void __init setup_bootmem_allocator(unsigned long start_pfn) | |||
262 | */ | 149 | */ |
263 | reserve_bootmem(__MEMORY_START, PAGE_SIZE); | 150 | reserve_bootmem(__MEMORY_START, PAGE_SIZE); |
264 | 151 | ||
152 | sparse_memory_present_with_active_regions(0); | ||
153 | |||
265 | #ifdef CONFIG_BLK_DEV_INITRD | 154 | #ifdef CONFIG_BLK_DEV_INITRD |
266 | ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); | 155 | ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); |
267 | if (&__rd_start != &__rd_end) { | 156 | if (&__rd_start != &__rd_end) { |
@@ -315,10 +204,6 @@ void __init setup_arch(char **cmdline_p) | |||
315 | { | 204 | { |
316 | enable_mmu(); | 205 | enable_mmu(); |
317 | 206 | ||
318 | #ifdef CONFIG_CMDLINE_BOOL | ||
319 | strcpy(COMMAND_LINE, CONFIG_CMDLINE); | ||
320 | #endif | ||
321 | |||
322 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); | 207 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); |
323 | 208 | ||
324 | #ifdef CONFIG_BLK_DEV_RAM | 209 | #ifdef CONFIG_BLK_DEV_RAM |
@@ -339,9 +224,22 @@ void __init setup_arch(char **cmdline_p) | |||
339 | data_resource.start = virt_to_phys(_etext); | 224 | data_resource.start = virt_to_phys(_etext); |
340 | data_resource.end = virt_to_phys(_edata)-1; | 225 | data_resource.end = virt_to_phys(_edata)-1; |
341 | 226 | ||
227 | memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; | ||
228 | memory_end = memory_start + __MEMORY_SIZE; | ||
229 | |||
230 | #ifdef CONFIG_CMDLINE_BOOL | ||
231 | strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); | ||
232 | #else | ||
233 | strlcpy(command_line, COMMAND_LINE, sizeof(command_line)); | ||
234 | #endif | ||
235 | |||
236 | /* Save unparsed command line copy for /proc/cmdline */ | ||
237 | memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); | ||
238 | *cmdline_p = command_line; | ||
239 | |||
342 | parse_early_param(); | 240 | parse_early_param(); |
343 | 241 | ||
344 | sh_mv_setup(cmdline_p); | 242 | sh_mv_setup(); |
345 | 243 | ||
346 | /* | 244 | /* |
347 | * Find the highest page frame number we have available | 245 | * Find the highest page frame number we have available |
@@ -355,8 +253,9 @@ void __init setup_arch(char **cmdline_p) | |||
355 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; | 253 | min_low_pfn = __MEMORY_START >> PAGE_SHIFT; |
356 | 254 | ||
357 | nodes_clear(node_online_map); | 255 | nodes_clear(node_online_map); |
256 | |||
257 | /* Setup bootmem with available RAM */ | ||
358 | setup_memory(); | 258 | setup_memory(); |
359 | paging_init(); | ||
360 | sparse_init(); | 259 | sparse_init(); |
361 | 260 | ||
362 | #ifdef CONFIG_DUMMY_CONSOLE | 261 | #ifdef CONFIG_DUMMY_CONSOLE |
@@ -366,46 +265,13 @@ void __init setup_arch(char **cmdline_p) | |||
366 | /* Perform the machine specific initialisation */ | 265 | /* Perform the machine specific initialisation */ |
367 | if (likely(sh_mv.mv_setup)) | 266 | if (likely(sh_mv.mv_setup)) |
368 | sh_mv.mv_setup(cmdline_p); | 267 | sh_mv.mv_setup(cmdline_p); |
369 | } | ||
370 | |||
371 | struct sh_machine_vector* __init get_mv_byname(const char* name) | ||
372 | { | ||
373 | extern long __machvec_start, __machvec_end; | ||
374 | struct sh_machine_vector *all_vecs = | ||
375 | (struct sh_machine_vector *)&__machvec_start; | ||
376 | |||
377 | int i, n = ((unsigned long)&__machvec_end | ||
378 | - (unsigned long)&__machvec_start)/ | ||
379 | sizeof(struct sh_machine_vector); | ||
380 | |||
381 | for (i = 0; i < n; ++i) { | ||
382 | struct sh_machine_vector *mv = &all_vecs[i]; | ||
383 | if (mv == NULL) | ||
384 | continue; | ||
385 | if (strcasecmp(name, get_system_type()) == 0) { | ||
386 | return mv; | ||
387 | } | ||
388 | } | ||
389 | return NULL; | ||
390 | } | ||
391 | |||
392 | static struct cpu cpu[NR_CPUS]; | ||
393 | |||
394 | static int __init topology_init(void) | ||
395 | { | ||
396 | int cpu_id; | ||
397 | 268 | ||
398 | for_each_possible_cpu(cpu_id) | 269 | paging_init(); |
399 | register_cpu(&cpu[cpu_id], cpu_id); | ||
400 | |||
401 | return 0; | ||
402 | } | 270 | } |
403 | 271 | ||
404 | subsys_initcall(topology_init); | ||
405 | |||
406 | static const char *cpu_name[] = { | 272 | static const char *cpu_name[] = { |
407 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", | 273 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", |
408 | [CPU_SH7604] = "SH7604", [CPU_SH7300] = "SH7300", | 274 | [CPU_SH7300] = "SH7300", |
409 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", | 275 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", |
410 | [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", | 276 | [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", |
411 | [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710", | 277 | [CPU_SH7709] = "SH7709", [CPU_SH7710] = "SH7710", |
@@ -419,7 +285,7 @@ static const char *cpu_name[] = { | |||
419 | [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", | 285 | [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", |
420 | [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", | 286 | [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", |
421 | [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", | 287 | [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", |
422 | [CPU_SH_NONE] = "Unknown" | 288 | [CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown" |
423 | }; | 289 | }; |
424 | 290 | ||
425 | const char *get_cpu_subtype(struct sh_cpuinfo *c) | 291 | const char *get_cpu_subtype(struct sh_cpuinfo *c) |
diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index c1cfcb9f047c..c968dcf09eee 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c | |||
@@ -78,6 +78,16 @@ DECLARE_EXPORT(__movstr); | |||
78 | DECLARE_EXPORT(__movmem_i4_even); | 78 | DECLARE_EXPORT(__movmem_i4_even); |
79 | DECLARE_EXPORT(__movmem_i4_odd); | 79 | DECLARE_EXPORT(__movmem_i4_odd); |
80 | DECLARE_EXPORT(__movmemSI12_i4); | 80 | DECLARE_EXPORT(__movmemSI12_i4); |
81 | |||
82 | #if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__)) | ||
83 | /* | ||
84 | * GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST | ||
85 | * compiler which include backported patches. | ||
86 | */ | ||
87 | DECLARE_EXPORT(__sdivsi3_i4i); | ||
88 | DECLARE_EXPORT(__udiv_qrnnd_16); | ||
89 | DECLARE_EXPORT(__udivsi3_i4i); | ||
90 | #endif | ||
81 | #else /* GCC 3.x */ | 91 | #else /* GCC 3.x */ |
82 | DECLARE_EXPORT(__movstr_i4_even); | 92 | DECLARE_EXPORT(__movstr_i4_even); |
83 | DECLARE_EXPORT(__movstr_i4_odd); | 93 | DECLARE_EXPORT(__movstr_i4_odd); |
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index e323e299878b..706d81ccd101 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/personality.h> | 23 | #include <linux/personality.h> |
24 | #include <linux/binfmts.h> | 24 | #include <linux/binfmts.h> |
25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
26 | #include <linux/io.h> | ||
26 | #include <asm/system.h> | 27 | #include <asm/system.h> |
27 | #include <asm/ucontext.h> | 28 | #include <asm/ucontext.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
@@ -261,7 +262,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, | |||
261 | goto badframe; | 262 | goto badframe; |
262 | /* It is more difficult to avoid calling this function than to | 263 | /* It is more difficult to avoid calling this function than to |
263 | call it and ignore errors. */ | 264 | call it and ignore errors. */ |
264 | do_sigaltstack(&st, NULL, regs->regs[15]); | 265 | do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame); |
265 | 266 | ||
266 | return r0; | 267 | return r0; |
267 | 268 | ||
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S index 7db1c2dc5992..ff5656e60c05 100644 --- a/arch/sh/kernel/syscalls.S +++ b/arch/sh/kernel/syscalls.S | |||
@@ -308,9 +308,9 @@ ENTRY(sys_call_table) | |||
308 | .long sys_utimes | 308 | .long sys_utimes |
309 | .long sys_fadvise64_64_wrapper | 309 | .long sys_fadvise64_64_wrapper |
310 | .long sys_ni_syscall /* Reserved for vserver */ | 310 | .long sys_ni_syscall /* Reserved for vserver */ |
311 | .long sys_ni_syscall /* Reserved for mbind */ | 311 | .long sys_mbind |
312 | .long sys_ni_syscall /* 275 - get_mempolicy */ | 312 | .long sys_get_mempolicy /* 275 */ |
313 | .long sys_ni_syscall /* set_mempolicy */ | 313 | .long sys_set_mempolicy |
314 | .long sys_mq_open | 314 | .long sys_mq_open |
315 | .long sys_mq_unlink | 315 | .long sys_mq_unlink |
316 | .long sys_mq_timedsend | 316 | .long sys_mq_timedsend |
diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 2d997e2a5b6c..097ebd49f1bf 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | static int tmu_timer_start(void) | 31 | static int tmu_timer_start(void) |
32 | { | 32 | { |
33 | ctrl_outb(ctrl_inb(TMU_TSTR) | 0x3, TMU_TSTR); | 33 | ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR); |
34 | return 0; | 34 | return 0; |
35 | } | 35 | } |
36 | 36 | ||
@@ -52,7 +52,7 @@ static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload) | |||
52 | 52 | ||
53 | static int tmu_timer_stop(void) | 53 | static int tmu_timer_stop(void) |
54 | { | 54 | { |
55 | ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x3, TMU_TSTR); | 55 | ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR); |
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
58 | 58 | ||
@@ -174,7 +174,8 @@ static int tmu_timer_init(void) | |||
174 | 174 | ||
175 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ | 175 | #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && \ |
176 | !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ | 176 | !defined(CONFIG_CPU_SUBTYPE_SH7760) && \ |
177 | !defined(CONFIG_CPU_SUBTYPE_SH7785) | 177 | !defined(CONFIG_CPU_SUBTYPE_SH7785) && \ |
178 | !defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
178 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); | 179 | ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); |
179 | #endif | 180 | #endif |
180 | 181 | ||
diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c new file mode 100644 index 000000000000..9b5844a1bdaa --- /dev/null +++ b/arch/sh/kernel/topology.c | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/topology.c | ||
3 | * | ||
4 | * Copyright (C) 2007 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/cpu.h> | ||
11 | #include <linux/cpumask.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/percpu.h> | ||
14 | #include <linux/node.h> | ||
15 | #include <linux/nodemask.h> | ||
16 | |||
17 | static DEFINE_PER_CPU(struct cpu, cpu_devices); | ||
18 | |||
19 | static int __init topology_init(void) | ||
20 | { | ||
21 | int i, ret; | ||
22 | |||
23 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
24 | for_each_online_node(i) | ||
25 | register_one_node(i); | ||
26 | #endif | ||
27 | |||
28 | for_each_present_cpu(i) { | ||
29 | ret = register_cpu(&per_cpu(cpu_devices, i), i); | ||
30 | if (unlikely(ret)) | ||
31 | printk(KERN_WARNING "%s: register_cpu %d failed (%d)\n", | ||
32 | __FUNCTION__, i, ret); | ||
33 | } | ||
34 | |||
35 | #if defined(CONFIG_NUMA) && !defined(CONFIG_SMP) | ||
36 | /* | ||
37 | * In the UP case, make sure the CPU association is still | ||
38 | * registered under each node. Without this, sysfs fails | ||
39 | * to make the connection between nodes other than node0 | ||
40 | * and cpu0. | ||
41 | */ | ||
42 | for_each_online_node(i) | ||
43 | if (i != numa_node_id()) | ||
44 | register_cpu_under_node(raw_smp_processor_id(), i); | ||
45 | #endif | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | subsys_initcall(topology_init); | ||
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 09480887076b..05a40f3c30bf 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c | |||
@@ -584,7 +584,7 @@ uspace_segv: | |||
584 | info.si_signo = SIGBUS; | 584 | info.si_signo = SIGBUS; |
585 | info.si_errno = 0; | 585 | info.si_errno = 0; |
586 | info.si_code = si_code; | 586 | info.si_code = si_code; |
587 | info.si_addr = (void *) address; | 587 | info.si_addr = (void __user *)address; |
588 | force_sig_info(SIGBUS, &info, current); | 588 | force_sig_info(SIGBUS, &info, current); |
589 | } else { | 589 | } else { |
590 | if (regs->pc & 1) | 590 | if (regs->pc & 1) |
@@ -617,7 +617,7 @@ uspace_segv: | |||
617 | */ | 617 | */ |
618 | int is_dsp_inst(struct pt_regs *regs) | 618 | int is_dsp_inst(struct pt_regs *regs) |
619 | { | 619 | { |
620 | unsigned short inst; | 620 | unsigned short inst = 0; |
621 | 621 | ||
622 | /* | 622 | /* |
623 | * Safe guard if DSP mode is already enabled or we're lacking | 623 | * Safe guard if DSP mode is already enabled or we're lacking |
@@ -645,7 +645,6 @@ asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, | |||
645 | unsigned long r6, unsigned long r7, | 645 | unsigned long r6, unsigned long r7, |
646 | struct pt_regs __regs) | 646 | struct pt_regs __regs) |
647 | { | 647 | { |
648 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
649 | siginfo_t info; | 648 | siginfo_t info; |
650 | 649 | ||
651 | switch (r4) { | 650 | switch (r4) { |
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 4c5b57e9c3c1..0696402f446a 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S | |||
@@ -97,18 +97,20 @@ SECTIONS | |||
97 | __initramfs_end = .; | 97 | __initramfs_end = .; |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | . = ALIGN(4); | ||
100 | __machvec_start = .; | 101 | __machvec_start = .; |
101 | .init.machvec : { *(.init.machvec) } | 102 | .machvec.init : { *(.machvec.init) } |
102 | __machvec_end = .; | 103 | __machvec_end = .; |
103 | . = ALIGN(PAGE_SIZE); | ||
104 | __init_end = .; | ||
105 | |||
106 | . = ALIGN(4); | ||
107 | __bss_start = .; /* BSS */ | ||
108 | .bss : { *(.bss) } | ||
109 | 104 | ||
110 | . = ALIGN(4); | 105 | . = ALIGN(PAGE_SIZE); |
111 | _end = . ; | 106 | .bss : { |
107 | __init_end = .; | ||
108 | __bss_start = .; /* BSS */ | ||
109 | *(.bss.page_aligned) | ||
110 | *(.bss) | ||
111 | . = ALIGN(4); | ||
112 | _end = . ; | ||
113 | } | ||
112 | 114 | ||
113 | /* When something in the kernel is NOT compiled as a module, the | 115 | /* When something in the kernel is NOT compiled as a module, the |
114 | * module cleanup code and data are put into these segments. Both | 116 | * module cleanup code and data are put into these segments. Both |