diff options
Diffstat (limited to 'arch/sh/kernel')
26 files changed, 658 insertions, 289 deletions
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index c89289831053..62bf373266f7 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 | |||
@@ -22,5 +22,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | |||
22 | obj-$(CONFIG_PM) += pm.o | 22 | obj-$(CONFIG_PM) += pm.o |
23 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 23 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
24 | obj-$(CONFIG_BINFMT_ELF) += dump_task.o | 24 | obj-$(CONFIG_BINFMT_ELF) += dump_task.o |
25 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o | ||
25 | 26 | ||
26 | EXTRA_CFLAGS += -Werror | 27 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index 1ef21cc087f3..e01283d49cbf 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 | |||
@@ -18,5 +18,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | |||
18 | obj-$(CONFIG_PM) += pm.o | 18 | obj-$(CONFIG_PM) += pm.o |
19 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 19 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
20 | obj-$(CONFIG_BINFMT_ELF) += dump_task.o | 20 | obj-$(CONFIG_BINFMT_ELF) += dump_task.o |
21 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o | ||
21 | 22 | ||
22 | EXTRA_CFLAGS += -Werror | 23 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile index cc1836e47a5d..462a8f6dfee2 100644 --- a/arch/sh/kernel/cpu/irq/Makefile +++ b/arch/sh/kernel/cpu/irq/Makefile | |||
@@ -6,4 +6,3 @@ obj-y += intc.o | |||
6 | obj-$(CONFIG_SUPERH32) += imask.o | 6 | obj-$(CONFIG_SUPERH32) += imask.o |
7 | obj-$(CONFIG_CPU_SH5) += intc-sh5.o | 7 | obj-$(CONFIG_CPU_SH5) += intc-sh5.o |
8 | obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o | 8 | obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o |
9 | obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o | ||
diff --git a/arch/sh/kernel/cpu/irq/intc-sh5.c b/arch/sh/kernel/cpu/irq/intc-sh5.c index 43ee7a9a4f0b..d6e0e2bdaad5 100644 --- a/arch/sh/kernel/cpu/irq/intc-sh5.c +++ b/arch/sh/kernel/cpu/irq/intc-sh5.c | |||
@@ -75,21 +75,6 @@ int intc_evt_to_irq[(0xE20/0x20)+1] = { | |||
75 | -1, -1 /* 0xE00 - 0xE20 */ | 75 | -1, -1 /* 0xE00 - 0xE20 */ |
76 | }; | 76 | }; |
77 | 77 | ||
78 | /* | ||
79 | * Opposite mapper. | ||
80 | */ | ||
81 | static int IRQ_to_vectorN[NR_INTC_IRQS] = { | ||
82 | 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ | ||
83 | -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ | ||
84 | 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ | ||
85 | -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ | ||
86 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ | ||
87 | 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ | ||
88 | -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ | ||
89 | -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ | ||
90 | |||
91 | }; | ||
92 | |||
93 | static unsigned long intc_virt; | 78 | static unsigned long intc_virt; |
94 | 79 | ||
95 | static unsigned int startup_intc_irq(unsigned int irq); | 80 | static unsigned int startup_intc_irq(unsigned int irq); |
@@ -176,6 +161,18 @@ void make_intc_irq(unsigned int irq) | |||
176 | } | 161 | } |
177 | 162 | ||
178 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) | 163 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) |
164 | static int IRQ_to_vectorN[NR_INTC_IRQS] = { | ||
165 | 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ | ||
166 | -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ | ||
167 | 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ | ||
168 | -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ | ||
169 | 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ | ||
170 | 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ | ||
171 | -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ | ||
172 | -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ | ||
173 | |||
174 | }; | ||
175 | |||
179 | int intc_irq_describe(char* p, int irq) | 176 | int intc_irq_describe(char* p, int irq) |
180 | { | 177 | { |
181 | if (irq < NR_INTC_IRQS) | 178 | if (irq < NR_INTC_IRQS) |
diff --git a/arch/sh/kernel/cpu/irq/maskreg.c b/arch/sh/kernel/cpu/irq/maskreg.c deleted file mode 100644 index 978992e367a5..000000000000 --- a/arch/sh/kernel/cpu/irq/maskreg.c +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | /* | ||
2 | * Interrupt handling for Simple external interrupt mask register | ||
3 | * | ||
4 | * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp> | ||
5 | * | ||
6 | * This is for the machine which have single 16 bit register | ||
7 | * for masking external IRQ individually. | ||
8 | * Each bit of the register is for masking each interrupt. | ||
9 | * | ||
10 | * This file may be copied or modified under the terms of the GNU | ||
11 | * General Public License. See linux/COPYING for more information. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/io.h> | ||
18 | |||
19 | /* address of external interrupt mask register */ | ||
20 | unsigned long irq_mask_register; | ||
21 | |||
22 | /* forward declaration */ | ||
23 | static unsigned int startup_maskreg_irq(unsigned int irq); | ||
24 | static void shutdown_maskreg_irq(unsigned int irq); | ||
25 | static void enable_maskreg_irq(unsigned int irq); | ||
26 | static void disable_maskreg_irq(unsigned int irq); | ||
27 | static void mask_and_ack_maskreg(unsigned int); | ||
28 | static void end_maskreg_irq(unsigned int irq); | ||
29 | |||
30 | /* hw_interrupt_type */ | ||
31 | static struct hw_interrupt_type maskreg_irq_type = { | ||
32 | .typename = "Mask Register", | ||
33 | .startup = startup_maskreg_irq, | ||
34 | .shutdown = shutdown_maskreg_irq, | ||
35 | .enable = enable_maskreg_irq, | ||
36 | .disable = disable_maskreg_irq, | ||
37 | .ack = mask_and_ack_maskreg, | ||
38 | .end = end_maskreg_irq | ||
39 | }; | ||
40 | |||
41 | /* actual implementation */ | ||
42 | static unsigned int startup_maskreg_irq(unsigned int irq) | ||
43 | { | ||
44 | enable_maskreg_irq(irq); | ||
45 | return 0; /* never anything pending */ | ||
46 | } | ||
47 | |||
48 | static void shutdown_maskreg_irq(unsigned int irq) | ||
49 | { | ||
50 | disable_maskreg_irq(irq); | ||
51 | } | ||
52 | |||
53 | static void disable_maskreg_irq(unsigned int irq) | ||
54 | { | ||
55 | unsigned short val, mask = 0x01 << irq; | ||
56 | |||
57 | BUG_ON(!irq_mask_register); | ||
58 | |||
59 | /* Set "irq"th bit */ | ||
60 | val = ctrl_inw(irq_mask_register); | ||
61 | val |= mask; | ||
62 | ctrl_outw(val, irq_mask_register); | ||
63 | } | ||
64 | |||
65 | static void enable_maskreg_irq(unsigned int irq) | ||
66 | { | ||
67 | unsigned short val, mask = ~(0x01 << irq); | ||
68 | |||
69 | BUG_ON(!irq_mask_register); | ||
70 | |||
71 | /* Clear "irq"th bit */ | ||
72 | val = ctrl_inw(irq_mask_register); | ||
73 | val &= mask; | ||
74 | ctrl_outw(val, irq_mask_register); | ||
75 | } | ||
76 | |||
77 | static void mask_and_ack_maskreg(unsigned int irq) | ||
78 | { | ||
79 | disable_maskreg_irq(irq); | ||
80 | } | ||
81 | |||
82 | static void end_maskreg_irq(unsigned int irq) | ||
83 | { | ||
84 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
85 | enable_maskreg_irq(irq); | ||
86 | } | ||
87 | |||
88 | void make_maskreg_irq(unsigned int irq) | ||
89 | { | ||
90 | disable_irq_nosync(irq); | ||
91 | irq_desc[irq].handler = &maskreg_irq_type; | ||
92 | disable_maskreg_irq(irq); | ||
93 | } | ||
diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index f2b9238cda04..9e89984c4f1d 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c | |||
@@ -126,12 +126,18 @@ int __init detect_cpu_and_cache_system(void) | |||
126 | CPU_HAS_LLSC; | 126 | CPU_HAS_LLSC; |
127 | break; | 127 | break; |
128 | case 0x3008: | 128 | case 0x3008: |
129 | if (prr == 0xa0) { | 129 | if (prr == 0xa0 || prr == 0xa1) { |
130 | boot_cpu_data.type = CPU_SH7722; | 130 | boot_cpu_data.type = CPU_SH7722; |
131 | boot_cpu_data.icache.ways = 4; | 131 | boot_cpu_data.icache.ways = 4; |
132 | boot_cpu_data.dcache.ways = 4; | 132 | boot_cpu_data.dcache.ways = 4; |
133 | boot_cpu_data.flags |= CPU_HAS_LLSC; | 133 | boot_cpu_data.flags |= CPU_HAS_LLSC; |
134 | } | 134 | } |
135 | else if (prr == 0x70) { | ||
136 | boot_cpu_data.type = CPU_SH7366; | ||
137 | boot_cpu_data.icache.ways = 4; | ||
138 | boot_cpu_data.dcache.ways = 4; | ||
139 | boot_cpu_data.flags |= CPU_HAS_LLSC; | ||
140 | } | ||
135 | break; | 141 | break; |
136 | case 0x4000: /* 1st cut */ | 142 | case 0x4000: /* 1st cut */ |
137 | case 0x4001: /* 2nd cut */ | 143 | case 0x4001: /* 2nd cut */ |
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 08ac6387bf17..5d890ac8e793 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o | |||
9 | obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o | 9 | obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.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_SH7366) += setup-sh7366.o | ||
12 | obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o | 13 | obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o |
13 | 14 | ||
14 | # SMP setup | 15 | # SMP setup |
@@ -21,6 +22,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o | |||
21 | clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o | 22 | clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o |
22 | clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o | 23 | clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o |
23 | clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o | 24 | clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o |
25 | clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o | ||
24 | clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o | 26 | clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o |
25 | 27 | ||
26 | obj-y += $(clock-y) | 28 | obj-y += $(clock-y) |
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index a0fd8bb21f7c..299138ebe160 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 2 | * arch/sh/kernel/cpu/sh4a/clock-sh7722.c |
3 | * | 3 | * |
4 | * SH7722 support for the clock framework | 4 | * SH7722 & SH7366 support for the clock framework |
5 | * | 5 | * |
6 | * Copyright (c) 2006-2007 Nomad Global Solutions Inc | 6 | * Copyright (c) 2006-2007 Nomad Global Solutions Inc |
7 | * Based on code for sh7343 by Paul Mundt | 7 | * Based on code for sh7343 by Paul Mundt |
@@ -417,15 +417,19 @@ static int sh7722_siu_which(struct clk *clk) | |||
417 | return 0; | 417 | return 0; |
418 | if (!strcmp(clk->name, "siu_b_clk")) | 418 | if (!strcmp(clk->name, "siu_b_clk")) |
419 | return 1; | 419 | return 1; |
420 | #if defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
420 | if (!strcmp(clk->name, "irda_clk")) | 421 | if (!strcmp(clk->name, "irda_clk")) |
421 | return 2; | 422 | return 2; |
423 | #endif | ||
422 | return -EINVAL; | 424 | return -EINVAL; |
423 | } | 425 | } |
424 | 426 | ||
425 | static unsigned long sh7722_siu_regs[] = { | 427 | static unsigned long sh7722_siu_regs[] = { |
426 | [0] = SCLKACR, | 428 | [0] = SCLKACR, |
427 | [1] = SCLKBCR, | 429 | [1] = SCLKBCR, |
430 | #if defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
428 | [2] = IrDACLKCR, | 431 | [2] = IrDACLKCR, |
432 | #endif | ||
429 | }; | 433 | }; |
430 | 434 | ||
431 | static int sh7722_siu_start_stop(struct clk *clk, int enable) | 435 | static int sh7722_siu_start_stop(struct clk *clk, int enable) |
@@ -571,10 +575,12 @@ static struct clk sh7722_siu_b_clock = { | |||
571 | .ops = &sh7722_siu_clk_ops, | 575 | .ops = &sh7722_siu_clk_ops, |
572 | }; | 576 | }; |
573 | 577 | ||
578 | #if defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
574 | static struct clk sh7722_irda_clock = { | 579 | static struct clk sh7722_irda_clock = { |
575 | .name = "irda_clk", | 580 | .name = "irda_clk", |
576 | .ops = &sh7722_siu_clk_ops, | 581 | .ops = &sh7722_siu_clk_ops, |
577 | }; | 582 | }; |
583 | #endif | ||
578 | 584 | ||
579 | static struct clk sh7722_video_clock = { | 585 | static struct clk sh7722_video_clock = { |
580 | .name = "video_clk", | 586 | .name = "video_clk", |
@@ -588,7 +594,9 @@ static struct clk *sh7722_clocks[] = { | |||
588 | &sh7722_sdram_clock, | 594 | &sh7722_sdram_clock, |
589 | &sh7722_siu_a_clock, | 595 | &sh7722_siu_a_clock, |
590 | &sh7722_siu_b_clock, | 596 | &sh7722_siu_b_clock, |
597 | #if defined(CONFIG_CPU_SUBTYPE_SH7722) | ||
591 | &sh7722_irda_clock, | 598 | &sh7722_irda_clock, |
599 | #endif | ||
592 | &sh7722_video_clock, | 600 | &sh7722_video_clock, |
593 | }; | 601 | }; |
594 | 602 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c new file mode 100644 index 000000000000..967e8b69a2f8 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * SH7366 Setup | ||
3 | * | ||
4 | * Copyright (C) 2008 Renesas Solutions | ||
5 | * | ||
6 | * Based on linux/arch/sh/kernel/cpu/sh4a/setup-sh7722.c | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/serial.h> | ||
15 | #include <asm/sci.h> | ||
16 | |||
17 | static struct plat_sci_port sci_platform_data[] = { | ||
18 | { | ||
19 | .mapbase = 0xffe00000, | ||
20 | .flags = UPF_BOOT_AUTOCONF, | ||
21 | .type = PORT_SCIF, | ||
22 | .irqs = { 80, 80, 80, 80 }, | ||
23 | }, { | ||
24 | .flags = 0, | ||
25 | } | ||
26 | }; | ||
27 | |||
28 | static struct platform_device sci_device = { | ||
29 | .name = "sh-sci", | ||
30 | .id = -1, | ||
31 | .dev = { | ||
32 | .platform_data = sci_platform_data, | ||
33 | }, | ||
34 | }; | ||
35 | |||
36 | static struct platform_device *sh7366_devices[] __initdata = { | ||
37 | &sci_device, | ||
38 | }; | ||
39 | |||
40 | static int __init sh7366_devices_setup(void) | ||
41 | { | ||
42 | return platform_add_devices(sh7366_devices, | ||
43 | ARRAY_SIZE(sh7366_devices)); | ||
44 | } | ||
45 | __initcall(sh7366_devices_setup); | ||
46 | |||
47 | enum { | ||
48 | UNUSED=0, | ||
49 | |||
50 | /* interrupt sources */ | ||
51 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, | ||
52 | ICB, | ||
53 | DMAC0, DMAC1, DMAC2, DMAC3, | ||
54 | VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU, | ||
55 | MFI, VPU, USB, | ||
56 | MMC_MMC1I, MMC_MMC2I, MMC_MMC3I, | ||
57 | DMAC4, DMAC5, DMAC_DADERR, | ||
58 | SCIF, SCIFA1, SCIFA2, | ||
59 | DENC, MSIOF, | ||
60 | FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, | ||
61 | I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI, | ||
62 | SDHI0, SDHI1, SDHI2, SDHI3, | ||
63 | CMT, TSIF, SIU, | ||
64 | TMU0, TMU1, TMU2, | ||
65 | VEU2, LCDC, | ||
66 | |||
67 | /* interrupt groups */ | ||
68 | |||
69 | DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C, SDHI, | ||
70 | }; | ||
71 | |||
72 | static struct intc_vect vectors[] __initdata = { | ||
73 | INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), | ||
74 | INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), | ||
75 | INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), | ||
76 | INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0), | ||
77 | INTC_VECT(ICB, 0x700), | ||
78 | INTC_VECT(DMAC0, 0x800), INTC_VECT(DMAC1, 0x820), | ||
79 | INTC_VECT(DMAC2, 0x840), INTC_VECT(DMAC3, 0x860), | ||
80 | INTC_VECT(VIO_CEUI, 0x880), INTC_VECT(VIO_BEUI, 0x8a0), | ||
81 | INTC_VECT(VIO_VEUI, 0x8c0), INTC_VECT(VOU, 0x8e0), | ||
82 | INTC_VECT(MFI, 0x900), INTC_VECT(VPU, 0x980), INTC_VECT(USB, 0xa20), | ||
83 | INTC_VECT(MMC_MMC1I, 0xb00), INTC_VECT(MMC_MMC2I, 0xb20), | ||
84 | INTC_VECT(MMC_MMC3I, 0xb40), | ||
85 | INTC_VECT(DMAC4, 0xb80), INTC_VECT(DMAC5, 0xba0), | ||
86 | INTC_VECT(DMAC_DADERR, 0xbc0), | ||
87 | INTC_VECT(SCIF, 0xc00), INTC_VECT(SCIFA1, 0xc20), | ||
88 | INTC_VECT(SCIFA2, 0xc40), | ||
89 | INTC_VECT(DENC, 0xc60), INTC_VECT(MSIOF, 0xc80), | ||
90 | INTC_VECT(FLCTL_FLSTEI, 0xd80), INTC_VECT(FLCTL_FLENDI, 0xda0), | ||
91 | INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0), | ||
92 | INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20), | ||
93 | INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60), | ||
94 | INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0), | ||
95 | INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0), | ||
96 | INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20), | ||
97 | INTC_VECT(SIU, 0xf80), | ||
98 | INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), | ||
99 | INTC_VECT(TMU2, 0x440), | ||
100 | INTC_VECT(VEU2, 0x580), INTC_VECT(LCDC, 0x580), | ||
101 | }; | ||
102 | |||
103 | static struct intc_group groups[] __initdata = { | ||
104 | INTC_GROUP(DMAC0123, DMAC0, DMAC1, DMAC2, DMAC3), | ||
105 | INTC_GROUP(VIOVOU, VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU), | ||
106 | INTC_GROUP(MMC, MMC_MMC1I, MMC_MMC2I, MMC_MMC3I), | ||
107 | INTC_GROUP(DMAC45, DMAC4, DMAC5, DMAC_DADERR), | ||
108 | INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI, | ||
109 | FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), | ||
110 | INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI), | ||
111 | INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3), | ||
112 | }; | ||
113 | |||
114 | static struct intc_mask_reg mask_registers[] __initdata = { | ||
115 | { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ | ||
116 | { } }, | ||
117 | { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ | ||
118 | { VOU, VIO_VEUI, VIO_BEUI, VIO_CEUI, DMAC3, DMAC2, DMAC1, DMAC0 } }, | ||
119 | { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */ | ||
120 | { 0, 0, 0, VPU, 0, 0, 0, MFI } }, | ||
121 | { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */ | ||
122 | { 0, 0, 0, ICB } }, | ||
123 | { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */ | ||
124 | { 0, TMU2, TMU1, TMU0, VEU2, 0, 0, LCDC } }, | ||
125 | { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */ | ||
126 | { 0, DMAC_DADERR, DMAC5, DMAC4, DENC, SCIFA2, SCIFA1, SCIF } }, | ||
127 | { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */ | ||
128 | { 0, 0, 0, 0, 0, 0, 0, MSIOF } }, | ||
129 | { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */ | ||
130 | { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, | ||
131 | FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } }, | ||
132 | { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ | ||
133 | { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } }, | ||
134 | { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ | ||
135 | { 0, 0, 0, CMT, 0, USB, } }, | ||
136 | { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ | ||
137 | { 0, MMC_MMC3I, MMC_MMC2I, MMC_MMC1I } }, | ||
138 | { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */ | ||
139 | { 0, 0, 0, 0, 0, 0, 0, TSIF } }, | ||
140 | { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */ | ||
141 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | ||
142 | }; | ||
143 | |||
144 | static struct intc_prio_reg prio_registers[] __initdata = { | ||
145 | { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2 } }, | ||
146 | { 0xa4080004, 0, 16, 4, /* IPRB */ { VEU2, LCDC, ICB } }, | ||
147 | { 0xa4080008, 0, 16, 4, /* IPRC */ { } }, | ||
148 | { 0xa408000c, 0, 16, 4, /* IPRD */ { } }, | ||
149 | { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0123, VIOVOU, MFI, VPU } }, | ||
150 | { 0xa4080014, 0, 16, 4, /* IPRF */ { 0, DMAC45, USB, CMT } }, | ||
151 | { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF, SCIFA1, SCIFA2, DENC } }, | ||
152 | { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF, 0, FLCTL, I2C } }, | ||
153 | { 0xa4080020, 0, 16, 4, /* IPRI */ { 0, 0, TSIF, } }, | ||
154 | { 0xa4080024, 0, 16, 4, /* IPRJ */ { 0, 0, SIU } }, | ||
155 | { 0xa4080028, 0, 16, 4, /* IPRK */ { 0, MMC, 0, SDHI } }, | ||
156 | { 0xa408002c, 0, 16, 4, /* IPRL */ { } }, | ||
157 | { 0xa4140010, 0, 32, 4, /* INTPRI00 */ | ||
158 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | ||
159 | }; | ||
160 | |||
161 | static struct intc_sense_reg sense_registers[] __initdata = { | ||
162 | { 0xa414001c, 16, 2, /* ICR1 */ | ||
163 | { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, | ||
164 | }; | ||
165 | |||
166 | static DECLARE_INTC_DESC(intc_desc, "sh7366", vectors, groups, | ||
167 | mask_registers, prio_registers, sense_registers); | ||
168 | |||
169 | void __init plat_irq_setup(void) | ||
170 | { | ||
171 | register_intc_controller(&intc_desc); | ||
172 | } | ||
173 | |||
174 | void __init plat_mem_setup(void) | ||
175 | { | ||
176 | /* TODO: Register Node 1 */ | ||
177 | } | ||
diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 15d167fd0ae7..31f8cb0f6374 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c | |||
@@ -20,19 +20,18 @@ int __init detect_cpu_and_cache_system(void) | |||
20 | { | 20 | { |
21 | unsigned long long cir; | 21 | unsigned long long cir; |
22 | 22 | ||
23 | /* Do peeks in real mode to avoid having to set up a mapping for the | 23 | /* |
24 | WPC registers. On SH5-101 cut2, such a mapping would be exposed to | 24 | * Do peeks in real mode to avoid having to set up a mapping for |
25 | an address translation erratum which would make it hard to set up | 25 | * the WPC registers. On SH5-101 cut2, such a mapping would be |
26 | correctly. */ | 26 | * exposed to an address translation erratum which would make it |
27 | * hard to set up correctly. | ||
28 | */ | ||
27 | cir = peek_real_address_q(0x0d000008); | 29 | cir = peek_real_address_q(0x0d000008); |
28 | if ((cir & 0xffff) == 0x5103) { | 30 | if ((cir & 0xffff) == 0x5103) |
29 | boot_cpu_data.type = CPU_SH5_103; | 31 | boot_cpu_data.type = CPU_SH5_103; |
30 | } else if (((cir >> 32) & 0xffff) == 0x51e2) { | 32 | else if (((cir >> 32) & 0xffff) == 0x51e2) |
31 | /* CPU.VCR aliased at CIR address on SH5-101 */ | 33 | /* CPU.VCR aliased at CIR address on SH5-101 */ |
32 | boot_cpu_data.type = CPU_SH5_101; | 34 | boot_cpu_data.type = CPU_SH5_101; |
33 | } else { | ||
34 | boot_cpu_data.type = CPU_SH_NONE; | ||
35 | } | ||
36 | 35 | ||
37 | /* | 36 | /* |
38 | * First, setup some sane values for the I-cache. | 37 | * First, setup some sane values for the I-cache. |
@@ -40,37 +39,33 @@ int __init detect_cpu_and_cache_system(void) | |||
40 | boot_cpu_data.icache.ways = 4; | 39 | boot_cpu_data.icache.ways = 4; |
41 | boot_cpu_data.icache.sets = 256; | 40 | boot_cpu_data.icache.sets = 256; |
42 | boot_cpu_data.icache.linesz = L1_CACHE_BYTES; | 41 | boot_cpu_data.icache.linesz = L1_CACHE_BYTES; |
42 | boot_cpu_data.icache.way_incr = (1 << 13); | ||
43 | boot_cpu_data.icache.entry_shift = 5; | ||
44 | boot_cpu_data.icache.way_size = boot_cpu_data.icache.sets * | ||
45 | boot_cpu_data.icache.linesz; | ||
46 | boot_cpu_data.icache.entry_mask = 0x1fe0; | ||
47 | boot_cpu_data.icache.flags = 0; | ||
43 | 48 | ||
44 | #if 0 | ||
45 | /* | 49 | /* |
46 | * FIXME: This can probably be cleaned up a bit as well.. for example, | 50 | * Next, setup some sane values for the D-cache. |
47 | * do we really need the way shift _and_ the way_step_shift ?? Judging | 51 | * |
48 | * by the existing code, I would guess no.. is there any valid reason | 52 | * On the SH5, these are pretty consistent with the I-cache settings, |
49 | * why we need to be tracking this around? | 53 | * so we just copy over the existing definitions.. these can be fixed |
54 | * up later, especially if we add runtime CPU probing. | ||
55 | * | ||
56 | * Though in the meantime it saves us from having to duplicate all of | ||
57 | * the above definitions.. | ||
50 | */ | 58 | */ |
51 | boot_cpu_data.icache.way_shift = 13; | 59 | boot_cpu_data.dcache = boot_cpu_data.icache; |
52 | boot_cpu_data.icache.entry_shift = 5; | ||
53 | boot_cpu_data.icache.set_shift = 4; | ||
54 | boot_cpu_data.icache.way_step_shift = 16; | ||
55 | boot_cpu_data.icache.asid_shift = 2; | ||
56 | 60 | ||
57 | /* | 61 | /* |
58 | * way offset = cache size / associativity, so just don't factor in | 62 | * Setup any cache-related flags here |
59 | * associativity in the first place.. | ||
60 | */ | 63 | */ |
61 | boot_cpu_data.icache.way_ofs = boot_cpu_data.icache.sets * | 64 | #if defined(CONFIG_CACHE_WRITETHROUGH) |
62 | boot_cpu_data.icache.linesz; | 65 | set_bit(SH_CACHE_MODE_WT, &(boot_cpu_data.dcache.flags)); |
63 | 66 | #elif defined(CONFIG_CACHE_WRITEBACK) | |
64 | boot_cpu_data.icache.asid_mask = 0x3fc; | 67 | set_bit(SH_CACHE_MODE_WB, &(boot_cpu_data.dcache.flags)); |
65 | boot_cpu_data.icache.idx_mask = 0x1fe0; | ||
66 | boot_cpu_data.icache.epn_mask = 0xffffe000; | ||
67 | #endif | 68 | #endif |
68 | 69 | ||
69 | boot_cpu_data.icache.flags = 0; | ||
70 | |||
71 | /* A trivial starting point.. */ | ||
72 | memcpy(&boot_cpu_data.dcache, | ||
73 | &boot_cpu_data.icache, sizeof(struct cache_info)); | ||
74 | |||
75 | return 0; | 70 | return 0; |
76 | } | 71 | } |
diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c index 71c9fde2fd90..2b8991229900 100644 --- a/arch/sh/kernel/io.c +++ b/arch/sh/kernel/io.c | |||
@@ -63,7 +63,13 @@ EXPORT_SYMBOL(memset_io); | |||
63 | 63 | ||
64 | void __iomem *ioport_map(unsigned long port, unsigned int nr) | 64 | void __iomem *ioport_map(unsigned long port, unsigned int nr) |
65 | { | 65 | { |
66 | return sh_mv.mv_ioport_map(port, nr); | 66 | void __iomem *ret; |
67 | |||
68 | ret = __ioport_map_trapped(port, nr); | ||
69 | if (ret) | ||
70 | return ret; | ||
71 | |||
72 | return __ioport_map(port, nr); | ||
67 | } | 73 | } |
68 | EXPORT_SYMBOL(ioport_map); | 74 | EXPORT_SYMBOL(ioport_map); |
69 | 75 | ||
diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 771ea4230441..db769449f5a7 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c | |||
@@ -33,17 +33,17 @@ static inline void delay(void) | |||
33 | 33 | ||
34 | u8 generic_inb(unsigned long port) | 34 | u8 generic_inb(unsigned long port) |
35 | { | 35 | { |
36 | return ctrl_inb((unsigned long __force)ioport_map(port, 1)); | 36 | return ctrl_inb((unsigned long __force)__ioport_map(port, 1)); |
37 | } | 37 | } |
38 | 38 | ||
39 | u16 generic_inw(unsigned long port) | 39 | u16 generic_inw(unsigned long port) |
40 | { | 40 | { |
41 | return ctrl_inw((unsigned long __force)ioport_map(port, 2)); | 41 | return ctrl_inw((unsigned long __force)__ioport_map(port, 2)); |
42 | } | 42 | } |
43 | 43 | ||
44 | u32 generic_inl(unsigned long port) | 44 | u32 generic_inl(unsigned long port) |
45 | { | 45 | { |
46 | return ctrl_inl((unsigned long __force)ioport_map(port, 4)); | 46 | return ctrl_inl((unsigned long __force)__ioport_map(port, 4)); |
47 | } | 47 | } |
48 | 48 | ||
49 | u8 generic_inb_p(unsigned long port) | 49 | u8 generic_inb_p(unsigned long port) |
@@ -81,7 +81,7 @@ void generic_insb(unsigned long port, void *dst, unsigned long count) | |||
81 | volatile u8 *port_addr; | 81 | volatile u8 *port_addr; |
82 | u8 *buf = dst; | 82 | u8 *buf = dst; |
83 | 83 | ||
84 | port_addr = (volatile u8 *)ioport_map(port, 1); | 84 | port_addr = (volatile u8 *)__ioport_map(port, 1); |
85 | while (count--) | 85 | while (count--) |
86 | *buf++ = *port_addr; | 86 | *buf++ = *port_addr; |
87 | } | 87 | } |
@@ -91,7 +91,7 @@ void generic_insw(unsigned long port, void *dst, unsigned long count) | |||
91 | volatile u16 *port_addr; | 91 | volatile u16 *port_addr; |
92 | u16 *buf = dst; | 92 | u16 *buf = dst; |
93 | 93 | ||
94 | port_addr = (volatile u16 *)ioport_map(port, 2); | 94 | port_addr = (volatile u16 *)__ioport_map(port, 2); |
95 | while (count--) | 95 | while (count--) |
96 | *buf++ = *port_addr; | 96 | *buf++ = *port_addr; |
97 | 97 | ||
@@ -103,7 +103,7 @@ void generic_insl(unsigned long port, void *dst, unsigned long count) | |||
103 | volatile u32 *port_addr; | 103 | volatile u32 *port_addr; |
104 | u32 *buf = dst; | 104 | u32 *buf = dst; |
105 | 105 | ||
106 | port_addr = (volatile u32 *)ioport_map(port, 4); | 106 | port_addr = (volatile u32 *)__ioport_map(port, 4); |
107 | while (count--) | 107 | while (count--) |
108 | *buf++ = *port_addr; | 108 | *buf++ = *port_addr; |
109 | 109 | ||
@@ -112,17 +112,17 @@ void generic_insl(unsigned long port, void *dst, unsigned long count) | |||
112 | 112 | ||
113 | void generic_outb(u8 b, unsigned long port) | 113 | void generic_outb(u8 b, unsigned long port) |
114 | { | 114 | { |
115 | ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); | 115 | ctrl_outb(b, (unsigned long __force)__ioport_map(port, 1)); |
116 | } | 116 | } |
117 | 117 | ||
118 | void generic_outw(u16 b, unsigned long port) | 118 | void generic_outw(u16 b, unsigned long port) |
119 | { | 119 | { |
120 | ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); | 120 | ctrl_outw(b, (unsigned long __force)__ioport_map(port, 2)); |
121 | } | 121 | } |
122 | 122 | ||
123 | void generic_outl(u32 b, unsigned long port) | 123 | void generic_outl(u32 b, unsigned long port) |
124 | { | 124 | { |
125 | ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); | 125 | ctrl_outl(b, (unsigned long __force)__ioport_map(port, 4)); |
126 | } | 126 | } |
127 | 127 | ||
128 | void generic_outb_p(u8 b, unsigned long port) | 128 | void generic_outb_p(u8 b, unsigned long port) |
@@ -153,7 +153,7 @@ void generic_outsb(unsigned long port, const void *src, unsigned long count) | |||
153 | volatile u8 *port_addr; | 153 | volatile u8 *port_addr; |
154 | const u8 *buf = src; | 154 | const u8 *buf = src; |
155 | 155 | ||
156 | port_addr = (volatile u8 __force *)ioport_map(port, 1); | 156 | port_addr = (volatile u8 __force *)__ioport_map(port, 1); |
157 | 157 | ||
158 | while (count--) | 158 | while (count--) |
159 | *port_addr = *buf++; | 159 | *port_addr = *buf++; |
@@ -164,7 +164,7 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count) | |||
164 | volatile u16 *port_addr; | 164 | volatile u16 *port_addr; |
165 | const u16 *buf = src; | 165 | const u16 *buf = src; |
166 | 166 | ||
167 | port_addr = (volatile u16 __force *)ioport_map(port, 2); | 167 | port_addr = (volatile u16 __force *)__ioport_map(port, 2); |
168 | 168 | ||
169 | while (count--) | 169 | while (count--) |
170 | *port_addr = *buf++; | 170 | *port_addr = *buf++; |
@@ -177,7 +177,7 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count) | |||
177 | volatile u32 *port_addr; | 177 | volatile u32 *port_addr; |
178 | const u32 *buf = src; | 178 | const u32 *buf = src; |
179 | 179 | ||
180 | port_addr = (volatile u32 __force *)ioport_map(port, 4); | 180 | port_addr = (volatile u32 __force *)__ioport_map(port, 4); |
181 | while (count--) | 181 | while (count--) |
182 | *port_addr = *buf++; | 182 | *port_addr = *buf++; |
183 | 183 | ||
diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c new file mode 100644 index 000000000000..86a665d92201 --- /dev/null +++ b/arch/sh/kernel/io_trapped.c | |||
@@ -0,0 +1,276 @@ | |||
1 | /* | ||
2 | * Trapped io support | ||
3 | * | ||
4 | * Copyright (C) 2008 Magnus Damm | ||
5 | * | ||
6 | * Intercept io operations by trapping. | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/bitops.h> | ||
15 | #include <linux/vmalloc.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <asm/system.h> | ||
18 | #include <asm/mmu_context.h> | ||
19 | #include <asm/uaccess.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/io_trapped.h> | ||
22 | |||
23 | #define TRAPPED_PAGES_MAX 16 | ||
24 | |||
25 | #ifdef CONFIG_HAS_IOPORT | ||
26 | LIST_HEAD(trapped_io); | ||
27 | EXPORT_SYMBOL_GPL(trapped_io); | ||
28 | #endif | ||
29 | #ifdef CONFIG_HAS_IOMEM | ||
30 | LIST_HEAD(trapped_mem); | ||
31 | EXPORT_SYMBOL_GPL(trapped_mem); | ||
32 | #endif | ||
33 | static DEFINE_SPINLOCK(trapped_lock); | ||
34 | |||
35 | int __init register_trapped_io(struct trapped_io *tiop) | ||
36 | { | ||
37 | struct resource *res; | ||
38 | unsigned long len = 0, flags = 0; | ||
39 | struct page *pages[TRAPPED_PAGES_MAX]; | ||
40 | int k, n; | ||
41 | |||
42 | /* structure must be page aligned */ | ||
43 | if ((unsigned long)tiop & (PAGE_SIZE - 1)) | ||
44 | goto bad; | ||
45 | |||
46 | for (k = 0; k < tiop->num_resources; k++) { | ||
47 | res = tiop->resource + k; | ||
48 | len += roundup((res->end - res->start) + 1, PAGE_SIZE); | ||
49 | flags |= res->flags; | ||
50 | } | ||
51 | |||
52 | /* support IORESOURCE_IO _or_ MEM, not both */ | ||
53 | if (hweight_long(flags) != 1) | ||
54 | goto bad; | ||
55 | |||
56 | n = len >> PAGE_SHIFT; | ||
57 | |||
58 | if (n >= TRAPPED_PAGES_MAX) | ||
59 | goto bad; | ||
60 | |||
61 | for (k = 0; k < n; k++) | ||
62 | pages[k] = virt_to_page(tiop); | ||
63 | |||
64 | tiop->virt_base = vmap(pages, n, VM_MAP, PAGE_NONE); | ||
65 | if (!tiop->virt_base) | ||
66 | goto bad; | ||
67 | |||
68 | len = 0; | ||
69 | for (k = 0; k < tiop->num_resources; k++) { | ||
70 | res = tiop->resource + k; | ||
71 | pr_info("trapped io 0x%08lx overrides %s 0x%08lx\n", | ||
72 | (unsigned long)(tiop->virt_base + len), | ||
73 | res->flags & IORESOURCE_IO ? "io" : "mmio", | ||
74 | (unsigned long)res->start); | ||
75 | len += roundup((res->end - res->start) + 1, PAGE_SIZE); | ||
76 | } | ||
77 | |||
78 | tiop->magic = IO_TRAPPED_MAGIC; | ||
79 | INIT_LIST_HEAD(&tiop->list); | ||
80 | spin_lock_irq(&trapped_lock); | ||
81 | if (flags & IORESOURCE_IO) | ||
82 | list_add(&tiop->list, &trapped_io); | ||
83 | if (flags & IORESOURCE_MEM) | ||
84 | list_add(&tiop->list, &trapped_mem); | ||
85 | spin_unlock_irq(&trapped_lock); | ||
86 | |||
87 | return 0; | ||
88 | bad: | ||
89 | pr_warning("unable to install trapped io filter\n"); | ||
90 | return -1; | ||
91 | } | ||
92 | EXPORT_SYMBOL_GPL(register_trapped_io); | ||
93 | |||
94 | void __iomem *match_trapped_io_handler(struct list_head *list, | ||
95 | unsigned long offset, | ||
96 | unsigned long size) | ||
97 | { | ||
98 | unsigned long voffs; | ||
99 | struct trapped_io *tiop; | ||
100 | struct resource *res; | ||
101 | int k, len; | ||
102 | |||
103 | spin_lock_irq(&trapped_lock); | ||
104 | list_for_each_entry(tiop, list, list) { | ||
105 | voffs = 0; | ||
106 | for (k = 0; k < tiop->num_resources; k++) { | ||
107 | res = tiop->resource + k; | ||
108 | if (res->start == offset) { | ||
109 | spin_unlock_irq(&trapped_lock); | ||
110 | return tiop->virt_base + voffs; | ||
111 | } | ||
112 | |||
113 | len = (res->end - res->start) + 1; | ||
114 | voffs += roundup(len, PAGE_SIZE); | ||
115 | } | ||
116 | } | ||
117 | spin_unlock_irq(&trapped_lock); | ||
118 | return NULL; | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(match_trapped_io_handler); | ||
121 | |||
122 | static struct trapped_io *lookup_tiop(unsigned long address) | ||
123 | { | ||
124 | pgd_t *pgd_k; | ||
125 | pud_t *pud_k; | ||
126 | pmd_t *pmd_k; | ||
127 | pte_t *pte_k; | ||
128 | pte_t entry; | ||
129 | |||
130 | pgd_k = swapper_pg_dir + pgd_index(address); | ||
131 | if (!pgd_present(*pgd_k)) | ||
132 | return NULL; | ||
133 | |||
134 | pud_k = pud_offset(pgd_k, address); | ||
135 | if (!pud_present(*pud_k)) | ||
136 | return NULL; | ||
137 | |||
138 | pmd_k = pmd_offset(pud_k, address); | ||
139 | if (!pmd_present(*pmd_k)) | ||
140 | return NULL; | ||
141 | |||
142 | pte_k = pte_offset_kernel(pmd_k, address); | ||
143 | entry = *pte_k; | ||
144 | |||
145 | return pfn_to_kaddr(pte_pfn(entry)); | ||
146 | } | ||
147 | |||
148 | static unsigned long lookup_address(struct trapped_io *tiop, | ||
149 | unsigned long address) | ||
150 | { | ||
151 | struct resource *res; | ||
152 | unsigned long vaddr = (unsigned long)tiop->virt_base; | ||
153 | unsigned long len; | ||
154 | int k; | ||
155 | |||
156 | for (k = 0; k < tiop->num_resources; k++) { | ||
157 | res = tiop->resource + k; | ||
158 | len = roundup((res->end - res->start) + 1, PAGE_SIZE); | ||
159 | if (address < (vaddr + len)) | ||
160 | return res->start + (address - vaddr); | ||
161 | vaddr += len; | ||
162 | } | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static unsigned long long copy_word(unsigned long src_addr, int src_len, | ||
167 | unsigned long dst_addr, int dst_len) | ||
168 | { | ||
169 | unsigned long long tmp = 0; | ||
170 | |||
171 | switch (src_len) { | ||
172 | case 1: | ||
173 | tmp = ctrl_inb(src_addr); | ||
174 | break; | ||
175 | case 2: | ||
176 | tmp = ctrl_inw(src_addr); | ||
177 | break; | ||
178 | case 4: | ||
179 | tmp = ctrl_inl(src_addr); | ||
180 | break; | ||
181 | case 8: | ||
182 | tmp = ctrl_inq(src_addr); | ||
183 | break; | ||
184 | } | ||
185 | |||
186 | switch (dst_len) { | ||
187 | case 1: | ||
188 | ctrl_outb(tmp, dst_addr); | ||
189 | break; | ||
190 | case 2: | ||
191 | ctrl_outw(tmp, dst_addr); | ||
192 | break; | ||
193 | case 4: | ||
194 | ctrl_outl(tmp, dst_addr); | ||
195 | break; | ||
196 | case 8: | ||
197 | ctrl_outq(tmp, dst_addr); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | return tmp; | ||
202 | } | ||
203 | |||
204 | static unsigned long from_device(void *dst, const void *src, unsigned long cnt) | ||
205 | { | ||
206 | struct trapped_io *tiop; | ||
207 | unsigned long src_addr = (unsigned long)src; | ||
208 | unsigned long long tmp; | ||
209 | |||
210 | pr_debug("trapped io read 0x%08lx (%ld)\n", src_addr, cnt); | ||
211 | tiop = lookup_tiop(src_addr); | ||
212 | WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC)); | ||
213 | |||
214 | src_addr = lookup_address(tiop, src_addr); | ||
215 | if (!src_addr) | ||
216 | return cnt; | ||
217 | |||
218 | tmp = copy_word(src_addr, | ||
219 | max_t(unsigned long, cnt, | ||
220 | (tiop->minimum_bus_width / 8)), | ||
221 | (unsigned long)dst, cnt); | ||
222 | |||
223 | pr_debug("trapped io read 0x%08lx -> 0x%08llx\n", src_addr, tmp); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static unsigned long to_device(void *dst, const void *src, unsigned long cnt) | ||
228 | { | ||
229 | struct trapped_io *tiop; | ||
230 | unsigned long dst_addr = (unsigned long)dst; | ||
231 | unsigned long long tmp; | ||
232 | |||
233 | pr_debug("trapped io write 0x%08lx (%ld)\n", dst_addr, cnt); | ||
234 | tiop = lookup_tiop(dst_addr); | ||
235 | WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC)); | ||
236 | |||
237 | dst_addr = lookup_address(tiop, dst_addr); | ||
238 | if (!dst_addr) | ||
239 | return cnt; | ||
240 | |||
241 | tmp = copy_word((unsigned long)src, cnt, | ||
242 | dst_addr, max_t(unsigned long, cnt, | ||
243 | (tiop->minimum_bus_width / 8))); | ||
244 | |||
245 | pr_debug("trapped io write 0x%08lx -> 0x%08llx\n", dst_addr, tmp); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static struct mem_access trapped_io_access = { | ||
250 | from_device, | ||
251 | to_device, | ||
252 | }; | ||
253 | |||
254 | int handle_trapped_io(struct pt_regs *regs, unsigned long address) | ||
255 | { | ||
256 | mm_segment_t oldfs; | ||
257 | opcode_t instruction; | ||
258 | int tmp; | ||
259 | |||
260 | if (!lookup_tiop(address)) | ||
261 | return 0; | ||
262 | |||
263 | WARN_ON(user_mode(regs)); | ||
264 | |||
265 | oldfs = get_fs(); | ||
266 | set_fs(KERNEL_DS); | ||
267 | if (copy_from_user(&instruction, (void *)(regs->pc), | ||
268 | sizeof(instruction))) { | ||
269 | set_fs(oldfs); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | tmp = handle_unaligned_access(instruction, regs, &trapped_io_access); | ||
274 | set_fs(oldfs); | ||
275 | return tmp == 0; | ||
276 | } | ||
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 0586bc62ad96..9bf19b00696a 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c | |||
@@ -248,9 +248,6 @@ asmlinkage void do_softirq(void) | |||
248 | 248 | ||
249 | void __init init_IRQ(void) | 249 | void __init init_IRQ(void) |
250 | { | 250 | { |
251 | #ifdef CONFIG_CPU_HAS_PINT_IRQ | ||
252 | init_IRQ_pint(); | ||
253 | #endif | ||
254 | plat_irq_setup(); | 251 | plat_irq_setup(); |
255 | 252 | ||
256 | /* Perform the machine specific initialisation */ | 253 | /* Perform the machine specific initialisation */ |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index cff3b7dc9c56..046999b1d1af 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
@@ -623,6 +623,7 @@ extern void interruptible_sleep_on(wait_queue_head_t *q); | |||
623 | 623 | ||
624 | #define mid_sched ((unsigned long) interruptible_sleep_on) | 624 | #define mid_sched ((unsigned long) interruptible_sleep_on) |
625 | 625 | ||
626 | #ifdef CONFIG_FRAME_POINTER | ||
626 | static int in_sh64_switch_to(unsigned long pc) | 627 | static int in_sh64_switch_to(unsigned long pc) |
627 | { | 628 | { |
628 | extern char __sh64_switch_to_end; | 629 | extern char __sh64_switch_to_end; |
@@ -631,12 +632,10 @@ static int in_sh64_switch_to(unsigned long pc) | |||
631 | return (pc >= (unsigned long) sh64_switch_to) && | 632 | return (pc >= (unsigned long) sh64_switch_to) && |
632 | (pc < (unsigned long) &__sh64_switch_to_end); | 633 | (pc < (unsigned long) &__sh64_switch_to_end); |
633 | } | 634 | } |
635 | #endif | ||
634 | 636 | ||
635 | unsigned long get_wchan(struct task_struct *p) | 637 | unsigned long get_wchan(struct task_struct *p) |
636 | { | 638 | { |
637 | unsigned long schedule_fp; | ||
638 | unsigned long sh64_switch_to_fp; | ||
639 | unsigned long schedule_caller_pc; | ||
640 | unsigned long pc; | 639 | unsigned long pc; |
641 | 640 | ||
642 | if (!p || p == current || p->state == TASK_RUNNING) | 641 | if (!p || p == current || p->state == TASK_RUNNING) |
@@ -649,6 +648,10 @@ unsigned long get_wchan(struct task_struct *p) | |||
649 | 648 | ||
650 | #ifdef CONFIG_FRAME_POINTER | 649 | #ifdef CONFIG_FRAME_POINTER |
651 | if (in_sh64_switch_to(pc)) { | 650 | if (in_sh64_switch_to(pc)) { |
651 | unsigned long schedule_fp; | ||
652 | unsigned long sh64_switch_to_fp; | ||
653 | unsigned long schedule_caller_pc; | ||
654 | |||
652 | sh64_switch_to_fp = (long) p->thread.sp; | 655 | sh64_switch_to_fp = (long) p->thread.sp; |
653 | /* r14 is saved at offset 4 in the sh64_switch_to frame */ | 656 | /* r14 is saved at offset 4 in the sh64_switch_to frame */ |
654 | schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); | 657 | schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); |
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index ce0664a58b49..fddb547f3c2b 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c | |||
@@ -220,7 +220,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
220 | dp = ((unsigned long) child) + THREAD_SIZE - | 220 | dp = ((unsigned long) child) + THREAD_SIZE - |
221 | sizeof(struct pt_dspregs); | 221 | sizeof(struct pt_dspregs); |
222 | if (*((int *) (dp - 4)) == SR_FD) { | 222 | if (*((int *) (dp - 4)) == SR_FD) { |
223 | copy_to_user(addr, (void *) dp, | 223 | copy_to_user((void *)addr, (void *) dp, |
224 | sizeof(struct pt_dspregs)); | 224 | sizeof(struct pt_dspregs)); |
225 | ret = 0; | 225 | ret = 0; |
226 | } | 226 | } |
@@ -234,7 +234,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
234 | dp = ((unsigned long) child) + THREAD_SIZE - | 234 | dp = ((unsigned long) child) + THREAD_SIZE - |
235 | sizeof(struct pt_dspregs); | 235 | sizeof(struct pt_dspregs); |
236 | if (*((int *) (dp - 4)) == SR_FD) { | 236 | if (*((int *) (dp - 4)) == SR_FD) { |
237 | copy_from_user((void *) dp, addr, | 237 | copy_from_user((void *) dp, (void *)addr, |
238 | sizeof(struct pt_dspregs)); | 238 | sizeof(struct pt_dspregs)); |
239 | ret = 0; | 239 | ret = 0; |
240 | } | 240 | } |
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 18a5baf2cbad..ff4f54a47c07 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -333,7 +333,7 @@ static const char *cpu_name[] = { | |||
333 | [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785", | 333 | [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785", |
334 | [CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3", | 334 | [CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3", |
335 | [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103", | 335 | [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103", |
336 | [CPU_SH_NONE] = "Unknown" | 336 | [CPU_SH7366] = "SH7366", [CPU_SH_NONE] = "Unknown" |
337 | }; | 337 | }; |
338 | 338 | ||
339 | const char *get_cpu_subtype(struct sh_cpuinfo *c) | 339 | const char *get_cpu_subtype(struct sh_cpuinfo *c) |
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 719e127a7c05..a46cc3a41148 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S | |||
@@ -338,6 +338,8 @@ ENTRY(sys_call_table) | |||
338 | .long sys_epoll_pwait | 338 | .long sys_epoll_pwait |
339 | .long sys_utimensat /* 320 */ | 339 | .long sys_utimensat /* 320 */ |
340 | .long sys_signalfd | 340 | .long sys_signalfd |
341 | .long sys_ni_syscall | 341 | .long sys_timerfd_create |
342 | .long sys_eventfd | 342 | .long sys_eventfd |
343 | .long sys_fallocate | 343 | .long sys_fallocate |
344 | .long sys_timerfd_settime /* 325 */ | ||
345 | .long sys_timerfd_gettime | ||
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 12c7340356ae..d5d7843aad94 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S | |||
@@ -376,6 +376,8 @@ sys_call_table: | |||
376 | .long sys_epoll_pwait | 376 | .long sys_epoll_pwait |
377 | .long sys_utimensat | 377 | .long sys_utimensat |
378 | .long sys_signalfd | 378 | .long sys_signalfd |
379 | .long sys_ni_syscall /* 350 */ | 379 | .long sys_timerfd_create /* 350 */ |
380 | .long sys_eventfd | 380 | .long sys_eventfd |
381 | .long sys_fallocate | 381 | .long sys_fallocate |
382 | .long sys_timerfd_settime | ||
383 | .long sys_timerfd_gettime | ||
diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 2bc04bfee738..7281342c044d 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c | |||
@@ -120,10 +120,6 @@ static long last_rtc_update; | |||
120 | */ | 120 | */ |
121 | void handle_timer_tick(void) | 121 | void handle_timer_tick(void) |
122 | { | 122 | { |
123 | do_timer(1); | ||
124 | #ifndef CONFIG_SMP | ||
125 | update_process_times(user_mode(get_irq_regs())); | ||
126 | #endif | ||
127 | if (current->pid) | 123 | if (current->pid) |
128 | profile_tick(CPU_PROFILING); | 124 | profile_tick(CPU_PROFILING); |
129 | 125 | ||
@@ -133,6 +129,16 @@ void handle_timer_tick(void) | |||
133 | #endif | 129 | #endif |
134 | 130 | ||
135 | /* | 131 | /* |
132 | * Here we are in the timer irq handler. We just have irqs locally | ||
133 | * disabled but we don't know if the timer_bh is running on the other | ||
134 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | ||
135 | * the irq version of write_lock because as just said we have irq | ||
136 | * locally disabled. -arca | ||
137 | */ | ||
138 | write_seqlock(&xtime_lock); | ||
139 | do_timer(1); | ||
140 | |||
141 | /* | ||
136 | * If we have an externally synchronized Linux clock, then update | 142 | * If we have an externally synchronized Linux clock, then update |
137 | * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | 143 | * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
138 | * called as close as possible to 500 ms before the new second starts. | 144 | * called as close as possible to 500 ms before the new second starts. |
@@ -147,6 +153,11 @@ void handle_timer_tick(void) | |||
147 | /* do it again in 60s */ | 153 | /* do it again in 60s */ |
148 | last_rtc_update = xtime.tv_sec - 600; | 154 | last_rtc_update = xtime.tv_sec - 600; |
149 | } | 155 | } |
156 | write_sequnlock(&xtime_lock); | ||
157 | |||
158 | #ifndef CONFIG_SMP | ||
159 | update_process_times(user_mode(get_irq_regs())); | ||
160 | #endif | ||
150 | } | 161 | } |
151 | #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ | 162 | #endif /* !CONFIG_GENERIC_CLOCKEVENTS */ |
152 | 163 | ||
diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c index f819ba38a6ce..898977ee2030 100644 --- a/arch/sh/kernel/time_64.c +++ b/arch/sh/kernel/time_64.c | |||
@@ -229,15 +229,22 @@ static long last_rtc_update; | |||
229 | static inline void do_timer_interrupt(void) | 229 | static inline void do_timer_interrupt(void) |
230 | { | 230 | { |
231 | unsigned long long current_ctc; | 231 | unsigned long long current_ctc; |
232 | |||
233 | if (current->pid) | ||
234 | profile_tick(CPU_PROFILING); | ||
235 | |||
236 | /* | ||
237 | * Here we are in the timer irq handler. We just have irqs locally | ||
238 | * disabled but we don't know if the timer_bh is running on the other | ||
239 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | ||
240 | * the irq version of write_lock because as just said we have irq | ||
241 | * locally disabled. -arca | ||
242 | */ | ||
243 | write_lock(&xtime_lock); | ||
232 | asm ("getcon cr62, %0" : "=r" (current_ctc)); | 244 | asm ("getcon cr62, %0" : "=r" (current_ctc)); |
233 | ctc_last_interrupt = (unsigned long) current_ctc; | 245 | ctc_last_interrupt = (unsigned long) current_ctc; |
234 | 246 | ||
235 | do_timer(1); | 247 | do_timer(1); |
236 | #ifndef CONFIG_SMP | ||
237 | update_process_times(user_mode(get_irq_regs())); | ||
238 | #endif | ||
239 | if (current->pid) | ||
240 | profile_tick(CPU_PROFILING); | ||
241 | 248 | ||
242 | #ifdef CONFIG_HEARTBEAT | 249 | #ifdef CONFIG_HEARTBEAT |
243 | if (sh_mv.mv_heartbeat != NULL) | 250 | if (sh_mv.mv_heartbeat != NULL) |
@@ -259,6 +266,11 @@ static inline void do_timer_interrupt(void) | |||
259 | /* do it again in 60 s */ | 266 | /* do it again in 60 s */ |
260 | last_rtc_update = xtime.tv_sec - 600; | 267 | last_rtc_update = xtime.tv_sec - 600; |
261 | } | 268 | } |
269 | write_unlock(&xtime_lock); | ||
270 | |||
271 | #ifndef CONFIG_SMP | ||
272 | update_process_times(user_mode(get_irq_regs())); | ||
273 | #endif | ||
262 | } | 274 | } |
263 | 275 | ||
264 | /* | 276 | /* |
@@ -275,16 +287,7 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
275 | timer_status &= ~0x100; | 287 | timer_status &= ~0x100; |
276 | ctrl_outw(timer_status, TMU0_TCR); | 288 | ctrl_outw(timer_status, TMU0_TCR); |
277 | 289 | ||
278 | /* | ||
279 | * Here we are in the timer irq handler. We just have irqs locally | ||
280 | * disabled but we don't know if the timer_bh is running on the other | ||
281 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | ||
282 | * the irq version of write_lock because as just said we have irq | ||
283 | * locally disabled. -arca | ||
284 | */ | ||
285 | write_lock(&xtime_lock); | ||
286 | do_timer_interrupt(); | 290 | do_timer_interrupt(); |
287 | write_unlock(&xtime_lock); | ||
288 | 291 | ||
289 | return IRQ_HANDLED; | 292 | return IRQ_HANDLED; |
290 | } | 293 | } |
diff --git a/arch/sh/kernel/timers/timer-cmt.c b/arch/sh/kernel/timers/timer-cmt.c index 499e07beebe2..71312324b5de 100644 --- a/arch/sh/kernel/timers/timer-cmt.c +++ b/arch/sh/kernel/timers/timer-cmt.c | |||
@@ -100,16 +100,7 @@ static irqreturn_t cmt_timer_interrupt(int irq, void *dev_id) | |||
100 | timer_status &= ~0x80; | 100 | timer_status &= ~0x80; |
101 | ctrl_outw(timer_status, CMT_CMCSR_0); | 101 | ctrl_outw(timer_status, CMT_CMCSR_0); |
102 | 102 | ||
103 | /* | ||
104 | * Here we are in the timer irq handler. We just have irqs locally | ||
105 | * disabled but we don't know if the timer_bh is running on the other | ||
106 | * CPU. We need to avoid to SMP race with it. NOTE: we don' t need | ||
107 | * the irq version of write_lock because as just said we have irq | ||
108 | * locally disabled. -arca | ||
109 | */ | ||
110 | write_seqlock(&xtime_lock); | ||
111 | handle_timer_tick(); | 103 | handle_timer_tick(); |
112 | write_sequnlock(&xtime_lock); | ||
113 | 104 | ||
114 | return IRQ_HANDLED; | 105 | return IRQ_HANDLED; |
115 | } | 106 | } |
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c index b7499a2a9188..ade9d6eb29f9 100644 --- a/arch/sh/kernel/timers/timer-mtu2.c +++ b/arch/sh/kernel/timers/timer-mtu2.c | |||
@@ -100,9 +100,7 @@ static irqreturn_t mtu2_timer_interrupt(int irq, void *dev_id) | |||
100 | ctrl_outb(timer_status, MTU2_TSR_1); | 100 | ctrl_outb(timer_status, MTU2_TSR_1); |
101 | 101 | ||
102 | /* Do timer tick */ | 102 | /* Do timer tick */ |
103 | write_seqlock(&xtime_lock); | ||
104 | handle_timer_tick(); | 103 | handle_timer_tick(); |
105 | write_sequnlock(&xtime_lock); | ||
106 | 104 | ||
107 | return IRQ_HANDLED; | 105 | return IRQ_HANDLED; |
108 | } | 106 | } |
@@ -156,7 +154,6 @@ static int mtu2_timer_stop(void) | |||
156 | 154 | ||
157 | static int mtu2_timer_init(void) | 155 | static int mtu2_timer_init(void) |
158 | { | 156 | { |
159 | u8 tmp; | ||
160 | unsigned long interval; | 157 | unsigned long interval; |
161 | 158 | ||
162 | setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq); | 159 | setup_irq(CONFIG_SH_TIMER_IRQ, &mtu2_irq); |
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 2e58f7a6b746..baa4fa368dce 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -147,6 +147,36 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) | |||
147 | return -EFAULT; | 147 | return -EFAULT; |
148 | } | 148 | } |
149 | 149 | ||
150 | static inline void sign_extend(unsigned int count, unsigned char *dst) | ||
151 | { | ||
152 | #ifdef __LITTLE_ENDIAN__ | ||
153 | if ((count == 1) && dst[0] & 0x80) { | ||
154 | dst[1] = 0xff; | ||
155 | dst[2] = 0xff; | ||
156 | dst[3] = 0xff; | ||
157 | } | ||
158 | if ((count == 2) && dst[1] & 0x80) { | ||
159 | dst[2] = 0xff; | ||
160 | dst[3] = 0xff; | ||
161 | } | ||
162 | #else | ||
163 | if ((count == 1) && dst[3] & 0x80) { | ||
164 | dst[2] = 0xff; | ||
165 | dst[1] = 0xff; | ||
166 | dst[0] = 0xff; | ||
167 | } | ||
168 | if ((count == 2) && dst[2] & 0x80) { | ||
169 | dst[1] = 0xff; | ||
170 | dst[0] = 0xff; | ||
171 | } | ||
172 | #endif | ||
173 | } | ||
174 | |||
175 | static struct mem_access user_mem_access = { | ||
176 | copy_from_user, | ||
177 | copy_to_user, | ||
178 | }; | ||
179 | |||
150 | /* | 180 | /* |
151 | * handle an instruction that does an unaligned memory access by emulating the | 181 | * handle an instruction that does an unaligned memory access by emulating the |
152 | * desired behaviour | 182 | * desired behaviour |
@@ -154,7 +184,8 @@ static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) | |||
154 | * (if that instruction is in a branch delay slot) | 184 | * (if that instruction is in a branch delay slot) |
155 | * - return 0 if emulation okay, -EFAULT on existential error | 185 | * - return 0 if emulation okay, -EFAULT on existential error |
156 | */ | 186 | */ |
157 | static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | 187 | static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs, |
188 | struct mem_access *ma) | ||
158 | { | 189 | { |
159 | int ret, index, count; | 190 | int ret, index, count; |
160 | unsigned long *rm, *rn; | 191 | unsigned long *rm, *rn; |
@@ -178,25 +209,13 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
178 | dst = (unsigned char*) rn; | 209 | dst = (unsigned char*) rn; |
179 | *(unsigned long*)dst = 0; | 210 | *(unsigned long*)dst = 0; |
180 | 211 | ||
181 | #ifdef __LITTLE_ENDIAN__ | 212 | #if !defined(__LITTLE_ENDIAN__) |
182 | if (copy_from_user(dst, src, count)) | ||
183 | goto fetch_fault; | ||
184 | |||
185 | if ((count == 2) && dst[1] & 0x80) { | ||
186 | dst[2] = 0xff; | ||
187 | dst[3] = 0xff; | ||
188 | } | ||
189 | #else | ||
190 | dst += 4-count; | 213 | dst += 4-count; |
191 | 214 | #endif | |
192 | if (__copy_user(dst, src, count)) | 215 | if (ma->from(dst, src, count)) |
193 | goto fetch_fault; | 216 | goto fetch_fault; |
194 | 217 | ||
195 | if ((count == 2) && dst[2] & 0x80) { | 218 | sign_extend(count, dst); |
196 | dst[0] = 0xff; | ||
197 | dst[1] = 0xff; | ||
198 | } | ||
199 | #endif | ||
200 | } else { | 219 | } else { |
201 | /* to memory */ | 220 | /* to memory */ |
202 | src = (unsigned char*) rm; | 221 | src = (unsigned char*) rm; |
@@ -206,7 +225,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
206 | dst = (unsigned char*) *rn; | 225 | dst = (unsigned char*) *rn; |
207 | dst += regs->regs[0]; | 226 | dst += regs->regs[0]; |
208 | 227 | ||
209 | if (copy_to_user(dst, src, count)) | 228 | if (ma->to(dst, src, count)) |
210 | goto fetch_fault; | 229 | goto fetch_fault; |
211 | } | 230 | } |
212 | ret = 0; | 231 | ret = 0; |
@@ -217,7 +236,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
217 | dst = (unsigned char*) *rn; | 236 | dst = (unsigned char*) *rn; |
218 | dst += (instruction&0x000F)<<2; | 237 | dst += (instruction&0x000F)<<2; |
219 | 238 | ||
220 | if (copy_to_user(dst,src,4)) | 239 | if (ma->to(dst, src, 4)) |
221 | goto fetch_fault; | 240 | goto fetch_fault; |
222 | ret = 0; | 241 | ret = 0; |
223 | break; | 242 | break; |
@@ -230,7 +249,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
230 | #if !defined(__LITTLE_ENDIAN__) | 249 | #if !defined(__LITTLE_ENDIAN__) |
231 | src += 4-count; | 250 | src += 4-count; |
232 | #endif | 251 | #endif |
233 | if (copy_to_user(dst, src, count)) | 252 | if (ma->to(dst, src, count)) |
234 | goto fetch_fault; | 253 | goto fetch_fault; |
235 | ret = 0; | 254 | ret = 0; |
236 | break; | 255 | break; |
@@ -241,7 +260,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
241 | dst = (unsigned char*) rn; | 260 | dst = (unsigned char*) rn; |
242 | *(unsigned long*)dst = 0; | 261 | *(unsigned long*)dst = 0; |
243 | 262 | ||
244 | if (copy_from_user(dst,src,4)) | 263 | if (ma->from(dst, src, 4)) |
245 | goto fetch_fault; | 264 | goto fetch_fault; |
246 | ret = 0; | 265 | ret = 0; |
247 | break; | 266 | break; |
@@ -253,25 +272,12 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
253 | dst = (unsigned char*) rn; | 272 | dst = (unsigned char*) rn; |
254 | *(unsigned long*)dst = 0; | 273 | *(unsigned long*)dst = 0; |
255 | 274 | ||
256 | #ifdef __LITTLE_ENDIAN__ | 275 | #if !defined(__LITTLE_ENDIAN__) |
257 | if (copy_from_user(dst, src, count)) | ||
258 | goto fetch_fault; | ||
259 | |||
260 | if ((count == 2) && dst[1] & 0x80) { | ||
261 | dst[2] = 0xff; | ||
262 | dst[3] = 0xff; | ||
263 | } | ||
264 | #else | ||
265 | dst += 4-count; | 276 | dst += 4-count; |
266 | |||
267 | if (copy_from_user(dst, src, count)) | ||
268 | goto fetch_fault; | ||
269 | |||
270 | if ((count == 2) && dst[2] & 0x80) { | ||
271 | dst[0] = 0xff; | ||
272 | dst[1] = 0xff; | ||
273 | } | ||
274 | #endif | 277 | #endif |
278 | if (ma->from(dst, src, count)) | ||
279 | goto fetch_fault; | ||
280 | sign_extend(count, dst); | ||
275 | ret = 0; | 281 | ret = 0; |
276 | break; | 282 | break; |
277 | 283 | ||
@@ -285,7 +291,7 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
285 | dst = (unsigned char*) *rm; /* called Rn in the spec */ | 291 | dst = (unsigned char*) *rm; /* called Rn in the spec */ |
286 | dst += (instruction&0x000F)<<1; | 292 | dst += (instruction&0x000F)<<1; |
287 | 293 | ||
288 | if (copy_to_user(dst, src, 2)) | 294 | if (ma->to(dst, src, 2)) |
289 | goto fetch_fault; | 295 | goto fetch_fault; |
290 | ret = 0; | 296 | ret = 0; |
291 | break; | 297 | break; |
@@ -299,21 +305,9 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
299 | #if !defined(__LITTLE_ENDIAN__) | 305 | #if !defined(__LITTLE_ENDIAN__) |
300 | dst += 2; | 306 | dst += 2; |
301 | #endif | 307 | #endif |
302 | 308 | if (ma->from(dst, src, 2)) | |
303 | if (copy_from_user(dst, src, 2)) | ||
304 | goto fetch_fault; | 309 | goto fetch_fault; |
305 | 310 | sign_extend(2, dst); | |
306 | #ifdef __LITTLE_ENDIAN__ | ||
307 | if (dst[1] & 0x80) { | ||
308 | dst[2] = 0xff; | ||
309 | dst[3] = 0xff; | ||
310 | } | ||
311 | #else | ||
312 | if (dst[2] & 0x80) { | ||
313 | dst[0] = 0xff; | ||
314 | dst[1] = 0xff; | ||
315 | } | ||
316 | #endif | ||
317 | ret = 0; | 311 | ret = 0; |
318 | break; | 312 | break; |
319 | } | 313 | } |
@@ -332,11 +326,14 @@ static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) | |||
332 | * emulate the instruction in the delay slot | 326 | * emulate the instruction in the delay slot |
333 | * - fetches the instruction from PC+2 | 327 | * - fetches the instruction from PC+2 |
334 | */ | 328 | */ |
335 | static inline int handle_unaligned_delayslot(struct pt_regs *regs) | 329 | static inline int handle_delayslot(struct pt_regs *regs, |
330 | opcode_t old_instruction, | ||
331 | struct mem_access *ma) | ||
336 | { | 332 | { |
337 | u16 instruction; | 333 | opcode_t instruction; |
334 | void *addr = (void *)(regs->pc + instruction_size(old_instruction)); | ||
338 | 335 | ||
339 | if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) { | 336 | if (copy_from_user(&instruction, addr, sizeof(instruction))) { |
340 | /* the instruction-fetch faulted */ | 337 | /* the instruction-fetch faulted */ |
341 | if (user_mode(regs)) | 338 | if (user_mode(regs)) |
342 | return -EFAULT; | 339 | return -EFAULT; |
@@ -346,7 +343,7 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) | |||
346 | regs, 0); | 343 | regs, 0); |
347 | } | 344 | } |
348 | 345 | ||
349 | return handle_unaligned_ins(instruction,regs); | 346 | return handle_unaligned_ins(instruction, regs, ma); |
350 | } | 347 | } |
351 | 348 | ||
352 | /* | 349 | /* |
@@ -369,10 +366,11 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs) | |||
369 | * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit | 366 | * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit |
370 | * opcodes.. | 367 | * opcodes.. |
371 | */ | 368 | */ |
372 | #ifndef CONFIG_CPU_SH2A | 369 | |
373 | static int handle_unaligned_notify_count = 10; | 370 | static int handle_unaligned_notify_count = 10; |
374 | 371 | ||
375 | static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | 372 | int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, |
373 | struct mem_access *ma) | ||
376 | { | 374 | { |
377 | u_int rm; | 375 | u_int rm; |
378 | int ret, index; | 376 | int ret, index; |
@@ -387,7 +385,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
387 | printk(KERN_NOTICE "Fixing up unaligned userspace access " | 385 | printk(KERN_NOTICE "Fixing up unaligned userspace access " |
388 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", | 386 | "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", |
389 | current->comm, task_pid_nr(current), | 387 | current->comm, task_pid_nr(current), |
390 | (u16 *)regs->pc, instruction); | 388 | (void *)regs->pc, instruction); |
391 | } | 389 | } |
392 | 390 | ||
393 | ret = -EFAULT; | 391 | ret = -EFAULT; |
@@ -395,19 +393,19 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
395 | case 0x0000: | 393 | case 0x0000: |
396 | if (instruction==0x000B) { | 394 | if (instruction==0x000B) { |
397 | /* rts */ | 395 | /* rts */ |
398 | ret = handle_unaligned_delayslot(regs); | 396 | ret = handle_delayslot(regs, instruction, ma); |
399 | if (ret==0) | 397 | if (ret==0) |
400 | regs->pc = regs->pr; | 398 | regs->pc = regs->pr; |
401 | } | 399 | } |
402 | else if ((instruction&0x00FF)==0x0023) { | 400 | else if ((instruction&0x00FF)==0x0023) { |
403 | /* braf @Rm */ | 401 | /* braf @Rm */ |
404 | ret = handle_unaligned_delayslot(regs); | 402 | ret = handle_delayslot(regs, instruction, ma); |
405 | if (ret==0) | 403 | if (ret==0) |
406 | regs->pc += rm + 4; | 404 | regs->pc += rm + 4; |
407 | } | 405 | } |
408 | else if ((instruction&0x00FF)==0x0003) { | 406 | else if ((instruction&0x00FF)==0x0003) { |
409 | /* bsrf @Rm */ | 407 | /* bsrf @Rm */ |
410 | ret = handle_unaligned_delayslot(regs); | 408 | ret = handle_delayslot(regs, instruction, ma); |
411 | if (ret==0) { | 409 | if (ret==0) { |
412 | regs->pr = regs->pc + 4; | 410 | regs->pr = regs->pc + 4; |
413 | regs->pc += rm + 4; | 411 | regs->pc += rm + 4; |
@@ -428,13 +426,13 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
428 | case 0x4000: | 426 | case 0x4000: |
429 | if ((instruction&0x00FF)==0x002B) { | 427 | if ((instruction&0x00FF)==0x002B) { |
430 | /* jmp @Rm */ | 428 | /* jmp @Rm */ |
431 | ret = handle_unaligned_delayslot(regs); | 429 | ret = handle_delayslot(regs, instruction, ma); |
432 | if (ret==0) | 430 | if (ret==0) |
433 | regs->pc = rm; | 431 | regs->pc = rm; |
434 | } | 432 | } |
435 | else if ((instruction&0x00FF)==0x000B) { | 433 | else if ((instruction&0x00FF)==0x000B) { |
436 | /* jsr @Rm */ | 434 | /* jsr @Rm */ |
437 | ret = handle_unaligned_delayslot(regs); | 435 | ret = handle_delayslot(regs, instruction, ma); |
438 | if (ret==0) { | 436 | if (ret==0) { |
439 | regs->pr = regs->pc + 4; | 437 | regs->pr = regs->pc + 4; |
440 | regs->pc = rm; | 438 | regs->pc = rm; |
@@ -461,7 +459,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
461 | case 0x0B00: /* bf lab - no delayslot*/ | 459 | case 0x0B00: /* bf lab - no delayslot*/ |
462 | break; | 460 | break; |
463 | case 0x0F00: /* bf/s lab */ | 461 | case 0x0F00: /* bf/s lab */ |
464 | ret = handle_unaligned_delayslot(regs); | 462 | ret = handle_delayslot(regs, instruction, ma); |
465 | if (ret==0) { | 463 | if (ret==0) { |
466 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) | 464 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) |
467 | if ((regs->sr & 0x00000001) != 0) | 465 | if ((regs->sr & 0x00000001) != 0) |
@@ -474,7 +472,7 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
474 | case 0x0900: /* bt lab - no delayslot */ | 472 | case 0x0900: /* bt lab - no delayslot */ |
475 | break; | 473 | break; |
476 | case 0x0D00: /* bt/s lab */ | 474 | case 0x0D00: /* bt/s lab */ |
477 | ret = handle_unaligned_delayslot(regs); | 475 | ret = handle_delayslot(regs, instruction, ma); |
478 | if (ret==0) { | 476 | if (ret==0) { |
479 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) | 477 | #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) |
480 | if ((regs->sr & 0x00000001) == 0) | 478 | if ((regs->sr & 0x00000001) == 0) |
@@ -488,13 +486,13 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
488 | break; | 486 | break; |
489 | 487 | ||
490 | case 0xA000: /* bra label */ | 488 | case 0xA000: /* bra label */ |
491 | ret = handle_unaligned_delayslot(regs); | 489 | ret = handle_delayslot(regs, instruction, ma); |
492 | if (ret==0) | 490 | if (ret==0) |
493 | regs->pc += SH_PC_12BIT_OFFSET(instruction); | 491 | regs->pc += SH_PC_12BIT_OFFSET(instruction); |
494 | break; | 492 | break; |
495 | 493 | ||
496 | case 0xB000: /* bsr label */ | 494 | case 0xB000: /* bsr label */ |
497 | ret = handle_unaligned_delayslot(regs); | 495 | ret = handle_delayslot(regs, instruction, ma); |
498 | if (ret==0) { | 496 | if (ret==0) { |
499 | regs->pr = regs->pc + 4; | 497 | regs->pr = regs->pc + 4; |
500 | regs->pc += SH_PC_12BIT_OFFSET(instruction); | 498 | regs->pc += SH_PC_12BIT_OFFSET(instruction); |
@@ -505,12 +503,11 @@ static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) | |||
505 | 503 | ||
506 | /* handle non-delay-slot instruction */ | 504 | /* handle non-delay-slot instruction */ |
507 | simple: | 505 | simple: |
508 | ret = handle_unaligned_ins(instruction,regs); | 506 | ret = handle_unaligned_ins(instruction, regs, ma); |
509 | if (ret==0) | 507 | if (ret==0) |
510 | regs->pc += instruction_size(instruction); | 508 | regs->pc += instruction_size(instruction); |
511 | return ret; | 509 | return ret; |
512 | } | 510 | } |
513 | #endif /* CONFIG_CPU_SH2A */ | ||
514 | 511 | ||
515 | #ifdef CONFIG_CPU_HAS_SR_RB | 512 | #ifdef CONFIG_CPU_HAS_SR_RB |
516 | #define lookup_exception_vector(x) \ | 513 | #define lookup_exception_vector(x) \ |
@@ -538,10 +535,8 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
538 | unsigned long error_code = 0; | 535 | unsigned long error_code = 0; |
539 | mm_segment_t oldfs; | 536 | mm_segment_t oldfs; |
540 | siginfo_t info; | 537 | siginfo_t info; |
541 | #ifndef CONFIG_CPU_SH2A | 538 | opcode_t instruction; |
542 | u16 instruction; | ||
543 | int tmp; | 539 | int tmp; |
544 | #endif | ||
545 | 540 | ||
546 | /* Intentional ifdef */ | 541 | /* Intentional ifdef */ |
547 | #ifdef CONFIG_CPU_HAS_SR_RB | 542 | #ifdef CONFIG_CPU_HAS_SR_RB |
@@ -561,9 +556,9 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
561 | goto uspace_segv; | 556 | goto uspace_segv; |
562 | } | 557 | } |
563 | 558 | ||
564 | #ifndef CONFIG_CPU_SH2A | ||
565 | set_fs(USER_DS); | 559 | set_fs(USER_DS); |
566 | if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { | 560 | if (copy_from_user(&instruction, (void *)(regs->pc), |
561 | sizeof(instruction))) { | ||
567 | /* Argh. Fault on the instruction itself. | 562 | /* Argh. Fault on the instruction itself. |
568 | This should never happen non-SMP | 563 | This should never happen non-SMP |
569 | */ | 564 | */ |
@@ -571,13 +566,12 @@ asmlinkage void do_address_error(struct pt_regs *regs, | |||
571 | goto uspace_segv; | 566 | goto uspace_segv; |
572 | } | 567 | } |
573 | 568 | ||
574 | tmp = handle_unaligned_access(instruction, regs); | 569 | tmp = handle_unaligned_access(instruction, regs, |
570 | &user_mem_access); | ||
575 | set_fs(oldfs); | 571 | set_fs(oldfs); |
576 | 572 | ||
577 | if (tmp==0) | 573 | if (tmp==0) |
578 | return; /* sorted */ | 574 | return; /* sorted */ |
579 | #endif | ||
580 | |||
581 | uspace_segv: | 575 | uspace_segv: |
582 | printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " | 576 | printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " |
583 | "access (PC %lx PR %lx)\n", current->comm, regs->pc, | 577 | "access (PC %lx PR %lx)\n", current->comm, regs->pc, |
@@ -592,9 +586,9 @@ uspace_segv: | |||
592 | if (regs->pc & 1) | 586 | if (regs->pc & 1) |
593 | die("unaligned program counter", regs, error_code); | 587 | die("unaligned program counter", regs, error_code); |
594 | 588 | ||
595 | #ifndef CONFIG_CPU_SH2A | ||
596 | set_fs(KERNEL_DS); | 589 | set_fs(KERNEL_DS); |
597 | if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { | 590 | if (copy_from_user(&instruction, (void *)(regs->pc), |
591 | sizeof(instruction))) { | ||
598 | /* Argh. Fault on the instruction itself. | 592 | /* Argh. Fault on the instruction itself. |
599 | This should never happen non-SMP | 593 | This should never happen non-SMP |
600 | */ | 594 | */ |
@@ -602,14 +596,8 @@ uspace_segv: | |||
602 | die("insn faulting in do_address_error", regs, 0); | 596 | die("insn faulting in do_address_error", regs, 0); |
603 | } | 597 | } |
604 | 598 | ||
605 | handle_unaligned_access(instruction, regs); | 599 | handle_unaligned_access(instruction, regs, &user_mem_access); |
606 | set_fs(oldfs); | 600 | set_fs(oldfs); |
607 | #else | ||
608 | printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " | ||
609 | "access\n", current->comm); | ||
610 | |||
611 | force_sig(SIGSEGV, current); | ||
612 | #endif | ||
613 | } | 601 | } |
614 | } | 602 | } |
615 | 603 | ||
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index c0b3c6f6edb5..a55ac81d795b 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c | |||
@@ -630,7 +630,7 @@ static int misaligned_fpu_load(struct pt_regs *regs, | |||
630 | current->thread.fpu.hard.fp_regs[destreg] = buflo; | 630 | current->thread.fpu.hard.fp_regs[destreg] = buflo; |
631 | current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; | 631 | current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; |
632 | } else { | 632 | } else { |
633 | #if defined(CONFIG_LITTLE_ENDIAN) | 633 | #if defined(CONFIG_CPU_LITTLE_ENDIAN) |
634 | current->thread.fpu.hard.fp_regs[destreg] = bufhi; | 634 | current->thread.fpu.hard.fp_regs[destreg] = bufhi; |
635 | current->thread.fpu.hard.fp_regs[destreg+1] = buflo; | 635 | current->thread.fpu.hard.fp_regs[destreg+1] = buflo; |
636 | #else | 636 | #else |
@@ -700,7 +700,7 @@ static int misaligned_fpu_store(struct pt_regs *regs, | |||
700 | buflo = current->thread.fpu.hard.fp_regs[srcreg]; | 700 | buflo = current->thread.fpu.hard.fp_regs[srcreg]; |
701 | bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; | 701 | bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; |
702 | } else { | 702 | } else { |
703 | #if defined(CONFIG_LITTLE_ENDIAN) | 703 | #if defined(CONFIG_CPU_LITTLE_ENDIAN) |
704 | bufhi = current->thread.fpu.hard.fp_regs[srcreg]; | 704 | bufhi = current->thread.fpu.hard.fp_regs[srcreg]; |
705 | buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; | 705 | buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; |
706 | #else | 706 | #else |
diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S index 3f1bd6392bb3..d1e177009a41 100644 --- a/arch/sh/kernel/vmlinux_64.lds.S +++ b/arch/sh/kernel/vmlinux_64.lds.S | |||
@@ -51,7 +51,7 @@ SECTIONS | |||
51 | KPROBES_TEXT | 51 | KPROBES_TEXT |
52 | *(.fixup) | 52 | *(.fixup) |
53 | *(.gnu.warning) | 53 | *(.gnu.warning) |
54 | #ifdef CONFIG_LITTLE_ENDIAN | 54 | #ifdef CONFIG_CPU_LITTLE_ENDIAN |
55 | } = 0x6ff0fff0 | 55 | } = 0x6ff0fff0 |
56 | #else | 56 | #else |
57 | } = 0xf0fff06f | 57 | } = 0xf0fff06f |