diff options
Diffstat (limited to 'arch/sh/kernel')
42 files changed, 2203 insertions, 2068 deletions
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 48edfb145fb4..2e1b86e16ab5 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 | |||
@@ -4,25 +4,31 @@ | |||
4 | 4 | ||
5 | extra-y := head_32.o init_task.o vmlinux.lds | 5 | extra-y := head_32.o init_task.o vmlinux.lds |
6 | 6 | ||
7 | obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \ | 7 | ifdef CONFIG_FUNCTION_TRACER |
8 | ptrace_32.o setup.o signal_32.o sys_sh.o sys_sh32.o \ | 8 | # Do not profile debug and lowlevel utilities |
9 | syscalls_32.o time_32.o topology.o traps.o traps_32.o | 9 | CFLAGS_REMOVE_ftrace.o = -pg |
10 | endif | ||
11 | |||
12 | obj-y := debugtraps.o idle.o io.o io_generic.o irq.o \ | ||
13 | machvec.o process_32.o ptrace_32.o setup.o signal_32.o \ | ||
14 | sys_sh.o sys_sh32.o syscalls_32.o time_32.o topology.o \ | ||
15 | traps.o traps_32.o | ||
10 | 16 | ||
11 | obj-y += cpu/ timers/ | 17 | obj-y += cpu/ timers/ |
12 | obj-$(CONFIG_VSYSCALL) += vsyscall/ | 18 | obj-$(CONFIG_VSYSCALL) += vsyscall/ |
13 | obj-$(CONFIG_SMP) += smp.o | 19 | obj-$(CONFIG_SMP) += smp.o |
14 | obj-$(CONFIG_CF_ENABLER) += cf-enabler.o | ||
15 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o | 20 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o |
16 | obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o | 21 | obj-$(CONFIG_KGDB) += kgdb.o |
17 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o | 22 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o |
18 | obj-$(CONFIG_MODULES) += sh_ksyms_32.o module.o | 23 | obj-$(CONFIG_MODULES) += sh_ksyms_32.o module.o |
19 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 24 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
20 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 25 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
21 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 26 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
22 | obj-$(CONFIG_PM) += pm.o | ||
23 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 27 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
24 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o | 28 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o |
25 | obj-$(CONFIG_KPROBES) += kprobes.o | 29 | obj-$(CONFIG_KPROBES) += kprobes.o |
26 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o | 30 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o |
31 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | ||
32 | obj-$(CONFIG_DUMP_CODE) += disassemble.o | ||
27 | 33 | ||
28 | EXTRA_CFLAGS += -Werror | 34 | EXTRA_CFLAGS += -Werror |
diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index c97660b2b48d..fe425d7f6871 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 | |||
@@ -1,21 +1,18 @@ | |||
1 | extra-y := head_64.o init_task.o vmlinux.lds | 1 | extra-y := head_64.o init_task.o vmlinux.lds |
2 | 2 | ||
3 | obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_64.o \ | 3 | obj-y := debugtraps.o idle.o io.o io_generic.o irq.o machvec.o process_64.o \ |
4 | ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \ | 4 | ptrace_64.o setup.o signal_64.o sys_sh.o sys_sh64.o \ |
5 | syscalls_64.o time_64.o topology.o traps.o traps_64.o | 5 | syscalls_64.o time_64.o topology.o traps.o traps_64.o |
6 | 6 | ||
7 | obj-y += cpu/ timers/ | 7 | obj-y += cpu/ timers/ |
8 | obj-$(CONFIG_VSYSCALL) += vsyscall/ | 8 | obj-$(CONFIG_VSYSCALL) += vsyscall/ |
9 | obj-$(CONFIG_SMP) += smp.o | 9 | obj-$(CONFIG_SMP) += smp.o |
10 | obj-$(CONFIG_CF_ENABLER) += cf-enabler.o | ||
11 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o | 10 | obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o |
12 | obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o | ||
13 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o | 11 | obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o |
14 | obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o | 12 | obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o |
15 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 13 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
16 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 14 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
17 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 15 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
18 | obj-$(CONFIG_PM) += pm.o | ||
19 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 16 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
20 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o | 17 | obj-$(CONFIG_IO_TRAPPED) += io_trapped.o |
21 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o | 18 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o |
diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c deleted file mode 100644 index bea40339919b..000000000000 --- a/arch/sh/kernel/cf-enabler.c +++ /dev/null | |||
@@ -1,168 +0,0 @@ | |||
1 | /* $Id: cf-enabler.c,v 1.4 2004/02/22 22:44:36 kkojima Exp $ | ||
2 | * | ||
3 | * linux/drivers/block/cf-enabler.c | ||
4 | * | ||
5 | * Copyright (C) 1999 Niibe Yutaka | ||
6 | * Copyright (C) 2000 Toshiharu Nozawa | ||
7 | * Copyright (C) 2001 A&D Co., Ltd. | ||
8 | * | ||
9 | * Enable the CF configuration. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/mm.h> | ||
14 | #include <linux/vmalloc.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/irq.h> | ||
18 | |||
19 | /* | ||
20 | * You can connect Compact Flash directly to the bus of SuperH. | ||
21 | * This is the enabler for that. | ||
22 | * | ||
23 | * SIM: How generic is this really? It looks pretty board, or at | ||
24 | * least SH sub-type, specific to me. | ||
25 | * I know it doesn't work on the Overdrive! | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | * 0xB8000000 : Attribute | ||
30 | * 0xB8001000 : Common Memory | ||
31 | * 0xBA000000 : I/O | ||
32 | */ | ||
33 | #if defined(CONFIG_CPU_SH4) | ||
34 | /* SH4 can't access PCMCIA interface through P2 area. | ||
35 | * we must remap it with appropriate attribute bit of the page set. | ||
36 | * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */ | ||
37 | |||
38 | #if defined(CONFIG_CF_AREA6) | ||
39 | #define slot_no 0 | ||
40 | #else | ||
41 | #define slot_no 1 | ||
42 | #endif | ||
43 | |||
44 | /* use this pointer to access to directly connected compact flash io area*/ | ||
45 | void *cf_io_base; | ||
46 | |||
47 | static int __init allocate_cf_area(void) | ||
48 | { | ||
49 | pgprot_t prot; | ||
50 | unsigned long paddrbase, psize; | ||
51 | |||
52 | /* open I/O area window */ | ||
53 | paddrbase = virt_to_phys((void*)CONFIG_CF_BASE_ADDR); | ||
54 | psize = PAGE_SIZE; | ||
55 | prot = PAGE_KERNEL_PCC(slot_no, _PAGE_PCC_IO16); | ||
56 | cf_io_base = p3_ioremap(paddrbase, psize, prot.pgprot); | ||
57 | if (!cf_io_base) { | ||
58 | printk("allocate_cf_area : can't open CF I/O window!\n"); | ||
59 | return -ENOMEM; | ||
60 | } | ||
61 | /* printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n", | ||
62 | paddrbase, psize, prot.pgprot, cf_io_base);*/ | ||
63 | |||
64 | /* XXX : do we need attribute and common-memory area also? */ | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | #endif | ||
69 | |||
70 | static int __init cf_init_default(void) | ||
71 | { | ||
72 | /* You must have enabled the card, and set the level interrupt | ||
73 | * before reaching this point. Possibly in boot ROM or boot loader. | ||
74 | */ | ||
75 | #if defined(CONFIG_CPU_SH4) | ||
76 | allocate_cf_area(); | ||
77 | #endif | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | #if defined(CONFIG_SH_SOLUTION_ENGINE) | ||
83 | #include <mach-se/mach/se.h> | ||
84 | #elif defined(CONFIG_SH_7722_SOLUTION_ENGINE) | ||
85 | #include <mach-se/mach/se7722.h> | ||
86 | #elif defined(CONFIG_SH_7721_SOLUTION_ENGINE) | ||
87 | #include <mach-se/mach/se7721.h> | ||
88 | #endif | ||
89 | |||
90 | /* | ||
91 | * SolutionEngine Seriese | ||
92 | * | ||
93 | * about MS770xSE | ||
94 | * 0xB8400000 : Common Memory | ||
95 | * 0xB8500000 : Attribute | ||
96 | * 0xB8600000 : I/O | ||
97 | * | ||
98 | * about MS7722SE | ||
99 | * 0xB0400000 : Common Memory | ||
100 | * 0xB0500000 : Attribute | ||
101 | * 0xB0600000 : I/O | ||
102 | */ | ||
103 | |||
104 | #if defined(CONFIG_SH_SOLUTION_ENGINE) || \ | ||
105 | defined(CONFIG_SH_7722_SOLUTION_ENGINE) || \ | ||
106 | defined(CONFIG_SH_7721_SOLUTION_ENGINE) | ||
107 | static int __init cf_init_se(void) | ||
108 | { | ||
109 | if ((ctrl_inw(MRSHPC_CSR) & 0x000c) != 0) | ||
110 | return 0; /* Not detected */ | ||
111 | |||
112 | if ((ctrl_inw(MRSHPC_CSR) & 0x0080) == 0) { | ||
113 | ctrl_outw(0x0674, MRSHPC_CPWCR); /* Card Vcc is 3.3v? */ | ||
114 | } else { | ||
115 | ctrl_outw(0x0678, MRSHPC_CPWCR); /* Card Vcc is 5V */ | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * PC-Card window open | ||
120 | * flag == COMMON/ATTRIBUTE/IO | ||
121 | */ | ||
122 | /* common window open */ | ||
123 | ctrl_outw(0x8a84, MRSHPC_MW0CR1); | ||
124 | if((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) | ||
125 | /* common mode & bus width 16bit SWAP = 1*/ | ||
126 | ctrl_outw(0x0b00, MRSHPC_MW0CR2); | ||
127 | else | ||
128 | /* common mode & bus width 16bit SWAP = 0*/ | ||
129 | ctrl_outw(0x0300, MRSHPC_MW0CR2); | ||
130 | |||
131 | /* attribute window open */ | ||
132 | ctrl_outw(0x8a85, MRSHPC_MW1CR1); | ||
133 | if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) | ||
134 | /* attribute mode & bus width 16bit SWAP = 1*/ | ||
135 | ctrl_outw(0x0a00, MRSHPC_MW1CR2); | ||
136 | else | ||
137 | /* attribute mode & bus width 16bit SWAP = 0*/ | ||
138 | ctrl_outw(0x0200, MRSHPC_MW1CR2); | ||
139 | |||
140 | /* I/O window open */ | ||
141 | ctrl_outw(0x8a86, MRSHPC_IOWCR1); | ||
142 | ctrl_outw(0x0008, MRSHPC_CDCR); /* I/O card mode */ | ||
143 | if ((ctrl_inw(MRSHPC_CSR) & 0x4000) != 0) | ||
144 | ctrl_outw(0x0a00, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1*/ | ||
145 | else | ||
146 | ctrl_outw(0x0200, MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0*/ | ||
147 | |||
148 | ctrl_outw(0x2000, MRSHPC_ICR); | ||
149 | ctrl_outb(0x00, PA_MRSHPC_MW2 + 0x206); | ||
150 | ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200); | ||
151 | return 0; | ||
152 | } | ||
153 | #else | ||
154 | static int __init cf_init_se(void) | ||
155 | { | ||
156 | return -1; | ||
157 | } | ||
158 | #endif | ||
159 | |||
160 | static int __init cf_init(void) | ||
161 | { | ||
162 | if (mach_is_se() || mach_is_7722se() || mach_is_7721se()) | ||
163 | return cf_init_se(); | ||
164 | |||
165 | return cf_init_default(); | ||
166 | } | ||
167 | |||
168 | __initcall (cf_init); | ||
diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index b7e46d5bba43..7b17137536d6 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c | |||
@@ -117,6 +117,11 @@ int clk_enable(struct clk *clk) | |||
117 | unsigned long flags; | 117 | unsigned long flags; |
118 | int ret; | 118 | int ret; |
119 | 119 | ||
120 | if (!clk) | ||
121 | return -EINVAL; | ||
122 | |||
123 | clk_enable(clk->parent); | ||
124 | |||
120 | spin_lock_irqsave(&clock_lock, flags); | 125 | spin_lock_irqsave(&clock_lock, flags); |
121 | ret = __clk_enable(clk); | 126 | ret = __clk_enable(clk); |
122 | spin_unlock_irqrestore(&clock_lock, flags); | 127 | spin_unlock_irqrestore(&clock_lock, flags); |
@@ -147,9 +152,14 @@ void clk_disable(struct clk *clk) | |||
147 | { | 152 | { |
148 | unsigned long flags; | 153 | unsigned long flags; |
149 | 154 | ||
155 | if (!clk) | ||
156 | return; | ||
157 | |||
150 | spin_lock_irqsave(&clock_lock, flags); | 158 | spin_lock_irqsave(&clock_lock, flags); |
151 | __clk_disable(clk); | 159 | __clk_disable(clk); |
152 | spin_unlock_irqrestore(&clock_lock, flags); | 160 | spin_unlock_irqrestore(&clock_lock, flags); |
161 | |||
162 | clk_disable(clk->parent); | ||
153 | } | 163 | } |
154 | EXPORT_SYMBOL_GPL(clk_disable); | 164 | EXPORT_SYMBOL_GPL(clk_disable); |
155 | 165 | ||
diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 75fb03d35670..d29e69c156f0 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c | |||
@@ -261,9 +261,11 @@ asmlinkage void __init sh_cpu_init(void) | |||
261 | cache_init(); | 261 | cache_init(); |
262 | 262 | ||
263 | if (raw_smp_processor_id() == 0) { | 263 | if (raw_smp_processor_id() == 0) { |
264 | #ifdef CONFIG_MMU | ||
264 | shm_align_mask = max_t(unsigned long, | 265 | shm_align_mask = max_t(unsigned long, |
265 | current_cpu_data.dcache.way_size - 1, | 266 | current_cpu_data.dcache.way_size - 1, |
266 | PAGE_SIZE - 1); | 267 | PAGE_SIZE - 1); |
268 | #endif | ||
267 | 269 | ||
268 | /* Boot CPU sets the cache shape */ | 270 | /* Boot CPU sets the cache shape */ |
269 | detect_cache_shape(); | 271 | detect_cache_shape(); |
diff --git a/arch/sh/kernel/cpu/sh2a/Makefile b/arch/sh/kernel/cpu/sh2a/Makefile index 428450cc0809..45f85c77ef75 100644 --- a/arch/sh/kernel/cpu/sh2a/Makefile +++ b/arch/sh/kernel/cpu/sh2a/Makefile | |||
@@ -8,9 +8,10 @@ common-y += ex.o entry.o | |||
8 | 8 | ||
9 | obj-$(CONFIG_SH_FPU) += fpu.o | 9 | obj-$(CONFIG_SH_FPU) += fpu.o |
10 | 10 | ||
11 | obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o | 11 | obj-$(CONFIG_CPU_SUBTYPE_SH7201) += setup-sh7201.o clock-sh7201.o |
12 | obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o | 12 | obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o |
13 | obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o | 13 | obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o |
14 | obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o | ||
14 | obj-$(CONFIG_CPU_SUBTYPE_MXG) += setup-mxg.o clock-sh7206.o | 15 | obj-$(CONFIG_CPU_SUBTYPE_MXG) += setup-mxg.o clock-sh7206.o |
15 | 16 | ||
16 | # Pinmux setup | 17 | # Pinmux setup |
diff --git a/arch/sh/kernel/cpu/sh2a/clock-sh7201.c b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c new file mode 100644 index 000000000000..020a96fe961a --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/clock-sh7201.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/cpu/sh2a/clock-sh7201.c | ||
3 | * | ||
4 | * SH7201 support for the clock framework | ||
5 | * | ||
6 | * Copyright (C) 2008 Peter Griffin <pgriffin@mpc-data.co.uk> | ||
7 | * | ||
8 | * Based on clock-sh4.c | ||
9 | * Copyright (C) 2005 Paul Mundt | ||
10 | * | ||
11 | * This file is subject to the terms and conditions of the GNU General Public | ||
12 | * License. See the file "COPYING" in the main directory of this archive | ||
13 | * for more details. | ||
14 | */ | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <asm/clock.h> | ||
18 | #include <asm/freq.h> | ||
19 | #include <asm/io.h> | ||
20 | |||
21 | const static int pll1rate[]={1,2,3,4,6,8}; | ||
22 | const static int pfc_divisors[]={1,2,3,4,6,8,12}; | ||
23 | #define ifc_divisors pfc_divisors | ||
24 | |||
25 | #if (CONFIG_SH_CLK_MD == 0) | ||
26 | #define PLL2 (4) | ||
27 | #elif (CONFIG_SH_CLK_MD == 2) | ||
28 | #define PLL2 (2) | ||
29 | #elif (CONFIG_SH_CLK_MD == 3) | ||
30 | #define PLL2 (1) | ||
31 | #else | ||
32 | #error "Illegal Clock Mode!" | ||
33 | #endif | ||
34 | |||
35 | static void master_clk_init(struct clk *clk) | ||
36 | { | ||
37 | clk->rate = 10000000 * PLL2 * pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0007]; | ||
38 | } | ||
39 | |||
40 | static struct clk_ops sh7201_master_clk_ops = { | ||
41 | .init = master_clk_init, | ||
42 | }; | ||
43 | |||
44 | static void module_clk_recalc(struct clk *clk) | ||
45 | { | ||
46 | int idx = (ctrl_inw(FREQCR) & 0x0007); | ||
47 | clk->rate = clk->parent->rate / pfc_divisors[idx]; | ||
48 | } | ||
49 | |||
50 | static struct clk_ops sh7201_module_clk_ops = { | ||
51 | .recalc = module_clk_recalc, | ||
52 | }; | ||
53 | |||
54 | static void bus_clk_recalc(struct clk *clk) | ||
55 | { | ||
56 | int idx = (ctrl_inw(FREQCR) & 0x0007); | ||
57 | clk->rate = clk->parent->rate / pfc_divisors[idx]; | ||
58 | } | ||
59 | |||
60 | static struct clk_ops sh7201_bus_clk_ops = { | ||
61 | .recalc = bus_clk_recalc, | ||
62 | }; | ||
63 | |||
64 | static void cpu_clk_recalc(struct clk *clk) | ||
65 | { | ||
66 | int idx = ((ctrl_inw(FREQCR) >> 4) & 0x0007); | ||
67 | clk->rate = clk->parent->rate / ifc_divisors[idx]; | ||
68 | } | ||
69 | |||
70 | static struct clk_ops sh7201_cpu_clk_ops = { | ||
71 | .recalc = cpu_clk_recalc, | ||
72 | }; | ||
73 | |||
74 | static struct clk_ops *sh7201_clk_ops[] = { | ||
75 | &sh7201_master_clk_ops, | ||
76 | &sh7201_module_clk_ops, | ||
77 | &sh7201_bus_clk_ops, | ||
78 | &sh7201_cpu_clk_ops, | ||
79 | }; | ||
80 | |||
81 | void __init arch_init_clk_ops(struct clk_ops **ops, int idx) | ||
82 | { | ||
83 | if (idx < ARRAY_SIZE(sh7201_clk_ops)) | ||
84 | *ops = sh7201_clk_ops[idx]; | ||
85 | } | ||
diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c index 6e79132f6f30..e098e2f6aa08 100644 --- a/arch/sh/kernel/cpu/sh2a/probe.c +++ b/arch/sh/kernel/cpu/sh2a/probe.c | |||
@@ -18,16 +18,17 @@ int __init detect_cpu_and_cache_system(void) | |||
18 | /* All SH-2A CPUs have support for 16 and 32-bit opcodes.. */ | 18 | /* All SH-2A CPUs have support for 16 and 32-bit opcodes.. */ |
19 | boot_cpu_data.flags |= CPU_HAS_OP32; | 19 | boot_cpu_data.flags |= CPU_HAS_OP32; |
20 | 20 | ||
21 | #if defined(CONFIG_CPU_SUBTYPE_SH7203) | 21 | #if defined(CONFIG_CPU_SUBTYPE_SH7201) |
22 | boot_cpu_data.type = CPU_SH7201; | ||
23 | boot_cpu_data.flags |= CPU_HAS_FPU; | ||
24 | #elif defined(CONFIG_CPU_SUBTYPE_SH7203) | ||
22 | boot_cpu_data.type = CPU_SH7203; | 25 | boot_cpu_data.type = CPU_SH7203; |
23 | /* SH7203 has an FPU.. */ | ||
24 | boot_cpu_data.flags |= CPU_HAS_FPU; | 26 | boot_cpu_data.flags |= CPU_HAS_FPU; |
25 | #elif defined(CONFIG_CPU_SUBTYPE_SH7263) | 27 | #elif defined(CONFIG_CPU_SUBTYPE_SH7263) |
26 | boot_cpu_data.type = CPU_SH7263; | 28 | boot_cpu_data.type = CPU_SH7263; |
27 | boot_cpu_data.flags |= CPU_HAS_FPU; | 29 | boot_cpu_data.flags |= CPU_HAS_FPU; |
28 | #elif defined(CONFIG_CPU_SUBTYPE_SH7206) | 30 | #elif defined(CONFIG_CPU_SUBTYPE_SH7206) |
29 | boot_cpu_data.type = CPU_SH7206; | 31 | boot_cpu_data.type = CPU_SH7206; |
30 | /* While SH7206 has a DSP.. */ | ||
31 | boot_cpu_data.flags |= CPU_HAS_DSP; | 32 | boot_cpu_data.flags |= CPU_HAS_DSP; |
32 | #elif defined(CONFIG_CPU_SUBTYPE_MXG) | 33 | #elif defined(CONFIG_CPU_SUBTYPE_MXG) |
33 | boot_cpu_data.type = CPU_MXG; | 34 | boot_cpu_data.type = CPU_MXG; |
diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c new file mode 100644 index 000000000000..0631e421c022 --- /dev/null +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /* | ||
2 | * SH7201 setup | ||
3 | * | ||
4 | * Copyright (C) 2008 Peter Griffin pgriffin@mpc-data.co.uk | ||
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/serial_sci.h> | ||
14 | |||
15 | enum { | ||
16 | UNUSED = 0, | ||
17 | |||
18 | /* interrupt sources */ | ||
19 | IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, | ||
20 | PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7, | ||
21 | ADC_ADI, | ||
22 | MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D, | ||
23 | MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F, | ||
24 | MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U, | ||
25 | MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U, | ||
26 | MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V, | ||
27 | MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V, | ||
28 | MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W, | ||
29 | RTC_ARM, RTC_PRD, RTC_CUP, | ||
30 | WDT, | ||
31 | IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, IIC30_TEI, | ||
32 | IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, IIC31_TEI, | ||
33 | IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, IIC32_TEI, | ||
34 | |||
35 | DMAC0_DMINT0, DMAC1_DMINT1, | ||
36 | DMAC2_DMINT2, DMAC3_DMINT3, | ||
37 | |||
38 | SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI, | ||
39 | SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI, | ||
40 | SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI, | ||
41 | SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI, | ||
42 | SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI, | ||
43 | SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI, | ||
44 | SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI, | ||
45 | SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI, | ||
46 | |||
47 | DMAC0_DMINTA, DMAC4_DMINT4, DMAC5_DMINT5, DMAC6_DMINT6, | ||
48 | DMAC7_DMINT7, | ||
49 | |||
50 | RCAN0_ERS, RCAN0_OVR, | ||
51 | RCAN0_SLE, | ||
52 | RCAN0_RM0, RCAN0_RM1, | ||
53 | |||
54 | RCAN1_ERS, RCAN1_OVR, | ||
55 | RCAN1_SLE, | ||
56 | RCAN1_RM0, RCAN1_RM1, | ||
57 | |||
58 | SSI0_SSII, SSI1_SSII, | ||
59 | |||
60 | TMR0_CMIA0, TMR0_CMIB0, TMR0_OVI0, | ||
61 | TMR1_CMIA1, TMR1_CMIB1, TMR1_OVI1, | ||
62 | |||
63 | /* interrupt groups */ | ||
64 | |||
65 | IRQ, PINT, ADC, | ||
66 | MTU20_ABCD, MTU20_VEF, MTU21_AB, MTU21_VU, MTU22_AB, MTU22_VU, | ||
67 | MTU23_ABCD, MTU24_ABCD, MTU25_UVW, | ||
68 | RTC, IIC30, IIC31, IIC32, | ||
69 | SCIF0, SCIF1, SCIF2, SCIF3, SCIF4, SCIF5, SCIF6, SCIF7, | ||
70 | RCAN0, RCAN1, TMR0, TMR1 | ||
71 | |||
72 | }; | ||
73 | |||
74 | static struct intc_vect vectors[] __initdata = { | ||
75 | INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65), | ||
76 | INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67), | ||
77 | INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69), | ||
78 | INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71), | ||
79 | INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81), | ||
80 | INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83), | ||
81 | INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85), | ||
82 | INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87), | ||
83 | |||
84 | INTC_IRQ(ADC_ADI, 92), | ||
85 | |||
86 | INTC_IRQ(MTU2_TGI0A, 108), INTC_IRQ(MTU2_TGI0B, 109), | ||
87 | INTC_IRQ(MTU2_TGI0C, 110), INTC_IRQ(MTU2_TGI0D, 111), | ||
88 | INTC_IRQ(MTU2_TCI0V, 112), | ||
89 | INTC_IRQ(MTU2_TGI0E, 113), INTC_IRQ(MTU2_TGI0F, 114), | ||
90 | |||
91 | INTC_IRQ(MTU2_TGI1A, 116), INTC_IRQ(MTU2_TGI1B, 117), | ||
92 | INTC_IRQ(MTU2_TCI1V, 120), INTC_IRQ(MTU2_TCI1U, 121), | ||
93 | |||
94 | INTC_IRQ(MTU2_TGI2A, 124), INTC_IRQ(MTU2_TGI2B, 125), | ||
95 | INTC_IRQ(MTU2_TCI2V, 128), INTC_IRQ(MTU2_TCI2U, 129), | ||
96 | |||
97 | INTC_IRQ(MTU2_TGI3A, 132), INTC_IRQ(MTU2_TGI3B, 133), | ||
98 | INTC_IRQ(MTU2_TGI3C, 134), INTC_IRQ(MTU2_TGI3D, 135), | ||
99 | INTC_IRQ(MTU2_TCI3V, 136), | ||
100 | |||
101 | INTC_IRQ(MTU2_TGI4A, 140), INTC_IRQ(MTU2_TGI4B, 141), | ||
102 | INTC_IRQ(MTU2_TGI4C, 142), INTC_IRQ(MTU2_TGI4D, 143), | ||
103 | INTC_IRQ(MTU2_TCI4V, 144), | ||
104 | |||
105 | INTC_IRQ(MTU2_TGI5U, 148), INTC_IRQ(MTU2_TGI5V, 149), | ||
106 | INTC_IRQ(MTU2_TGI5W, 150), | ||
107 | |||
108 | INTC_IRQ(RTC_ARM, 152), INTC_IRQ(RTC_PRD, 153), | ||
109 | INTC_IRQ(RTC_CUP, 154), INTC_IRQ(WDT, 156), | ||
110 | |||
111 | INTC_IRQ(IIC30_STPI, 157), INTC_IRQ(IIC30_NAKI, 158), | ||
112 | INTC_IRQ(IIC30_RXI, 159), INTC_IRQ(IIC30_TXI, 160), | ||
113 | INTC_IRQ(IIC30_TEI, 161), | ||
114 | |||
115 | INTC_IRQ(IIC31_STPI, 164), INTC_IRQ(IIC31_NAKI, 165), | ||
116 | INTC_IRQ(IIC31_RXI, 166), INTC_IRQ(IIC31_TXI, 167), | ||
117 | INTC_IRQ(IIC31_TEI, 168), | ||
118 | |||
119 | INTC_IRQ(IIC32_STPI, 170), INTC_IRQ(IIC32_NAKI, 171), | ||
120 | INTC_IRQ(IIC32_RXI, 172), INTC_IRQ(IIC32_TXI, 173), | ||
121 | INTC_IRQ(IIC32_TEI, 174), | ||
122 | |||
123 | INTC_IRQ(DMAC0_DMINT0, 176), INTC_IRQ(DMAC1_DMINT1, 177), | ||
124 | INTC_IRQ(DMAC2_DMINT2, 178), INTC_IRQ(DMAC3_DMINT3, 179), | ||
125 | |||
126 | INTC_IRQ(SCIF0_BRI, 180), INTC_IRQ(SCIF0_ERI, 181), | ||
127 | INTC_IRQ(SCIF0_RXI, 182), INTC_IRQ(SCIF0_TXI, 183), | ||
128 | INTC_IRQ(SCIF1_BRI, 184), INTC_IRQ(SCIF1_ERI, 185), | ||
129 | INTC_IRQ(SCIF1_RXI, 186), INTC_IRQ(SCIF1_TXI, 187), | ||
130 | INTC_IRQ(SCIF2_BRI, 188), INTC_IRQ(SCIF2_ERI, 189), | ||
131 | INTC_IRQ(SCIF2_RXI, 190), INTC_IRQ(SCIF2_TXI, 191), | ||
132 | INTC_IRQ(SCIF3_BRI, 192), INTC_IRQ(SCIF3_ERI, 193), | ||
133 | INTC_IRQ(SCIF3_RXI, 194), INTC_IRQ(SCIF3_TXI, 195), | ||
134 | INTC_IRQ(SCIF4_BRI, 196), INTC_IRQ(SCIF4_ERI, 197), | ||
135 | INTC_IRQ(SCIF4_RXI, 198), INTC_IRQ(SCIF4_TXI, 199), | ||
136 | INTC_IRQ(SCIF5_BRI, 200), INTC_IRQ(SCIF5_ERI, 201), | ||
137 | INTC_IRQ(SCIF5_RXI, 202), INTC_IRQ(SCIF5_TXI, 203), | ||
138 | INTC_IRQ(SCIF6_BRI, 204), INTC_IRQ(SCIF6_ERI, 205), | ||
139 | INTC_IRQ(SCIF6_RXI, 206), INTC_IRQ(SCIF6_TXI, 207), | ||
140 | INTC_IRQ(SCIF7_BRI, 208), INTC_IRQ(SCIF7_ERI, 209), | ||
141 | INTC_IRQ(SCIF7_RXI, 210), INTC_IRQ(SCIF7_TXI, 211), | ||
142 | |||
143 | INTC_IRQ(DMAC0_DMINTA, 212), INTC_IRQ(DMAC4_DMINT4, 216), | ||
144 | INTC_IRQ(DMAC5_DMINT5, 217), INTC_IRQ(DMAC6_DMINT6, 218), | ||
145 | INTC_IRQ(DMAC7_DMINT7, 219), | ||
146 | |||
147 | INTC_IRQ(RCAN0_ERS, 228), INTC_IRQ(RCAN0_OVR, 229), | ||
148 | INTC_IRQ(RCAN0_SLE, 230), | ||
149 | INTC_IRQ(RCAN0_RM0, 231), INTC_IRQ(RCAN0_RM1, 232), | ||
150 | |||
151 | INTC_IRQ(RCAN1_ERS, 234), INTC_IRQ(RCAN1_OVR, 235), | ||
152 | INTC_IRQ(RCAN1_SLE, 236), | ||
153 | INTC_IRQ(RCAN1_RM0, 237), INTC_IRQ(RCAN1_RM1, 238), | ||
154 | |||
155 | INTC_IRQ(SSI0_SSII, 244), INTC_IRQ(SSI1_SSII, 245), | ||
156 | |||
157 | INTC_IRQ(TMR0_CMIA0, 246), INTC_IRQ(TMR0_CMIB0, 247), | ||
158 | INTC_IRQ(TMR0_OVI0, 248), | ||
159 | |||
160 | INTC_IRQ(TMR1_CMIA1, 252), INTC_IRQ(TMR1_CMIB1, 253), | ||
161 | INTC_IRQ(TMR1_OVI1, 254), | ||
162 | |||
163 | }; | ||
164 | |||
165 | static struct intc_group groups[] __initdata = { | ||
166 | INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3, | ||
167 | PINT4, PINT5, PINT6, PINT7), | ||
168 | INTC_GROUP(MTU20_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D), | ||
169 | INTC_GROUP(MTU20_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F), | ||
170 | |||
171 | INTC_GROUP(MTU21_AB, MTU2_TGI1A, MTU2_TGI1B), | ||
172 | INTC_GROUP(MTU21_VU, MTU2_TCI1V, MTU2_TCI1U), | ||
173 | INTC_GROUP(MTU22_AB, MTU2_TGI2A, MTU2_TGI2B), | ||
174 | INTC_GROUP(MTU22_VU, MTU2_TCI2V, MTU2_TCI2U), | ||
175 | INTC_GROUP(MTU23_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D), | ||
176 | INTC_GROUP(MTU24_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D), | ||
177 | INTC_GROUP(MTU25_UVW, MTU2_TGI5U, MTU2_TGI5V, MTU2_TGI5W), | ||
178 | INTC_GROUP(RTC, RTC_ARM, RTC_PRD, RTC_CUP ), | ||
179 | |||
180 | INTC_GROUP(IIC30, IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, | ||
181 | IIC30_TEI), | ||
182 | INTC_GROUP(IIC31, IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, | ||
183 | IIC31_TEI), | ||
184 | INTC_GROUP(IIC32, IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, | ||
185 | IIC32_TEI), | ||
186 | |||
187 | INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI), | ||
188 | INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI), | ||
189 | INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI), | ||
190 | INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI), | ||
191 | INTC_GROUP(SCIF4, SCIF4_BRI, SCIF4_ERI, SCIF4_RXI, SCIF4_TXI), | ||
192 | INTC_GROUP(SCIF5, SCIF5_BRI, SCIF5_ERI, SCIF5_RXI, SCIF5_TXI), | ||
193 | INTC_GROUP(SCIF6, SCIF6_BRI, SCIF6_ERI, SCIF6_RXI, SCIF6_TXI), | ||
194 | INTC_GROUP(SCIF7, SCIF7_BRI, SCIF7_ERI, SCIF7_RXI, SCIF7_TXI), | ||
195 | |||
196 | INTC_GROUP(RCAN0, RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1, | ||
197 | RCAN0_SLE), | ||
198 | INTC_GROUP(RCAN1, RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1, | ||
199 | RCAN1_SLE), | ||
200 | |||
201 | INTC_GROUP(TMR0, TMR0_CMIA0, TMR0_CMIB0, TMR0_OVI0), | ||
202 | INTC_GROUP(TMR1, TMR1_CMIA1, TMR1_CMIB1, TMR1_OVI1), | ||
203 | }; | ||
204 | |||
205 | static struct intc_prio_reg prio_registers[] __initdata = { | ||
206 | { 0xfffe9418, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } }, | ||
207 | { 0xfffe941a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } }, | ||
208 | { 0xfffe9420, 0, 16, 4, /* IPR05 */ { PINT, 0, ADC_ADI, 0 } }, | ||
209 | { 0xfffe9800, 0, 16, 4, /* IPR06 */ { 0, MTU20_ABCD, MTU20_VEF, MTU21_AB } }, | ||
210 | { 0xfffe9802, 0, 16, 4, /* IPR07 */ { MTU21_VU, MTU22_AB, MTU22_VU, MTU23_ABCD } }, | ||
211 | { 0xfffe9804, 0, 16, 4, /* IPR08 */ { MTU2_TCI3V, MTU24_ABCD, MTU2_TCI4V, MTU25_UVW } }, | ||
212 | |||
213 | { 0xfffe9806, 0, 16, 4, /* IPR09 */ { RTC, WDT, IIC30, 0 } }, | ||
214 | { 0xfffe9808, 0, 16, 4, /* IPR10 */ { IIC31, IIC32, DMAC0_DMINT0, DMAC1_DMINT1 } }, | ||
215 | { 0xfffe980a, 0, 16, 4, /* IPR11 */ { DMAC2_DMINT2, DMAC3_DMINT3, SCIF0 , SCIF1 } }, | ||
216 | { 0xfffe980c, 0, 16, 4, /* IPR12 */ { SCIF2, SCIF3, SCIF4, SCIF5 } }, | ||
217 | { 0xfffe980e, 0, 16, 4, /* IPR13 */ { SCIF6, SCIF7, DMAC0_DMINTA, DMAC4_DMINT4 } }, | ||
218 | { 0xfffe9810, 0, 16, 4, /* IPR14 */ { DMAC5_DMINT5, DMAC6_DMINT6, DMAC7_DMINT7, 0 } }, | ||
219 | { 0xfffe9812, 0, 16, 4, /* IPR15 */ { 0, RCAN0, RCAN1, 0 } }, | ||
220 | { 0xfffe9814, 0, 16, 4, /* IPR16 */ { SSI0_SSII, SSI1_SSII, TMR0, TMR1 } }, | ||
221 | }; | ||
222 | |||
223 | static struct intc_mask_reg mask_registers[] __initdata = { | ||
224 | { 0xfffe9408, 0, 16, /* PINTER */ | ||
225 | { 0, 0, 0, 0, 0, 0, 0, 0, | ||
226 | PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } }, | ||
227 | }; | ||
228 | |||
229 | static DECLARE_INTC_DESC(intc_desc, "sh7201", vectors, groups, | ||
230 | mask_registers, prio_registers, NULL); | ||
231 | |||
232 | static struct plat_sci_port sci_platform_data[] = { | ||
233 | { | ||
234 | .mapbase = 0xfffe8000, | ||
235 | .flags = UPF_BOOT_AUTOCONF, | ||
236 | .type = PORT_SCIF, | ||
237 | .irqs = { 181, 182, 183, 180} | ||
238 | }, { | ||
239 | .mapbase = 0xfffe8800, | ||
240 | .flags = UPF_BOOT_AUTOCONF, | ||
241 | .type = PORT_SCIF, | ||
242 | .irqs = { 185, 186, 187, 184} | ||
243 | }, { | ||
244 | .mapbase = 0xfffe9000, | ||
245 | .flags = UPF_BOOT_AUTOCONF, | ||
246 | .type = PORT_SCIF, | ||
247 | .irqs = { 189, 186, 187, 188} | ||
248 | }, { | ||
249 | .mapbase = 0xfffe9800, | ||
250 | .flags = UPF_BOOT_AUTOCONF, | ||
251 | .type = PORT_SCIF, | ||
252 | .irqs = { 193, 194, 195, 192} | ||
253 | }, { | ||
254 | .mapbase = 0xfffea000, | ||
255 | .flags = UPF_BOOT_AUTOCONF, | ||
256 | .type = PORT_SCIF, | ||
257 | .irqs = { 196, 198, 199, 196} | ||
258 | }, { | ||
259 | .mapbase = 0xfffea800, | ||
260 | .flags = UPF_BOOT_AUTOCONF, | ||
261 | .type = PORT_SCIF, | ||
262 | .irqs = { 201, 202, 203, 200} | ||
263 | }, { | ||
264 | .mapbase = 0xfffeb000, | ||
265 | .flags = UPF_BOOT_AUTOCONF, | ||
266 | .type = PORT_SCIF, | ||
267 | .irqs = { 205, 206, 207, 204} | ||
268 | }, { | ||
269 | .mapbase = 0xfffeb800, | ||
270 | .flags = UPF_BOOT_AUTOCONF, | ||
271 | .type = PORT_SCIF, | ||
272 | .irqs = { 209, 210, 211, 208} | ||
273 | }, { | ||
274 | .flags = 0, | ||
275 | } | ||
276 | }; | ||
277 | |||
278 | static struct platform_device sci_device = { | ||
279 | .name = "sh-sci", | ||
280 | .id = -1, | ||
281 | .dev = { | ||
282 | .platform_data = sci_platform_data, | ||
283 | }, | ||
284 | }; | ||
285 | |||
286 | static struct resource rtc_resources[] = { | ||
287 | [0] = { | ||
288 | .start = 0xffff0800, | ||
289 | .end = 0xffff2000 + 0x58 - 1, | ||
290 | .flags = IORESOURCE_IO, | ||
291 | }, | ||
292 | [1] = { | ||
293 | /* Period IRQ */ | ||
294 | .start = 153, | ||
295 | .flags = IORESOURCE_IRQ, | ||
296 | }, | ||
297 | [2] = { | ||
298 | /* Carry IRQ */ | ||
299 | .start = 154, | ||
300 | .flags = IORESOURCE_IRQ, | ||
301 | }, | ||
302 | [3] = { | ||
303 | /* Alarm IRQ */ | ||
304 | .start = 152, | ||
305 | .flags = IORESOURCE_IRQ, | ||
306 | }, | ||
307 | }; | ||
308 | |||
309 | static struct platform_device rtc_device = { | ||
310 | .name = "sh-rtc", | ||
311 | .id = -1, | ||
312 | .num_resources = ARRAY_SIZE(rtc_resources), | ||
313 | .resource = rtc_resources, | ||
314 | }; | ||
315 | |||
316 | static struct platform_device *sh7201_devices[] __initdata = { | ||
317 | &sci_device, | ||
318 | &rtc_device, | ||
319 | }; | ||
320 | |||
321 | static int __init sh7201_devices_setup(void) | ||
322 | { | ||
323 | return platform_add_devices(sh7201_devices, | ||
324 | ARRAY_SIZE(sh7201_devices)); | ||
325 | } | ||
326 | __initcall(sh7201_devices_setup); | ||
327 | |||
328 | void __init plat_irq_setup(void) | ||
329 | { | ||
330 | register_intc_controller(&intc_desc); | ||
331 | } | ||
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 3fe482dd05c1..b4106d0c68ec 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -52,7 +52,7 @@ | |||
52 | * syscall # | 52 | * syscall # |
53 | * | 53 | * |
54 | */ | 54 | */ |
55 | #if defined(CONFIG_KGDB_NMI) | 55 | #if defined(CONFIG_KGDB) |
56 | NMI_VEC = 0x1c0 ! Must catch early for debounce | 56 | NMI_VEC = 0x1c0 ! Must catch early for debounce |
57 | #endif | 57 | #endif |
58 | 58 | ||
@@ -307,7 +307,7 @@ skip_restore: | |||
307 | 6: or k0, k2 ! Set the IMASK-bits | 307 | 6: or k0, k2 ! Set the IMASK-bits |
308 | ldc k2, ssr | 308 | ldc k2, ssr |
309 | ! | 309 | ! |
310 | #if defined(CONFIG_KGDB_NMI) | 310 | #if defined(CONFIG_KGDB) |
311 | ! Clear in_nmi | 311 | ! Clear in_nmi |
312 | mov.l 6f, k0 | 312 | mov.l 6f, k0 |
313 | mov #0, k1 | 313 | mov #0, k1 |
@@ -320,7 +320,7 @@ skip_restore: | |||
320 | 320 | ||
321 | .align 2 | 321 | .align 2 |
322 | 5: .long 0x00001000 ! DSP | 322 | 5: .long 0x00001000 ! DSP |
323 | #ifdef CONFIG_KGDB_NMI | 323 | #ifdef CONFIG_KGDB |
324 | 6: .long in_nmi | 324 | 6: .long in_nmi |
325 | #endif | 325 | #endif |
326 | 7: .long 0x30000000 | 326 | 7: .long 0x30000000 |
@@ -376,9 +376,9 @@ tlb_miss: | |||
376 | ! | 376 | ! |
377 | .balign 512,0,512 | 377 | .balign 512,0,512 |
378 | interrupt: | 378 | interrupt: |
379 | mov.l 2f, k2 | ||
380 | mov.l 3f, k3 | 379 | mov.l 3f, k3 |
381 | #if defined(CONFIG_KGDB_NMI) | 380 | #if defined(CONFIG_KGDB) |
381 | mov.l 2f, k2 | ||
382 | ! Debounce (filter nested NMI) | 382 | ! Debounce (filter nested NMI) |
383 | mov.l @k2, k0 | 383 | mov.l @k2, k0 |
384 | mov.l 5f, k1 | 384 | mov.l 5f, k1 |
@@ -390,16 +390,16 @@ interrupt: | |||
390 | rte | 390 | rte |
391 | nop | 391 | nop |
392 | .align 2 | 392 | .align 2 |
393 | 2: .long INTEVT | ||
393 | 5: .long NMI_VEC | 394 | 5: .long NMI_VEC |
394 | 6: .long in_nmi | 395 | 6: .long in_nmi |
395 | 0: | 396 | 0: |
396 | #endif /* defined(CONFIG_KGDB_NMI) */ | 397 | #endif /* defined(CONFIG_KGDB) */ |
397 | bra handle_exception | 398 | bra handle_exception |
398 | mov #-1, k2 ! interrupt exception marker | 399 | mov #-1, k2 ! interrupt exception marker |
399 | 400 | ||
400 | .align 2 | 401 | .align 2 |
401 | 1: .long EXPEVT | 402 | 1: .long EXPEVT |
402 | 2: .long INTEVT | ||
403 | 3: .long ret_from_irq | 403 | 3: .long ret_from_irq |
404 | 4: .long ret_from_exception | 404 | 4: .long ret_from_exception |
405 | 405 | ||
diff --git a/arch/sh/kernel/cpu/sh3/ex.S b/arch/sh/kernel/cpu/sh3/ex.S index dac429726899..e5a0de39a2db 100644 --- a/arch/sh/kernel/cpu/sh3/ex.S +++ b/arch/sh/kernel/cpu/sh3/ex.S | |||
@@ -26,7 +26,7 @@ | |||
26 | #define fpu_error_trap_handler exception_error | 26 | #define fpu_error_trap_handler exception_error |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #if !defined(CONFIG_KGDB_NMI) | 29 | #if !defined(CONFIG_KGDB) |
30 | #define kgdb_handle_exception exception_error | 30 | #define kgdb_handle_exception exception_error |
31 | #endif | 31 | #endif |
32 | 32 | ||
diff --git a/arch/sh/kernel/cpu/sh4/softfloat.c b/arch/sh/kernel/cpu/sh4/softfloat.c index 2b747f3b02bd..42edf2e54e85 100644 --- a/arch/sh/kernel/cpu/sh4/softfloat.c +++ b/arch/sh/kernel/cpu/sh4/softfloat.c | |||
@@ -37,6 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <cpu/fpu.h> | 39 | #include <cpu/fpu.h> |
40 | #include <asm/div64.h> | ||
40 | 41 | ||
41 | #define LIT64( a ) a##LL | 42 | #define LIT64( a ) a##LL |
42 | 43 | ||
@@ -67,16 +68,16 @@ typedef unsigned long long float64; | |||
67 | extern void float_raise(unsigned int flags); /* in fpu.c */ | 68 | extern void float_raise(unsigned int flags); /* in fpu.c */ |
68 | extern int float_rounding_mode(void); /* in fpu.c */ | 69 | extern int float_rounding_mode(void); /* in fpu.c */ |
69 | 70 | ||
70 | inline bits64 extractFloat64Frac(float64 a); | 71 | bits64 extractFloat64Frac(float64 a); |
71 | inline flag extractFloat64Sign(float64 a); | 72 | flag extractFloat64Sign(float64 a); |
72 | inline int16 extractFloat64Exp(float64 a); | 73 | int16 extractFloat64Exp(float64 a); |
73 | inline int16 extractFloat32Exp(float32 a); | 74 | int16 extractFloat32Exp(float32 a); |
74 | inline flag extractFloat32Sign(float32 a); | 75 | flag extractFloat32Sign(float32 a); |
75 | inline bits32 extractFloat32Frac(float32 a); | 76 | bits32 extractFloat32Frac(float32 a); |
76 | inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig); | 77 | float64 packFloat64(flag zSign, int16 zExp, bits64 zSig); |
77 | inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr); | 78 | void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr); |
78 | inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig); | 79 | float32 packFloat32(flag zSign, int16 zExp, bits32 zSig); |
79 | inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr); | 80 | void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr); |
80 | float64 float64_sub(float64 a, float64 b); | 81 | float64 float64_sub(float64 a, float64 b); |
81 | float32 float32_sub(float32 a, float32 b); | 82 | float32 float32_sub(float32 a, float32 b); |
82 | float32 float32_add(float32 a, float32 b); | 83 | float32 float32_add(float32 a, float32 b); |
@@ -86,11 +87,11 @@ float32 float32_div(float32 a, float32 b); | |||
86 | float32 float32_mul(float32 a, float32 b); | 87 | float32 float32_mul(float32 a, float32 b); |
87 | float64 float64_mul(float64 a, float64 b); | 88 | float64 float64_mul(float64 a, float64 b); |
88 | float32 float64_to_float32(float64 a); | 89 | float32 float64_to_float32(float64 a); |
89 | inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, | 90 | void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, |
90 | bits64 * z1Ptr); | 91 | bits64 * z1Ptr); |
91 | inline void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, | 92 | void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, |
92 | bits64 * z1Ptr); | 93 | bits64 * z1Ptr); |
93 | inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr); | 94 | void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr); |
94 | 95 | ||
95 | static int8 countLeadingZeros32(bits32 a); | 96 | static int8 countLeadingZeros32(bits32 a); |
96 | static int8 countLeadingZeros64(bits64 a); | 97 | static int8 countLeadingZeros64(bits64 a); |
@@ -110,42 +111,42 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b); | |||
110 | static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr, | 111 | static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr, |
111 | bits32 * zSigPtr); | 112 | bits32 * zSigPtr); |
112 | 113 | ||
113 | inline bits64 extractFloat64Frac(float64 a) | 114 | bits64 extractFloat64Frac(float64 a) |
114 | { | 115 | { |
115 | return a & LIT64(0x000FFFFFFFFFFFFF); | 116 | return a & LIT64(0x000FFFFFFFFFFFFF); |
116 | } | 117 | } |
117 | 118 | ||
118 | inline flag extractFloat64Sign(float64 a) | 119 | flag extractFloat64Sign(float64 a) |
119 | { | 120 | { |
120 | return a >> 63; | 121 | return a >> 63; |
121 | } | 122 | } |
122 | 123 | ||
123 | inline int16 extractFloat64Exp(float64 a) | 124 | int16 extractFloat64Exp(float64 a) |
124 | { | 125 | { |
125 | return (a >> 52) & 0x7FF; | 126 | return (a >> 52) & 0x7FF; |
126 | } | 127 | } |
127 | 128 | ||
128 | inline int16 extractFloat32Exp(float32 a) | 129 | int16 extractFloat32Exp(float32 a) |
129 | { | 130 | { |
130 | return (a >> 23) & 0xFF; | 131 | return (a >> 23) & 0xFF; |
131 | } | 132 | } |
132 | 133 | ||
133 | inline flag extractFloat32Sign(float32 a) | 134 | flag extractFloat32Sign(float32 a) |
134 | { | 135 | { |
135 | return a >> 31; | 136 | return a >> 31; |
136 | } | 137 | } |
137 | 138 | ||
138 | inline bits32 extractFloat32Frac(float32 a) | 139 | bits32 extractFloat32Frac(float32 a) |
139 | { | 140 | { |
140 | return a & 0x007FFFFF; | 141 | return a & 0x007FFFFF; |
141 | } | 142 | } |
142 | 143 | ||
143 | inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig) | 144 | float64 packFloat64(flag zSign, int16 zExp, bits64 zSig) |
144 | { | 145 | { |
145 | return (((bits64) zSign) << 63) + (((bits64) zExp) << 52) + zSig; | 146 | return (((bits64) zSign) << 63) + (((bits64) zExp) << 52) + zSig; |
146 | } | 147 | } |
147 | 148 | ||
148 | inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr) | 149 | void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr) |
149 | { | 150 | { |
150 | bits64 z; | 151 | bits64 z; |
151 | 152 | ||
@@ -338,12 +339,12 @@ static float64 addFloat64Sigs(float64 a, float64 b, flag zSign) | |||
338 | 339 | ||
339 | } | 340 | } |
340 | 341 | ||
341 | inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig) | 342 | float32 packFloat32(flag zSign, int16 zExp, bits32 zSig) |
342 | { | 343 | { |
343 | return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig; | 344 | return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig; |
344 | } | 345 | } |
345 | 346 | ||
346 | inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr) | 347 | void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr) |
347 | { | 348 | { |
348 | bits32 z; | 349 | bits32 z; |
349 | if (count == 0) { | 350 | if (count == 0) { |
@@ -634,7 +635,7 @@ normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr, bits64 * zSigPtr) | |||
634 | *zExpPtr = 1 - shiftCount; | 635 | *zExpPtr = 1 - shiftCount; |
635 | } | 636 | } |
636 | 637 | ||
637 | inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, | 638 | void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, |
638 | bits64 * z1Ptr) | 639 | bits64 * z1Ptr) |
639 | { | 640 | { |
640 | bits64 z1; | 641 | bits64 z1; |
@@ -644,7 +645,7 @@ inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, | |||
644 | *z0Ptr = a0 + b0 + (z1 < a1); | 645 | *z0Ptr = a0 + b0 + (z1 < a1); |
645 | } | 646 | } |
646 | 647 | ||
647 | inline void | 648 | void |
648 | sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, | 649 | sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, |
649 | bits64 * z1Ptr) | 650 | bits64 * z1Ptr) |
650 | { | 651 | { |
@@ -656,11 +657,14 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b) | |||
656 | { | 657 | { |
657 | bits64 b0, b1; | 658 | bits64 b0, b1; |
658 | bits64 rem0, rem1, term0, term1; | 659 | bits64 rem0, rem1, term0, term1; |
659 | bits64 z; | 660 | bits64 z, tmp; |
660 | if (b <= a0) | 661 | if (b <= a0) |
661 | return LIT64(0xFFFFFFFFFFFFFFFF); | 662 | return LIT64(0xFFFFFFFFFFFFFFFF); |
662 | b0 = b >> 32; | 663 | b0 = b >> 32; |
663 | z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : (a0 / b0) << 32; | 664 | tmp = a0; |
665 | do_div(tmp, b0); | ||
666 | |||
667 | z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : tmp << 32; | ||
664 | mul64To128(b, z, &term0, &term1); | 668 | mul64To128(b, z, &term0, &term1); |
665 | sub128(a0, a1, term0, term1, &rem0, &rem1); | 669 | sub128(a0, a1, term0, term1, &rem0, &rem1); |
666 | while (((sbits64) rem0) < 0) { | 670 | while (((sbits64) rem0) < 0) { |
@@ -669,11 +673,13 @@ static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b) | |||
669 | add128(rem0, rem1, b0, b1, &rem0, &rem1); | 673 | add128(rem0, rem1, b0, b1, &rem0, &rem1); |
670 | } | 674 | } |
671 | rem0 = (rem0 << 32) | (rem1 >> 32); | 675 | rem0 = (rem0 << 32) | (rem1 >> 32); |
672 | z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; | 676 | tmp = rem0; |
677 | do_div(tmp, b0); | ||
678 | z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : tmp; | ||
673 | return z; | 679 | return z; |
674 | } | 680 | } |
675 | 681 | ||
676 | inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr) | 682 | void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr) |
677 | { | 683 | { |
678 | bits32 aHigh, aLow, bHigh, bLow; | 684 | bits32 aHigh, aLow, bHigh, bLow; |
679 | bits64 z0, zMiddleA, zMiddleB, z1; | 685 | bits64 z0, zMiddleA, zMiddleB, z1; |
@@ -769,7 +775,8 @@ float32 float32_div(float32 a, float32 b) | |||
769 | { | 775 | { |
770 | flag aSign, bSign, zSign; | 776 | flag aSign, bSign, zSign; |
771 | int16 aExp, bExp, zExp; | 777 | int16 aExp, bExp, zExp; |
772 | bits32 aSig, bSig, zSig; | 778 | bits32 aSig, bSig; |
779 | uint64_t zSig; | ||
773 | 780 | ||
774 | aSig = extractFloat32Frac(a); | 781 | aSig = extractFloat32Frac(a); |
775 | aExp = extractFloat32Exp(a); | 782 | aExp = extractFloat32Exp(a); |
@@ -804,11 +811,13 @@ float32 float32_div(float32 a, float32 b) | |||
804 | aSig >>= 1; | 811 | aSig >>= 1; |
805 | ++zExp; | 812 | ++zExp; |
806 | } | 813 | } |
807 | zSig = (((bits64) aSig) << 32) / bSig; | 814 | zSig = (((bits64) aSig) << 32); |
815 | do_div(zSig, bSig); | ||
816 | |||
808 | if ((zSig & 0x3F) == 0) { | 817 | if ((zSig & 0x3F) == 0) { |
809 | zSig |= (((bits64) bSig) * zSig != ((bits64) aSig) << 32); | 818 | zSig |= (((bits64) bSig) * zSig != ((bits64) aSig) << 32); |
810 | } | 819 | } |
811 | return roundAndPackFloat32(zSign, zExp, zSig); | 820 | return roundAndPackFloat32(zSign, zExp, (bits32)zSig); |
812 | 821 | ||
813 | } | 822 | } |
814 | 823 | ||
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index db913855c2fd..0e174af21874 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c | |||
@@ -229,7 +229,7 @@ struct frqcr_context sh7722_get_clk_context(const char *name) | |||
229 | } | 229 | } |
230 | 230 | ||
231 | /** | 231 | /** |
232 | * sh7722_find_divisors - find divisor for setting rate | 232 | * sh7722_find_div_index - find divisor for setting rate |
233 | * | 233 | * |
234 | * All sh7722 clocks use the same set of multipliers/divisors. This function | 234 | * All sh7722 clocks use the same set of multipliers/divisors. This function |
235 | * chooses correct divisor to set the rate of clock with parent clock that | 235 | * chooses correct divisor to set the rate of clock with parent clock that |
@@ -238,7 +238,7 @@ struct frqcr_context sh7722_get_clk_context(const char *name) | |||
238 | * @parent_rate: rate of parent clock | 238 | * @parent_rate: rate of parent clock |
239 | * @rate: requested rate to be set | 239 | * @rate: requested rate to be set |
240 | */ | 240 | */ |
241 | static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate) | 241 | static int sh7722_find_div_index(unsigned long parent_rate, unsigned rate) |
242 | { | 242 | { |
243 | unsigned div2 = parent_rate * 2 / rate; | 243 | unsigned div2 = parent_rate * 2 / rate; |
244 | int index; | 244 | int index; |
@@ -247,12 +247,12 @@ static int sh7722_find_divisors(unsigned long parent_rate, unsigned rate) | |||
247 | return -EINVAL; | 247 | return -EINVAL; |
248 | 248 | ||
249 | for (index = 1; index < ARRAY_SIZE(divisors2); index++) { | 249 | for (index = 1; index < ARRAY_SIZE(divisors2); index++) { |
250 | if (div2 > divisors2[index] && div2 <= divisors2[index]) | 250 | if (div2 > divisors2[index - 1] && div2 <= divisors2[index]) |
251 | break; | 251 | break; |
252 | } | 252 | } |
253 | if (index >= ARRAY_SIZE(divisors2)) | 253 | if (index >= ARRAY_SIZE(divisors2)) |
254 | index = ARRAY_SIZE(divisors2) - 1; | 254 | index = ARRAY_SIZE(divisors2) - 1; |
255 | return divisors2[index]; | 255 | return index; |
256 | } | 256 | } |
257 | 257 | ||
258 | static void sh7722_frqcr_recalc(struct clk *clk) | 258 | static void sh7722_frqcr_recalc(struct clk *clk) |
@@ -279,12 +279,12 @@ static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate, | |||
279 | return -EINVAL; | 279 | return -EINVAL; |
280 | 280 | ||
281 | /* look for multiplier/divisor pair */ | 281 | /* look for multiplier/divisor pair */ |
282 | div = sh7722_find_divisors(parent_rate, rate); | 282 | div = sh7722_find_div_index(parent_rate, rate); |
283 | if (div<0) | 283 | if (div<0) |
284 | return div; | 284 | return div; |
285 | 285 | ||
286 | /* calculate new value of clock rate */ | 286 | /* calculate new value of clock rate */ |
287 | clk->rate = parent_rate * 2 / div; | 287 | clk->rate = parent_rate * 2 / divisors2[div]; |
288 | frqcr = ctrl_inl(FRQCR); | 288 | frqcr = ctrl_inl(FRQCR); |
289 | 289 | ||
290 | /* FIXME: adjust as algo_id specifies */ | 290 | /* FIXME: adjust as algo_id specifies */ |
@@ -353,7 +353,7 @@ static int sh7722_frqcr_set_rate(struct clk *clk, unsigned long rate, | |||
353 | int part_div; | 353 | int part_div; |
354 | 354 | ||
355 | if (likely(!err)) { | 355 | if (likely(!err)) { |
356 | part_div = sh7722_find_divisors(parent_rate, | 356 | part_div = sh7722_find_div_index(parent_rate, |
357 | rate); | 357 | rate); |
358 | if (part_div > 0) { | 358 | if (part_div > 0) { |
359 | part_ctx = sh7722_get_clk_context( | 359 | part_ctx = sh7722_get_clk_context( |
@@ -394,12 +394,12 @@ static long sh7722_frqcr_round_rate(struct clk *clk, unsigned long rate) | |||
394 | int div; | 394 | int div; |
395 | 395 | ||
396 | /* look for multiplier/divisor pair */ | 396 | /* look for multiplier/divisor pair */ |
397 | div = sh7722_find_divisors(parent_rate, rate); | 397 | div = sh7722_find_div_index(parent_rate, rate); |
398 | if (div < 0) | 398 | if (div < 0) |
399 | return clk->rate; | 399 | return clk->rate; |
400 | 400 | ||
401 | /* calculate new value of clock rate */ | 401 | /* calculate new value of clock rate */ |
402 | return parent_rate * 2 / div; | 402 | return parent_rate * 2 / divisors2[div]; |
403 | } | 403 | } |
404 | 404 | ||
405 | static struct clk_ops sh7722_frqcr_clk_ops = { | 405 | static struct clk_ops sh7722_frqcr_clk_ops = { |
@@ -421,7 +421,7 @@ static int sh7722_siu_set_rate(struct clk *clk, unsigned long rate, int algo_id) | |||
421 | int div; | 421 | int div; |
422 | 422 | ||
423 | r = ctrl_inl(clk->arch_flags); | 423 | r = ctrl_inl(clk->arch_flags); |
424 | div = sh7722_find_divisors(clk->parent->rate, rate); | 424 | div = sh7722_find_div_index(clk->parent->rate, rate); |
425 | if (div < 0) | 425 | if (div < 0) |
426 | return div; | 426 | return div; |
427 | r = (r & ~0xF) | div; | 427 | r = (r & ~0xF) | div; |
@@ -516,16 +516,19 @@ static struct clk_ops sh7722_video_clk_ops = { | |||
516 | static struct clk sh7722_umem_clock = { | 516 | static struct clk sh7722_umem_clock = { |
517 | .name = "umem_clk", | 517 | .name = "umem_clk", |
518 | .ops = &sh7722_frqcr_clk_ops, | 518 | .ops = &sh7722_frqcr_clk_ops, |
519 | .flags = CLK_RATE_PROPAGATES, | ||
519 | }; | 520 | }; |
520 | 521 | ||
521 | static struct clk sh7722_sh_clock = { | 522 | static struct clk sh7722_sh_clock = { |
522 | .name = "sh_clk", | 523 | .name = "sh_clk", |
523 | .ops = &sh7722_frqcr_clk_ops, | 524 | .ops = &sh7722_frqcr_clk_ops, |
525 | .flags = CLK_RATE_PROPAGATES, | ||
524 | }; | 526 | }; |
525 | 527 | ||
526 | static struct clk sh7722_peripheral_clock = { | 528 | static struct clk sh7722_peripheral_clock = { |
527 | .name = "peripheral_clk", | 529 | .name = "peripheral_clk", |
528 | .ops = &sh7722_frqcr_clk_ops, | 530 | .ops = &sh7722_frqcr_clk_ops, |
531 | .flags = CLK_RATE_PROPAGATES, | ||
529 | }; | 532 | }; |
530 | 533 | ||
531 | static struct clk sh7722_sdram_clock = { | 534 | static struct clk sh7722_sdram_clock = { |
@@ -533,6 +536,11 @@ static struct clk sh7722_sdram_clock = { | |||
533 | .ops = &sh7722_frqcr_clk_ops, | 536 | .ops = &sh7722_frqcr_clk_ops, |
534 | }; | 537 | }; |
535 | 538 | ||
539 | static struct clk sh7722_r_clock = { | ||
540 | .name = "r_clk", | ||
541 | .rate = 32768, | ||
542 | .flags = CLK_RATE_PROPAGATES, | ||
543 | }; | ||
536 | 544 | ||
537 | #ifndef CONFIG_CPU_SUBTYPE_SH7343 | 545 | #ifndef CONFIG_CPU_SUBTYPE_SH7343 |
538 | 546 | ||
@@ -567,12 +575,30 @@ static struct clk sh7722_video_clock = { | |||
567 | .ops = &sh7722_video_clk_ops, | 575 | .ops = &sh7722_video_clk_ops, |
568 | }; | 576 | }; |
569 | 577 | ||
570 | static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg, | 578 | #define MSTPCR_ARCH_FLAGS(reg, bit) (((reg) << 8) | (bit)) |
571 | int enable) | 579 | #define MSTPCR_ARCH_FLAGS_REG(value) ((value) >> 8) |
580 | #define MSTPCR_ARCH_FLAGS_BIT(value) ((value) & 0xff) | ||
581 | |||
582 | static int sh7722_mstpcr_start_stop(struct clk *clk, int enable) | ||
572 | { | 583 | { |
573 | unsigned long bit = clk->arch_flags; | 584 | unsigned long bit = MSTPCR_ARCH_FLAGS_BIT(clk->arch_flags); |
585 | unsigned long reg; | ||
574 | unsigned long r; | 586 | unsigned long r; |
575 | 587 | ||
588 | switch(MSTPCR_ARCH_FLAGS_REG(clk->arch_flags)) { | ||
589 | case 0: | ||
590 | reg = MSTPCR0; | ||
591 | break; | ||
592 | case 1: | ||
593 | reg = MSTPCR1; | ||
594 | break; | ||
595 | case 2: | ||
596 | reg = MSTPCR2; | ||
597 | break; | ||
598 | default: | ||
599 | return -EINVAL; | ||
600 | } | ||
601 | |||
576 | r = ctrl_inl(reg); | 602 | r = ctrl_inl(reg); |
577 | 603 | ||
578 | if (enable) | 604 | if (enable) |
@@ -584,96 +610,175 @@ static int sh7722_mstpcr_start_stop(struct clk *clk, unsigned long reg, | |||
584 | return 0; | 610 | return 0; |
585 | } | 611 | } |
586 | 612 | ||
587 | static void sh7722_mstpcr0_enable(struct clk *clk) | 613 | static void sh7722_mstpcr_enable(struct clk *clk) |
588 | { | ||
589 | sh7722_mstpcr_start_stop(clk, MSTPCR0, 1); | ||
590 | } | ||
591 | |||
592 | static void sh7722_mstpcr0_disable(struct clk *clk) | ||
593 | { | ||
594 | sh7722_mstpcr_start_stop(clk, MSTPCR0, 0); | ||
595 | } | ||
596 | |||
597 | static void sh7722_mstpcr1_enable(struct clk *clk) | ||
598 | { | ||
599 | sh7722_mstpcr_start_stop(clk, MSTPCR1, 1); | ||
600 | } | ||
601 | |||
602 | static void sh7722_mstpcr1_disable(struct clk *clk) | ||
603 | { | 614 | { |
604 | sh7722_mstpcr_start_stop(clk, MSTPCR1, 0); | 615 | sh7722_mstpcr_start_stop(clk, 1); |
605 | } | 616 | } |
606 | 617 | ||
607 | static void sh7722_mstpcr2_enable(struct clk *clk) | 618 | static void sh7722_mstpcr_disable(struct clk *clk) |
608 | { | 619 | { |
609 | sh7722_mstpcr_start_stop(clk, MSTPCR2, 1); | 620 | sh7722_mstpcr_start_stop(clk, 0); |
610 | } | 621 | } |
611 | 622 | ||
612 | static void sh7722_mstpcr2_disable(struct clk *clk) | 623 | static void sh7722_mstpcr_recalc(struct clk *clk) |
613 | { | 624 | { |
614 | sh7722_mstpcr_start_stop(clk, MSTPCR2, 0); | 625 | if (clk->parent) |
626 | clk->rate = clk->parent->rate; | ||
615 | } | 627 | } |
616 | 628 | ||
617 | static struct clk_ops sh7722_mstpcr0_clk_ops = { | 629 | static struct clk_ops sh7722_mstpcr_clk_ops = { |
618 | .enable = sh7722_mstpcr0_enable, | 630 | .enable = sh7722_mstpcr_enable, |
619 | .disable = sh7722_mstpcr0_disable, | 631 | .disable = sh7722_mstpcr_disable, |
620 | }; | 632 | .recalc = sh7722_mstpcr_recalc, |
621 | |||
622 | static struct clk_ops sh7722_mstpcr1_clk_ops = { | ||
623 | .enable = sh7722_mstpcr1_enable, | ||
624 | .disable = sh7722_mstpcr1_disable, | ||
625 | }; | 633 | }; |
626 | 634 | ||
627 | static struct clk_ops sh7722_mstpcr2_clk_ops = { | 635 | #define MSTPCR(_name, _parent, regnr, bitnr) \ |
628 | .enable = sh7722_mstpcr2_enable, | 636 | { \ |
629 | .disable = sh7722_mstpcr2_disable, | 637 | .name = _name, \ |
630 | }; | 638 | .arch_flags = MSTPCR_ARCH_FLAGS(regnr, bitnr), \ |
631 | 639 | .ops = (void *)_parent, \ | |
632 | #define DECLARE_MSTPCRN(regnr, bitnr, bitstr) \ | ||
633 | { \ | ||
634 | .name = "mstp" __stringify(regnr) bitstr, \ | ||
635 | .arch_flags = bitnr, \ | ||
636 | .ops = &sh7722_mstpcr ## regnr ## _clk_ops, \ | ||
637 | } | 640 | } |
638 | 641 | ||
639 | #define DECLARE_MSTPCR(regnr) \ | 642 | static struct clk sh7722_mstpcr_clocks[] = { |
640 | DECLARE_MSTPCRN(regnr, 31, "31"), \ | 643 | #if defined(CONFIG_CPU_SUBTYPE_SH7722) |
641 | DECLARE_MSTPCRN(regnr, 30, "30"), \ | 644 | MSTPCR("uram0", "umem_clk", 0, 28), |
642 | DECLARE_MSTPCRN(regnr, 29, "29"), \ | 645 | MSTPCR("xymem0", "bus_clk", 0, 26), |
643 | DECLARE_MSTPCRN(regnr, 28, "28"), \ | 646 | MSTPCR("tmu0", "peripheral_clk", 0, 15), |
644 | DECLARE_MSTPCRN(regnr, 27, "27"), \ | 647 | MSTPCR("cmt0", "r_clk", 0, 14), |
645 | DECLARE_MSTPCRN(regnr, 26, "26"), \ | 648 | MSTPCR("rwdt0", "r_clk", 0, 13), |
646 | DECLARE_MSTPCRN(regnr, 25, "25"), \ | 649 | MSTPCR("flctl0", "peripheral_clk", 0, 10), |
647 | DECLARE_MSTPCRN(regnr, 24, "24"), \ | 650 | MSTPCR("scif0", "peripheral_clk", 0, 7), |
648 | DECLARE_MSTPCRN(regnr, 23, "23"), \ | 651 | MSTPCR("scif1", "peripheral_clk", 0, 6), |
649 | DECLARE_MSTPCRN(regnr, 22, "22"), \ | 652 | MSTPCR("scif2", "peripheral_clk", 0, 5), |
650 | DECLARE_MSTPCRN(regnr, 21, "21"), \ | 653 | MSTPCR("i2c0", "peripheral_clk", 1, 9), |
651 | DECLARE_MSTPCRN(regnr, 20, "20"), \ | 654 | MSTPCR("rtc0", "r_clk", 1, 8), |
652 | DECLARE_MSTPCRN(regnr, 19, "19"), \ | 655 | MSTPCR("sdhi0", "peripheral_clk", 2, 18), |
653 | DECLARE_MSTPCRN(regnr, 18, "18"), \ | 656 | MSTPCR("keysc0", "r_clk", 2, 14), |
654 | DECLARE_MSTPCRN(regnr, 17, "17"), \ | 657 | MSTPCR("usbf0", "peripheral_clk", 2, 11), |
655 | DECLARE_MSTPCRN(regnr, 16, "16"), \ | 658 | MSTPCR("2dg0", "bus_clk", 2, 9), |
656 | DECLARE_MSTPCRN(regnr, 15, "15"), \ | 659 | MSTPCR("siu0", "bus_clk", 2, 8), |
657 | DECLARE_MSTPCRN(regnr, 14, "14"), \ | 660 | MSTPCR("vou0", "bus_clk", 2, 5), |
658 | DECLARE_MSTPCRN(regnr, 13, "13"), \ | 661 | MSTPCR("jpu0", "bus_clk", 2, 6), |
659 | DECLARE_MSTPCRN(regnr, 12, "12"), \ | 662 | MSTPCR("beu0", "bus_clk", 2, 4), |
660 | DECLARE_MSTPCRN(regnr, 11, "11"), \ | 663 | MSTPCR("ceu0", "bus_clk", 2, 3), |
661 | DECLARE_MSTPCRN(regnr, 10, "10"), \ | 664 | MSTPCR("veu0", "bus_clk", 2, 2), |
662 | DECLARE_MSTPCRN(regnr, 9, "09"), \ | 665 | MSTPCR("vpu0", "bus_clk", 2, 1), |
663 | DECLARE_MSTPCRN(regnr, 8, "08"), \ | 666 | MSTPCR("lcdc0", "bus_clk", 2, 0), |
664 | DECLARE_MSTPCRN(regnr, 7, "07"), \ | 667 | #endif |
665 | DECLARE_MSTPCRN(regnr, 6, "06"), \ | 668 | #if defined(CONFIG_CPU_SUBTYPE_SH7723) |
666 | DECLARE_MSTPCRN(regnr, 5, "05"), \ | 669 | /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ |
667 | DECLARE_MSTPCRN(regnr, 4, "04"), \ | 670 | MSTPCR("tlb0", "cpu_clk", 0, 31), |
668 | DECLARE_MSTPCRN(regnr, 3, "03"), \ | 671 | MSTPCR("ic0", "cpu_clk", 0, 30), |
669 | DECLARE_MSTPCRN(regnr, 2, "02"), \ | 672 | MSTPCR("oc0", "cpu_clk", 0, 29), |
670 | DECLARE_MSTPCRN(regnr, 1, "01"), \ | 673 | MSTPCR("l2c0", "sh_clk", 0, 28), |
671 | DECLARE_MSTPCRN(regnr, 0, "00") | 674 | MSTPCR("ilmem0", "cpu_clk", 0, 27), |
672 | 675 | MSTPCR("fpu0", "cpu_clk", 0, 24), | |
673 | static struct clk sh7722_mstpcr[] = { | 676 | MSTPCR("intc0", "cpu_clk", 0, 22), |
674 | DECLARE_MSTPCR(0), | 677 | MSTPCR("dmac0", "bus_clk", 0, 21), |
675 | DECLARE_MSTPCR(1), | 678 | MSTPCR("sh0", "sh_clk", 0, 20), |
676 | DECLARE_MSTPCR(2), | 679 | MSTPCR("hudi0", "peripheral_clk", 0, 19), |
680 | MSTPCR("ubc0", "cpu_clk", 0, 17), | ||
681 | MSTPCR("tmu0", "peripheral_clk", 0, 15), | ||
682 | MSTPCR("cmt0", "r_clk", 0, 14), | ||
683 | MSTPCR("rwdt0", "r_clk", 0, 13), | ||
684 | MSTPCR("dmac1", "bus_clk", 0, 12), | ||
685 | MSTPCR("tmu1", "peripheral_clk", 0, 11), | ||
686 | MSTPCR("flctl0", "peripheral_clk", 0, 10), | ||
687 | MSTPCR("scif0", "peripheral_clk", 0, 9), | ||
688 | MSTPCR("scif1", "peripheral_clk", 0, 8), | ||
689 | MSTPCR("scif2", "peripheral_clk", 0, 7), | ||
690 | MSTPCR("scif3", "bus_clk", 0, 6), | ||
691 | MSTPCR("scif4", "bus_clk", 0, 5), | ||
692 | MSTPCR("scif5", "bus_clk", 0, 4), | ||
693 | MSTPCR("msiof0", "bus_clk", 0, 2), | ||
694 | MSTPCR("msiof1", "bus_clk", 0, 1), | ||
695 | MSTPCR("meram0", "sh_clk", 0, 0), | ||
696 | MSTPCR("i2c0", "peripheral_clk", 1, 9), | ||
697 | MSTPCR("rtc0", "r_clk", 1, 8), | ||
698 | MSTPCR("atapi0", "sh_clk", 2, 28), | ||
699 | MSTPCR("adc0", "peripheral_clk", 2, 28), | ||
700 | MSTPCR("tpu0", "bus_clk", 2, 25), | ||
701 | MSTPCR("irda0", "peripheral_clk", 2, 24), | ||
702 | MSTPCR("tsif0", "bus_clk", 2, 22), | ||
703 | MSTPCR("icb0", "bus_clk", 2, 21), | ||
704 | MSTPCR("sdhi0", "bus_clk", 2, 18), | ||
705 | MSTPCR("sdhi1", "bus_clk", 2, 17), | ||
706 | MSTPCR("keysc0", "r_clk", 2, 14), | ||
707 | MSTPCR("usb0", "bus_clk", 2, 11), | ||
708 | MSTPCR("2dg0", "bus_clk", 2, 10), | ||
709 | MSTPCR("siu0", "bus_clk", 2, 8), | ||
710 | MSTPCR("veu1", "bus_clk", 2, 6), | ||
711 | MSTPCR("vou0", "bus_clk", 2, 5), | ||
712 | MSTPCR("beu0", "bus_clk", 2, 4), | ||
713 | MSTPCR("ceu0", "bus_clk", 2, 3), | ||
714 | MSTPCR("veu0", "bus_clk", 2, 2), | ||
715 | MSTPCR("vpu0", "bus_clk", 2, 1), | ||
716 | MSTPCR("lcdc0", "bus_clk", 2, 0), | ||
717 | #endif | ||
718 | #if defined(CONFIG_CPU_SUBTYPE_SH7343) | ||
719 | MSTPCR("uram0", "umem_clk", 0, 28), | ||
720 | MSTPCR("xymem0", "bus_clk", 0, 26), | ||
721 | MSTPCR("tmu0", "peripheral_clk", 0, 15), | ||
722 | MSTPCR("cmt0", "r_clk", 0, 14), | ||
723 | MSTPCR("rwdt0", "r_clk", 0, 13), | ||
724 | MSTPCR("scif0", "peripheral_clk", 0, 7), | ||
725 | MSTPCR("scif1", "peripheral_clk", 0, 6), | ||
726 | MSTPCR("scif2", "peripheral_clk", 0, 5), | ||
727 | MSTPCR("scif3", "peripheral_clk", 0, 4), | ||
728 | MSTPCR("i2c0", "peripheral_clk", 1, 9), | ||
729 | MSTPCR("i2c1", "peripheral_clk", 1, 8), | ||
730 | MSTPCR("sdhi0", "peripheral_clk", 2, 18), | ||
731 | MSTPCR("keysc0", "r_clk", 2, 14), | ||
732 | MSTPCR("usbf0", "peripheral_clk", 2, 11), | ||
733 | MSTPCR("siu0", "bus_clk", 2, 8), | ||
734 | MSTPCR("jpu0", "bus_clk", 2, 6), | ||
735 | MSTPCR("vou0", "bus_clk", 2, 5), | ||
736 | MSTPCR("beu0", "bus_clk", 2, 4), | ||
737 | MSTPCR("ceu0", "bus_clk", 2, 3), | ||
738 | MSTPCR("veu0", "bus_clk", 2, 2), | ||
739 | MSTPCR("vpu0", "bus_clk", 2, 1), | ||
740 | MSTPCR("lcdc0", "bus_clk", 2, 0), | ||
741 | #endif | ||
742 | #if defined(CONFIG_CPU_SUBTYPE_SH7366) | ||
743 | /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */ | ||
744 | MSTPCR("tlb0", "cpu_clk", 0, 31), | ||
745 | MSTPCR("ic0", "cpu_clk", 0, 30), | ||
746 | MSTPCR("oc0", "cpu_clk", 0, 29), | ||
747 | MSTPCR("rsmem0", "sh_clk", 0, 28), | ||
748 | MSTPCR("xymem0", "cpu_clk", 0, 26), | ||
749 | MSTPCR("intc30", "peripheral_clk", 0, 23), | ||
750 | MSTPCR("intc0", "peripheral_clk", 0, 22), | ||
751 | MSTPCR("dmac0", "bus_clk", 0, 21), | ||
752 | MSTPCR("sh0", "sh_clk", 0, 20), | ||
753 | MSTPCR("hudi0", "peripheral_clk", 0, 19), | ||
754 | MSTPCR("ubc0", "cpu_clk", 0, 17), | ||
755 | MSTPCR("tmu0", "peripheral_clk", 0, 15), | ||
756 | MSTPCR("cmt0", "r_clk", 0, 14), | ||
757 | MSTPCR("rwdt0", "r_clk", 0, 13), | ||
758 | MSTPCR("flctl0", "peripheral_clk", 0, 10), | ||
759 | MSTPCR("scif0", "peripheral_clk", 0, 7), | ||
760 | MSTPCR("scif1", "bus_clk", 0, 6), | ||
761 | MSTPCR("scif2", "bus_clk", 0, 5), | ||
762 | MSTPCR("msiof0", "peripheral_clk", 0, 2), | ||
763 | MSTPCR("sbr0", "peripheral_clk", 0, 1), | ||
764 | MSTPCR("i2c0", "peripheral_clk", 1, 9), | ||
765 | MSTPCR("icb0", "bus_clk", 2, 27), | ||
766 | MSTPCR("meram0", "sh_clk", 2, 26), | ||
767 | MSTPCR("dacc0", "peripheral_clk", 2, 24), | ||
768 | MSTPCR("dacy0", "peripheral_clk", 2, 23), | ||
769 | MSTPCR("tsif0", "bus_clk", 2, 22), | ||
770 | MSTPCR("sdhi0", "bus_clk", 2, 18), | ||
771 | MSTPCR("mmcif0", "bus_clk", 2, 17), | ||
772 | MSTPCR("usb0", "bus_clk", 2, 11), | ||
773 | MSTPCR("siu0", "bus_clk", 2, 8), | ||
774 | MSTPCR("veu1", "bus_clk", 2, 7), | ||
775 | MSTPCR("vou0", "bus_clk", 2, 5), | ||
776 | MSTPCR("beu0", "bus_clk", 2, 4), | ||
777 | MSTPCR("ceu0", "bus_clk", 2, 3), | ||
778 | MSTPCR("veu0", "bus_clk", 2, 2), | ||
779 | MSTPCR("vpu0", "bus_clk", 2, 1), | ||
780 | MSTPCR("lcdc0", "bus_clk", 2, 0), | ||
781 | #endif | ||
677 | }; | 782 | }; |
678 | 783 | ||
679 | static struct clk *sh7722_clocks[] = { | 784 | static struct clk *sh7722_clocks[] = { |
@@ -710,21 +815,30 @@ arch_init_clk_ops(struct clk_ops **ops, int type) | |||
710 | 815 | ||
711 | int __init arch_clk_init(void) | 816 | int __init arch_clk_init(void) |
712 | { | 817 | { |
713 | struct clk *master; | 818 | struct clk *clk; |
714 | int i; | 819 | int i; |
715 | 820 | ||
716 | master = clk_get(NULL, "master_clk"); | 821 | clk = clk_get(NULL, "master_clk"); |
717 | for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) { | 822 | for (i = 0; i < ARRAY_SIZE(sh7722_clocks); i++) { |
718 | pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name); | 823 | pr_debug( "Registering clock '%s'\n", sh7722_clocks[i]->name); |
719 | sh7722_clocks[i]->parent = master; | 824 | sh7722_clocks[i]->parent = clk; |
720 | clk_register(sh7722_clocks[i]); | 825 | clk_register(sh7722_clocks[i]); |
721 | } | 826 | } |
722 | clk_put(master); | 827 | clk_put(clk); |
723 | 828 | ||
724 | for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr); i++) { | 829 | clk_register(&sh7722_r_clock); |
725 | pr_debug( "Registering mstpcr '%s'\n", sh7722_mstpcr[i].name); | 830 | |
726 | clk_register(&sh7722_mstpcr[i]); | 831 | for (i = 0; i < ARRAY_SIZE(sh7722_mstpcr_clocks); i++) { |
832 | pr_debug( "Registering mstpcr clock '%s'\n", | ||
833 | sh7722_mstpcr_clocks[i].name); | ||
834 | clk = clk_get(NULL, (void *) sh7722_mstpcr_clocks[i].ops); | ||
835 | sh7722_mstpcr_clocks[i].parent = clk; | ||
836 | sh7722_mstpcr_clocks[i].ops = &sh7722_mstpcr_clk_ops; | ||
837 | clk_register(&sh7722_mstpcr_clocks[i]); | ||
838 | clk_put(clk); | ||
727 | } | 839 | } |
728 | 840 | ||
841 | clk_recalc_rate(&sh7722_r_clock); /* make sure rate gets propagated */ | ||
842 | |||
729 | return 0; | 843 | return 0; |
730 | } | 844 | } |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 78881b4214da..0623e377f488 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c | |||
@@ -30,6 +30,7 @@ static struct resource iic0_resources[] = { | |||
30 | 30 | ||
31 | static struct platform_device iic0_device = { | 31 | static struct platform_device iic0_device = { |
32 | .name = "i2c-sh_mobile", | 32 | .name = "i2c-sh_mobile", |
33 | .id = 0, /* "i2c0" clock */ | ||
33 | .num_resources = ARRAY_SIZE(iic0_resources), | 34 | .num_resources = ARRAY_SIZE(iic0_resources), |
34 | .resource = iic0_resources, | 35 | .resource = iic0_resources, |
35 | }; | 36 | }; |
@@ -50,6 +51,7 @@ static struct resource iic1_resources[] = { | |||
50 | 51 | ||
51 | static struct platform_device iic1_device = { | 52 | static struct platform_device iic1_device = { |
52 | .name = "i2c-sh_mobile", | 53 | .name = "i2c-sh_mobile", |
54 | .id = 1, /* "i2c1" clock */ | ||
53 | .num_resources = ARRAY_SIZE(iic1_resources), | 55 | .num_resources = ARRAY_SIZE(iic1_resources), |
54 | .resource = iic1_resources, | 56 | .resource = iic1_resources, |
55 | }; | 57 | }; |
@@ -115,7 +117,22 @@ static struct plat_sci_port sci_platform_data[] = { | |||
115 | .mapbase = 0xffe00000, | 117 | .mapbase = 0xffe00000, |
116 | .flags = UPF_BOOT_AUTOCONF, | 118 | .flags = UPF_BOOT_AUTOCONF, |
117 | .type = PORT_SCIF, | 119 | .type = PORT_SCIF, |
118 | .irqs = { 80, 81, 83, 82 }, | 120 | .irqs = { 80, 80, 80, 80 }, |
121 | }, { | ||
122 | .mapbase = 0xffe10000, | ||
123 | .flags = UPF_BOOT_AUTOCONF, | ||
124 | .type = PORT_SCIF, | ||
125 | .irqs = { 81, 81, 81, 81 }, | ||
126 | }, { | ||
127 | .mapbase = 0xffe20000, | ||
128 | .flags = UPF_BOOT_AUTOCONF, | ||
129 | .type = PORT_SCIF, | ||
130 | .irqs = { 82, 82, 82, 82 }, | ||
131 | }, { | ||
132 | .mapbase = 0xffe30000, | ||
133 | .flags = UPF_BOOT_AUTOCONF, | ||
134 | .type = PORT_SCIF, | ||
135 | .irqs = { 83, 83, 83, 83 }, | ||
119 | }, { | 136 | }, { |
120 | .flags = 0, | 137 | .flags = 0, |
121 | } | 138 | } |
@@ -139,18 +156,10 @@ static struct platform_device *sh7343_devices[] __initdata = { | |||
139 | 156 | ||
140 | static int __init sh7343_devices_setup(void) | 157 | static int __init sh7343_devices_setup(void) |
141 | { | 158 | { |
142 | clk_always_enable("mstp031"); /* TLB */ | 159 | clk_always_enable("uram0"); /* URAM */ |
143 | clk_always_enable("mstp030"); /* IC */ | 160 | clk_always_enable("xymem0"); /* XYMEM */ |
144 | clk_always_enable("mstp029"); /* OC */ | 161 | clk_always_enable("veu0"); /* VEU */ |
145 | clk_always_enable("mstp028"); /* URAM */ | 162 | clk_always_enable("vpu0"); /* VPU */ |
146 | clk_always_enable("mstp026"); /* XYMEM */ | ||
147 | clk_always_enable("mstp023"); /* INTC3 */ | ||
148 | clk_always_enable("mstp022"); /* INTC */ | ||
149 | clk_always_enable("mstp020"); /* SuperHyway */ | ||
150 | clk_always_enable("mstp109"); /* I2C0 */ | ||
151 | clk_always_enable("mstp108"); /* I2C1 */ | ||
152 | clk_always_enable("mstp202"); /* VEU */ | ||
153 | clk_always_enable("mstp201"); /* VPU */ | ||
154 | 163 | ||
155 | platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); | 164 | platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); |
156 | platform_resource_setup_memory(&veu_device, "veu", 2 << 20); | 165 | platform_resource_setup_memory(&veu_device, "veu", 2 << 20); |
@@ -171,7 +180,7 @@ enum { | |||
171 | MMC_ERR, MMC_TRAN, MMC_FSTAT, MMC_FRDY, | 180 | MMC_ERR, MMC_TRAN, MMC_FSTAT, MMC_FRDY, |
172 | DMAC4, DMAC5, DMAC_DADERR, | 181 | DMAC4, DMAC5, DMAC_DADERR, |
173 | KEYSC, | 182 | KEYSC, |
174 | SCIF, SCIF1, SCIF2, SCIF3, SCIF4, | 183 | SCIF, SCIF1, SCIF2, SCIF3, |
175 | SIOF0, SIOF1, SIO, | 184 | SIOF0, SIOF1, SIO, |
176 | FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, | 185 | FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, |
177 | I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI, | 186 | I2C0_ALI, I2C0_TACKI, I2C0_WAITI, I2C0_DTEI, |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index e17db39b97aa..839ae97a7fd2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c | |||
@@ -32,6 +32,7 @@ static struct resource iic_resources[] = { | |||
32 | 32 | ||
33 | static struct platform_device iic_device = { | 33 | static struct platform_device iic_device = { |
34 | .name = "i2c-sh_mobile", | 34 | .name = "i2c-sh_mobile", |
35 | .id = 0, /* "i2c0" clock */ | ||
35 | .num_resources = ARRAY_SIZE(iic_resources), | 36 | .num_resources = ARRAY_SIZE(iic_resources), |
36 | .resource = iic_resources, | 37 | .resource = iic_resources, |
37 | }; | 38 | }; |
@@ -176,19 +177,11 @@ static struct platform_device *sh7366_devices[] __initdata = { | |||
176 | 177 | ||
177 | static int __init sh7366_devices_setup(void) | 178 | static int __init sh7366_devices_setup(void) |
178 | { | 179 | { |
179 | clk_always_enable("mstp031"); /* TLB */ | 180 | clk_always_enable("rsmem0"); /* RSMEM */ |
180 | clk_always_enable("mstp030"); /* IC */ | 181 | clk_always_enable("xymem0"); /* XYMEM */ |
181 | clk_always_enable("mstp029"); /* OC */ | 182 | clk_always_enable("veu1"); /* VEU-2 */ |
182 | clk_always_enable("mstp028"); /* RSMEM */ | 183 | clk_always_enable("veu0"); /* VEU-1 */ |
183 | clk_always_enable("mstp026"); /* XYMEM */ | 184 | clk_always_enable("vpu0"); /* VPU */ |
184 | clk_always_enable("mstp023"); /* INTC3 */ | ||
185 | clk_always_enable("mstp022"); /* INTC */ | ||
186 | clk_always_enable("mstp020"); /* SuperHyway */ | ||
187 | clk_always_enable("mstp109"); /* I2C */ | ||
188 | clk_always_enable("mstp211"); /* USB */ | ||
189 | clk_always_enable("mstp207"); /* VEU-2 */ | ||
190 | clk_always_enable("mstp202"); /* VEU-1 */ | ||
191 | clk_always_enable("mstp201"); /* VPU */ | ||
192 | 185 | ||
193 | platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20); | 186 | platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20); |
194 | platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); | 187 | platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index ef77ee1d9f53..50cf6838ec41 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c | |||
@@ -62,7 +62,7 @@ static struct resource usbf_resources[] = { | |||
62 | 62 | ||
63 | static struct platform_device usbf_device = { | 63 | static struct platform_device usbf_device = { |
64 | .name = "m66592_udc", | 64 | .name = "m66592_udc", |
65 | .id = -1, | 65 | .id = 0, /* "usbf0" clock */ |
66 | .dev = { | 66 | .dev = { |
67 | .dma_mask = NULL, | 67 | .dma_mask = NULL, |
68 | .coherent_dma_mask = 0xffffffff, | 68 | .coherent_dma_mask = 0xffffffff, |
@@ -87,6 +87,7 @@ static struct resource iic_resources[] = { | |||
87 | 87 | ||
88 | static struct platform_device iic_device = { | 88 | static struct platform_device iic_device = { |
89 | .name = "i2c-sh_mobile", | 89 | .name = "i2c-sh_mobile", |
90 | .id = 0, /* "i2c0" clock */ | ||
90 | .num_resources = ARRAY_SIZE(iic_resources), | 91 | .num_resources = ARRAY_SIZE(iic_resources), |
91 | .resource = iic_resources, | 92 | .resource = iic_resources, |
92 | }; | 93 | }; |
@@ -147,6 +148,34 @@ static struct platform_device veu_device = { | |||
147 | .num_resources = ARRAY_SIZE(veu_resources), | 148 | .num_resources = ARRAY_SIZE(veu_resources), |
148 | }; | 149 | }; |
149 | 150 | ||
151 | static struct uio_info jpu_platform_data = { | ||
152 | .name = "JPU", | ||
153 | .version = "0", | ||
154 | .irq = 27, | ||
155 | }; | ||
156 | |||
157 | static struct resource jpu_resources[] = { | ||
158 | [0] = { | ||
159 | .name = "JPU", | ||
160 | .start = 0xfea00000, | ||
161 | .end = 0xfea102d0, | ||
162 | .flags = IORESOURCE_MEM, | ||
163 | }, | ||
164 | [1] = { | ||
165 | /* place holder for contiguous memory */ | ||
166 | }, | ||
167 | }; | ||
168 | |||
169 | static struct platform_device jpu_device = { | ||
170 | .name = "uio_pdrv_genirq", | ||
171 | .id = 2, | ||
172 | .dev = { | ||
173 | .platform_data = &jpu_platform_data, | ||
174 | }, | ||
175 | .resource = jpu_resources, | ||
176 | .num_resources = ARRAY_SIZE(jpu_resources), | ||
177 | }; | ||
178 | |||
150 | static struct plat_sci_port sci_platform_data[] = { | 179 | static struct plat_sci_port sci_platform_data[] = { |
151 | { | 180 | { |
152 | .mapbase = 0xffe00000, | 181 | .mapbase = 0xffe00000, |
@@ -186,24 +215,21 @@ static struct platform_device *sh7722_devices[] __initdata = { | |||
186 | &sci_device, | 215 | &sci_device, |
187 | &vpu_device, | 216 | &vpu_device, |
188 | &veu_device, | 217 | &veu_device, |
218 | &jpu_device, | ||
189 | }; | 219 | }; |
190 | 220 | ||
191 | static int __init sh7722_devices_setup(void) | 221 | static int __init sh7722_devices_setup(void) |
192 | { | 222 | { |
193 | clk_always_enable("mstp031"); /* TLB */ | 223 | clk_always_enable("uram0"); /* URAM */ |
194 | clk_always_enable("mstp030"); /* IC */ | 224 | clk_always_enable("xymem0"); /* XYMEM */ |
195 | clk_always_enable("mstp029"); /* OC */ | 225 | clk_always_enable("rtc0"); /* RTC */ |
196 | clk_always_enable("mstp028"); /* URAM */ | 226 | clk_always_enable("veu0"); /* VEU */ |
197 | clk_always_enable("mstp026"); /* XYMEM */ | 227 | clk_always_enable("vpu0"); /* VPU */ |
198 | clk_always_enable("mstp022"); /* INTC */ | 228 | clk_always_enable("jpu0"); /* JPU */ |
199 | clk_always_enable("mstp020"); /* SuperHyway */ | ||
200 | clk_always_enable("mstp109"); /* I2C */ | ||
201 | clk_always_enable("mstp211"); /* USB */ | ||
202 | clk_always_enable("mstp202"); /* VEU */ | ||
203 | clk_always_enable("mstp201"); /* VPU */ | ||
204 | 229 | ||
205 | platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); | 230 | platform_resource_setup_memory(&vpu_device, "vpu", 1 << 20); |
206 | platform_resource_setup_memory(&veu_device, "veu", 2 << 20); | 231 | platform_resource_setup_memory(&veu_device, "veu", 2 << 20); |
232 | platform_resource_setup_memory(&jpu_device, "jpu", 2 << 20); | ||
207 | 233 | ||
208 | return platform_add_devices(sh7722_devices, | 234 | return platform_add_devices(sh7722_devices, |
209 | ARRAY_SIZE(sh7722_devices)); | 235 | ARRAY_SIZE(sh7722_devices)); |
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 6d9e6972cfc9..849770d780ae 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c | |||
@@ -215,6 +215,7 @@ static struct resource iic_resources[] = { | |||
215 | 215 | ||
216 | static struct platform_device iic_device = { | 216 | static struct platform_device iic_device = { |
217 | .name = "i2c-sh_mobile", | 217 | .name = "i2c-sh_mobile", |
218 | .id = 0, /* "i2c0" clock */ | ||
218 | .num_resources = ARRAY_SIZE(iic_resources), | 219 | .num_resources = ARRAY_SIZE(iic_resources), |
219 | .resource = iic_resources, | 220 | .resource = iic_resources, |
220 | }; | 221 | }; |
@@ -231,19 +232,11 @@ static struct platform_device *sh7723_devices[] __initdata = { | |||
231 | 232 | ||
232 | static int __init sh7723_devices_setup(void) | 233 | static int __init sh7723_devices_setup(void) |
233 | { | 234 | { |
234 | clk_always_enable("mstp031"); /* TLB */ | 235 | clk_always_enable("meram0"); /* MERAM */ |
235 | clk_always_enable("mstp030"); /* IC */ | 236 | clk_always_enable("rtc0"); /* RTC */ |
236 | clk_always_enable("mstp029"); /* OC */ | 237 | clk_always_enable("veu1"); /* VEU2H1 */ |
237 | clk_always_enable("mstp024"); /* FPU */ | 238 | clk_always_enable("veu0"); /* VEU2H0 */ |
238 | clk_always_enable("mstp022"); /* INTC */ | 239 | clk_always_enable("vpu0"); /* VPU */ |
239 | clk_always_enable("mstp020"); /* SuperHyway */ | ||
240 | clk_always_enable("mstp000"); /* MERAM */ | ||
241 | clk_always_enable("mstp109"); /* I2C */ | ||
242 | clk_always_enable("mstp108"); /* RTC */ | ||
243 | clk_always_enable("mstp211"); /* USB */ | ||
244 | clk_always_enable("mstp206"); /* VEU2H1 */ | ||
245 | clk_always_enable("mstp202"); /* VEU2H0 */ | ||
246 | clk_always_enable("mstp201"); /* VPU */ | ||
247 | 240 | ||
248 | platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20); | 241 | platform_resource_setup_memory(&vpu_device, "vpu", 2 << 20); |
249 | platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); | 242 | platform_resource_setup_memory(&veu0_device, "veu0", 2 << 20); |
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S index 13b66746410a..591741383ee6 100644 --- a/arch/sh/kernel/debugtraps.S +++ b/arch/sh/kernel/debugtraps.S | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Debug trap jump tables for SuperH | 4 | * Debug trap jump tables for SuperH |
5 | * | 5 | * |
6 | * Copyright (C) 2006 Paul Mundt | 6 | * Copyright (C) 2006 - 2008 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 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 | 9 | * License. See the file "COPYING" in the main directory of this archive |
@@ -12,12 +12,13 @@ | |||
12 | #include <linux/sys.h> | 12 | #include <linux/sys.h> |
13 | #include <linux/linkage.h> | 13 | #include <linux/linkage.h> |
14 | 14 | ||
15 | #if !defined(CONFIG_SH_KGDB) | 15 | #if !defined(CONFIG_KGDB) |
16 | #define kgdb_handle_exception debug_trap_handler | 16 | #define breakpoint_trap_handler debug_trap_handler |
17 | #define singlestep_trap_handler debug_trap_handler | ||
17 | #endif | 18 | #endif |
18 | 19 | ||
19 | #if !defined(CONFIG_SH_STANDARD_BIOS) | 20 | #if !defined(CONFIG_SH_STANDARD_BIOS) |
20 | #define sh_bios_handler debug_trap_handler | 21 | #define sh_bios_handler debug_trap_handler |
21 | #endif | 22 | #endif |
22 | 23 | ||
23 | .data | 24 | .data |
@@ -35,7 +36,7 @@ ENTRY(debug_trap_table) | |||
35 | .long debug_trap_handler /* 0x39 */ | 36 | .long debug_trap_handler /* 0x39 */ |
36 | .long debug_trap_handler /* 0x3a */ | 37 | .long debug_trap_handler /* 0x3a */ |
37 | .long debug_trap_handler /* 0x3b */ | 38 | .long debug_trap_handler /* 0x3b */ |
38 | .long kgdb_handle_exception /* 0x3c */ | 39 | .long breakpoint_trap_handler /* 0x3c */ |
39 | .long debug_trap_handler /* 0x3d */ | 40 | .long singlestep_trap_handler /* 0x3d */ |
40 | .long bug_trap_handler /* 0x3e */ | 41 | .long bug_trap_handler /* 0x3e */ |
41 | .long sh_bios_handler /* 0x3f */ | 42 | .long sh_bios_handler /* 0x3f */ |
diff --git a/arch/sh/kernel/disassemble.c b/arch/sh/kernel/disassemble.c new file mode 100644 index 000000000000..64d5d8dded7c --- /dev/null +++ b/arch/sh/kernel/disassemble.c | |||
@@ -0,0 +1,573 @@ | |||
1 | /* | ||
2 | * Disassemble SuperH instructions. | ||
3 | * | ||
4 | * Copyright (C) 1999 kaz Kojima | ||
5 | * Copyright (C) 2008 Paul Mundt | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/uaccess.h> | ||
14 | |||
15 | /* | ||
16 | * Format of an instruction in memory. | ||
17 | */ | ||
18 | typedef enum { | ||
19 | HEX_0, HEX_1, HEX_2, HEX_3, HEX_4, HEX_5, HEX_6, HEX_7, | ||
20 | HEX_8, HEX_9, HEX_A, HEX_B, HEX_C, HEX_D, HEX_E, HEX_F, | ||
21 | REG_N, REG_M, REG_NM, REG_B, | ||
22 | BRANCH_12, BRANCH_8, | ||
23 | DISP_8, DISP_4, | ||
24 | IMM_4, IMM_4BY2, IMM_4BY4, PCRELIMM_8BY2, PCRELIMM_8BY4, | ||
25 | IMM_8, IMM_8BY2, IMM_8BY4, | ||
26 | } sh_nibble_type; | ||
27 | |||
28 | typedef enum { | ||
29 | A_END, A_BDISP12, A_BDISP8, | ||
30 | A_DEC_M, A_DEC_N, | ||
31 | A_DISP_GBR, A_DISP_PC, A_DISP_REG_M, A_DISP_REG_N, | ||
32 | A_GBR, | ||
33 | A_IMM, | ||
34 | A_INC_M, A_INC_N, | ||
35 | A_IND_M, A_IND_N, A_IND_R0_REG_M, A_IND_R0_REG_N, | ||
36 | A_MACH, A_MACL, | ||
37 | A_PR, A_R0, A_R0_GBR, A_REG_M, A_REG_N, A_REG_B, | ||
38 | A_SR, A_VBR, A_SSR, A_SPC, A_SGR, A_DBR, | ||
39 | F_REG_N, F_REG_M, D_REG_N, D_REG_M, | ||
40 | X_REG_N, /* Only used for argument parsing */ | ||
41 | X_REG_M, /* Only used for argument parsing */ | ||
42 | DX_REG_N, DX_REG_M, V_REG_N, V_REG_M, | ||
43 | FD_REG_N, | ||
44 | XMTRX_M4, | ||
45 | F_FR0, | ||
46 | FPUL_N, FPUL_M, FPSCR_N, FPSCR_M, | ||
47 | } sh_arg_type; | ||
48 | |||
49 | static struct sh_opcode_info { | ||
50 | char *name; | ||
51 | sh_arg_type arg[7]; | ||
52 | sh_nibble_type nibbles[4]; | ||
53 | } sh_table[] = { | ||
54 | {"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM_8}}, | ||
55 | {"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}}, | ||
56 | {"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}}, | ||
57 | {"addv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_F}}, | ||
58 | {"and",{A_IMM,A_R0},{HEX_C,HEX_9,IMM_8}}, | ||
59 | {"and",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_9}}, | ||
60 | {"and.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM_8}}, | ||
61 | {"bra",{A_BDISP12},{HEX_A,BRANCH_12}}, | ||
62 | {"bsr",{A_BDISP12},{HEX_B,BRANCH_12}}, | ||
63 | {"bt",{A_BDISP8},{HEX_8,HEX_9,BRANCH_8}}, | ||
64 | {"bf",{A_BDISP8},{HEX_8,HEX_B,BRANCH_8}}, | ||
65 | {"bt.s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, | ||
66 | {"bt/s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, | ||
67 | {"bf.s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, | ||
68 | {"bf/s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, | ||
69 | {"clrmac",{0},{HEX_0,HEX_0,HEX_2,HEX_8}}, | ||
70 | {"clrs",{0},{HEX_0,HEX_0,HEX_4,HEX_8}}, | ||
71 | {"clrt",{0},{HEX_0,HEX_0,HEX_0,HEX_8}}, | ||
72 | {"cmp/eq",{A_IMM,A_R0},{HEX_8,HEX_8,IMM_8}}, | ||
73 | {"cmp/eq",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_0}}, | ||
74 | {"cmp/ge",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_3}}, | ||
75 | {"cmp/gt",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_7}}, | ||
76 | {"cmp/hi",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_6}}, | ||
77 | {"cmp/hs",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_2}}, | ||
78 | {"cmp/pl",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_5}}, | ||
79 | {"cmp/pz",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_1}}, | ||
80 | {"cmp/str",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_C}}, | ||
81 | {"div0s",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_7}}, | ||
82 | {"div0u",{0},{HEX_0,HEX_0,HEX_1,HEX_9}}, | ||
83 | {"div1",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_4}}, | ||
84 | {"exts.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_E}}, | ||
85 | {"exts.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_F}}, | ||
86 | {"extu.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_C}}, | ||
87 | {"extu.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_D}}, | ||
88 | {"jmp",{A_IND_N},{HEX_4,REG_N,HEX_2,HEX_B}}, | ||
89 | {"jsr",{A_IND_N},{HEX_4,REG_N,HEX_0,HEX_B}}, | ||
90 | {"ldc",{A_REG_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_E}}, | ||
91 | {"ldc",{A_REG_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_E}}, | ||
92 | {"ldc",{A_REG_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_E}}, | ||
93 | {"ldc",{A_REG_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_E}}, | ||
94 | {"ldc",{A_REG_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_E}}, | ||
95 | {"ldc",{A_REG_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_E}}, | ||
96 | {"ldc",{A_REG_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_E}}, | ||
97 | {"ldc.l",{A_INC_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_7}}, | ||
98 | {"ldc.l",{A_INC_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_7}}, | ||
99 | {"ldc.l",{A_INC_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_7}}, | ||
100 | {"ldc.l",{A_INC_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_7}}, | ||
101 | {"ldc.l",{A_INC_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_7}}, | ||
102 | {"ldc.l",{A_INC_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_7}}, | ||
103 | {"ldc.l",{A_INC_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_7}}, | ||
104 | {"lds",{A_REG_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_A}}, | ||
105 | {"lds",{A_REG_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_A}}, | ||
106 | {"lds",{A_REG_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_A}}, | ||
107 | {"lds",{A_REG_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_A}}, | ||
108 | {"lds",{A_REG_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_A}}, | ||
109 | {"lds.l",{A_INC_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_6}}, | ||
110 | {"lds.l",{A_INC_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_6}}, | ||
111 | {"lds.l",{A_INC_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_6}}, | ||
112 | {"lds.l",{A_INC_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_6}}, | ||
113 | {"lds.l",{A_INC_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_6}}, | ||
114 | {"ldtlb",{0},{HEX_0,HEX_0,HEX_3,HEX_8}}, | ||
115 | {"mac.w",{A_INC_M,A_INC_N},{HEX_4,REG_N,REG_M,HEX_F}}, | ||
116 | {"mov",{A_IMM,A_REG_N},{HEX_E,REG_N,IMM_8}}, | ||
117 | {"mov",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_3}}, | ||
118 | {"mov.b",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_4}}, | ||
119 | {"mov.b",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_4}}, | ||
120 | {"mov.b",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_0}}, | ||
121 | {"mov.b",{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM_4}}, | ||
122 | {"mov.b",{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM_8}}, | ||
123 | {"mov.b",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_C}}, | ||
124 | {"mov.b",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_4}}, | ||
125 | {"mov.b",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_0}}, | ||
126 | {"mov.b",{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM_4}}, | ||
127 | {"mov.b",{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM_8}}, | ||
128 | {"mov.l",{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM_4BY4}}, | ||
129 | {"mov.l",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_6}}, | ||
130 | {"mov.l",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_6}}, | ||
131 | {"mov.l",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_2}}, | ||
132 | {"mov.l",{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM_4BY4}}, | ||
133 | {"mov.l",{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM_8BY4}}, | ||
134 | {"mov.l",{A_DISP_PC,A_REG_N},{HEX_D,REG_N,PCRELIMM_8BY4}}, | ||
135 | {"mov.l",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_E}}, | ||
136 | {"mov.l",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_6}}, | ||
137 | {"mov.l",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_2}}, | ||
138 | {"mov.l",{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM_8BY4}}, | ||
139 | {"mov.w",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_5}}, | ||
140 | {"mov.w",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_5}}, | ||
141 | {"mov.w",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_1}}, | ||
142 | {"mov.w",{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM_4BY2}}, | ||
143 | {"mov.w",{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM_8BY2}}, | ||
144 | {"mov.w",{A_DISP_PC,A_REG_N},{HEX_9,REG_N,PCRELIMM_8BY2}}, | ||
145 | {"mov.w",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_D}}, | ||
146 | {"mov.w",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_5}}, | ||
147 | {"mov.w",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_1}}, | ||
148 | {"mov.w",{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM_4BY2}}, | ||
149 | {"mov.w",{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM_8BY2}}, | ||
150 | {"mova",{A_DISP_PC,A_R0},{HEX_C,HEX_7,PCRELIMM_8BY4}}, | ||
151 | {"movca.l",{A_R0,A_IND_N},{HEX_0,REG_N,HEX_C,HEX_3}}, | ||
152 | {"movt",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_9}}, | ||
153 | {"muls",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_F}}, | ||
154 | {"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, | ||
155 | {"mulu",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_E}}, | ||
156 | {"neg",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_B}}, | ||
157 | {"negc",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_A}}, | ||
158 | {"nop",{0},{HEX_0,HEX_0,HEX_0,HEX_9}}, | ||
159 | {"not",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_7}}, | ||
160 | {"ocbi",{A_IND_N},{HEX_0,REG_N,HEX_9,HEX_3}}, | ||
161 | {"ocbp",{A_IND_N},{HEX_0,REG_N,HEX_A,HEX_3}}, | ||
162 | {"ocbwb",{A_IND_N},{HEX_0,REG_N,HEX_B,HEX_3}}, | ||
163 | {"or",{A_IMM,A_R0},{HEX_C,HEX_B,IMM_8}}, | ||
164 | {"or",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_B}}, | ||
165 | {"or.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM_8}}, | ||
166 | {"pref",{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}}, | ||
167 | {"rotcl",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_4}}, | ||
168 | {"rotcr",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_5}}, | ||
169 | {"rotl",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_4}}, | ||
170 | {"rotr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_5}}, | ||
171 | {"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}}, | ||
172 | {"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}}, | ||
173 | {"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}}, | ||
174 | {"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}}, | ||
175 | {"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}}, | ||
176 | {"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}}, | ||
177 | {"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}}, | ||
178 | {"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}}, | ||
179 | {"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}}, | ||
180 | {"shll16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_8}}, | ||
181 | {"shll2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_8}}, | ||
182 | {"shll8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_8}}, | ||
183 | {"shlr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_1}}, | ||
184 | {"shlr16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_9}}, | ||
185 | {"shlr2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_9}}, | ||
186 | {"shlr8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_9}}, | ||
187 | {"sleep",{0},{HEX_0,HEX_0,HEX_1,HEX_B}}, | ||
188 | {"stc",{A_SR,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_2}}, | ||
189 | {"stc",{A_GBR,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_2}}, | ||
190 | {"stc",{A_VBR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_2}}, | ||
191 | {"stc",{A_SSR,A_REG_N},{HEX_0,REG_N,HEX_3,HEX_2}}, | ||
192 | {"stc",{A_SPC,A_REG_N},{HEX_0,REG_N,HEX_4,HEX_2}}, | ||
193 | {"stc",{A_SGR,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_2}}, | ||
194 | {"stc",{A_DBR,A_REG_N},{HEX_0,REG_N,HEX_7,HEX_2}}, | ||
195 | {"stc",{A_REG_B,A_REG_N},{HEX_0,REG_N,REG_B,HEX_2}}, | ||
196 | {"stc.l",{A_SR,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_3}}, | ||
197 | {"stc.l",{A_GBR,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_3}}, | ||
198 | {"stc.l",{A_VBR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_3}}, | ||
199 | {"stc.l",{A_SSR,A_DEC_N},{HEX_4,REG_N,HEX_3,HEX_3}}, | ||
200 | {"stc.l",{A_SPC,A_DEC_N},{HEX_4,REG_N,HEX_4,HEX_3}}, | ||
201 | {"stc.l",{A_SGR,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_3}}, | ||
202 | {"stc.l",{A_DBR,A_DEC_N},{HEX_4,REG_N,HEX_7,HEX_3}}, | ||
203 | {"stc.l",{A_REG_B,A_DEC_N},{HEX_4,REG_N,REG_B,HEX_3}}, | ||
204 | {"sts",{A_MACH,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_A}}, | ||
205 | {"sts",{A_MACL,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_A}}, | ||
206 | {"sts",{A_PR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_A}}, | ||
207 | {"sts",{FPUL_M,A_REG_N},{HEX_0,REG_N,HEX_5,HEX_A}}, | ||
208 | {"sts",{FPSCR_M,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_A}}, | ||
209 | {"sts.l",{A_MACH,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_2}}, | ||
210 | {"sts.l",{A_MACL,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_2}}, | ||
211 | {"sts.l",{A_PR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_2}}, | ||
212 | {"sts.l",{FPUL_M,A_DEC_N},{HEX_4,REG_N,HEX_5,HEX_2}}, | ||
213 | {"sts.l",{FPSCR_M,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_2}}, | ||
214 | {"sub",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_8}}, | ||
215 | {"subc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_A}}, | ||
216 | {"subv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_B}}, | ||
217 | {"swap.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_8}}, | ||
218 | {"swap.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_9}}, | ||
219 | {"tas.b",{A_IND_N},{HEX_4,REG_N,HEX_1,HEX_B}}, | ||
220 | {"trapa",{A_IMM},{HEX_C,HEX_3,IMM_8}}, | ||
221 | {"tst",{A_IMM,A_R0},{HEX_C,HEX_8,IMM_8}}, | ||
222 | {"tst",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_8}}, | ||
223 | {"tst.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM_8}}, | ||
224 | {"xor",{A_IMM,A_R0},{HEX_C,HEX_A,IMM_8}}, | ||
225 | {"xor",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_A}}, | ||
226 | {"xor.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM_8}}, | ||
227 | {"xtrct",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_D}}, | ||
228 | {"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, | ||
229 | {"dt",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_0}}, | ||
230 | {"dmuls.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_D}}, | ||
231 | {"dmulu.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_5}}, | ||
232 | {"mac.l",{A_INC_M,A_INC_N},{HEX_0,REG_N,REG_M,HEX_F}}, | ||
233 | {"braf",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_3}}, | ||
234 | {"bsrf",{A_REG_N},{HEX_0,REG_N,HEX_0,HEX_3}}, | ||
235 | {"fabs",{FD_REG_N},{HEX_F,REG_N,HEX_5,HEX_D}}, | ||
236 | {"fadd",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, | ||
237 | {"fadd",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, | ||
238 | {"fcmp/eq",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, | ||
239 | {"fcmp/eq",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, | ||
240 | {"fcmp/gt",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, | ||
241 | {"fcmp/gt",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, | ||
242 | {"fcnvds",{D_REG_N,FPUL_M},{HEX_F,REG_N,HEX_B,HEX_D}}, | ||
243 | {"fcnvsd",{FPUL_M,D_REG_N},{HEX_F,REG_N,HEX_A,HEX_D}}, | ||
244 | {"fdiv",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, | ||
245 | {"fdiv",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, | ||
246 | {"fipr",{V_REG_M,V_REG_N},{HEX_F,REG_NM,HEX_E,HEX_D}}, | ||
247 | {"fldi0",{F_REG_N},{HEX_F,REG_N,HEX_8,HEX_D}}, | ||
248 | {"fldi1",{F_REG_N},{HEX_F,REG_N,HEX_9,HEX_D}}, | ||
249 | {"flds",{F_REG_N,FPUL_M},{HEX_F,REG_N,HEX_1,HEX_D}}, | ||
250 | {"float",{FPUL_M,FD_REG_N},{HEX_F,REG_N,HEX_2,HEX_D}}, | ||
251 | {"fmac",{F_FR0,F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_E}}, | ||
252 | {"fmov",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, | ||
253 | {"fmov",{DX_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, | ||
254 | {"fmov",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | ||
255 | {"fmov",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | ||
256 | {"fmov",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | ||
257 | {"fmov",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | ||
258 | {"fmov",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | ||
259 | {"fmov",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | ||
260 | {"fmov",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | ||
261 | {"fmov",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | ||
262 | {"fmov",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | ||
263 | {"fmov",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | ||
264 | {"fmov",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | ||
265 | {"fmov",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | ||
266 | {"fmov.d",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | ||
267 | {"fmov.d",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | ||
268 | {"fmov.d",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | ||
269 | {"fmov.d",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | ||
270 | {"fmov.d",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | ||
271 | {"fmov.d",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | ||
272 | {"fmov.s",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | ||
273 | {"fmov.s",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | ||
274 | {"fmov.s",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | ||
275 | {"fmov.s",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | ||
276 | {"fmov.s",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | ||
277 | {"fmov.s",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | ||
278 | {"fmul",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, | ||
279 | {"fmul",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, | ||
280 | {"fneg",{FD_REG_N},{HEX_F,REG_N,HEX_4,HEX_D}}, | ||
281 | {"frchg",{0},{HEX_F,HEX_B,HEX_F,HEX_D}}, | ||
282 | {"fschg",{0},{HEX_F,HEX_3,HEX_F,HEX_D}}, | ||
283 | {"fsqrt",{FD_REG_N},{HEX_F,REG_N,HEX_6,HEX_D}}, | ||
284 | {"fsts",{FPUL_M,F_REG_N},{HEX_F,REG_N,HEX_0,HEX_D}}, | ||
285 | {"fsub",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, | ||
286 | {"fsub",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, | ||
287 | {"ftrc",{FD_REG_N,FPUL_M},{HEX_F,REG_N,HEX_3,HEX_D}}, | ||
288 | {"ftrv",{XMTRX_M4,V_REG_N},{HEX_F,REG_NM,HEX_F,HEX_D}}, | ||
289 | { 0 }, | ||
290 | }; | ||
291 | |||
292 | static void print_sh_insn(u32 memaddr, u16 insn) | ||
293 | { | ||
294 | int relmask = ~0; | ||
295 | int nibs[4] = { (insn >> 12) & 0xf, (insn >> 8) & 0xf, (insn >> 4) & 0xf, insn & 0xf}; | ||
296 | int lastsp; | ||
297 | struct sh_opcode_info *op = sh_table; | ||
298 | |||
299 | for (; op->name; op++) { | ||
300 | int n; | ||
301 | int imm = 0; | ||
302 | int rn = 0; | ||
303 | int rm = 0; | ||
304 | int rb = 0; | ||
305 | int disp_pc; | ||
306 | int disp_pc_addr = 0; | ||
307 | |||
308 | for (n = 0; n < 4; n++) { | ||
309 | int i = op->nibbles[n]; | ||
310 | |||
311 | if (i < 16) { | ||
312 | if (nibs[n] == i) | ||
313 | continue; | ||
314 | goto fail; | ||
315 | } | ||
316 | switch (i) { | ||
317 | case BRANCH_8: | ||
318 | imm = (nibs[2] << 4) | (nibs[3]); | ||
319 | if (imm & 0x80) | ||
320 | imm |= ~0xff; | ||
321 | imm = ((char)imm) * 2 + 4 ; | ||
322 | goto ok; | ||
323 | case BRANCH_12: | ||
324 | imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); | ||
325 | if (imm & 0x800) | ||
326 | imm |= ~0xfff; | ||
327 | imm = imm * 2 + 4; | ||
328 | goto ok; | ||
329 | case IMM_4: | ||
330 | imm = nibs[3]; | ||
331 | goto ok; | ||
332 | case IMM_4BY2: | ||
333 | imm = nibs[3] <<1; | ||
334 | goto ok; | ||
335 | case IMM_4BY4: | ||
336 | imm = nibs[3] <<2; | ||
337 | goto ok; | ||
338 | case IMM_8: | ||
339 | imm = (nibs[2] << 4) | nibs[3]; | ||
340 | goto ok; | ||
341 | case PCRELIMM_8BY2: | ||
342 | imm = ((nibs[2] << 4) | nibs[3]) <<1; | ||
343 | relmask = ~1; | ||
344 | goto ok; | ||
345 | case PCRELIMM_8BY4: | ||
346 | imm = ((nibs[2] << 4) | nibs[3]) <<2; | ||
347 | relmask = ~3; | ||
348 | goto ok; | ||
349 | case IMM_8BY2: | ||
350 | imm = ((nibs[2] << 4) | nibs[3]) <<1; | ||
351 | goto ok; | ||
352 | case IMM_8BY4: | ||
353 | imm = ((nibs[2] << 4) | nibs[3]) <<2; | ||
354 | goto ok; | ||
355 | case DISP_8: | ||
356 | imm = (nibs[2] << 4) | (nibs[3]); | ||
357 | goto ok; | ||
358 | case DISP_4: | ||
359 | imm = nibs[3]; | ||
360 | goto ok; | ||
361 | case REG_N: | ||
362 | rn = nibs[n]; | ||
363 | break; | ||
364 | case REG_M: | ||
365 | rm = nibs[n]; | ||
366 | break; | ||
367 | case REG_NM: | ||
368 | rn = (nibs[n] & 0xc) >> 2; | ||
369 | rm = (nibs[n] & 0x3); | ||
370 | break; | ||
371 | case REG_B: | ||
372 | rb = nibs[n] & 0x07; | ||
373 | break; | ||
374 | default: | ||
375 | return; | ||
376 | } | ||
377 | } | ||
378 | |||
379 | ok: | ||
380 | printk("%-8s ", op->name); | ||
381 | lastsp = (op->arg[0] == A_END); | ||
382 | disp_pc = 0; | ||
383 | for (n = 0; n < 6 && op->arg[n] != A_END; n++) { | ||
384 | if (n && op->arg[1] != A_END) | ||
385 | printk(", "); | ||
386 | switch (op->arg[n]) { | ||
387 | case A_IMM: | ||
388 | printk("#%d", (char)(imm)); | ||
389 | break; | ||
390 | case A_R0: | ||
391 | printk("r0"); | ||
392 | break; | ||
393 | case A_REG_N: | ||
394 | printk("r%d", rn); | ||
395 | break; | ||
396 | case A_INC_N: | ||
397 | printk("@r%d+", rn); | ||
398 | break; | ||
399 | case A_DEC_N: | ||
400 | printk("@-r%d", rn); | ||
401 | break; | ||
402 | case A_IND_N: | ||
403 | printk("@r%d", rn); | ||
404 | break; | ||
405 | case A_DISP_REG_N: | ||
406 | printk("@(%d,r%d)", imm, rn); | ||
407 | break; | ||
408 | case A_REG_M: | ||
409 | printk("r%d", rm); | ||
410 | break; | ||
411 | case A_INC_M: | ||
412 | printk("@r%d+", rm); | ||
413 | break; | ||
414 | case A_DEC_M: | ||
415 | printk("@-r%d", rm); | ||
416 | break; | ||
417 | case A_IND_M: | ||
418 | printk("@r%d", rm); | ||
419 | break; | ||
420 | case A_DISP_REG_M: | ||
421 | printk("@(%d,r%d)", imm, rm); | ||
422 | break; | ||
423 | case A_REG_B: | ||
424 | printk("r%d_bank", rb); | ||
425 | break; | ||
426 | case A_DISP_PC: | ||
427 | disp_pc = 1; | ||
428 | disp_pc_addr = imm + 4 + (memaddr & relmask); | ||
429 | printk("%08x <%pS>", disp_pc_addr, | ||
430 | (void *)disp_pc_addr); | ||
431 | break; | ||
432 | case A_IND_R0_REG_N: | ||
433 | printk("@(r0,r%d)", rn); | ||
434 | break; | ||
435 | case A_IND_R0_REG_M: | ||
436 | printk("@(r0,r%d)", rm); | ||
437 | break; | ||
438 | case A_DISP_GBR: | ||
439 | printk("@(%d,gbr)",imm); | ||
440 | break; | ||
441 | case A_R0_GBR: | ||
442 | printk("@(r0,gbr)"); | ||
443 | break; | ||
444 | case A_BDISP12: | ||
445 | case A_BDISP8: | ||
446 | printk("%08x", imm + memaddr); | ||
447 | break; | ||
448 | case A_SR: | ||
449 | printk("sr"); | ||
450 | break; | ||
451 | case A_GBR: | ||
452 | printk("gbr"); | ||
453 | break; | ||
454 | case A_VBR: | ||
455 | printk("vbr"); | ||
456 | break; | ||
457 | case A_SSR: | ||
458 | printk("ssr"); | ||
459 | break; | ||
460 | case A_SPC: | ||
461 | printk("spc"); | ||
462 | break; | ||
463 | case A_MACH: | ||
464 | printk("mach"); | ||
465 | break; | ||
466 | case A_MACL: | ||
467 | printk("macl"); | ||
468 | break; | ||
469 | case A_PR: | ||
470 | printk("pr"); | ||
471 | break; | ||
472 | case A_SGR: | ||
473 | printk("sgr"); | ||
474 | break; | ||
475 | case A_DBR: | ||
476 | printk("dbr"); | ||
477 | break; | ||
478 | case FD_REG_N: | ||
479 | if (0) | ||
480 | goto d_reg_n; | ||
481 | case F_REG_N: | ||
482 | printk("fr%d", rn); | ||
483 | break; | ||
484 | case F_REG_M: | ||
485 | printk("fr%d", rm); | ||
486 | break; | ||
487 | case DX_REG_N: | ||
488 | if (rn & 1) { | ||
489 | printk("xd%d", rn & ~1); | ||
490 | break; | ||
491 | } | ||
492 | d_reg_n: | ||
493 | case D_REG_N: | ||
494 | printk("dr%d", rn); | ||
495 | break; | ||
496 | case DX_REG_M: | ||
497 | if (rm & 1) { | ||
498 | printk("xd%d", rm & ~1); | ||
499 | break; | ||
500 | } | ||
501 | case D_REG_M: | ||
502 | printk("dr%d", rm); | ||
503 | break; | ||
504 | case FPSCR_M: | ||
505 | case FPSCR_N: | ||
506 | printk("fpscr"); | ||
507 | break; | ||
508 | case FPUL_M: | ||
509 | case FPUL_N: | ||
510 | printk("fpul"); | ||
511 | break; | ||
512 | case F_FR0: | ||
513 | printk("fr0"); | ||
514 | break; | ||
515 | case V_REG_N: | ||
516 | printk("fv%d", rn*4); | ||
517 | break; | ||
518 | case V_REG_M: | ||
519 | printk("fv%d", rm*4); | ||
520 | break; | ||
521 | case XMTRX_M4: | ||
522 | printk("xmtrx"); | ||
523 | break; | ||
524 | default: | ||
525 | return; | ||
526 | } | ||
527 | } | ||
528 | |||
529 | if (disp_pc && strcmp(op->name, "mova") != 0) { | ||
530 | u32 val; | ||
531 | |||
532 | if (relmask == ~1) | ||
533 | __get_user(val, (u16 *)disp_pc_addr); | ||
534 | else | ||
535 | __get_user(val, (u32 *)disp_pc_addr); | ||
536 | |||
537 | printk(" ! %08x <%pS>", val, (void *)val); | ||
538 | } | ||
539 | |||
540 | return; | ||
541 | fail: | ||
542 | ; | ||
543 | |||
544 | } | ||
545 | |||
546 | printk(".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]); | ||
547 | } | ||
548 | |||
549 | void show_code(struct pt_regs *regs) | ||
550 | { | ||
551 | unsigned short *pc = (unsigned short *)regs->pc; | ||
552 | long i; | ||
553 | |||
554 | if (regs->pc & 0x1) | ||
555 | return; | ||
556 | |||
557 | printk("Code:\n"); | ||
558 | |||
559 | for (i = -3 ; i < 6 ; i++) { | ||
560 | unsigned short insn; | ||
561 | |||
562 | if (__get_user(insn, pc + i)) { | ||
563 | printk(" (Bad address in pc)\n"); | ||
564 | break; | ||
565 | } | ||
566 | |||
567 | printk("%s%08lx: ", (i ? " ": "->"), (unsigned long)(pc + i)); | ||
568 | print_sh_insn((unsigned long)(pc + i), insn); | ||
569 | printk("\n"); | ||
570 | } | ||
571 | |||
572 | printk("\n"); | ||
573 | } | ||
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 5b7efc4016fa..d62359cfbbe2 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -308,15 +308,19 @@ ENTRY(system_call) | |||
308 | mov.l 1f, r9 | 308 | mov.l 1f, r9 |
309 | mov.l @r9, r8 ! Read from TRA (Trap Address) Register | 309 | mov.l @r9, r8 ! Read from TRA (Trap Address) Register |
310 | #endif | 310 | #endif |
311 | |||
312 | mov #OFF_TRA, r10 | ||
313 | add r15, r10 | ||
314 | mov.l r8, @r10 ! set TRA value to tra | ||
315 | |||
311 | /* | 316 | /* |
312 | * Check the trap type | 317 | * Check the trap type |
313 | */ | 318 | */ |
314 | mov #((0x20 << 2) - 1), r9 | 319 | mov #((0x20 << 2) - 1), r9 |
315 | cmp/hi r9, r8 | 320 | cmp/hi r9, r8 |
316 | bt/s debug_trap ! it's a debug trap.. | 321 | bt/s debug_trap ! it's a debug trap.. |
317 | mov #OFF_TRA, r9 | 322 | nop |
318 | add r15, r9 | 323 | |
319 | mov.l r8, @r9 ! set TRA value to tra | ||
320 | #ifdef CONFIG_TRACE_IRQFLAGS | 324 | #ifdef CONFIG_TRACE_IRQFLAGS |
321 | mov.l 5f, r10 | 325 | mov.l 5f, r10 |
322 | jsr @r10 | 326 | jsr @r10 |
@@ -371,47 +375,3 @@ syscall_exit: | |||
371 | #endif | 375 | #endif |
372 | 7: .long do_syscall_trace_enter | 376 | 7: .long do_syscall_trace_enter |
373 | 8: .long do_syscall_trace_leave | 377 | 8: .long do_syscall_trace_leave |
374 | |||
375 | #ifdef CONFIG_FUNCTION_TRACER | ||
376 | .align 2 | ||
377 | .globl _mcount | ||
378 | .type _mcount,@function | ||
379 | .globl mcount | ||
380 | .type mcount,@function | ||
381 | _mcount: | ||
382 | mcount: | ||
383 | mov.l r4, @-r15 | ||
384 | mov.l r5, @-r15 | ||
385 | mov.l r6, @-r15 | ||
386 | mov.l r7, @-r15 | ||
387 | sts.l pr, @-r15 | ||
388 | |||
389 | mov.l @(20,r15),r4 | ||
390 | sts pr, r5 | ||
391 | |||
392 | mov.l 1f, r6 | ||
393 | mov.l ftrace_stub, r7 | ||
394 | cmp/eq r6, r7 | ||
395 | bt skip_trace | ||
396 | |||
397 | mov.l @r6, r6 | ||
398 | jsr @r6 | ||
399 | nop | ||
400 | |||
401 | skip_trace: | ||
402 | |||
403 | lds.l @r15+, pr | ||
404 | mov.l @r15+, r7 | ||
405 | mov.l @r15+, r6 | ||
406 | mov.l @r15+, r5 | ||
407 | rts | ||
408 | mov.l @r15+, r4 | ||
409 | |||
410 | .align 2 | ||
411 | 1: .long ftrace_trace_function | ||
412 | |||
413 | .globl ftrace_stub | ||
414 | ftrace_stub: | ||
415 | rts | ||
416 | nop | ||
417 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c new file mode 100644 index 000000000000..4c3247477aa3 --- /dev/null +++ b/arch/sh/kernel/ftrace.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Matt Fleming <mjf@gentoo.org> | ||
3 | * Copyright (C) 2008 Paul Mundt <lethal@linux-sh.org> | ||
4 | * | ||
5 | * Code for replacing ftrace calls with jumps. | ||
6 | * | ||
7 | * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com> | ||
8 | * | ||
9 | * Thanks goes to Ingo Molnar, for suggesting the idea. | ||
10 | * Mathieu Desnoyers, for suggesting postponing the modifications. | ||
11 | * Arjan van de Ven, for keeping me straight, and explaining to me | ||
12 | * the dangers of modifying code on the run. | ||
13 | */ | ||
14 | #include <linux/uaccess.h> | ||
15 | #include <linux/ftrace.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <asm/ftrace.h> | ||
20 | #include <asm/cacheflush.h> | ||
21 | |||
22 | static unsigned char ftrace_nop[] = { | ||
23 | 0x09, 0x00, /* nop */ | ||
24 | 0x09, 0x00, /* nop */ | ||
25 | }; | ||
26 | |||
27 | static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; | ||
28 | |||
29 | unsigned char *ftrace_nop_replace(void) | ||
30 | { | ||
31 | return ftrace_nop; | ||
32 | } | ||
33 | |||
34 | static int is_sh_nop(unsigned char *ip) | ||
35 | { | ||
36 | return strncmp(ip, ftrace_nop, sizeof(ftrace_nop)); | ||
37 | } | ||
38 | |||
39 | unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | ||
40 | { | ||
41 | /* Place the address in the memory table. */ | ||
42 | if (addr == CALLER_ADDR) | ||
43 | __raw_writel(addr + MCOUNT_INSN_OFFSET, ftrace_replaced_code); | ||
44 | else | ||
45 | __raw_writel(addr, ftrace_replaced_code); | ||
46 | |||
47 | /* | ||
48 | * No locking needed, this must be called via kstop_machine | ||
49 | * which in essence is like running on a uniprocessor machine. | ||
50 | */ | ||
51 | return ftrace_replaced_code; | ||
52 | } | ||
53 | |||
54 | int ftrace_modify_code(unsigned long ip, unsigned char *old_code, | ||
55 | unsigned char *new_code) | ||
56 | { | ||
57 | unsigned char replaced[MCOUNT_INSN_SIZE]; | ||
58 | |||
59 | /* | ||
60 | * Note: Due to modules and __init, code can | ||
61 | * disappear and change, we need to protect against faulting | ||
62 | * as well as code changing. We do this by using the | ||
63 | * probe_kernel_* functions. | ||
64 | * | ||
65 | * No real locking needed, this code is run through | ||
66 | * kstop_machine, or before SMP starts. | ||
67 | */ | ||
68 | |||
69 | /* | ||
70 | * If we're trying to nop out a call to a function, we instead | ||
71 | * place a call to the address after the memory table. | ||
72 | */ | ||
73 | if (is_sh_nop(new_code) == 0) | ||
74 | __raw_writel(ip + MCOUNT_INSN_SIZE, (unsigned long)new_code); | ||
75 | |||
76 | /* read the text we want to modify */ | ||
77 | if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) | ||
78 | return -EFAULT; | ||
79 | |||
80 | /* Make sure it is what we expect it to be */ | ||
81 | if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) | ||
82 | return -EINVAL; | ||
83 | |||
84 | /* replace the text with the new text */ | ||
85 | if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) | ||
86 | return -EPERM; | ||
87 | |||
88 | flush_icache_range(ip, ip + MCOUNT_INSN_SIZE); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | int ftrace_update_ftrace_func(ftrace_func_t func) | ||
94 | { | ||
95 | unsigned long ip = (unsigned long)(&ftrace_call); | ||
96 | unsigned char old[MCOUNT_INSN_SIZE], *new; | ||
97 | |||
98 | memcpy(old, (unsigned char *)(ip + MCOUNT_INSN_OFFSET), MCOUNT_INSN_SIZE); | ||
99 | new = ftrace_call_replace(ip, (unsigned long)func); | ||
100 | |||
101 | return ftrace_modify_code(ip + MCOUNT_INSN_OFFSET, old, new); | ||
102 | } | ||
103 | |||
104 | int ftrace_make_nop(struct module *mod, | ||
105 | struct dyn_ftrace *rec, unsigned long addr) | ||
106 | { | ||
107 | unsigned char *new, *old; | ||
108 | unsigned long ip = rec->ip; | ||
109 | |||
110 | old = ftrace_call_replace(ip, addr); | ||
111 | new = ftrace_nop_replace(); | ||
112 | |||
113 | return ftrace_modify_code(rec->ip, old, new); | ||
114 | } | ||
115 | |||
116 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | ||
117 | { | ||
118 | unsigned char *new, *old; | ||
119 | unsigned long ip = rec->ip; | ||
120 | |||
121 | old = ftrace_nop_replace(); | ||
122 | new = ftrace_call_replace(ip, addr); | ||
123 | |||
124 | return ftrace_modify_code(rec->ip, old, new); | ||
125 | } | ||
126 | |||
127 | int __init ftrace_dyn_arch_init(void *data) | ||
128 | { | ||
129 | /* The return code is retured via data */ | ||
130 | __raw_writel(0, (unsigned long)data); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index ae0a382a82eb..788605ff7088 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S | |||
@@ -80,8 +80,14 @@ ENTRY(_stext) | |||
80 | mov.l 7f, r0 | 80 | mov.l 7f, r0 |
81 | ldc r0, r7_bank ! ... and initial thread_info | 81 | ldc r0, r7_bank ! ... and initial thread_info |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | ! Clear BSS area | 84 | #ifndef CONFIG_SH_NO_BSS_INIT |
85 | /* | ||
86 | * Don't clear BSS if running on slow platforms such as an RTL simulation, | ||
87 | * remote memory via SHdebug link, etc. For these the memory can be guaranteed | ||
88 | * to be all zero on boot anyway. | ||
89 | */ | ||
90 | ! Clear BSS area | ||
85 | #ifdef CONFIG_SMP | 91 | #ifdef CONFIG_SMP |
86 | mov.l 3f, r0 | 92 | mov.l 3f, r0 |
87 | cmp/eq #0, r0 ! skip clear if set to zero | 93 | cmp/eq #0, r0 ! skip clear if set to zero |
@@ -97,6 +103,8 @@ ENTRY(_stext) | |||
97 | mov.l r0,@-r2 | 103 | mov.l r0,@-r2 |
98 | 104 | ||
99 | 10: | 105 | 10: |
106 | #endif | ||
107 | |||
100 | ! Additional CPU initialization | 108 | ! Additional CPU initialization |
101 | mov.l 6f, r0 | 109 | mov.l 6f, r0 |
102 | jsr @r0 | 110 | jsr @r0 |
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c new file mode 100644 index 000000000000..fe59ccfc1152 --- /dev/null +++ b/arch/sh/kernel/idle.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * The idle loop for all SuperH platforms. | ||
3 | * | ||
4 | * Copyright (C) 2002 - 2008 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/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/mm.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/tick.h> | ||
15 | #include <linux/preempt.h> | ||
16 | #include <linux/thread_info.h> | ||
17 | #include <linux/irqflags.h> | ||
18 | #include <asm/pgalloc.h> | ||
19 | #include <asm/system.h> | ||
20 | #include <asm/atomic.h> | ||
21 | |||
22 | static int hlt_counter; | ||
23 | void (*pm_idle)(void); | ||
24 | void (*pm_power_off)(void); | ||
25 | EXPORT_SYMBOL(pm_power_off); | ||
26 | |||
27 | static int __init nohlt_setup(char *__unused) | ||
28 | { | ||
29 | hlt_counter = 1; | ||
30 | return 1; | ||
31 | } | ||
32 | __setup("nohlt", nohlt_setup); | ||
33 | |||
34 | static int __init hlt_setup(char *__unused) | ||
35 | { | ||
36 | hlt_counter = 0; | ||
37 | return 1; | ||
38 | } | ||
39 | __setup("hlt", hlt_setup); | ||
40 | |||
41 | static void default_idle(void) | ||
42 | { | ||
43 | if (!hlt_counter) { | ||
44 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
45 | smp_mb__after_clear_bit(); | ||
46 | set_bl_bit(); | ||
47 | stop_critical_timings(); | ||
48 | |||
49 | while (!need_resched()) | ||
50 | cpu_sleep(); | ||
51 | |||
52 | start_critical_timings(); | ||
53 | clear_bl_bit(); | ||
54 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
55 | } else | ||
56 | while (!need_resched()) | ||
57 | cpu_relax(); | ||
58 | } | ||
59 | |||
60 | void cpu_idle(void) | ||
61 | { | ||
62 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
63 | |||
64 | /* endless idle loop with no priority at all */ | ||
65 | while (1) { | ||
66 | void (*idle)(void) = pm_idle; | ||
67 | |||
68 | if (!idle) | ||
69 | idle = default_idle; | ||
70 | |||
71 | tick_nohz_stop_sched_tick(1); | ||
72 | while (!need_resched()) | ||
73 | idle(); | ||
74 | tick_nohz_restart_sched_tick(); | ||
75 | |||
76 | preempt_enable_no_resched(); | ||
77 | schedule(); | ||
78 | preempt_disable(); | ||
79 | check_pgt_cache(); | ||
80 | } | ||
81 | } | ||
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c new file mode 100644 index 000000000000..7c747e7d71b8 --- /dev/null +++ b/arch/sh/kernel/kgdb.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * SuperH KGDB support | ||
3 | * | ||
4 | * Copyright (C) 2008 Paul Mundt | ||
5 | * | ||
6 | * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel. | ||
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/kgdb.h> | ||
13 | #include <linux/kdebug.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <asm/cacheflush.h> | ||
17 | |||
18 | char in_nmi = 0; /* Set during NMI to prevent re-entry */ | ||
19 | |||
20 | /* Macros for single step instruction identification */ | ||
21 | #define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) | ||
22 | #define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) | ||
23 | #define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ | ||
24 | (((op) & 0x7f ) << 1)) | ||
25 | #define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) | ||
26 | #define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) | ||
27 | #define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) | ||
28 | #define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ | ||
29 | (((op) & 0x7ff) << 1)) | ||
30 | #define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) | ||
31 | #define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) | ||
32 | #define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) | ||
33 | #define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ | ||
34 | (((op) & 0x7ff) << 1)) | ||
35 | #define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) | ||
36 | #define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) | ||
37 | #define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) | ||
38 | #define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) | ||
39 | #define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) | ||
40 | #define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) | ||
41 | #define OPCODE_RTS(op) ((op) == 0xb) | ||
42 | #define OPCODE_RTE(op) ((op) == 0x2b) | ||
43 | |||
44 | #define SR_T_BIT_MASK 0x1 | ||
45 | #define STEP_OPCODE 0xc33d | ||
46 | |||
47 | /* Calculate the new address for after a step */ | ||
48 | static short *get_step_address(struct pt_regs *linux_regs) | ||
49 | { | ||
50 | opcode_t op = __raw_readw(linux_regs->pc); | ||
51 | long addr; | ||
52 | |||
53 | /* BT */ | ||
54 | if (OPCODE_BT(op)) { | ||
55 | if (linux_regs->sr & SR_T_BIT_MASK) | ||
56 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); | ||
57 | else | ||
58 | addr = linux_regs->pc + 2; | ||
59 | } | ||
60 | |||
61 | /* BTS */ | ||
62 | else if (OPCODE_BTS(op)) { | ||
63 | if (linux_regs->sr & SR_T_BIT_MASK) | ||
64 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); | ||
65 | else | ||
66 | addr = linux_regs->pc + 4; /* Not in delay slot */ | ||
67 | } | ||
68 | |||
69 | /* BF */ | ||
70 | else if (OPCODE_BF(op)) { | ||
71 | if (!(linux_regs->sr & SR_T_BIT_MASK)) | ||
72 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); | ||
73 | else | ||
74 | addr = linux_regs->pc + 2; | ||
75 | } | ||
76 | |||
77 | /* BFS */ | ||
78 | else if (OPCODE_BFS(op)) { | ||
79 | if (!(linux_regs->sr & SR_T_BIT_MASK)) | ||
80 | addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op); | ||
81 | else | ||
82 | addr = linux_regs->pc + 4; /* Not in delay slot */ | ||
83 | } | ||
84 | |||
85 | /* BRA */ | ||
86 | else if (OPCODE_BRA(op)) | ||
87 | addr = linux_regs->pc + 4 + OPCODE_BRA_DISP(op); | ||
88 | |||
89 | /* BRAF */ | ||
90 | else if (OPCODE_BRAF(op)) | ||
91 | addr = linux_regs->pc + 4 | ||
92 | + linux_regs->regs[OPCODE_BRAF_REG(op)]; | ||
93 | |||
94 | /* BSR */ | ||
95 | else if (OPCODE_BSR(op)) | ||
96 | addr = linux_regs->pc + 4 + OPCODE_BSR_DISP(op); | ||
97 | |||
98 | /* BSRF */ | ||
99 | else if (OPCODE_BSRF(op)) | ||
100 | addr = linux_regs->pc + 4 | ||
101 | + linux_regs->regs[OPCODE_BSRF_REG(op)]; | ||
102 | |||
103 | /* JMP */ | ||
104 | else if (OPCODE_JMP(op)) | ||
105 | addr = linux_regs->regs[OPCODE_JMP_REG(op)]; | ||
106 | |||
107 | /* JSR */ | ||
108 | else if (OPCODE_JSR(op)) | ||
109 | addr = linux_regs->regs[OPCODE_JSR_REG(op)]; | ||
110 | |||
111 | /* RTS */ | ||
112 | else if (OPCODE_RTS(op)) | ||
113 | addr = linux_regs->pr; | ||
114 | |||
115 | /* RTE */ | ||
116 | else if (OPCODE_RTE(op)) | ||
117 | addr = linux_regs->regs[15]; | ||
118 | |||
119 | /* Other */ | ||
120 | else | ||
121 | addr = linux_regs->pc + instruction_size(op); | ||
122 | |||
123 | flush_icache_range(addr, addr + instruction_size(op)); | ||
124 | return (short *)addr; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Replace the instruction immediately after the current instruction | ||
129 | * (i.e. next in the expected flow of control) with a trap instruction, | ||
130 | * so that returning will cause only a single instruction to be executed. | ||
131 | * Note that this model is slightly broken for instructions with delay | ||
132 | * slots (e.g. B[TF]S, BSR, BRA etc), where both the branch and the | ||
133 | * instruction in the delay slot will be executed. | ||
134 | */ | ||
135 | |||
136 | static unsigned long stepped_address; | ||
137 | static opcode_t stepped_opcode; | ||
138 | |||
139 | static void do_single_step(struct pt_regs *linux_regs) | ||
140 | { | ||
141 | /* Determine where the target instruction will send us to */ | ||
142 | unsigned short *addr = get_step_address(linux_regs); | ||
143 | |||
144 | stepped_address = (int)addr; | ||
145 | |||
146 | /* Replace it */ | ||
147 | stepped_opcode = __raw_readw((long)addr); | ||
148 | *addr = STEP_OPCODE; | ||
149 | |||
150 | /* Flush and return */ | ||
151 | flush_icache_range((long)addr, (long)addr + | ||
152 | instruction_size(stepped_opcode)); | ||
153 | } | ||
154 | |||
155 | /* Undo a single step */ | ||
156 | static void undo_single_step(struct pt_regs *linux_regs) | ||
157 | { | ||
158 | /* If we have stepped, put back the old instruction */ | ||
159 | /* Use stepped_address in case we stopped elsewhere */ | ||
160 | if (stepped_opcode != 0) { | ||
161 | __raw_writew(stepped_opcode, stepped_address); | ||
162 | flush_icache_range(stepped_address, stepped_address + 2); | ||
163 | } | ||
164 | |||
165 | stepped_opcode = 0; | ||
166 | } | ||
167 | |||
168 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
169 | { | ||
170 | int i; | ||
171 | |||
172 | for (i = 0; i < 16; i++) | ||
173 | gdb_regs[GDB_R0 + i] = regs->regs[i]; | ||
174 | |||
175 | gdb_regs[GDB_PC] = regs->pc; | ||
176 | gdb_regs[GDB_PR] = regs->pr; | ||
177 | gdb_regs[GDB_SR] = regs->sr; | ||
178 | gdb_regs[GDB_GBR] = regs->gbr; | ||
179 | gdb_regs[GDB_MACH] = regs->mach; | ||
180 | gdb_regs[GDB_MACL] = regs->macl; | ||
181 | |||
182 | __asm__ __volatile__ ("stc vbr, %0" : "=r" (gdb_regs[GDB_VBR])); | ||
183 | } | ||
184 | |||
185 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
186 | { | ||
187 | int i; | ||
188 | |||
189 | for (i = 0; i < 16; i++) | ||
190 | regs->regs[GDB_R0 + i] = gdb_regs[GDB_R0 + i]; | ||
191 | |||
192 | regs->pc = gdb_regs[GDB_PC]; | ||
193 | regs->pr = gdb_regs[GDB_PR]; | ||
194 | regs->sr = gdb_regs[GDB_SR]; | ||
195 | regs->gbr = gdb_regs[GDB_GBR]; | ||
196 | regs->mach = gdb_regs[GDB_MACH]; | ||
197 | regs->macl = gdb_regs[GDB_MACL]; | ||
198 | |||
199 | __asm__ __volatile__ ("ldc %0, vbr" : : "r" (gdb_regs[GDB_VBR])); | ||
200 | } | ||
201 | |||
202 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | ||
203 | { | ||
204 | gdb_regs[GDB_R15] = p->thread.sp; | ||
205 | gdb_regs[GDB_PC] = p->thread.pc; | ||
206 | } | ||
207 | |||
208 | int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | ||
209 | char *remcomInBuffer, char *remcomOutBuffer, | ||
210 | struct pt_regs *linux_regs) | ||
211 | { | ||
212 | unsigned long addr; | ||
213 | char *ptr; | ||
214 | |||
215 | /* Undo any stepping we may have done */ | ||
216 | undo_single_step(linux_regs); | ||
217 | |||
218 | switch (remcomInBuffer[0]) { | ||
219 | case 'c': | ||
220 | case 's': | ||
221 | /* try to read optional parameter, pc unchanged if no parm */ | ||
222 | ptr = &remcomInBuffer[1]; | ||
223 | if (kgdb_hex2long(&ptr, &addr)) | ||
224 | linux_regs->pc = addr; | ||
225 | case 'D': | ||
226 | case 'k': | ||
227 | atomic_set(&kgdb_cpu_doing_single_step, -1); | ||
228 | |||
229 | if (remcomInBuffer[0] == 's') { | ||
230 | do_single_step(linux_regs); | ||
231 | kgdb_single_step = 1; | ||
232 | |||
233 | atomic_set(&kgdb_cpu_doing_single_step, | ||
234 | raw_smp_processor_id()); | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | /* this means that we do not want to exit from the handler: */ | ||
241 | return -1; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * The primary entry points for the kgdb debug trap table entries. | ||
246 | */ | ||
247 | BUILD_TRAP_HANDLER(singlestep) | ||
248 | { | ||
249 | unsigned long flags; | ||
250 | TRAP_HANDLER_DECL; | ||
251 | |||
252 | local_irq_save(flags); | ||
253 | regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); | ||
254 | kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); | ||
255 | local_irq_restore(flags); | ||
256 | } | ||
257 | |||
258 | |||
259 | BUILD_TRAP_HANDLER(breakpoint) | ||
260 | { | ||
261 | unsigned long flags; | ||
262 | TRAP_HANDLER_DECL; | ||
263 | |||
264 | local_irq_save(flags); | ||
265 | kgdb_handle_exception(vec >> 2, SIGTRAP, 0, regs); | ||
266 | local_irq_restore(flags); | ||
267 | } | ||
268 | |||
269 | int kgdb_arch_init(void) | ||
270 | { | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | void kgdb_arch_exit(void) | ||
275 | { | ||
276 | } | ||
277 | |||
278 | struct kgdb_arch arch_kgdb_ops = { | ||
279 | /* Breakpoint instruction: trapa #0x3c */ | ||
280 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | ||
281 | .gdb_bpt_instr = { 0x3c, 0xc3 }, | ||
282 | #else | ||
283 | .gdb_bpt_instr = { 0xc3, 0x3c }, | ||
284 | #endif | ||
285 | }; | ||
diff --git a/arch/sh/kernel/kgdb_jmp.S b/arch/sh/kernel/kgdb_jmp.S deleted file mode 100644 index 339bb1d7ff0b..000000000000 --- a/arch/sh/kernel/kgdb_jmp.S +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | #include <linux/linkage.h> | ||
2 | |||
3 | ENTRY(setjmp) | ||
4 | add #(9*4), r4 | ||
5 | sts.l pr, @-r4 | ||
6 | mov.l r15, @-r4 | ||
7 | mov.l r14, @-r4 | ||
8 | mov.l r13, @-r4 | ||
9 | mov.l r12, @-r4 | ||
10 | mov.l r11, @-r4 | ||
11 | mov.l r10, @-r4 | ||
12 | mov.l r9, @-r4 | ||
13 | mov.l r8, @-r4 | ||
14 | rts | ||
15 | mov #0, r0 | ||
16 | |||
17 | ENTRY(longjmp) | ||
18 | mov.l @r4+, r8 | ||
19 | mov.l @r4+, r9 | ||
20 | mov.l @r4+, r10 | ||
21 | mov.l @r4+, r11 | ||
22 | mov.l @r4+, r12 | ||
23 | mov.l @r4+, r13 | ||
24 | mov.l @r4+, r14 | ||
25 | mov.l @r4+, r15 | ||
26 | lds.l @r4+, pr | ||
27 | mov r5, r0 | ||
28 | tst r0, r0 | ||
29 | bf 1f | ||
30 | mov #1, r0 ! in case val==0 | ||
31 | 1: rts | ||
32 | nop | ||
33 | |||
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c deleted file mode 100644 index bf8ac4c71640..000000000000 --- a/arch/sh/kernel/kgdb_stub.c +++ /dev/null | |||
@@ -1,1052 +0,0 @@ | |||
1 | /* | ||
2 | * May be copied or modified under the terms of the GNU General Public | ||
3 | * License. See linux/COPYING for more information. | ||
4 | * | ||
5 | * Contains extracts from code by Glenn Engel, Jim Kingdon, | ||
6 | * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>, | ||
7 | * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>, | ||
8 | * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>. | ||
9 | * | ||
10 | * This version by Henry Bell <henry.bell@st.com> | ||
11 | * Minor modifications by Jeremy Siegel <jsiegel@mvista.com> | ||
12 | * | ||
13 | * Contains low-level support for remote debug using GDB. | ||
14 | * | ||
15 | * To enable debugger support, two things need to happen. A call to | ||
16 | * set_debug_traps() is necessary in order to allow any breakpoints | ||
17 | * or error conditions to be properly intercepted and reported to gdb. | ||
18 | * A breakpoint also needs to be generated to begin communication. This | ||
19 | * is most easily accomplished by a call to breakpoint() which does | ||
20 | * a trapa if the initialisation phase has been successfully completed. | ||
21 | * | ||
22 | * In this case, set_debug_traps() is not used to "take over" exceptions; | ||
23 | * other kernel code is modified instead to enter the kgdb functions here | ||
24 | * when appropriate (see entry.S for breakpoint traps and NMI interrupts, | ||
25 | * see traps.c for kernel error exceptions). | ||
26 | * | ||
27 | * The following gdb commands are supported: | ||
28 | * | ||
29 | * Command Function Return value | ||
30 | * | ||
31 | * g return the value of the CPU registers hex data or ENN | ||
32 | * G set the value of the CPU registers OK or ENN | ||
33 | * | ||
34 | * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN | ||
35 | * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN | ||
36 | * XAA..AA,LLLL: Same, but data is binary (not hex) OK or ENN | ||
37 | * | ||
38 | * c Resume at current address SNN ( signal NN) | ||
39 | * cAA..AA Continue at address AA..AA SNN | ||
40 | * CNN; Resume at current address with signal SNN | ||
41 | * CNN;AA..AA Resume at address AA..AA with signal SNN | ||
42 | * | ||
43 | * s Step one instruction SNN | ||
44 | * sAA..AA Step one instruction from AA..AA SNN | ||
45 | * SNN; Step one instruction with signal SNN | ||
46 | * SNNAA..AA Step one instruction from AA..AA w/NN SNN | ||
47 | * | ||
48 | * k kill (Detach GDB) | ||
49 | * | ||
50 | * d Toggle debug flag | ||
51 | * D Detach GDB | ||
52 | * | ||
53 | * Hct Set thread t for operations, OK or ENN | ||
54 | * c = 'c' (step, cont), c = 'g' (other | ||
55 | * operations) | ||
56 | * | ||
57 | * qC Query current thread ID QCpid | ||
58 | * qfThreadInfo Get list of current threads (first) m<id> | ||
59 | * qsThreadInfo " " " " " (subsequent) | ||
60 | * qOffsets Get section offsets Text=x;Data=y;Bss=z | ||
61 | * | ||
62 | * TXX Find if thread XX is alive OK or ENN | ||
63 | * ? What was the last sigval ? SNN (signal NN) | ||
64 | * O Output to GDB console | ||
65 | * | ||
66 | * Remote communication protocol. | ||
67 | * | ||
68 | * A debug packet whose contents are <data> is encapsulated for | ||
69 | * transmission in the form: | ||
70 | * | ||
71 | * $ <data> # CSUM1 CSUM2 | ||
72 | * | ||
73 | * <data> must be ASCII alphanumeric and cannot include characters | ||
74 | * '$' or '#'. If <data> starts with two characters followed by | ||
75 | * ':', then the existing stubs interpret this as a sequence number. | ||
76 | * | ||
77 | * CSUM1 and CSUM2 are ascii hex representation of an 8-bit | ||
78 | * checksum of <data>, the most significant nibble is sent first. | ||
79 | * the hex digits 0-9,a-f are used. | ||
80 | * | ||
81 | * Receiver responds with: | ||
82 | * | ||
83 | * + - if CSUM is correct and ready for next packet | ||
84 | * - - if CSUM is incorrect | ||
85 | * | ||
86 | * Responses can be run-length encoded to save space. A '*' means that | ||
87 | * the next character is an ASCII encoding giving a repeat count which | ||
88 | * stands for that many repetitions of the character preceding the '*'. | ||
89 | * The encoding is n+29, yielding a printable character where n >=3 | ||
90 | * (which is where RLE starts to win). Don't use an n > 126. | ||
91 | * | ||
92 | * So "0* " means the same as "0000". | ||
93 | */ | ||
94 | |||
95 | #include <linux/string.h> | ||
96 | #include <linux/kernel.h> | ||
97 | #include <linux/sched.h> | ||
98 | #include <linux/smp.h> | ||
99 | #include <linux/spinlock.h> | ||
100 | #include <linux/delay.h> | ||
101 | #include <linux/linkage.h> | ||
102 | #include <linux/init.h> | ||
103 | #include <linux/console.h> | ||
104 | #include <linux/sysrq.h> | ||
105 | #include <linux/module.h> | ||
106 | #include <asm/system.h> | ||
107 | #include <asm/cacheflush.h> | ||
108 | #include <asm/current.h> | ||
109 | #include <asm/signal.h> | ||
110 | #include <asm/pgtable.h> | ||
111 | #include <asm/ptrace.h> | ||
112 | #include <asm/kgdb.h> | ||
113 | #include <asm/io.h> | ||
114 | |||
115 | /* Function pointers for linkage */ | ||
116 | kgdb_debug_hook_t *kgdb_debug_hook; | ||
117 | kgdb_bus_error_hook_t *kgdb_bus_err_hook; | ||
118 | |||
119 | int (*kgdb_getchar)(void); | ||
120 | EXPORT_SYMBOL_GPL(kgdb_getchar); | ||
121 | void (*kgdb_putchar)(int); | ||
122 | EXPORT_SYMBOL_GPL(kgdb_putchar); | ||
123 | |||
124 | static void put_debug_char(int c) | ||
125 | { | ||
126 | if (!kgdb_putchar) | ||
127 | return; | ||
128 | (*kgdb_putchar)(c); | ||
129 | } | ||
130 | static int get_debug_char(void) | ||
131 | { | ||
132 | if (!kgdb_getchar) | ||
133 | return -1; | ||
134 | return (*kgdb_getchar)(); | ||
135 | } | ||
136 | |||
137 | /* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */ | ||
138 | #define BUFMAX 1024 | ||
139 | #define NUMREGBYTES (MAXREG*4) | ||
140 | #define OUTBUFMAX (NUMREGBYTES*2+512) | ||
141 | |||
142 | enum { | ||
143 | R0 = 0, R1, R2, R3, R4, R5, R6, R7, | ||
144 | R8, R9, R10, R11, R12, R13, R14, R15, | ||
145 | PC, PR, GBR, VBR, MACH, MACL, SR, | ||
146 | /* */ | ||
147 | MAXREG | ||
148 | }; | ||
149 | |||
150 | static unsigned int registers[MAXREG]; | ||
151 | struct kgdb_regs trap_registers; | ||
152 | |||
153 | char kgdb_in_gdb_mode; | ||
154 | char in_nmi; /* Set during NMI to prevent reentry */ | ||
155 | int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ | ||
156 | |||
157 | /* Default values for SCI (can override via kernel args in setup.c) */ | ||
158 | #ifndef CONFIG_KGDB_DEFPORT | ||
159 | #define CONFIG_KGDB_DEFPORT 1 | ||
160 | #endif | ||
161 | |||
162 | #ifndef CONFIG_KGDB_DEFBAUD | ||
163 | #define CONFIG_KGDB_DEFBAUD 115200 | ||
164 | #endif | ||
165 | |||
166 | #if defined(CONFIG_KGDB_DEFPARITY_E) | ||
167 | #define CONFIG_KGDB_DEFPARITY 'E' | ||
168 | #elif defined(CONFIG_KGDB_DEFPARITY_O) | ||
169 | #define CONFIG_KGDB_DEFPARITY 'O' | ||
170 | #else /* CONFIG_KGDB_DEFPARITY_N */ | ||
171 | #define CONFIG_KGDB_DEFPARITY 'N' | ||
172 | #endif | ||
173 | |||
174 | #ifdef CONFIG_KGDB_DEFBITS_7 | ||
175 | #define CONFIG_KGDB_DEFBITS '7' | ||
176 | #else /* CONFIG_KGDB_DEFBITS_8 */ | ||
177 | #define CONFIG_KGDB_DEFBITS '8' | ||
178 | #endif | ||
179 | |||
180 | /* SCI/UART settings, used in kgdb_console_setup() */ | ||
181 | int kgdb_portnum = CONFIG_KGDB_DEFPORT; | ||
182 | EXPORT_SYMBOL_GPL(kgdb_portnum); | ||
183 | int kgdb_baud = CONFIG_KGDB_DEFBAUD; | ||
184 | EXPORT_SYMBOL_GPL(kgdb_baud); | ||
185 | char kgdb_parity = CONFIG_KGDB_DEFPARITY; | ||
186 | EXPORT_SYMBOL_GPL(kgdb_parity); | ||
187 | char kgdb_bits = CONFIG_KGDB_DEFBITS; | ||
188 | EXPORT_SYMBOL_GPL(kgdb_bits); | ||
189 | |||
190 | /* Jump buffer for setjmp/longjmp */ | ||
191 | static jmp_buf rem_com_env; | ||
192 | |||
193 | /* TRA differs sh3/4 */ | ||
194 | #if defined(CONFIG_CPU_SH3) | ||
195 | #define TRA 0xffffffd0 | ||
196 | #elif defined(CONFIG_CPU_SH4) | ||
197 | #define TRA 0xff000020 | ||
198 | #endif | ||
199 | |||
200 | /* Macros for single step instruction identification */ | ||
201 | #define OPCODE_BT(op) (((op) & 0xff00) == 0x8900) | ||
202 | #define OPCODE_BF(op) (((op) & 0xff00) == 0x8b00) | ||
203 | #define OPCODE_BTF_DISP(op) (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \ | ||
204 | (((op) & 0x7f ) << 1)) | ||
205 | #define OPCODE_BFS(op) (((op) & 0xff00) == 0x8f00) | ||
206 | #define OPCODE_BTS(op) (((op) & 0xff00) == 0x8d00) | ||
207 | #define OPCODE_BRA(op) (((op) & 0xf000) == 0xa000) | ||
208 | #define OPCODE_BRA_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ | ||
209 | (((op) & 0x7ff) << 1)) | ||
210 | #define OPCODE_BRAF(op) (((op) & 0xf0ff) == 0x0023) | ||
211 | #define OPCODE_BRAF_REG(op) (((op) & 0x0f00) >> 8) | ||
212 | #define OPCODE_BSR(op) (((op) & 0xf000) == 0xb000) | ||
213 | #define OPCODE_BSR_DISP(op) (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \ | ||
214 | (((op) & 0x7ff) << 1)) | ||
215 | #define OPCODE_BSRF(op) (((op) & 0xf0ff) == 0x0003) | ||
216 | #define OPCODE_BSRF_REG(op) (((op) >> 8) & 0xf) | ||
217 | #define OPCODE_JMP(op) (((op) & 0xf0ff) == 0x402b) | ||
218 | #define OPCODE_JMP_REG(op) (((op) >> 8) & 0xf) | ||
219 | #define OPCODE_JSR(op) (((op) & 0xf0ff) == 0x400b) | ||
220 | #define OPCODE_JSR_REG(op) (((op) >> 8) & 0xf) | ||
221 | #define OPCODE_RTS(op) ((op) == 0xb) | ||
222 | #define OPCODE_RTE(op) ((op) == 0x2b) | ||
223 | |||
224 | #define SR_T_BIT_MASK 0x1 | ||
225 | #define STEP_OPCODE 0xc320 | ||
226 | #define BIOS_CALL_TRAP 0x3f | ||
227 | |||
228 | /* Exception codes as per SH-4 core manual */ | ||
229 | #define ADDRESS_ERROR_LOAD_VEC 7 | ||
230 | #define ADDRESS_ERROR_STORE_VEC 8 | ||
231 | #define TRAP_VEC 11 | ||
232 | #define INVALID_INSN_VEC 12 | ||
233 | #define INVALID_SLOT_VEC 13 | ||
234 | #define NMI_VEC 14 | ||
235 | #define USER_BREAK_VEC 15 | ||
236 | #define SERIAL_BREAK_VEC 58 | ||
237 | |||
238 | /* Misc static */ | ||
239 | static int stepped_address; | ||
240 | static short stepped_opcode; | ||
241 | static char in_buffer[BUFMAX]; | ||
242 | static char out_buffer[OUTBUFMAX]; | ||
243 | |||
244 | static void kgdb_to_gdb(const char *s); | ||
245 | |||
246 | /* Convert ch to hex */ | ||
247 | static int hex(const char ch) | ||
248 | { | ||
249 | if ((ch >= 'a') && (ch <= 'f')) | ||
250 | return (ch - 'a' + 10); | ||
251 | if ((ch >= '0') && (ch <= '9')) | ||
252 | return (ch - '0'); | ||
253 | if ((ch >= 'A') && (ch <= 'F')) | ||
254 | return (ch - 'A' + 10); | ||
255 | return (-1); | ||
256 | } | ||
257 | |||
258 | /* Convert the memory pointed to by mem into hex, placing result in buf. | ||
259 | Returns a pointer to the last char put in buf (null) */ | ||
260 | static char *mem_to_hex(const char *mem, char *buf, const int count) | ||
261 | { | ||
262 | int i; | ||
263 | int ch; | ||
264 | unsigned short s_val; | ||
265 | unsigned long l_val; | ||
266 | |||
267 | /* Check for 16 or 32 */ | ||
268 | if (count == 2 && ((long) mem & 1) == 0) { | ||
269 | s_val = *(unsigned short *) mem; | ||
270 | mem = (char *) &s_val; | ||
271 | } else if (count == 4 && ((long) mem & 3) == 0) { | ||
272 | l_val = *(unsigned long *) mem; | ||
273 | mem = (char *) &l_val; | ||
274 | } | ||
275 | for (i = 0; i < count; i++) { | ||
276 | ch = *mem++; | ||
277 | buf = pack_hex_byte(buf, ch); | ||
278 | } | ||
279 | *buf = 0; | ||
280 | return (buf); | ||
281 | } | ||
282 | |||
283 | /* Convert the hex array pointed to by buf into binary, to be placed in mem. | ||
284 | Return a pointer to the character after the last byte written */ | ||
285 | static char *hex_to_mem(const char *buf, char *mem, const int count) | ||
286 | { | ||
287 | int i; | ||
288 | unsigned char ch; | ||
289 | |||
290 | for (i = 0; i < count; i++) { | ||
291 | ch = hex(*buf++) << 4; | ||
292 | ch = ch + hex(*buf++); | ||
293 | *mem++ = ch; | ||
294 | } | ||
295 | return (mem); | ||
296 | } | ||
297 | |||
298 | /* While finding valid hex chars, convert to an integer, then return it */ | ||
299 | static int hex_to_int(char **ptr, int *int_value) | ||
300 | { | ||
301 | int num_chars = 0; | ||
302 | int hex_value; | ||
303 | |||
304 | *int_value = 0; | ||
305 | |||
306 | while (**ptr) { | ||
307 | hex_value = hex(**ptr); | ||
308 | if (hex_value >= 0) { | ||
309 | *int_value = (*int_value << 4) | hex_value; | ||
310 | num_chars++; | ||
311 | } else | ||
312 | break; | ||
313 | (*ptr)++; | ||
314 | } | ||
315 | return num_chars; | ||
316 | } | ||
317 | |||
318 | /* Copy the binary array pointed to by buf into mem. Fix $, #, | ||
319 | and 0x7d escaped with 0x7d. Return a pointer to the character | ||
320 | after the last byte written. */ | ||
321 | static char *ebin_to_mem(const char *buf, char *mem, int count) | ||
322 | { | ||
323 | for (; count > 0; count--, buf++) { | ||
324 | if (*buf == 0x7d) | ||
325 | *mem++ = *(++buf) ^ 0x20; | ||
326 | else | ||
327 | *mem++ = *buf; | ||
328 | } | ||
329 | return mem; | ||
330 | } | ||
331 | |||
332 | /* Scan for the start char '$', read the packet and check the checksum */ | ||
333 | static void get_packet(char *buffer, int buflen) | ||
334 | { | ||
335 | unsigned char checksum; | ||
336 | unsigned char xmitcsum; | ||
337 | int i; | ||
338 | int count; | ||
339 | char ch; | ||
340 | |||
341 | do { | ||
342 | /* Ignore everything until the start character */ | ||
343 | while ((ch = get_debug_char()) != '$'); | ||
344 | |||
345 | checksum = 0; | ||
346 | xmitcsum = -1; | ||
347 | count = 0; | ||
348 | |||
349 | /* Now, read until a # or end of buffer is found */ | ||
350 | while (count < (buflen - 1)) { | ||
351 | ch = get_debug_char(); | ||
352 | |||
353 | if (ch == '#') | ||
354 | break; | ||
355 | |||
356 | checksum = checksum + ch; | ||
357 | buffer[count] = ch; | ||
358 | count = count + 1; | ||
359 | } | ||
360 | |||
361 | buffer[count] = 0; | ||
362 | |||
363 | /* Continue to read checksum following # */ | ||
364 | if (ch == '#') { | ||
365 | xmitcsum = hex(get_debug_char()) << 4; | ||
366 | xmitcsum += hex(get_debug_char()); | ||
367 | |||
368 | /* Checksum */ | ||
369 | if (checksum != xmitcsum) | ||
370 | put_debug_char('-'); /* Failed checksum */ | ||
371 | else { | ||
372 | /* Ack successful transfer */ | ||
373 | put_debug_char('+'); | ||
374 | |||
375 | /* If a sequence char is present, reply | ||
376 | the sequence ID */ | ||
377 | if (buffer[2] == ':') { | ||
378 | put_debug_char(buffer[0]); | ||
379 | put_debug_char(buffer[1]); | ||
380 | |||
381 | /* Remove sequence chars from buffer */ | ||
382 | count = strlen(buffer); | ||
383 | for (i = 3; i <= count; i++) | ||
384 | buffer[i - 3] = buffer[i]; | ||
385 | } | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | while (checksum != xmitcsum); /* Keep trying while we fail */ | ||
390 | } | ||
391 | |||
392 | /* Send the packet in the buffer with run-length encoding */ | ||
393 | static void put_packet(char *buffer) | ||
394 | { | ||
395 | int checksum; | ||
396 | char *src; | ||
397 | int runlen; | ||
398 | int encode; | ||
399 | |||
400 | do { | ||
401 | src = buffer; | ||
402 | put_debug_char('$'); | ||
403 | checksum = 0; | ||
404 | |||
405 | /* Continue while we still have chars left */ | ||
406 | while (*src) { | ||
407 | /* Check for runs up to 99 chars long */ | ||
408 | for (runlen = 1; runlen < 99; runlen++) { | ||
409 | if (src[0] != src[runlen]) | ||
410 | break; | ||
411 | } | ||
412 | |||
413 | if (runlen > 3) { | ||
414 | /* Got a useful amount, send encoding */ | ||
415 | encode = runlen + ' ' - 4; | ||
416 | put_debug_char(*src); checksum += *src; | ||
417 | put_debug_char('*'); checksum += '*'; | ||
418 | put_debug_char(encode); checksum += encode; | ||
419 | src += runlen; | ||
420 | } else { | ||
421 | /* Otherwise just send the current char */ | ||
422 | put_debug_char(*src); checksum += *src; | ||
423 | src += 1; | ||
424 | } | ||
425 | } | ||
426 | |||
427 | /* '#' Separator, put high and low components of checksum */ | ||
428 | put_debug_char('#'); | ||
429 | put_debug_char(hex_asc_hi(checksum)); | ||
430 | put_debug_char(hex_asc_lo(checksum)); | ||
431 | } | ||
432 | while ((get_debug_char()) != '+'); /* While no ack */ | ||
433 | } | ||
434 | |||
435 | /* A bus error has occurred - perform a longjmp to return execution and | ||
436 | allow handling of the error */ | ||
437 | static void kgdb_handle_bus_error(void) | ||
438 | { | ||
439 | longjmp(rem_com_env, 1); | ||
440 | } | ||
441 | |||
442 | /* Translate SH-3/4 exception numbers to unix-like signal values */ | ||
443 | static int compute_signal(const int excep_code) | ||
444 | { | ||
445 | int sigval; | ||
446 | |||
447 | switch (excep_code) { | ||
448 | |||
449 | case INVALID_INSN_VEC: | ||
450 | case INVALID_SLOT_VEC: | ||
451 | sigval = SIGILL; | ||
452 | break; | ||
453 | case ADDRESS_ERROR_LOAD_VEC: | ||
454 | case ADDRESS_ERROR_STORE_VEC: | ||
455 | sigval = SIGSEGV; | ||
456 | break; | ||
457 | |||
458 | case SERIAL_BREAK_VEC: | ||
459 | case NMI_VEC: | ||
460 | sigval = SIGINT; | ||
461 | break; | ||
462 | |||
463 | case USER_BREAK_VEC: | ||
464 | case TRAP_VEC: | ||
465 | sigval = SIGTRAP; | ||
466 | break; | ||
467 | |||
468 | default: | ||
469 | sigval = SIGBUS; /* "software generated" */ | ||
470 | break; | ||
471 | } | ||
472 | |||
473 | return (sigval); | ||
474 | } | ||
475 | |||
476 | /* Make a local copy of the registers passed into the handler (bletch) */ | ||
477 | static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs, | ||
478 | int *gdb_regs) | ||
479 | { | ||
480 | gdb_regs[R0] = regs->regs[R0]; | ||
481 | gdb_regs[R1] = regs->regs[R1]; | ||
482 | gdb_regs[R2] = regs->regs[R2]; | ||
483 | gdb_regs[R3] = regs->regs[R3]; | ||
484 | gdb_regs[R4] = regs->regs[R4]; | ||
485 | gdb_regs[R5] = regs->regs[R5]; | ||
486 | gdb_regs[R6] = regs->regs[R6]; | ||
487 | gdb_regs[R7] = regs->regs[R7]; | ||
488 | gdb_regs[R8] = regs->regs[R8]; | ||
489 | gdb_regs[R9] = regs->regs[R9]; | ||
490 | gdb_regs[R10] = regs->regs[R10]; | ||
491 | gdb_regs[R11] = regs->regs[R11]; | ||
492 | gdb_regs[R12] = regs->regs[R12]; | ||
493 | gdb_regs[R13] = regs->regs[R13]; | ||
494 | gdb_regs[R14] = regs->regs[R14]; | ||
495 | gdb_regs[R15] = regs->regs[R15]; | ||
496 | gdb_regs[PC] = regs->pc; | ||
497 | gdb_regs[PR] = regs->pr; | ||
498 | gdb_regs[GBR] = regs->gbr; | ||
499 | gdb_regs[MACH] = regs->mach; | ||
500 | gdb_regs[MACL] = regs->macl; | ||
501 | gdb_regs[SR] = regs->sr; | ||
502 | gdb_regs[VBR] = regs->vbr; | ||
503 | } | ||
504 | |||
505 | /* Copy local gdb registers back to kgdb regs, for later copy to kernel */ | ||
506 | static void gdb_regs_to_kgdb_regs(const int *gdb_regs, | ||
507 | struct kgdb_regs *regs) | ||
508 | { | ||
509 | regs->regs[R0] = gdb_regs[R0]; | ||
510 | regs->regs[R1] = gdb_regs[R1]; | ||
511 | regs->regs[R2] = gdb_regs[R2]; | ||
512 | regs->regs[R3] = gdb_regs[R3]; | ||
513 | regs->regs[R4] = gdb_regs[R4]; | ||
514 | regs->regs[R5] = gdb_regs[R5]; | ||
515 | regs->regs[R6] = gdb_regs[R6]; | ||
516 | regs->regs[R7] = gdb_regs[R7]; | ||
517 | regs->regs[R8] = gdb_regs[R8]; | ||
518 | regs->regs[R9] = gdb_regs[R9]; | ||
519 | regs->regs[R10] = gdb_regs[R10]; | ||
520 | regs->regs[R11] = gdb_regs[R11]; | ||
521 | regs->regs[R12] = gdb_regs[R12]; | ||
522 | regs->regs[R13] = gdb_regs[R13]; | ||
523 | regs->regs[R14] = gdb_regs[R14]; | ||
524 | regs->regs[R15] = gdb_regs[R15]; | ||
525 | regs->pc = gdb_regs[PC]; | ||
526 | regs->pr = gdb_regs[PR]; | ||
527 | regs->gbr = gdb_regs[GBR]; | ||
528 | regs->mach = gdb_regs[MACH]; | ||
529 | regs->macl = gdb_regs[MACL]; | ||
530 | regs->sr = gdb_regs[SR]; | ||
531 | regs->vbr = gdb_regs[VBR]; | ||
532 | } | ||
533 | |||
534 | /* Calculate the new address for after a step */ | ||
535 | static short *get_step_address(void) | ||
536 | { | ||
537 | short op = *(short *) trap_registers.pc; | ||
538 | long addr; | ||
539 | |||
540 | /* BT */ | ||
541 | if (OPCODE_BT(op)) { | ||
542 | if (trap_registers.sr & SR_T_BIT_MASK) | ||
543 | addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); | ||
544 | else | ||
545 | addr = trap_registers.pc + 2; | ||
546 | } | ||
547 | |||
548 | /* BTS */ | ||
549 | else if (OPCODE_BTS(op)) { | ||
550 | if (trap_registers.sr & SR_T_BIT_MASK) | ||
551 | addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); | ||
552 | else | ||
553 | addr = trap_registers.pc + 4; /* Not in delay slot */ | ||
554 | } | ||
555 | |||
556 | /* BF */ | ||
557 | else if (OPCODE_BF(op)) { | ||
558 | if (!(trap_registers.sr & SR_T_BIT_MASK)) | ||
559 | addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); | ||
560 | else | ||
561 | addr = trap_registers.pc + 2; | ||
562 | } | ||
563 | |||
564 | /* BFS */ | ||
565 | else if (OPCODE_BFS(op)) { | ||
566 | if (!(trap_registers.sr & SR_T_BIT_MASK)) | ||
567 | addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op); | ||
568 | else | ||
569 | addr = trap_registers.pc + 4; /* Not in delay slot */ | ||
570 | } | ||
571 | |||
572 | /* BRA */ | ||
573 | else if (OPCODE_BRA(op)) | ||
574 | addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op); | ||
575 | |||
576 | /* BRAF */ | ||
577 | else if (OPCODE_BRAF(op)) | ||
578 | addr = trap_registers.pc + 4 | ||
579 | + trap_registers.regs[OPCODE_BRAF_REG(op)]; | ||
580 | |||
581 | /* BSR */ | ||
582 | else if (OPCODE_BSR(op)) | ||
583 | addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op); | ||
584 | |||
585 | /* BSRF */ | ||
586 | else if (OPCODE_BSRF(op)) | ||
587 | addr = trap_registers.pc + 4 | ||
588 | + trap_registers.regs[OPCODE_BSRF_REG(op)]; | ||
589 | |||
590 | /* JMP */ | ||
591 | else if (OPCODE_JMP(op)) | ||
592 | addr = trap_registers.regs[OPCODE_JMP_REG(op)]; | ||
593 | |||
594 | /* JSR */ | ||
595 | else if (OPCODE_JSR(op)) | ||
596 | addr = trap_registers.regs[OPCODE_JSR_REG(op)]; | ||
597 | |||
598 | /* RTS */ | ||
599 | else if (OPCODE_RTS(op)) | ||
600 | addr = trap_registers.pr; | ||
601 | |||
602 | /* RTE */ | ||
603 | else if (OPCODE_RTE(op)) | ||
604 | addr = trap_registers.regs[15]; | ||
605 | |||
606 | /* Other */ | ||
607 | else | ||
608 | addr = trap_registers.pc + 2; | ||
609 | |||
610 | flush_icache_range(addr, addr + 2); | ||
611 | return (short *) addr; | ||
612 | } | ||
613 | |||
614 | /* Set up a single-step. Replace the instruction immediately after the | ||
615 | current instruction (i.e. next in the expected flow of control) with a | ||
616 | trap instruction, so that returning will cause only a single instruction | ||
617 | to be executed. Note that this model is slightly broken for instructions | ||
618 | with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch | ||
619 | and the instruction in the delay slot will be executed. */ | ||
620 | static void do_single_step(void) | ||
621 | { | ||
622 | unsigned short *addr = 0; | ||
623 | |||
624 | /* Determine where the target instruction will send us to */ | ||
625 | addr = get_step_address(); | ||
626 | stepped_address = (int)addr; | ||
627 | |||
628 | /* Replace it */ | ||
629 | stepped_opcode = *(short *)addr; | ||
630 | *addr = STEP_OPCODE; | ||
631 | |||
632 | /* Flush and return */ | ||
633 | flush_icache_range((long) addr, (long) addr + 2); | ||
634 | } | ||
635 | |||
636 | /* Undo a single step */ | ||
637 | static void undo_single_step(void) | ||
638 | { | ||
639 | /* If we have stepped, put back the old instruction */ | ||
640 | /* Use stepped_address in case we stopped elsewhere */ | ||
641 | if (stepped_opcode != 0) { | ||
642 | *(short*)stepped_address = stepped_opcode; | ||
643 | flush_icache_range(stepped_address, stepped_address + 2); | ||
644 | } | ||
645 | stepped_opcode = 0; | ||
646 | } | ||
647 | |||
648 | /* Send a signal message */ | ||
649 | static void send_signal_msg(const int signum) | ||
650 | { | ||
651 | out_buffer[0] = 'S'; | ||
652 | out_buffer[1] = hex_asc_hi(signum); | ||
653 | out_buffer[2] = hex_asc_lo(signum); | ||
654 | out_buffer[3] = 0; | ||
655 | put_packet(out_buffer); | ||
656 | } | ||
657 | |||
658 | /* Reply that all was well */ | ||
659 | static void send_ok_msg(void) | ||
660 | { | ||
661 | strcpy(out_buffer, "OK"); | ||
662 | put_packet(out_buffer); | ||
663 | } | ||
664 | |||
665 | /* Reply that an error occurred */ | ||
666 | static void send_err_msg(void) | ||
667 | { | ||
668 | strcpy(out_buffer, "E01"); | ||
669 | put_packet(out_buffer); | ||
670 | } | ||
671 | |||
672 | /* Empty message indicates unrecognised command */ | ||
673 | static void send_empty_msg(void) | ||
674 | { | ||
675 | put_packet(""); | ||
676 | } | ||
677 | |||
678 | /* Read memory due to 'm' message */ | ||
679 | static void read_mem_msg(void) | ||
680 | { | ||
681 | char *ptr; | ||
682 | int addr; | ||
683 | int length; | ||
684 | |||
685 | /* Jmp, disable bus error handler */ | ||
686 | if (setjmp(rem_com_env) == 0) { | ||
687 | |||
688 | kgdb_nofault = 1; | ||
689 | |||
690 | /* Walk through, have m<addr>,<length> */ | ||
691 | ptr = &in_buffer[1]; | ||
692 | if (hex_to_int(&ptr, &addr) && (*ptr++ == ',')) | ||
693 | if (hex_to_int(&ptr, &length)) { | ||
694 | ptr = 0; | ||
695 | if (length * 2 > OUTBUFMAX) | ||
696 | length = OUTBUFMAX / 2; | ||
697 | mem_to_hex((char *) addr, out_buffer, length); | ||
698 | } | ||
699 | if (ptr) | ||
700 | send_err_msg(); | ||
701 | else | ||
702 | put_packet(out_buffer); | ||
703 | } else | ||
704 | send_err_msg(); | ||
705 | |||
706 | /* Restore bus error handler */ | ||
707 | kgdb_nofault = 0; | ||
708 | } | ||
709 | |||
710 | /* Write memory due to 'M' or 'X' message */ | ||
711 | static void write_mem_msg(int binary) | ||
712 | { | ||
713 | char *ptr; | ||
714 | int addr; | ||
715 | int length; | ||
716 | |||
717 | if (setjmp(rem_com_env) == 0) { | ||
718 | |||
719 | kgdb_nofault = 1; | ||
720 | |||
721 | /* Walk through, have M<addr>,<length>:<data> */ | ||
722 | ptr = &in_buffer[1]; | ||
723 | if (hex_to_int(&ptr, &addr) && (*ptr++ == ',')) | ||
724 | if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) { | ||
725 | if (binary) | ||
726 | ebin_to_mem(ptr, (char*)addr, length); | ||
727 | else | ||
728 | hex_to_mem(ptr, (char*)addr, length); | ||
729 | flush_icache_range(addr, addr + length); | ||
730 | ptr = 0; | ||
731 | send_ok_msg(); | ||
732 | } | ||
733 | if (ptr) | ||
734 | send_err_msg(); | ||
735 | } else | ||
736 | send_err_msg(); | ||
737 | |||
738 | /* Restore bus error handler */ | ||
739 | kgdb_nofault = 0; | ||
740 | } | ||
741 | |||
742 | /* Continue message */ | ||
743 | static void continue_msg(void) | ||
744 | { | ||
745 | /* Try to read optional parameter, PC unchanged if none */ | ||
746 | char *ptr = &in_buffer[1]; | ||
747 | int addr; | ||
748 | |||
749 | if (hex_to_int(&ptr, &addr)) | ||
750 | trap_registers.pc = addr; | ||
751 | } | ||
752 | |||
753 | /* Continue message with signal */ | ||
754 | static void continue_with_sig_msg(void) | ||
755 | { | ||
756 | int signal; | ||
757 | char *ptr = &in_buffer[1]; | ||
758 | int addr; | ||
759 | |||
760 | /* Report limitation */ | ||
761 | kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n"); | ||
762 | |||
763 | /* Signal */ | ||
764 | hex_to_int(&ptr, &signal); | ||
765 | if (*ptr == ';') | ||
766 | ptr++; | ||
767 | |||
768 | /* Optional address */ | ||
769 | if (hex_to_int(&ptr, &addr)) | ||
770 | trap_registers.pc = addr; | ||
771 | } | ||
772 | |||
773 | /* Step message */ | ||
774 | static void step_msg(void) | ||
775 | { | ||
776 | continue_msg(); | ||
777 | do_single_step(); | ||
778 | } | ||
779 | |||
780 | /* Step message with signal */ | ||
781 | static void step_with_sig_msg(void) | ||
782 | { | ||
783 | continue_with_sig_msg(); | ||
784 | do_single_step(); | ||
785 | } | ||
786 | |||
787 | /* Send register contents */ | ||
788 | static void send_regs_msg(void) | ||
789 | { | ||
790 | kgdb_regs_to_gdb_regs(&trap_registers, registers); | ||
791 | mem_to_hex((char *) registers, out_buffer, NUMREGBYTES); | ||
792 | put_packet(out_buffer); | ||
793 | } | ||
794 | |||
795 | /* Set register contents - currently can't set other thread's registers */ | ||
796 | static void set_regs_msg(void) | ||
797 | { | ||
798 | kgdb_regs_to_gdb_regs(&trap_registers, registers); | ||
799 | hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES); | ||
800 | gdb_regs_to_kgdb_regs(registers, &trap_registers); | ||
801 | send_ok_msg(); | ||
802 | } | ||
803 | |||
804 | #ifdef CONFIG_SH_KGDB_CONSOLE | ||
805 | /* | ||
806 | * Bring up the ports.. | ||
807 | */ | ||
808 | static int __init kgdb_serial_setup(void) | ||
809 | { | ||
810 | struct console dummy; | ||
811 | return kgdb_console_setup(&dummy, 0); | ||
812 | } | ||
813 | #else | ||
814 | #define kgdb_serial_setup() 0 | ||
815 | #endif | ||
816 | |||
817 | /* The command loop, read and act on requests */ | ||
818 | static void kgdb_command_loop(const int excep_code, const int trapa_value) | ||
819 | { | ||
820 | int sigval; | ||
821 | |||
822 | /* Enter GDB mode (e.g. after detach) */ | ||
823 | if (!kgdb_in_gdb_mode) { | ||
824 | /* Do serial setup, notify user, issue preemptive ack */ | ||
825 | printk(KERN_NOTICE "KGDB: Waiting for GDB\n"); | ||
826 | kgdb_in_gdb_mode = 1; | ||
827 | put_debug_char('+'); | ||
828 | } | ||
829 | |||
830 | /* Reply to host that an exception has occurred */ | ||
831 | sigval = compute_signal(excep_code); | ||
832 | send_signal_msg(sigval); | ||
833 | |||
834 | /* TRAP_VEC exception indicates a software trap inserted in place of | ||
835 | code by GDB so back up PC by one instruction, as this instruction | ||
836 | will later be replaced by its original one. Do NOT do this for | ||
837 | trap 0xff, since that indicates a compiled-in breakpoint which | ||
838 | will not be replaced (and we would retake the trap forever) */ | ||
839 | if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2))) | ||
840 | trap_registers.pc -= 2; | ||
841 | |||
842 | /* Undo any stepping we may have done */ | ||
843 | undo_single_step(); | ||
844 | |||
845 | while (1) { | ||
846 | out_buffer[0] = 0; | ||
847 | get_packet(in_buffer, BUFMAX); | ||
848 | |||
849 | /* Examine first char of buffer to see what we need to do */ | ||
850 | switch (in_buffer[0]) { | ||
851 | case '?': /* Send which signal we've received */ | ||
852 | send_signal_msg(sigval); | ||
853 | break; | ||
854 | |||
855 | case 'g': /* Return the values of the CPU registers */ | ||
856 | send_regs_msg(); | ||
857 | break; | ||
858 | |||
859 | case 'G': /* Set the value of the CPU registers */ | ||
860 | set_regs_msg(); | ||
861 | break; | ||
862 | |||
863 | case 'm': /* Read LLLL bytes address AA..AA */ | ||
864 | read_mem_msg(); | ||
865 | break; | ||
866 | |||
867 | case 'M': /* Write LLLL bytes address AA..AA, ret OK */ | ||
868 | write_mem_msg(0); /* 0 = data in hex */ | ||
869 | break; | ||
870 | |||
871 | case 'X': /* Write LLLL bytes esc bin address AA..AA */ | ||
872 | if (kgdb_bits == '8') | ||
873 | write_mem_msg(1); /* 1 = data in binary */ | ||
874 | else | ||
875 | send_empty_msg(); | ||
876 | break; | ||
877 | |||
878 | case 'C': /* Continue, signum included, we ignore it */ | ||
879 | continue_with_sig_msg(); | ||
880 | return; | ||
881 | |||
882 | case 'c': /* Continue at address AA..AA (optional) */ | ||
883 | continue_msg(); | ||
884 | return; | ||
885 | |||
886 | case 'S': /* Step, signum included, we ignore it */ | ||
887 | step_with_sig_msg(); | ||
888 | return; | ||
889 | |||
890 | case 's': /* Step one instruction from AA..AA */ | ||
891 | step_msg(); | ||
892 | return; | ||
893 | |||
894 | case 'k': /* 'Kill the program' with a kernel ? */ | ||
895 | break; | ||
896 | |||
897 | case 'D': /* Detach from program, send reply OK */ | ||
898 | kgdb_in_gdb_mode = 0; | ||
899 | send_ok_msg(); | ||
900 | get_debug_char(); | ||
901 | return; | ||
902 | |||
903 | default: | ||
904 | send_empty_msg(); | ||
905 | break; | ||
906 | } | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /* There has been an exception, most likely a breakpoint. */ | ||
911 | static void handle_exception(struct pt_regs *regs) | ||
912 | { | ||
913 | int excep_code, vbr_val; | ||
914 | int count; | ||
915 | int trapa_value = ctrl_inl(TRA); | ||
916 | |||
917 | /* Copy kernel regs (from stack) */ | ||
918 | for (count = 0; count < 16; count++) | ||
919 | trap_registers.regs[count] = regs->regs[count]; | ||
920 | trap_registers.pc = regs->pc; | ||
921 | trap_registers.pr = regs->pr; | ||
922 | trap_registers.sr = regs->sr; | ||
923 | trap_registers.gbr = regs->gbr; | ||
924 | trap_registers.mach = regs->mach; | ||
925 | trap_registers.macl = regs->macl; | ||
926 | |||
927 | asm("stc vbr, %0":"=r"(vbr_val)); | ||
928 | trap_registers.vbr = vbr_val; | ||
929 | |||
930 | /* Get excode for command loop call, user access */ | ||
931 | asm("stc r2_bank, %0":"=r"(excep_code)); | ||
932 | |||
933 | /* Act on the exception */ | ||
934 | kgdb_command_loop(excep_code, trapa_value); | ||
935 | |||
936 | /* Copy back the (maybe modified) registers */ | ||
937 | for (count = 0; count < 16; count++) | ||
938 | regs->regs[count] = trap_registers.regs[count]; | ||
939 | regs->pc = trap_registers.pc; | ||
940 | regs->pr = trap_registers.pr; | ||
941 | regs->sr = trap_registers.sr; | ||
942 | regs->gbr = trap_registers.gbr; | ||
943 | regs->mach = trap_registers.mach; | ||
944 | regs->macl = trap_registers.macl; | ||
945 | |||
946 | vbr_val = trap_registers.vbr; | ||
947 | asm("ldc %0, vbr": :"r"(vbr_val)); | ||
948 | } | ||
949 | |||
950 | asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | ||
951 | unsigned long r6, unsigned long r7, | ||
952 | struct pt_regs __regs) | ||
953 | { | ||
954 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
955 | handle_exception(regs); | ||
956 | } | ||
957 | |||
958 | /* Initialise the KGDB data structures and serial configuration */ | ||
959 | int __init kgdb_init(void) | ||
960 | { | ||
961 | in_nmi = 0; | ||
962 | kgdb_nofault = 0; | ||
963 | stepped_opcode = 0; | ||
964 | kgdb_in_gdb_mode = 0; | ||
965 | |||
966 | if (kgdb_serial_setup() != 0) { | ||
967 | printk(KERN_NOTICE "KGDB: serial setup error\n"); | ||
968 | return -1; | ||
969 | } | ||
970 | |||
971 | /* Init ptr to exception handler */ | ||
972 | kgdb_debug_hook = handle_exception; | ||
973 | kgdb_bus_err_hook = kgdb_handle_bus_error; | ||
974 | |||
975 | /* Enter kgdb now if requested, or just report init done */ | ||
976 | printk(KERN_NOTICE "KGDB: stub is initialized.\n"); | ||
977 | |||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | /* Make function available for "user messages"; console will use it too. */ | ||
982 | |||
983 | char gdbmsgbuf[BUFMAX]; | ||
984 | #define MAXOUT ((BUFMAX-2)/2) | ||
985 | |||
986 | static void kgdb_msg_write(const char *s, unsigned count) | ||
987 | { | ||
988 | int i; | ||
989 | int wcount; | ||
990 | char *bufptr; | ||
991 | |||
992 | /* 'O'utput */ | ||
993 | gdbmsgbuf[0] = 'O'; | ||
994 | |||
995 | /* Fill and send buffers... */ | ||
996 | while (count > 0) { | ||
997 | bufptr = gdbmsgbuf + 1; | ||
998 | |||
999 | /* Calculate how many this time */ | ||
1000 | wcount = (count > MAXOUT) ? MAXOUT : count; | ||
1001 | |||
1002 | /* Pack in hex chars */ | ||
1003 | for (i = 0; i < wcount; i++) | ||
1004 | bufptr = pack_hex_byte(bufptr, s[i]); | ||
1005 | *bufptr = '\0'; | ||
1006 | |||
1007 | /* Move up */ | ||
1008 | s += wcount; | ||
1009 | count -= wcount; | ||
1010 | |||
1011 | /* Write packet */ | ||
1012 | put_packet(gdbmsgbuf); | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | static void kgdb_to_gdb(const char *s) | ||
1017 | { | ||
1018 | kgdb_msg_write(s, strlen(s)); | ||
1019 | } | ||
1020 | |||
1021 | #ifdef CONFIG_SH_KGDB_CONSOLE | ||
1022 | void kgdb_console_write(struct console *co, const char *s, unsigned count) | ||
1023 | { | ||
1024 | /* Bail if we're not talking to GDB */ | ||
1025 | if (!kgdb_in_gdb_mode) | ||
1026 | return; | ||
1027 | |||
1028 | kgdb_msg_write(s, count); | ||
1029 | } | ||
1030 | #endif | ||
1031 | |||
1032 | #ifdef CONFIG_KGDB_SYSRQ | ||
1033 | static void sysrq_handle_gdb(int key, struct tty_struct *tty) | ||
1034 | { | ||
1035 | printk("Entering GDB stub\n"); | ||
1036 | breakpoint(); | ||
1037 | } | ||
1038 | |||
1039 | static struct sysrq_key_op sysrq_gdb_op = { | ||
1040 | .handler = sysrq_handle_gdb, | ||
1041 | .help_msg = "Gdb", | ||
1042 | .action_msg = "GDB", | ||
1043 | }; | ||
1044 | |||
1045 | static int gdb_register_sysrq(void) | ||
1046 | { | ||
1047 | printk("Registering GDB sysrq handler\n"); | ||
1048 | register_sysrq_key('g', &sysrq_gdb_op); | ||
1049 | return 0; | ||
1050 | } | ||
1051 | module_init(gdb_register_sysrq); | ||
1052 | #endif | ||
diff --git a/arch/sh/kernel/pm.c b/arch/sh/kernel/pm.c deleted file mode 100644 index 10ab62c9aede..000000000000 --- a/arch/sh/kernel/pm.c +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /* | ||
2 | * Generic Power Management Routine | ||
3 | * | ||
4 | * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License. | ||
8 | */ | ||
9 | #include <linux/suspend.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/gfp.h> | ||
12 | #include <asm/freq.h> | ||
13 | #include <asm/io.h> | ||
14 | #include <asm/watchdog.h> | ||
15 | #include <asm/pm.h> | ||
16 | |||
17 | #define INTR_OFFSET 0x600 | ||
18 | |||
19 | #define STBCR 0xffffff82 | ||
20 | #define STBCR2 0xffffff88 | ||
21 | |||
22 | #define STBCR_STBY 0x80 | ||
23 | #define STBCR_MSTP2 0x04 | ||
24 | |||
25 | #define MCR 0xffffff68 | ||
26 | #define RTCNT 0xffffff70 | ||
27 | |||
28 | #define MCR_RMODE 2 | ||
29 | #define MCR_RFSH 4 | ||
30 | |||
31 | void pm_enter(void) | ||
32 | { | ||
33 | u8 stbcr, csr; | ||
34 | u16 frqcr, mcr; | ||
35 | u32 vbr_new, vbr_old; | ||
36 | |||
37 | set_bl_bit(); | ||
38 | |||
39 | /* set wdt */ | ||
40 | csr = sh_wdt_read_csr(); | ||
41 | csr &= ~WTCSR_TME; | ||
42 | csr |= WTCSR_CKS_4096; | ||
43 | sh_wdt_write_csr(csr); | ||
44 | csr = sh_wdt_read_csr(); | ||
45 | sh_wdt_write_cnt(0); | ||
46 | |||
47 | /* disable PLL1 */ | ||
48 | frqcr = ctrl_inw(FRQCR); | ||
49 | frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY); | ||
50 | ctrl_outw(frqcr, FRQCR); | ||
51 | |||
52 | /* enable standby */ | ||
53 | stbcr = ctrl_inb(STBCR); | ||
54 | ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR); | ||
55 | |||
56 | /* set self-refresh */ | ||
57 | mcr = ctrl_inw(MCR); | ||
58 | ctrl_outw(mcr & ~MCR_RFSH, MCR); | ||
59 | |||
60 | /* set interrupt handler */ | ||
61 | asm volatile("stc vbr, %0" : "=r" (vbr_old)); | ||
62 | vbr_new = get_zeroed_page(GFP_ATOMIC); | ||
63 | udelay(50); | ||
64 | memcpy((void*)(vbr_new + INTR_OFFSET), | ||
65 | &wakeup_start, &wakeup_end - &wakeup_start); | ||
66 | asm volatile("ldc %0, vbr" : : "r" (vbr_new)); | ||
67 | |||
68 | ctrl_outw(0, RTCNT); | ||
69 | ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR); | ||
70 | |||
71 | cpu_sleep(); | ||
72 | |||
73 | asm volatile("ldc %0, vbr" : : "r" (vbr_old)); | ||
74 | |||
75 | free_page(vbr_new); | ||
76 | |||
77 | /* enable PLL1 */ | ||
78 | frqcr = ctrl_inw(FRQCR); | ||
79 | frqcr |= FRQCR_PSTBY; | ||
80 | ctrl_outw(frqcr, FRQCR); | ||
81 | udelay(50); | ||
82 | frqcr |= FRQCR_PLLEN; | ||
83 | ctrl_outw(frqcr, FRQCR); | ||
84 | |||
85 | ctrl_outb(stbcr, STBCR); | ||
86 | |||
87 | clear_bl_bit(); | ||
88 | } | ||
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index b965f0282c7d..ddafbbbab2ab 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -32,65 +32,8 @@ | |||
32 | #include <asm/fpu.h> | 32 | #include <asm/fpu.h> |
33 | #include <asm/syscalls.h> | 33 | #include <asm/syscalls.h> |
34 | 34 | ||
35 | static int hlt_counter; | ||
36 | int ubc_usercnt = 0; | 35 | int ubc_usercnt = 0; |
37 | 36 | ||
38 | void (*pm_idle)(void); | ||
39 | void (*pm_power_off)(void); | ||
40 | EXPORT_SYMBOL(pm_power_off); | ||
41 | |||
42 | static int __init nohlt_setup(char *__unused) | ||
43 | { | ||
44 | hlt_counter = 1; | ||
45 | return 1; | ||
46 | } | ||
47 | __setup("nohlt", nohlt_setup); | ||
48 | |||
49 | static int __init hlt_setup(char *__unused) | ||
50 | { | ||
51 | hlt_counter = 0; | ||
52 | return 1; | ||
53 | } | ||
54 | __setup("hlt", hlt_setup); | ||
55 | |||
56 | static void default_idle(void) | ||
57 | { | ||
58 | if (!hlt_counter) { | ||
59 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
60 | smp_mb__after_clear_bit(); | ||
61 | set_bl_bit(); | ||
62 | while (!need_resched()) | ||
63 | cpu_sleep(); | ||
64 | clear_bl_bit(); | ||
65 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
66 | } else | ||
67 | while (!need_resched()) | ||
68 | cpu_relax(); | ||
69 | } | ||
70 | |||
71 | void cpu_idle(void) | ||
72 | { | ||
73 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
74 | |||
75 | /* endless idle loop with no priority at all */ | ||
76 | while (1) { | ||
77 | void (*idle)(void) = pm_idle; | ||
78 | |||
79 | if (!idle) | ||
80 | idle = default_idle; | ||
81 | |||
82 | tick_nohz_stop_sched_tick(1); | ||
83 | while (!need_resched()) | ||
84 | idle(); | ||
85 | tick_nohz_restart_sched_tick(); | ||
86 | |||
87 | preempt_enable_no_resched(); | ||
88 | schedule(); | ||
89 | preempt_disable(); | ||
90 | check_pgt_cache(); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | void machine_restart(char * __unused) | 37 | void machine_restart(char * __unused) |
95 | { | 38 | { |
96 | /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ | 39 | /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ |
@@ -115,8 +58,8 @@ void machine_power_off(void) | |||
115 | void show_regs(struct pt_regs * regs) | 58 | void show_regs(struct pt_regs * regs) |
116 | { | 59 | { |
117 | printk("\n"); | 60 | printk("\n"); |
118 | printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm); | 61 | printk("Pid : %d, Comm: \t\t%s\n", task_pid_nr(current), current->comm); |
119 | printk("CPU : %d %s (%s %.*s)\n", | 62 | printk("CPU : %d \t\t%s (%s %.*s)\n\n", |
120 | smp_processor_id(), print_tainted(), init_utsname()->release, | 63 | smp_processor_id(), print_tainted(), init_utsname()->release, |
121 | (int)strcspn(init_utsname()->version, " "), | 64 | (int)strcspn(init_utsname()->version, " "), |
122 | init_utsname()->version); | 65 | init_utsname()->version); |
@@ -148,26 +91,16 @@ void show_regs(struct pt_regs * regs) | |||
148 | regs->mach, regs->macl, regs->gbr, regs->pr); | 91 | regs->mach, regs->macl, regs->gbr, regs->pr); |
149 | 92 | ||
150 | show_trace(NULL, (unsigned long *)regs->regs[15], regs); | 93 | show_trace(NULL, (unsigned long *)regs->regs[15], regs); |
94 | show_code(regs); | ||
151 | } | 95 | } |
152 | 96 | ||
153 | /* | 97 | /* |
154 | * Create a kernel thread | 98 | * Create a kernel thread |
155 | */ | 99 | */ |
156 | 100 | ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) | |
157 | /* | 101 | { |
158 | * This is the mechanism for creating a new kernel thread. | 102 | do_exit(fn(arg)); |
159 | * | 103 | } |
160 | */ | ||
161 | extern void kernel_thread_helper(void); | ||
162 | __asm__(".align 5\n" | ||
163 | "kernel_thread_helper:\n\t" | ||
164 | "jsr @r5\n\t" | ||
165 | " nop\n\t" | ||
166 | "mov.l 1f, r1\n\t" | ||
167 | "jsr @r1\n\t" | ||
168 | " mov r0, r4\n\t" | ||
169 | ".align 2\n\t" | ||
170 | "1:.long do_exit"); | ||
171 | 104 | ||
172 | /* Don't use this in BL=1(cli). Or else, CPU resets! */ | 105 | /* Don't use this in BL=1(cli). Or else, CPU resets! */ |
173 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | 106 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index b7aa09235b51..a7e5f2e74bac 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/reboot.h> | 23 | #include <linux/reboot.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/proc_fs.h> | ||
27 | #include <linux/io.h> | 26 | #include <linux/io.h> |
28 | #include <asm/syscalls.h> | 27 | #include <asm/syscalls.h> |
29 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
@@ -33,56 +32,6 @@ | |||
33 | 32 | ||
34 | struct task_struct *last_task_used_math = NULL; | 33 | struct task_struct *last_task_used_math = NULL; |
35 | 34 | ||
36 | static int hlt_counter = 1; | ||
37 | |||
38 | #define HARD_IDLE_TIMEOUT (HZ / 3) | ||
39 | |||
40 | static int __init nohlt_setup(char *__unused) | ||
41 | { | ||
42 | hlt_counter = 1; | ||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | static int __init hlt_setup(char *__unused) | ||
47 | { | ||
48 | hlt_counter = 0; | ||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | __setup("nohlt", nohlt_setup); | ||
53 | __setup("hlt", hlt_setup); | ||
54 | |||
55 | static inline void hlt(void) | ||
56 | { | ||
57 | __asm__ __volatile__ ("sleep" : : : "memory"); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * The idle loop on a uniprocessor SH.. | ||
62 | */ | ||
63 | void cpu_idle(void) | ||
64 | { | ||
65 | /* endless idle loop with no priority at all */ | ||
66 | while (1) { | ||
67 | if (hlt_counter) { | ||
68 | while (!need_resched()) | ||
69 | cpu_relax(); | ||
70 | } else { | ||
71 | local_irq_disable(); | ||
72 | while (!need_resched()) { | ||
73 | local_irq_enable(); | ||
74 | hlt(); | ||
75 | local_irq_disable(); | ||
76 | } | ||
77 | local_irq_enable(); | ||
78 | } | ||
79 | preempt_enable_no_resched(); | ||
80 | schedule(); | ||
81 | preempt_disable(); | ||
82 | } | ||
83 | |||
84 | } | ||
85 | |||
86 | void machine_restart(char * __unused) | 35 | void machine_restart(char * __unused) |
87 | { | 36 | { |
88 | extern void phys_stext(void); | 37 | extern void phys_stext(void); |
@@ -97,13 +46,6 @@ void machine_halt(void) | |||
97 | 46 | ||
98 | void machine_power_off(void) | 47 | void machine_power_off(void) |
99 | { | 48 | { |
100 | #if 0 | ||
101 | /* Disable watchdog timer */ | ||
102 | ctrl_outl(0xa5000000, WTCSR); | ||
103 | /* Configure deep standby on sleep */ | ||
104 | ctrl_outl(0x03, STBCR); | ||
105 | #endif | ||
106 | |||
107 | __asm__ __volatile__ ( | 49 | __asm__ __volatile__ ( |
108 | "sleep\n\t" | 50 | "sleep\n\t" |
109 | "synci\n\t" | 51 | "synci\n\t" |
@@ -113,9 +55,6 @@ void machine_power_off(void) | |||
113 | panic("Unexpected wakeup!\n"); | 55 | panic("Unexpected wakeup!\n"); |
114 | } | 56 | } |
115 | 57 | ||
116 | void (*pm_power_off)(void) = machine_power_off; | ||
117 | EXPORT_SYMBOL(pm_power_off); | ||
118 | |||
119 | void show_regs(struct pt_regs * regs) | 58 | void show_regs(struct pt_regs * regs) |
120 | { | 59 | { |
121 | unsigned long long ah, al, bh, bl, ch, cl; | 60 | unsigned long long ah, al, bh, bl, ch, cl; |
@@ -365,18 +304,6 @@ void show_regs(struct pt_regs * regs) | |||
365 | } | 304 | } |
366 | } | 305 | } |
367 | 306 | ||
368 | struct task_struct * alloc_task_struct(void) | ||
369 | { | ||
370 | /* Get task descriptor pages */ | ||
371 | return (struct task_struct *) | ||
372 | __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)); | ||
373 | } | ||
374 | |||
375 | void free_task_struct(struct task_struct *p) | ||
376 | { | ||
377 | free_pages((unsigned long) p, get_order(THREAD_SIZE)); | ||
378 | } | ||
379 | |||
380 | /* | 307 | /* |
381 | * Create a kernel thread | 308 | * Create a kernel thread |
382 | */ | 309 | */ |
@@ -662,41 +589,3 @@ unsigned long get_wchan(struct task_struct *p) | |||
662 | #endif | 589 | #endif |
663 | return pc; | 590 | return pc; |
664 | } | 591 | } |
665 | |||
666 | /* Provide a /proc/asids file that lists out the | ||
667 | ASIDs currently associated with the processes. (If the DM.PC register is | ||
668 | examined through the debug link, this shows ASID + PC. To make use of this, | ||
669 | the PID->ASID relationship needs to be known. This is primarily for | ||
670 | debugging.) | ||
671 | */ | ||
672 | |||
673 | #if defined(CONFIG_SH64_PROC_ASIDS) | ||
674 | static int | ||
675 | asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) | ||
676 | { | ||
677 | int len=0; | ||
678 | struct task_struct *p; | ||
679 | read_lock(&tasklist_lock); | ||
680 | for_each_process(p) { | ||
681 | int pid = p->pid; | ||
682 | |||
683 | if (!pid) | ||
684 | continue; | ||
685 | if (p->mm) | ||
686 | len += sprintf(buf+len, "%5d : %02lx\n", pid, | ||
687 | asid_cache(smp_processor_id())); | ||
688 | else | ||
689 | len += sprintf(buf+len, "%5d : (none)\n", pid); | ||
690 | } | ||
691 | read_unlock(&tasklist_lock); | ||
692 | *eof = 1; | ||
693 | return len; | ||
694 | } | ||
695 | |||
696 | static int __init register_proc_asids(void) | ||
697 | { | ||
698 | create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); | ||
699 | return 0; | ||
700 | } | ||
701 | __initcall(register_proc_asids); | ||
702 | #endif | ||
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index e15b099c1f06..695097438f02 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/sh/kernel/ptrace_64.c | 2 | * arch/sh/kernel/ptrace_64.c |
3 | * | 3 | * |
4 | * Copyright (C) 2000, 2001 Paolo Alberelli | 4 | * Copyright (C) 2000, 2001 Paolo Alberelli |
5 | * Copyright (C) 2003 - 2007 Paul Mundt | 5 | * Copyright (C) 2003 - 2008 Paul Mundt |
6 | * | 6 | * |
7 | * Started from SH3/4 version: | 7 | * Started from SH3/4 version: |
8 | * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka | 8 | * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka |
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/audit.h> | 29 | #include <linux/audit.h> |
30 | #include <linux/seccomp.h> | 30 | #include <linux/seccomp.h> |
31 | #include <linux/tracehook.h> | 31 | #include <linux/tracehook.h> |
32 | #include <linux/elf.h> | ||
33 | #include <linux/regset.h> | ||
32 | #include <asm/io.h> | 34 | #include <asm/io.h> |
33 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
34 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
@@ -137,6 +139,165 @@ void user_disable_single_step(struct task_struct *child) | |||
137 | regs->sr &= ~SR_SSTEP; | 139 | regs->sr &= ~SR_SSTEP; |
138 | } | 140 | } |
139 | 141 | ||
142 | static int genregs_get(struct task_struct *target, | ||
143 | const struct user_regset *regset, | ||
144 | unsigned int pos, unsigned int count, | ||
145 | void *kbuf, void __user *ubuf) | ||
146 | { | ||
147 | const struct pt_regs *regs = task_pt_regs(target); | ||
148 | int ret; | ||
149 | |||
150 | /* PC, SR, SYSCALL */ | ||
151 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
152 | ®s->pc, | ||
153 | 0, 3 * sizeof(unsigned long long)); | ||
154 | |||
155 | /* R1 -> R63 */ | ||
156 | if (!ret) | ||
157 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
158 | regs->regs, | ||
159 | offsetof(struct pt_regs, regs[0]), | ||
160 | 63 * sizeof(unsigned long long)); | ||
161 | /* TR0 -> TR7 */ | ||
162 | if (!ret) | ||
163 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
164 | regs->tregs, | ||
165 | offsetof(struct pt_regs, tregs[0]), | ||
166 | 8 * sizeof(unsigned long long)); | ||
167 | |||
168 | if (!ret) | ||
169 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
170 | sizeof(struct pt_regs), -1); | ||
171 | |||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static int genregs_set(struct task_struct *target, | ||
176 | const struct user_regset *regset, | ||
177 | unsigned int pos, unsigned int count, | ||
178 | const void *kbuf, const void __user *ubuf) | ||
179 | { | ||
180 | struct pt_regs *regs = task_pt_regs(target); | ||
181 | int ret; | ||
182 | |||
183 | /* PC, SR, SYSCALL */ | ||
184 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
185 | ®s->pc, | ||
186 | 0, 3 * sizeof(unsigned long long)); | ||
187 | |||
188 | /* R1 -> R63 */ | ||
189 | if (!ret && count > 0) | ||
190 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
191 | regs->regs, | ||
192 | offsetof(struct pt_regs, regs[0]), | ||
193 | 63 * sizeof(unsigned long long)); | ||
194 | |||
195 | /* TR0 -> TR7 */ | ||
196 | if (!ret && count > 0) | ||
197 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
198 | regs->tregs, | ||
199 | offsetof(struct pt_regs, tregs[0]), | ||
200 | 8 * sizeof(unsigned long long)); | ||
201 | |||
202 | if (!ret) | ||
203 | ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, | ||
204 | sizeof(struct pt_regs), -1); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | #ifdef CONFIG_SH_FPU | ||
210 | int fpregs_get(struct task_struct *target, | ||
211 | const struct user_regset *regset, | ||
212 | unsigned int pos, unsigned int count, | ||
213 | void *kbuf, void __user *ubuf) | ||
214 | { | ||
215 | int ret; | ||
216 | |||
217 | ret = init_fpu(target); | ||
218 | if (ret) | ||
219 | return ret; | ||
220 | |||
221 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
222 | &target->thread.fpu.hard, 0, -1); | ||
223 | } | ||
224 | |||
225 | static int fpregs_set(struct task_struct *target, | ||
226 | const struct user_regset *regset, | ||
227 | unsigned int pos, unsigned int count, | ||
228 | const void *kbuf, const void __user *ubuf) | ||
229 | { | ||
230 | int ret; | ||
231 | |||
232 | ret = init_fpu(target); | ||
233 | if (ret) | ||
234 | return ret; | ||
235 | |||
236 | set_stopped_child_used_math(target); | ||
237 | |||
238 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
239 | &target->thread.fpu.hard, 0, -1); | ||
240 | } | ||
241 | |||
242 | static int fpregs_active(struct task_struct *target, | ||
243 | const struct user_regset *regset) | ||
244 | { | ||
245 | return tsk_used_math(target) ? regset->n : 0; | ||
246 | } | ||
247 | #endif | ||
248 | |||
249 | /* | ||
250 | * These are our native regset flavours. | ||
251 | */ | ||
252 | enum sh_regset { | ||
253 | REGSET_GENERAL, | ||
254 | #ifdef CONFIG_SH_FPU | ||
255 | REGSET_FPU, | ||
256 | #endif | ||
257 | }; | ||
258 | |||
259 | static const struct user_regset sh_regsets[] = { | ||
260 | /* | ||
261 | * Format is: | ||
262 | * PC, SR, SYSCALL, | ||
263 | * R1 --> R63, | ||
264 | * TR0 --> TR7, | ||
265 | */ | ||
266 | [REGSET_GENERAL] = { | ||
267 | .core_note_type = NT_PRSTATUS, | ||
268 | .n = ELF_NGREG, | ||
269 | .size = sizeof(long long), | ||
270 | .align = sizeof(long long), | ||
271 | .get = genregs_get, | ||
272 | .set = genregs_set, | ||
273 | }, | ||
274 | |||
275 | #ifdef CONFIG_SH_FPU | ||
276 | [REGSET_FPU] = { | ||
277 | .core_note_type = NT_PRFPREG, | ||
278 | .n = sizeof(struct user_fpu_struct) / | ||
279 | sizeof(long long), | ||
280 | .size = sizeof(long long), | ||
281 | .align = sizeof(long long), | ||
282 | .get = fpregs_get, | ||
283 | .set = fpregs_set, | ||
284 | .active = fpregs_active, | ||
285 | }, | ||
286 | #endif | ||
287 | }; | ||
288 | |||
289 | static const struct user_regset_view user_sh64_native_view = { | ||
290 | .name = "sh64", | ||
291 | .e_machine = EM_SH, | ||
292 | .regsets = sh_regsets, | ||
293 | .n = ARRAY_SIZE(sh_regsets), | ||
294 | }; | ||
295 | |||
296 | const struct user_regset_view *task_user_regset_view(struct task_struct *task) | ||
297 | { | ||
298 | return &user_sh64_native_view; | ||
299 | } | ||
300 | |||
140 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 301 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
141 | { | 302 | { |
142 | int ret; | 303 | int ret; |
@@ -195,10 +356,33 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
195 | } | 356 | } |
196 | break; | 357 | break; |
197 | 358 | ||
359 | case PTRACE_GETREGS: | ||
360 | return copy_regset_to_user(child, &user_sh64_native_view, | ||
361 | REGSET_GENERAL, | ||
362 | 0, sizeof(struct pt_regs), | ||
363 | (void __user *)data); | ||
364 | case PTRACE_SETREGS: | ||
365 | return copy_regset_from_user(child, &user_sh64_native_view, | ||
366 | REGSET_GENERAL, | ||
367 | 0, sizeof(struct pt_regs), | ||
368 | (const void __user *)data); | ||
369 | #ifdef CONFIG_SH_FPU | ||
370 | case PTRACE_GETFPREGS: | ||
371 | return copy_regset_to_user(child, &user_sh64_native_view, | ||
372 | REGSET_FPU, | ||
373 | 0, sizeof(struct user_fpu_struct), | ||
374 | (void __user *)data); | ||
375 | case PTRACE_SETFPREGS: | ||
376 | return copy_regset_from_user(child, &user_sh64_native_view, | ||
377 | REGSET_FPU, | ||
378 | 0, sizeof(struct user_fpu_struct), | ||
379 | (const void __user *)data); | ||
380 | #endif | ||
198 | default: | 381 | default: |
199 | ret = ptrace_request(child, request, addr, data); | 382 | ret = ptrace_request(child, request, addr, data); |
200 | break; | 383 | break; |
201 | } | 384 | } |
385 | |||
202 | return ret; | 386 | return ret; |
203 | } | 387 | } |
204 | 388 | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index e7152cc6930e..534247508572 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -417,6 +417,7 @@ void __init setup_arch(char **cmdline_p) | |||
417 | } | 417 | } |
418 | 418 | ||
419 | static const char *cpu_name[] = { | 419 | static const char *cpu_name[] = { |
420 | [CPU_SH7201] = "SH7201", | ||
420 | [CPU_SH7203] = "SH7203", [CPU_SH7263] = "SH7263", | 421 | [CPU_SH7203] = "SH7203", [CPU_SH7263] = "SH7263", |
421 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", | 422 | [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", |
422 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", | 423 | [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", |
diff --git a/arch/sh/kernel/sh_bios.c b/arch/sh/kernel/sh_bios.c index d1bcac4fa269..c852f7805728 100644 --- a/arch/sh/kernel/sh_bios.c +++ b/arch/sh/kernel/sh_bios.c | |||
@@ -8,69 +8,50 @@ | |||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <asm/sh_bios.h> | 9 | #include <asm/sh_bios.h> |
10 | 10 | ||
11 | #define BIOS_CALL_CONSOLE_WRITE 0 | 11 | #define BIOS_CALL_CONSOLE_WRITE 0 |
12 | #define BIOS_CALL_READ_BLOCK 1 | ||
13 | #define BIOS_CALL_ETH_NODE_ADDR 10 | 12 | #define BIOS_CALL_ETH_NODE_ADDR 10 |
14 | #define BIOS_CALL_SHUTDOWN 11 | 13 | #define BIOS_CALL_SHUTDOWN 11 |
15 | #define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ | 14 | #define BIOS_CALL_CHAR_OUT 0x1f /* TODO: hack */ |
16 | #define BIOS_CALL_GDB_GET_MODE_PTR 0xfe | 15 | #define BIOS_CALL_GDB_DETACH 0xff |
17 | #define BIOS_CALL_GDB_DETACH 0xff | ||
18 | 16 | ||
19 | static __inline__ long sh_bios_call(long func, long arg0, long arg1, long arg2, long arg3) | 17 | static inline long sh_bios_call(long func, long arg0, long arg1, long arg2, |
18 | long arg3) | ||
20 | { | 19 | { |
21 | register long r0 __asm__("r0") = func; | 20 | register long r0 __asm__("r0") = func; |
22 | register long r4 __asm__("r4") = arg0; | 21 | register long r4 __asm__("r4") = arg0; |
23 | register long r5 __asm__("r5") = arg1; | 22 | register long r5 __asm__("r5") = arg1; |
24 | register long r6 __asm__("r6") = arg2; | 23 | register long r6 __asm__("r6") = arg2; |
25 | register long r7 __asm__("r7") = arg3; | 24 | register long r7 __asm__("r7") = arg3; |
26 | __asm__ __volatile__("trapa #0x3f" | 25 | |
27 | : "=z" (r0) | 26 | __asm__ __volatile__("trapa #0x3f":"=z"(r0) |
28 | : "0" (r0), "r" (r4), "r" (r5), "r" (r6), "r" (r7) | 27 | :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7) |
29 | : "memory"); | 28 | :"memory"); |
30 | return r0; | 29 | return r0; |
31 | } | 30 | } |
32 | 31 | ||
33 | |||
34 | void sh_bios_console_write(const char *buf, unsigned int len) | 32 | void sh_bios_console_write(const char *buf, unsigned int len) |
35 | { | 33 | { |
36 | sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); | 34 | sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0); |
37 | } | 35 | } |
38 | 36 | ||
39 | |||
40 | void sh_bios_char_out(char ch) | 37 | void sh_bios_char_out(char ch) |
41 | { | 38 | { |
42 | sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0); | 39 | sh_bios_call(BIOS_CALL_CHAR_OUT, ch, 0, 0, 0); |
43 | } | ||
44 | |||
45 | |||
46 | int sh_bios_in_gdb_mode(void) | ||
47 | { | ||
48 | static char queried = 0; | ||
49 | static char *gdb_mode_p = 0; | ||
50 | |||
51 | if (!queried) | ||
52 | { | ||
53 | /* Query the gdb stub for address of its gdb mode variable */ | ||
54 | long r = sh_bios_call(BIOS_CALL_GDB_GET_MODE_PTR, 0, 0, 0, 0); | ||
55 | if (r != ~0) /* BIOS returns -1 for unknown function */ | ||
56 | gdb_mode_p = (char *)r; | ||
57 | queried = 1; | ||
58 | } | ||
59 | return (gdb_mode_p != 0 ? *gdb_mode_p : 0); | ||
60 | } | 40 | } |
61 | 41 | ||
62 | void sh_bios_gdb_detach(void) | 42 | void sh_bios_gdb_detach(void) |
63 | { | 43 | { |
64 | sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); | 44 | sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0); |
65 | } | 45 | } |
66 | EXPORT_SYMBOL(sh_bios_gdb_detach); | 46 | EXPORT_SYMBOL_GPL(sh_bios_gdb_detach); |
67 | 47 | ||
68 | void sh_bios_get_node_addr (unsigned char *node_addr) | 48 | void sh_bios_get_node_addr(unsigned char *node_addr) |
69 | { | 49 | { |
70 | sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0); | 50 | sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0); |
71 | } | 51 | } |
52 | EXPORT_SYMBOL_GPL(sh_bios_get_node_addr); | ||
72 | 53 | ||
73 | void sh_bios_shutdown(unsigned int how) | 54 | void sh_bios_shutdown(unsigned int how) |
74 | { | 55 | { |
75 | sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); | 56 | sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0); |
76 | } | 57 | } |
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 92ae5e6c099e..528de2955c81 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c | |||
@@ -52,16 +52,12 @@ EXPORT_SYMBOL(__const_udelay); | |||
52 | 52 | ||
53 | #define DECLARE_EXPORT(name) \ | 53 | #define DECLARE_EXPORT(name) \ |
54 | extern void name(void);EXPORT_SYMBOL(name) | 54 | extern void name(void);EXPORT_SYMBOL(name) |
55 | #define MAYBE_DECLARE_EXPORT(name) \ | ||
56 | extern void name(void) __weak;EXPORT_SYMBOL(name) | ||
57 | 55 | ||
58 | /* These symbols are generated by the compiler itself */ | ||
59 | DECLARE_EXPORT(__udivsi3); | 56 | DECLARE_EXPORT(__udivsi3); |
60 | DECLARE_EXPORT(__sdivsi3); | 57 | DECLARE_EXPORT(__sdivsi3); |
58 | DECLARE_EXPORT(__lshrsi3); | ||
61 | DECLARE_EXPORT(__ashrsi3); | 59 | DECLARE_EXPORT(__ashrsi3); |
62 | DECLARE_EXPORT(__ashlsi3); | 60 | DECLARE_EXPORT(__ashlsi3); |
63 | DECLARE_EXPORT(__ashrdi3); | ||
64 | DECLARE_EXPORT(__ashldi3); | ||
65 | DECLARE_EXPORT(__ashiftrt_r4_6); | 61 | DECLARE_EXPORT(__ashiftrt_r4_6); |
66 | DECLARE_EXPORT(__ashiftrt_r4_7); | 62 | DECLARE_EXPORT(__ashiftrt_r4_7); |
67 | DECLARE_EXPORT(__ashiftrt_r4_8); | 63 | DECLARE_EXPORT(__ashiftrt_r4_8); |
@@ -79,8 +75,7 @@ DECLARE_EXPORT(__ashiftrt_r4_23); | |||
79 | DECLARE_EXPORT(__ashiftrt_r4_24); | 75 | DECLARE_EXPORT(__ashiftrt_r4_24); |
80 | DECLARE_EXPORT(__ashiftrt_r4_27); | 76 | DECLARE_EXPORT(__ashiftrt_r4_27); |
81 | DECLARE_EXPORT(__ashiftrt_r4_30); | 77 | DECLARE_EXPORT(__ashiftrt_r4_30); |
82 | DECLARE_EXPORT(__lshrsi3); | 78 | DECLARE_EXPORT(__movstr); |
83 | DECLARE_EXPORT(__lshrdi3); | ||
84 | DECLARE_EXPORT(__movstrSI8); | 79 | DECLARE_EXPORT(__movstrSI8); |
85 | DECLARE_EXPORT(__movstrSI12); | 80 | DECLARE_EXPORT(__movstrSI12); |
86 | DECLARE_EXPORT(__movstrSI16); | 81 | DECLARE_EXPORT(__movstrSI16); |
@@ -95,31 +90,17 @@ DECLARE_EXPORT(__movstrSI48); | |||
95 | DECLARE_EXPORT(__movstrSI52); | 90 | DECLARE_EXPORT(__movstrSI52); |
96 | DECLARE_EXPORT(__movstrSI56); | 91 | DECLARE_EXPORT(__movstrSI56); |
97 | DECLARE_EXPORT(__movstrSI60); | 92 | DECLARE_EXPORT(__movstrSI60); |
98 | #if __GNUC__ == 4 | 93 | DECLARE_EXPORT(__movstr_i4_even); |
99 | DECLARE_EXPORT(__movmem); | 94 | DECLARE_EXPORT(__movstr_i4_odd); |
100 | #else | 95 | DECLARE_EXPORT(__movstrSI12_i4); |
101 | DECLARE_EXPORT(__movstr); | ||
102 | #endif | ||
103 | |||
104 | #if __GNUC__ == 4 | ||
105 | DECLARE_EXPORT(__movmem_i4_even); | 96 | DECLARE_EXPORT(__movmem_i4_even); |
106 | DECLARE_EXPORT(__movmem_i4_odd); | 97 | DECLARE_EXPORT(__movmem_i4_odd); |
107 | DECLARE_EXPORT(__movmemSI12_i4); | 98 | DECLARE_EXPORT(__movmemSI12_i4); |
108 | |||
109 | #if (__GNUC_MINOR__ >= 2 || defined(__GNUC_STM_RELEASE__)) | ||
110 | /* | ||
111 | * GCC >= 4.2 emits these for division, as do GCC 4.1.x versions of the ST | ||
112 | * compiler which include backported patches. | ||
113 | */ | ||
114 | DECLARE_EXPORT(__udiv_qrnnd_16); | 99 | DECLARE_EXPORT(__udiv_qrnnd_16); |
115 | MAYBE_DECLARE_EXPORT(__sdivsi3_i4i); | 100 | DECLARE_EXPORT(__sdivsi3_i4); |
116 | MAYBE_DECLARE_EXPORT(__udivsi3_i4i); | 101 | DECLARE_EXPORT(__udivsi3_i4); |
117 | #endif | 102 | DECLARE_EXPORT(__sdivsi3_i4i); |
118 | #else /* GCC 3.x */ | 103 | DECLARE_EXPORT(__udivsi3_i4i); |
119 | DECLARE_EXPORT(__movstr_i4_even); | ||
120 | DECLARE_EXPORT(__movstr_i4_odd); | ||
121 | DECLARE_EXPORT(__movstrSI12_i4); | ||
122 | #endif /* __GNUC__ == 4 */ | ||
123 | 104 | ||
124 | #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ | 105 | #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ |
125 | defined(CONFIG_SH7705_CACHE_32KB)) | 106 | defined(CONFIG_SH7705_CACHE_32KB)) |
diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index 9324d32adacc..0d74d6b8774e 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c | |||
@@ -65,15 +65,16 @@ EXPORT_SYMBOL(copy_page); | |||
65 | EXPORT_SYMBOL(__copy_user); | 65 | EXPORT_SYMBOL(__copy_user); |
66 | EXPORT_SYMBOL(empty_zero_page); | 66 | EXPORT_SYMBOL(empty_zero_page); |
67 | EXPORT_SYMBOL(memcpy); | 67 | EXPORT_SYMBOL(memcpy); |
68 | EXPORT_SYMBOL(memset); | ||
68 | EXPORT_SYMBOL(__udelay); | 69 | EXPORT_SYMBOL(__udelay); |
69 | EXPORT_SYMBOL(__ndelay); | 70 | EXPORT_SYMBOL(__ndelay); |
70 | EXPORT_SYMBOL(__const_udelay); | 71 | EXPORT_SYMBOL(__const_udelay); |
72 | EXPORT_SYMBOL(strlen); | ||
73 | EXPORT_SYMBOL(strcpy); | ||
71 | 74 | ||
72 | /* Ugh. These come in from libgcc.a at link time. */ | 75 | /* Ugh. These come in from libgcc.a at link time. */ |
73 | #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) | 76 | #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) |
74 | 77 | ||
75 | DECLARE_EXPORT(__sdivsi3); | 78 | DECLARE_EXPORT(__sdivsi3); |
76 | DECLARE_EXPORT(__sdivsi3_2); | ||
77 | DECLARE_EXPORT(__muldi3); | ||
78 | DECLARE_EXPORT(__udivsi3); | 79 | DECLARE_EXPORT(__udivsi3); |
79 | DECLARE_EXPORT(__div_table); | 80 | DECLARE_EXPORT(__div_table); |
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 69d09c0b3498..77c21bde376a 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c | |||
@@ -533,7 +533,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
533 | { | 533 | { |
534 | int ret; | 534 | int ret; |
535 | 535 | ||
536 | |||
537 | /* Set up the stack frame */ | 536 | /* Set up the stack frame */ |
538 | if (ka->sa.sa_flags & SA_SIGINFO) | 537 | if (ka->sa.sa_flags & SA_SIGINFO) |
539 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 538 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index ce3e851dffcb..b22fdfaaa191 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/sh/kernel/signal_64.c | 2 | * arch/sh/kernel/signal_64.c |
3 | * | 3 | * |
4 | * Copyright (C) 2000, 2001 Paolo Alberelli | 4 | * Copyright (C) 2000, 2001 Paolo Alberelli |
5 | * Copyright (C) 2003 Paul Mundt | 5 | * Copyright (C) 2003 - 2008 Paul Mundt |
6 | * Copyright (C) 2004 Richard Curnow | 6 | * Copyright (C) 2004 Richard Curnow |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -43,10 +43,38 @@ | |||
43 | 43 | ||
44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
45 | 45 | ||
46 | static void | 46 | static int |
47 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 47 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
48 | sigset_t *oldset, struct pt_regs * regs); | 48 | sigset_t *oldset, struct pt_regs * regs); |
49 | 49 | ||
50 | static inline void | ||
51 | handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) | ||
52 | { | ||
53 | /* If we're not from a syscall, bail out */ | ||
54 | if (regs->syscall_nr < 0) | ||
55 | return; | ||
56 | |||
57 | /* check for system call restart.. */ | ||
58 | switch (regs->regs[REG_RET]) { | ||
59 | case -ERESTART_RESTARTBLOCK: | ||
60 | case -ERESTARTNOHAND: | ||
61 | no_system_call_restart: | ||
62 | regs->regs[REG_RET] = -EINTR; | ||
63 | regs->sr |= 1; | ||
64 | break; | ||
65 | |||
66 | case -ERESTARTSYS: | ||
67 | if (!(sa->sa_flags & SA_RESTART)) | ||
68 | goto no_system_call_restart; | ||
69 | /* fallthrough */ | ||
70 | case -ERESTARTNOINTR: | ||
71 | /* Decode syscall # */ | ||
72 | regs->regs[REG_RET] = regs->syscall_nr; | ||
73 | regs->pc -= 4; | ||
74 | break; | ||
75 | } | ||
76 | } | ||
77 | |||
50 | /* | 78 | /* |
51 | * Note that 'init' is a special process: it doesn't get signals it doesn't | 79 | * Note that 'init' is a special process: it doesn't get signals it doesn't |
52 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 80 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
@@ -80,21 +108,23 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
80 | oldset = ¤t->blocked; | 108 | oldset = ¤t->blocked; |
81 | 109 | ||
82 | signr = get_signal_to_deliver(&info, &ka, regs, 0); | 110 | signr = get_signal_to_deliver(&info, &ka, regs, 0); |
83 | |||
84 | if (signr > 0) { | 111 | if (signr > 0) { |
85 | /* Whee! Actually deliver the signal. */ | 112 | if (regs->sr & 1) |
86 | handle_signal(signr, &info, &ka, oldset, regs); | 113 | handle_syscall_restart(regs, &ka.sa); |
87 | 114 | ||
88 | /* | 115 | /* Whee! Actually deliver the signal. */ |
89 | * If a signal was successfully delivered, the saved sigmask | 116 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
90 | * is in its frame, and we can clear the TIF_RESTORE_SIGMASK | 117 | /* |
91 | * flag. | 118 | * If a signal was successfully delivered, the |
92 | */ | 119 | * saved sigmask is in its frame, and we can |
93 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 120 | * clear the TIF_RESTORE_SIGMASK flag. |
94 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 121 | */ |
95 | 122 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | |
96 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | 123 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
97 | return 1; | 124 | |
125 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | ||
126 | return 1; | ||
127 | } | ||
98 | } | 128 | } |
99 | 129 | ||
100 | no_signal: | 130 | no_signal: |
@@ -129,7 +159,6 @@ no_signal: | |||
129 | /* | 159 | /* |
130 | * Atomically swap in the new signal mask, and wait for a signal. | 160 | * Atomically swap in the new signal mask, and wait for a signal. |
131 | */ | 161 | */ |
132 | |||
133 | asmlinkage int | 162 | asmlinkage int |
134 | sys_sigsuspend(old_sigset_t mask, | 163 | sys_sigsuspend(old_sigset_t mask, |
135 | unsigned long r3, unsigned long r4, unsigned long r5, | 164 | unsigned long r3, unsigned long r4, unsigned long r5, |
@@ -235,20 +264,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | |||
235 | return do_sigaltstack(uss, uoss, REF_REG_SP); | 264 | return do_sigaltstack(uss, uoss, REF_REG_SP); |
236 | } | 265 | } |
237 | 266 | ||
238 | |||
239 | /* | 267 | /* |
240 | * Do a signal return; undo the signal stack. | 268 | * Do a signal return; undo the signal stack. |
241 | */ | 269 | */ |
242 | 270 | struct sigframe { | |
243 | struct sigframe | ||
244 | { | ||
245 | struct sigcontext sc; | 271 | struct sigcontext sc; |
246 | unsigned long extramask[_NSIG_WORDS-1]; | 272 | unsigned long extramask[_NSIG_WORDS-1]; |
247 | long long retcode[2]; | 273 | long long retcode[2]; |
248 | }; | 274 | }; |
249 | 275 | ||
250 | struct rt_sigframe | 276 | struct rt_sigframe { |
251 | { | ||
252 | struct siginfo __user *pinfo; | 277 | struct siginfo __user *pinfo; |
253 | void *puc; | 278 | void *puc; |
254 | struct siginfo info; | 279 | struct siginfo info; |
@@ -450,7 +475,6 @@ badframe: | |||
450 | /* | 475 | /* |
451 | * Set up a signal frame. | 476 | * Set up a signal frame. |
452 | */ | 477 | */ |
453 | |||
454 | static int | 478 | static int |
455 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | 479 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, |
456 | unsigned long mask) | 480 | unsigned long mask) |
@@ -504,8 +528,8 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | |||
504 | void sa_default_restorer(void); /* See comments below */ | 528 | void sa_default_restorer(void); /* See comments below */ |
505 | void sa_default_rt_restorer(void); /* See comments below */ | 529 | void sa_default_rt_restorer(void); /* See comments below */ |
506 | 530 | ||
507 | static void setup_frame(int sig, struct k_sigaction *ka, | 531 | static int setup_frame(int sig, struct k_sigaction *ka, |
508 | sigset_t *set, struct pt_regs *regs) | 532 | sigset_t *set, struct pt_regs *regs) |
509 | { | 533 | { |
510 | struct sigframe __user *frame; | 534 | struct sigframe __user *frame; |
511 | int err = 0; | 535 | int err = 0; |
@@ -596,23 +620,21 @@ static void setup_frame(int sig, struct k_sigaction *ka, | |||
596 | 620 | ||
597 | set_fs(USER_DS); | 621 | set_fs(USER_DS); |
598 | 622 | ||
599 | #if DEBUG_SIG | ||
600 | /* Broken %016Lx */ | 623 | /* Broken %016Lx */ |
601 | printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", | 624 | pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", |
602 | signal, | 625 | signal, current->comm, current->pid, frame, |
603 | current->comm, current->pid, frame, | 626 | regs->pc >> 32, regs->pc & 0xffffffff, |
604 | regs->pc >> 32, regs->pc & 0xffffffff, | 627 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); |
605 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); | ||
606 | #endif | ||
607 | 628 | ||
608 | return; | 629 | return 0; |
609 | 630 | ||
610 | give_sigsegv: | 631 | give_sigsegv: |
611 | force_sigsegv(sig, current); | 632 | force_sigsegv(sig, current); |
633 | return -EFAULT; | ||
612 | } | 634 | } |
613 | 635 | ||
614 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 636 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
615 | sigset_t *set, struct pt_regs *regs) | 637 | sigset_t *set, struct pt_regs *regs) |
616 | { | 638 | { |
617 | struct rt_sigframe __user *frame; | 639 | struct rt_sigframe __user *frame; |
618 | int err = 0; | 640 | int err = 0; |
@@ -702,62 +724,46 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
702 | 724 | ||
703 | set_fs(USER_DS); | 725 | set_fs(USER_DS); |
704 | 726 | ||
705 | #if DEBUG_SIG | 727 | pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", |
706 | /* Broken %016Lx */ | 728 | signal, current->comm, current->pid, frame, |
707 | printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", | 729 | regs->pc >> 32, regs->pc & 0xffffffff, |
708 | signal, | 730 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); |
709 | current->comm, current->pid, frame, | ||
710 | regs->pc >> 32, regs->pc & 0xffffffff, | ||
711 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); | ||
712 | #endif | ||
713 | 731 | ||
714 | return; | 732 | return 0; |
715 | 733 | ||
716 | give_sigsegv: | 734 | give_sigsegv: |
717 | force_sigsegv(sig, current); | 735 | force_sigsegv(sig, current); |
736 | return -EFAULT; | ||
718 | } | 737 | } |
719 | 738 | ||
720 | /* | 739 | /* |
721 | * OK, we're invoking a handler | 740 | * OK, we're invoking a handler |
722 | */ | 741 | */ |
723 | 742 | static int | |
724 | static void | ||
725 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 743 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
726 | sigset_t *oldset, struct pt_regs * regs) | 744 | sigset_t *oldset, struct pt_regs * regs) |
727 | { | 745 | { |
728 | /* Are we from a system call? */ | 746 | int ret; |
729 | if (regs->syscall_nr >= 0) { | ||
730 | /* If so, check system call restarting.. */ | ||
731 | switch (regs->regs[REG_RET]) { | ||
732 | case -ERESTART_RESTARTBLOCK: | ||
733 | case -ERESTARTNOHAND: | ||
734 | no_system_call_restart: | ||
735 | regs->regs[REG_RET] = -EINTR; | ||
736 | break; | ||
737 | |||
738 | case -ERESTARTSYS: | ||
739 | if (!(ka->sa.sa_flags & SA_RESTART)) | ||
740 | goto no_system_call_restart; | ||
741 | /* fallthrough */ | ||
742 | case -ERESTARTNOINTR: | ||
743 | /* Decode syscall # */ | ||
744 | regs->regs[REG_RET] = regs->syscall_nr; | ||
745 | regs->pc -= 4; | ||
746 | } | ||
747 | } | ||
748 | 747 | ||
749 | /* Set up the stack frame */ | 748 | /* Set up the stack frame */ |
750 | if (ka->sa.sa_flags & SA_SIGINFO) | 749 | if (ka->sa.sa_flags & SA_SIGINFO) |
751 | setup_rt_frame(sig, ka, info, oldset, regs); | 750 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
752 | else | 751 | else |
753 | setup_frame(sig, ka, oldset, regs); | 752 | ret = setup_frame(sig, ka, oldset, regs); |
753 | |||
754 | if (ka->sa.sa_flags & SA_ONESHOT) | ||
755 | ka->sa.sa_handler = SIG_DFL; | ||
756 | |||
757 | if (ret == 0) { | ||
758 | spin_lock_irq(¤t->sighand->siglock); | ||
759 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
760 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
761 | sigaddset(¤t->blocked,sig); | ||
762 | recalc_sigpending(); | ||
763 | spin_unlock_irq(¤t->sighand->siglock); | ||
764 | } | ||
754 | 765 | ||
755 | spin_lock_irq(¤t->sighand->siglock); | 766 | return ret; |
756 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
757 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
758 | sigaddset(¤t->blocked,sig); | ||
759 | recalc_sigpending(); | ||
760 | spin_unlock_irq(¤t->sighand->siglock); | ||
761 | } | 767 | } |
762 | 768 | ||
763 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | 769 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 38f098c9c72d..58dfc02c7af1 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c | |||
@@ -22,102 +22,10 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/ipc.h> | 24 | #include <linux/ipc.h> |
25 | #include <asm/cacheflush.h> | ||
26 | #include <asm/syscalls.h> | 25 | #include <asm/syscalls.h> |
27 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
28 | #include <asm/unistd.h> | 27 | #include <asm/unistd.h> |
29 | 28 | ||
30 | unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ | ||
31 | EXPORT_SYMBOL(shm_align_mask); | ||
32 | |||
33 | #ifdef CONFIG_MMU | ||
34 | /* | ||
35 | * To avoid cache aliases, we map the shared page with same color. | ||
36 | */ | ||
37 | #define COLOUR_ALIGN(addr, pgoff) \ | ||
38 | ((((addr) + shm_align_mask) & ~shm_align_mask) + \ | ||
39 | (((pgoff) << PAGE_SHIFT) & shm_align_mask)) | ||
40 | |||
41 | unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, | ||
42 | unsigned long len, unsigned long pgoff, unsigned long flags) | ||
43 | { | ||
44 | struct mm_struct *mm = current->mm; | ||
45 | struct vm_area_struct *vma; | ||
46 | unsigned long start_addr; | ||
47 | int do_colour_align; | ||
48 | |||
49 | if (flags & MAP_FIXED) { | ||
50 | /* We do not accept a shared mapping if it would violate | ||
51 | * cache aliasing constraints. | ||
52 | */ | ||
53 | if ((flags & MAP_SHARED) && (addr & shm_align_mask)) | ||
54 | return -EINVAL; | ||
55 | return addr; | ||
56 | } | ||
57 | |||
58 | if (unlikely(len > TASK_SIZE)) | ||
59 | return -ENOMEM; | ||
60 | |||
61 | do_colour_align = 0; | ||
62 | if (filp || (flags & MAP_SHARED)) | ||
63 | do_colour_align = 1; | ||
64 | |||
65 | if (addr) { | ||
66 | if (do_colour_align) | ||
67 | addr = COLOUR_ALIGN(addr, pgoff); | ||
68 | else | ||
69 | addr = PAGE_ALIGN(addr); | ||
70 | |||
71 | vma = find_vma(mm, addr); | ||
72 | if (TASK_SIZE - len >= addr && | ||
73 | (!vma || addr + len <= vma->vm_start)) | ||
74 | return addr; | ||
75 | } | ||
76 | |||
77 | if (len > mm->cached_hole_size) { | ||
78 | start_addr = addr = mm->free_area_cache; | ||
79 | } else { | ||
80 | mm->cached_hole_size = 0; | ||
81 | start_addr = addr = TASK_UNMAPPED_BASE; | ||
82 | } | ||
83 | |||
84 | full_search: | ||
85 | if (do_colour_align) | ||
86 | addr = COLOUR_ALIGN(addr, pgoff); | ||
87 | else | ||
88 | addr = PAGE_ALIGN(mm->free_area_cache); | ||
89 | |||
90 | for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { | ||
91 | /* At this point: (!vma || addr < vma->vm_end). */ | ||
92 | if (unlikely(TASK_SIZE - len < addr)) { | ||
93 | /* | ||
94 | * Start a new search - just in case we missed | ||
95 | * some holes. | ||
96 | */ | ||
97 | if (start_addr != TASK_UNMAPPED_BASE) { | ||
98 | start_addr = addr = TASK_UNMAPPED_BASE; | ||
99 | mm->cached_hole_size = 0; | ||
100 | goto full_search; | ||
101 | } | ||
102 | return -ENOMEM; | ||
103 | } | ||
104 | if (likely(!vma || addr + len <= vma->vm_start)) { | ||
105 | /* | ||
106 | * Remember the place where we stopped the search: | ||
107 | */ | ||
108 | mm->free_area_cache = addr + len; | ||
109 | return addr; | ||
110 | } | ||
111 | if (addr + mm->cached_hole_size < vma->vm_start) | ||
112 | mm->cached_hole_size = vma->vm_start - addr; | ||
113 | |||
114 | addr = vma->vm_end; | ||
115 | if (do_colour_align) | ||
116 | addr = COLOUR_ALIGN(addr, pgoff); | ||
117 | } | ||
118 | } | ||
119 | #endif /* CONFIG_MMU */ | ||
120 | |||
121 | static inline long | 29 | static inline long |
122 | do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, | 30 | do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, |
123 | unsigned long flags, int fd, unsigned long pgoff) | 31 | unsigned long flags, int fd, unsigned long pgoff) |
diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 23ca711c27d2..8457f83242c5 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c | |||
@@ -125,11 +125,6 @@ void handle_timer_tick(void) | |||
125 | if (current->pid) | 125 | if (current->pid) |
126 | profile_tick(CPU_PROFILING); | 126 | profile_tick(CPU_PROFILING); |
127 | 127 | ||
128 | #ifdef CONFIG_HEARTBEAT | ||
129 | if (sh_mv.mv_heartbeat != NULL) | ||
130 | sh_mv.mv_heartbeat(); | ||
131 | #endif | ||
132 | |||
133 | /* | 128 | /* |
134 | * Here we are in the timer irq handler. We just have irqs locally | 129 | * Here we are in the timer irq handler. We just have irqs locally |
135 | * disabled but we don't know if the timer_bh is running on the other | 130 | * disabled but we don't know if the timer_bh is running on the other |
@@ -277,11 +272,4 @@ void __init time_init(void) | |||
277 | ((sh_hpt_frequency + 500) / 1000) / 1000, | 272 | ((sh_hpt_frequency + 500) / 1000) / 1000, |
278 | ((sh_hpt_frequency + 500) / 1000) % 1000); | 273 | ((sh_hpt_frequency + 500) / 1000) % 1000); |
279 | 274 | ||
280 | #if defined(CONFIG_SH_KGDB) | ||
281 | /* | ||
282 | * Set up kgdb as requested. We do it here because the serial | ||
283 | * init uses the timer vars we just set up for figuring baud. | ||
284 | */ | ||
285 | kgdb_init(); | ||
286 | #endif | ||
287 | } | 275 | } |
diff --git a/arch/sh/kernel/time_64.c b/arch/sh/kernel/time_64.c index bbb2af1004d9..59d2a03e8b3c 100644 --- a/arch/sh/kernel/time_64.c +++ b/arch/sh/kernel/time_64.c | |||
@@ -240,11 +240,6 @@ static inline void do_timer_interrupt(void) | |||
240 | 240 | ||
241 | do_timer(1); | 241 | do_timer(1); |
242 | 242 | ||
243 | #ifdef CONFIG_HEARTBEAT | ||
244 | if (sh_mv.mv_heartbeat != NULL) | ||
245 | sh_mv.mv_heartbeat(); | ||
246 | #endif | ||
247 | |||
248 | /* | 243 | /* |
249 | * If we have an externally synchronized Linux clock, then update | 244 | * If we have an externally synchronized Linux clock, then update |
250 | * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be | 245 | * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c index fe453c01f9c9..c3d237e1d566 100644 --- a/arch/sh/kernel/timers/timer-mtu2.c +++ b/arch/sh/kernel/timers/timer-mtu2.c | |||
@@ -34,7 +34,12 @@ | |||
34 | #define MTU2_TIER_1 0xfffe4384 | 34 | #define MTU2_TIER_1 0xfffe4384 |
35 | #define MTU2_TSR_1 0xfffe4385 | 35 | #define MTU2_TSR_1 0xfffe4385 |
36 | #define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ | 36 | #define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ |
37 | |||
38 | #if defined(CONFIG_CPU_SUBTYPE_SH7201) | ||
39 | #define MTU2_TGRA_1 0xfffe4388 | ||
40 | #else | ||
37 | #define MTU2_TGRA_1 0xfffe438a | 41 | #define MTU2_TGRA_1 0xfffe438a |
42 | #endif | ||
38 | 43 | ||
39 | #define STBCR3 0xfffe0408 | 44 | #define STBCR3 0xfffe0408 |
40 | 45 | ||
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 1e5c74efbacc..88807a2aacc3 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c | |||
@@ -28,17 +28,6 @@ | |||
28 | #include <asm/fpu.h> | 28 | #include <asm/fpu.h> |
29 | #include <asm/kprobes.h> | 29 | #include <asm/kprobes.h> |
30 | 30 | ||
31 | #ifdef CONFIG_SH_KGDB | ||
32 | #include <asm/kgdb.h> | ||
33 | #define CHK_REMOTE_DEBUG(regs) \ | ||
34 | { \ | ||
35 | if (kgdb_debug_hook && !user_mode(regs))\ | ||
36 | (*kgdb_debug_hook)(regs); \ | ||
37 | } | ||
38 | #else | ||
39 | #define CHK_REMOTE_DEBUG(regs) | ||
40 | #endif | ||
41 | |||
42 | #ifdef CONFIG_CPU_SH2 | 31 | #ifdef CONFIG_CPU_SH2 |
43 | # define TRAP_RESERVED_INST 4 | 32 | # define TRAP_RESERVED_INST 4 |
44 | # define TRAP_ILLEGAL_SLOT_INST 6 | 33 | # define TRAP_ILLEGAL_SLOT_INST 6 |
@@ -94,7 +83,6 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
94 | 83 | ||
95 | printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); | 84 | printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); |
96 | 85 | ||
97 | CHK_REMOTE_DEBUG(regs); | ||
98 | print_modules(); | 86 | print_modules(); |
99 | show_regs(regs); | 87 | show_regs(regs); |
100 | 88 | ||
@@ -683,13 +671,12 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, | |||
683 | error_code = lookup_exception_vector(); | 671 | error_code = lookup_exception_vector(); |
684 | 672 | ||
685 | local_irq_enable(); | 673 | local_irq_enable(); |
686 | CHK_REMOTE_DEBUG(regs); | ||
687 | force_sig(SIGILL, tsk); | 674 | force_sig(SIGILL, tsk); |
688 | die_if_no_fixup("reserved instruction", regs, error_code); | 675 | die_if_no_fixup("reserved instruction", regs, error_code); |
689 | } | 676 | } |
690 | 677 | ||
691 | #ifdef CONFIG_SH_FPU_EMU | 678 | #ifdef CONFIG_SH_FPU_EMU |
692 | static int emulate_branch(unsigned short inst, struct pt_regs* regs) | 679 | static int emulate_branch(unsigned short inst, struct pt_regs *regs) |
693 | { | 680 | { |
694 | /* | 681 | /* |
695 | * bfs: 8fxx: PC+=d*2+4; | 682 | * bfs: 8fxx: PC+=d*2+4; |
@@ -702,27 +689,32 @@ static int emulate_branch(unsigned short inst, struct pt_regs* regs) | |||
702 | * jsr: 4x0b: PC=Rn after PR=PC+4; | 689 | * jsr: 4x0b: PC=Rn after PR=PC+4; |
703 | * rts: 000b: PC=PR; | 690 | * rts: 000b: PC=PR; |
704 | */ | 691 | */ |
705 | if ((inst & 0xfd00) == 0x8d00) { | 692 | if (((inst & 0xf000) == 0xb000) || /* bsr */ |
693 | ((inst & 0xf0ff) == 0x0003) || /* bsrf */ | ||
694 | ((inst & 0xf0ff) == 0x400b)) /* jsr */ | ||
695 | regs->pr = regs->pc + 4; | ||
696 | |||
697 | if ((inst & 0xfd00) == 0x8d00) { /* bfs, bts */ | ||
706 | regs->pc += SH_PC_8BIT_OFFSET(inst); | 698 | regs->pc += SH_PC_8BIT_OFFSET(inst); |
707 | return 0; | 699 | return 0; |
708 | } | 700 | } |
709 | 701 | ||
710 | if ((inst & 0xe000) == 0xa000) { | 702 | if ((inst & 0xe000) == 0xa000) { /* bra, bsr */ |
711 | regs->pc += SH_PC_12BIT_OFFSET(inst); | 703 | regs->pc += SH_PC_12BIT_OFFSET(inst); |
712 | return 0; | 704 | return 0; |
713 | } | 705 | } |
714 | 706 | ||
715 | if ((inst & 0xf0df) == 0x0003) { | 707 | if ((inst & 0xf0df) == 0x0003) { /* braf, bsrf */ |
716 | regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4; | 708 | regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4; |
717 | return 0; | 709 | return 0; |
718 | } | 710 | } |
719 | 711 | ||
720 | if ((inst & 0xf0df) == 0x400b) { | 712 | if ((inst & 0xf0df) == 0x400b) { /* jmp, jsr */ |
721 | regs->pc = regs->regs[(inst & 0x0f00) >> 8]; | 713 | regs->pc = regs->regs[(inst & 0x0f00) >> 8]; |
722 | return 0; | 714 | return 0; |
723 | } | 715 | } |
724 | 716 | ||
725 | if ((inst & 0xffff) == 0x000b) { | 717 | if ((inst & 0xffff) == 0x000b) { /* rts */ |
726 | regs->pc = regs->pr; | 718 | regs->pc = regs->pr; |
727 | return 0; | 719 | return 0; |
728 | } | 720 | } |
@@ -756,7 +748,6 @@ asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, | |||
756 | inst = lookup_exception_vector(); | 748 | inst = lookup_exception_vector(); |
757 | 749 | ||
758 | local_irq_enable(); | 750 | local_irq_enable(); |
759 | CHK_REMOTE_DEBUG(regs); | ||
760 | force_sig(SIGILL, tsk); | 751 | force_sig(SIGILL, tsk); |
761 | die_if_no_fixup("illegal slot instruction", regs, inst); | 752 | die_if_no_fixup("illegal slot instruction", regs, inst); |
762 | } | 753 | } |
@@ -868,10 +859,7 @@ void show_trace(struct task_struct *tsk, unsigned long *sp, | |||
868 | if (regs && user_mode(regs)) | 859 | if (regs && user_mode(regs)) |
869 | return; | 860 | return; |
870 | 861 | ||
871 | printk("\nCall trace: "); | 862 | printk("\nCall trace:\n"); |
872 | #ifdef CONFIG_KALLSYMS | ||
873 | printk("\n"); | ||
874 | #endif | ||
875 | 863 | ||
876 | while (!kstack_end(sp)) { | 864 | while (!kstack_end(sp)) { |
877 | addr = *sp++; | 865 | addr = *sp++; |
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c index 95f4de0800ec..3f7e415be86a 100644 --- a/arch/sh/kernel/vsyscall/vsyscall.c +++ b/arch/sh/kernel/vsyscall/vsyscall.c | |||
@@ -59,8 +59,7 @@ int __init vsyscall_init(void) | |||
59 | } | 59 | } |
60 | 60 | ||
61 | /* Setup a VMA at program startup for the vsyscall page */ | 61 | /* Setup a VMA at program startup for the vsyscall page */ |
62 | int arch_setup_additional_pages(struct linux_binprm *bprm, | 62 | int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) |
63 | int executable_stack) | ||
64 | { | 63 | { |
65 | struct mm_struct *mm = current->mm; | 64 | struct mm_struct *mm = current->mm; |
66 | unsigned long addr; | 65 | unsigned long addr; |