diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/include/asm/reboot.h | 21 | ||||
-rw-r--r-- | arch/sh/include/asm/system.h | 1 | ||||
-rw-r--r-- | arch/sh/include/asm/system_32.h | 12 | ||||
-rw-r--r-- | arch/sh/include/asm/system_64.h | 7 | ||||
-rw-r--r-- | arch/sh/kernel/Makefile | 3 | ||||
-rw-r--r-- | arch/sh/kernel/idle.c | 14 | ||||
-rw-r--r-- | arch/sh/kernel/machine_kexec.c | 8 | ||||
-rw-r--r-- | arch/sh/kernel/process_32.c | 48 | ||||
-rw-r--r-- | arch/sh/kernel/process_64.c | 25 | ||||
-rw-r--r-- | arch/sh/kernel/reboot.c | 98 | ||||
-rw-r--r-- | arch/sh/kernel/smp.c | 9 |
11 files changed, 156 insertions, 90 deletions
diff --git a/arch/sh/include/asm/reboot.h b/arch/sh/include/asm/reboot.h new file mode 100644 index 000000000000..b3da0c63fc3d --- /dev/null +++ b/arch/sh/include/asm/reboot.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef __ASM_SH_REBOOT_H | ||
2 | #define __ASM_SH_REBOOT_H | ||
3 | |||
4 | #include <linux/kdebug.h> | ||
5 | |||
6 | struct pt_regs; | ||
7 | |||
8 | struct machine_ops { | ||
9 | void (*restart)(char *cmd); | ||
10 | void (*halt)(void); | ||
11 | void (*power_off)(void); | ||
12 | void (*shutdown)(void); | ||
13 | void (*crash_shutdown)(struct pt_regs *); | ||
14 | }; | ||
15 | |||
16 | extern struct machine_ops machine_ops; | ||
17 | |||
18 | /* arch/sh/kernel/machine_kexec.c */ | ||
19 | void native_machine_crash_shutdown(struct pt_regs *regs); | ||
20 | |||
21 | #endif /* __ASM_SH_REBOOT_H */ | ||
diff --git a/arch/sh/include/asm/system.h b/arch/sh/include/asm/system.h index 62e4fc1e4409..de2fc3963c12 100644 --- a/arch/sh/include/asm/system.h +++ b/arch/sh/include/asm/system.h | |||
@@ -143,6 +143,7 @@ extern struct dentry *sh_debugfs_root; | |||
143 | void per_cpu_trap_init(void); | 143 | void per_cpu_trap_init(void); |
144 | void default_idle(void); | 144 | void default_idle(void); |
145 | void cpu_idle_wait(void); | 145 | void cpu_idle_wait(void); |
146 | void stop_this_cpu(void *); | ||
146 | 147 | ||
147 | #ifdef CONFIG_SUPERH32 | 148 | #ifdef CONFIG_SUPERH32 |
148 | #define BUILD_TRAP_HANDLER(name) \ | 149 | #define BUILD_TRAP_HANDLER(name) \ |
diff --git a/arch/sh/include/asm/system_32.h b/arch/sh/include/asm/system_32.h index 06814f5b59c7..34bd2bac9a5f 100644 --- a/arch/sh/include/asm/system_32.h +++ b/arch/sh/include/asm/system_32.h | |||
@@ -2,6 +2,7 @@ | |||
2 | #define __ASM_SH_SYSTEM_32_H | 2 | #define __ASM_SH_SYSTEM_32_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <asm/mmu.h> | ||
5 | 6 | ||
6 | #ifdef CONFIG_SH_DSP | 7 | #ifdef CONFIG_SH_DSP |
7 | 8 | ||
@@ -216,6 +217,17 @@ static inline reg_size_t register_align(void *val) | |||
216 | int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, | 217 | int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, |
217 | struct mem_access *ma, int); | 218 | struct mem_access *ma, int); |
218 | 219 | ||
220 | static inline void trigger_address_error(void) | ||
221 | { | ||
222 | if (__in_29bit_mode()) | ||
223 | __asm__ __volatile__ ( | ||
224 | "ldc %0, sr\n\t" | ||
225 | "mov.l @%1, %0" | ||
226 | : | ||
227 | : "r" (0x10000000), "r" (0x80000001) | ||
228 | ); | ||
229 | } | ||
230 | |||
219 | asmlinkage void do_address_error(struct pt_regs *regs, | 231 | asmlinkage void do_address_error(struct pt_regs *regs, |
220 | unsigned long writeaccess, | 232 | unsigned long writeaccess, |
221 | unsigned long address); | 233 | unsigned long address); |
diff --git a/arch/sh/include/asm/system_64.h b/arch/sh/include/asm/system_64.h index ab1dd917ea87..604ba7802cc2 100644 --- a/arch/sh/include/asm/system_64.h +++ b/arch/sh/include/asm/system_64.h | |||
@@ -48,6 +48,13 @@ static inline reg_size_t register_align(void *val) | |||
48 | return (unsigned long long)(signed long long)(signed long)val; | 48 | return (unsigned long long)(signed long long)(signed long)val; |
49 | } | 49 | } |
50 | 50 | ||
51 | extern void phys_stext(void); | ||
52 | |||
53 | static inline void trigger_address_error(void) | ||
54 | { | ||
55 | phys_stext(); | ||
56 | } | ||
57 | |||
51 | #define SR_BL_LL 0x0000000010000000LL | 58 | #define SR_BL_LL 0x0000000010000000LL |
52 | 59 | ||
53 | static inline void set_bl_bit(void) | 60 | static inline void set_bl_bit(void) |
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 56704a6d723a..02fd3ae8b0ee 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -14,7 +14,8 @@ CFLAGS_REMOVE_return_address.o = -pg | |||
14 | obj-y := debugtraps.o dma-nommu.o dumpstack.o \ | 14 | obj-y := debugtraps.o dma-nommu.o dumpstack.o \ |
15 | idle.o io.o io_generic.o irq.o \ | 15 | idle.o io.o io_generic.o irq.o \ |
16 | irq_$(BITS).o machvec.o nmi_debug.o process.o \ | 16 | irq_$(BITS).o machvec.o nmi_debug.o process.o \ |
17 | process_$(BITS).o ptrace_$(BITS).o return_address.o \ | 17 | process_$(BITS).o ptrace_$(BITS).o \ |
18 | reboot.o return_address.o \ | ||
18 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ | 19 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ |
19 | syscalls_$(BITS).o time.o topology.o traps.o \ | 20 | syscalls_$(BITS).o time.o topology.o traps.o \ |
20 | traps_$(BITS).o unwinder.o | 21 | traps_$(BITS).o unwinder.o |
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 6b3d706deac1..0fd7b41f0a22 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c | |||
@@ -20,10 +20,9 @@ | |||
20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
21 | #include <asm/atomic.h> | 21 | #include <asm/atomic.h> |
22 | 22 | ||
23 | static int hlt_counter; | ||
24 | void (*pm_idle)(void) = NULL; | 23 | void (*pm_idle)(void) = NULL; |
25 | void (*pm_power_off)(void); | 24 | |
26 | EXPORT_SYMBOL(pm_power_off); | 25 | static int hlt_counter; |
27 | 26 | ||
28 | static int __init nohlt_setup(char *__unused) | 27 | static int __init nohlt_setup(char *__unused) |
29 | { | 28 | { |
@@ -131,6 +130,15 @@ static void do_nothing(void *unused) | |||
131 | { | 130 | { |
132 | } | 131 | } |
133 | 132 | ||
133 | void stop_this_cpu(void *unused) | ||
134 | { | ||
135 | local_irq_disable(); | ||
136 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
137 | |||
138 | for (;;) | ||
139 | cpu_sleep(); | ||
140 | } | ||
141 | |||
134 | /* | 142 | /* |
135 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of | 143 | * cpu_idle_wait - Used to ensure that all the CPUs discard old value of |
136 | * pm_idle and update to new pm_idle value. Required while changing pm_idle | 144 | * pm_idle and update to new pm_idle value. Required while changing pm_idle |
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index f52d8ed69e12..7672141c841b 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/io.h> | 22 | #include <asm/io.h> |
23 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
24 | #include <asm/sh_bios.h> | 24 | #include <asm/sh_bios.h> |
25 | #include <asm/reboot.h> | ||
25 | 26 | ||
26 | typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, | 27 | typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, |
27 | unsigned long reboot_code_buffer, | 28 | unsigned long reboot_code_buffer, |
@@ -31,12 +32,9 @@ extern const unsigned char relocate_new_kernel[]; | |||
31 | extern const unsigned int relocate_new_kernel_size; | 32 | extern const unsigned int relocate_new_kernel_size; |
32 | extern void *vbr_base; | 33 | extern void *vbr_base; |
33 | 34 | ||
34 | void machine_shutdown(void) | 35 | void native_machine_crash_shutdown(struct pt_regs *regs) |
35 | { | ||
36 | } | ||
37 | |||
38 | void machine_crash_shutdown(struct pt_regs *regs) | ||
39 | { | 36 | { |
37 | /* Nothing to do for UP, but definitely broken for SMP.. */ | ||
40 | } | 38 | } |
41 | 39 | ||
42 | /* | 40 | /* |
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 856010f9ebc9..b6f43f0ea743 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -16,63 +16,15 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/mm.h> | 17 | #include <linux/mm.h> |
18 | #include <linux/elfcore.h> | 18 | #include <linux/elfcore.h> |
19 | #include <linux/pm.h> | ||
20 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
21 | #include <linux/kexec.h> | ||
22 | #include <linux/kdebug.h> | ||
23 | #include <linux/tick.h> | ||
24 | #include <linux/reboot.h> | ||
25 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
26 | #include <linux/ftrace.h> | 21 | #include <linux/ftrace.h> |
27 | #include <linux/preempt.h> | ||
28 | #include <linux/hw_breakpoint.h> | 22 | #include <linux/hw_breakpoint.h> |
29 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
30 | #include <asm/mmu_context.h> | 24 | #include <asm/mmu_context.h> |
31 | #include <asm/pgalloc.h> | ||
32 | #include <asm/system.h> | 25 | #include <asm/system.h> |
33 | #include <asm/fpu.h> | 26 | #include <asm/fpu.h> |
34 | #include <asm/syscalls.h> | 27 | #include <asm/syscalls.h> |
35 | #include <asm/watchdog.h> | ||
36 | |||
37 | #ifdef CONFIG_32BIT | ||
38 | static void watchdog_trigger_immediate(void) | ||
39 | { | ||
40 | sh_wdt_write_cnt(0xFF); | ||
41 | sh_wdt_write_csr(0xC2); | ||
42 | } | ||
43 | |||
44 | void machine_restart(char * __unused) | ||
45 | { | ||
46 | local_irq_disable(); | ||
47 | |||
48 | /* Use watchdog timer to trigger reset */ | ||
49 | watchdog_trigger_immediate(); | ||
50 | |||
51 | while (1) | ||
52 | cpu_sleep(); | ||
53 | } | ||
54 | #else | ||
55 | void machine_restart(char * __unused) | ||
56 | { | ||
57 | /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ | ||
58 | asm volatile("ldc %0, sr\n\t" | ||
59 | "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | void machine_halt(void) | ||
64 | { | ||
65 | local_irq_disable(); | ||
66 | |||
67 | while (1) | ||
68 | cpu_sleep(); | ||
69 | } | ||
70 | |||
71 | void machine_power_off(void) | ||
72 | { | ||
73 | if (pm_power_off) | ||
74 | pm_power_off(); | ||
75 | } | ||
76 | 28 | ||
77 | void show_regs(struct pt_regs * regs) | 29 | void show_regs(struct pt_regs * regs) |
78 | { | 30 | { |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index c9554a70bd0e..6ae5987230f8 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
@@ -32,30 +32,7 @@ | |||
32 | 32 | ||
33 | struct task_struct *last_task_used_math = NULL; | 33 | struct task_struct *last_task_used_math = NULL; |
34 | 34 | ||
35 | void machine_restart(char * __unused) | 35 | void show_regs(struct pt_regs *regs) |
36 | { | ||
37 | extern void phys_stext(void); | ||
38 | |||
39 | phys_stext(); | ||
40 | } | ||
41 | |||
42 | void machine_halt(void) | ||
43 | { | ||
44 | for (;;); | ||
45 | } | ||
46 | |||
47 | void machine_power_off(void) | ||
48 | { | ||
49 | __asm__ __volatile__ ( | ||
50 | "sleep\n\t" | ||
51 | "synci\n\t" | ||
52 | "nop;nop;nop;nop\n\t" | ||
53 | ); | ||
54 | |||
55 | panic("Unexpected wakeup!\n"); | ||
56 | } | ||
57 | |||
58 | void show_regs(struct pt_regs * regs) | ||
59 | { | 36 | { |
60 | unsigned long long ah, al, bh, bl, ch, cl; | 37 | unsigned long long ah, al, bh, bl, ch, cl; |
61 | 38 | ||
diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c new file mode 100644 index 000000000000..b1fca66bb92e --- /dev/null +++ b/arch/sh/kernel/reboot.c | |||
@@ -0,0 +1,98 @@ | |||
1 | #include <linux/pm.h> | ||
2 | #include <linux/kexec.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/reboot.h> | ||
5 | #include <linux/module.h> | ||
6 | #ifdef CONFIG_SUPERH32 | ||
7 | #include <asm/watchdog.h> | ||
8 | #endif | ||
9 | #include <asm/addrspace.h> | ||
10 | #include <asm/reboot.h> | ||
11 | #include <asm/system.h> | ||
12 | |||
13 | void (*pm_power_off)(void); | ||
14 | EXPORT_SYMBOL(pm_power_off); | ||
15 | |||
16 | #ifdef CONFIG_SUPERH32 | ||
17 | static void watchdog_trigger_immediate(void) | ||
18 | { | ||
19 | sh_wdt_write_cnt(0xFF); | ||
20 | sh_wdt_write_csr(0xC2); | ||
21 | } | ||
22 | #endif | ||
23 | |||
24 | static void native_machine_restart(char * __unused) | ||
25 | { | ||
26 | local_irq_disable(); | ||
27 | |||
28 | /* Address error with SR.BL=1 first. */ | ||
29 | trigger_address_error(); | ||
30 | |||
31 | #ifdef CONFIG_SUPERH32 | ||
32 | /* If that fails or is unsupported, go for the watchdog next. */ | ||
33 | watchdog_trigger_immediate(); | ||
34 | #endif | ||
35 | |||
36 | /* | ||
37 | * Give up and sleep. | ||
38 | */ | ||
39 | while (1) | ||
40 | cpu_sleep(); | ||
41 | } | ||
42 | |||
43 | static void native_machine_shutdown(void) | ||
44 | { | ||
45 | smp_send_stop(); | ||
46 | } | ||
47 | |||
48 | static void native_machine_power_off(void) | ||
49 | { | ||
50 | if (pm_power_off) | ||
51 | pm_power_off(); | ||
52 | } | ||
53 | |||
54 | static void native_machine_halt(void) | ||
55 | { | ||
56 | /* stop other cpus */ | ||
57 | machine_shutdown(); | ||
58 | |||
59 | /* stop this cpu */ | ||
60 | stop_this_cpu(NULL); | ||
61 | } | ||
62 | |||
63 | struct machine_ops machine_ops = { | ||
64 | .power_off = native_machine_power_off, | ||
65 | .shutdown = native_machine_shutdown, | ||
66 | .restart = native_machine_restart, | ||
67 | .halt = native_machine_halt, | ||
68 | #ifdef CONFIG_KEXEC | ||
69 | .crash_shutdown = native_machine_crash_shutdown, | ||
70 | #endif | ||
71 | }; | ||
72 | |||
73 | void machine_power_off(void) | ||
74 | { | ||
75 | machine_ops.power_off(); | ||
76 | } | ||
77 | |||
78 | void machine_shutdown(void) | ||
79 | { | ||
80 | machine_ops.shutdown(); | ||
81 | } | ||
82 | |||
83 | void machine_restart(char *cmd) | ||
84 | { | ||
85 | machine_ops.restart(cmd); | ||
86 | } | ||
87 | |||
88 | void machine_halt(void) | ||
89 | { | ||
90 | machine_ops.halt(); | ||
91 | } | ||
92 | |||
93 | #ifdef CONFIG_KEXEC | ||
94 | void machine_crash_shutdown(struct pt_regs *regs) | ||
95 | { | ||
96 | machine_ops.crash_shutdown(regs); | ||
97 | } | ||
98 | #endif | ||
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 983e0792d5f3..e124cf7008df 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c | |||
@@ -161,15 +161,6 @@ void smp_send_reschedule(int cpu) | |||
161 | plat_send_ipi(cpu, SMP_MSG_RESCHEDULE); | 161 | plat_send_ipi(cpu, SMP_MSG_RESCHEDULE); |
162 | } | 162 | } |
163 | 163 | ||
164 | static void stop_this_cpu(void *unused) | ||
165 | { | ||
166 | cpu_clear(smp_processor_id(), cpu_online_map); | ||
167 | local_irq_disable(); | ||
168 | |||
169 | for (;;) | ||
170 | cpu_relax(); | ||
171 | } | ||
172 | |||
173 | void smp_send_stop(void) | 164 | void smp_send_stop(void) |
174 | { | 165 | { |
175 | smp_call_function(stop_this_cpu, 0, 0); | 166 | smp_call_function(stop_this_cpu, 0, 0); |