aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/include/asm/reboot.h21
-rw-r--r--arch/sh/include/asm/system.h1
-rw-r--r--arch/sh/include/asm/system_32.h12
-rw-r--r--arch/sh/include/asm/system_64.h7
-rw-r--r--arch/sh/kernel/Makefile3
-rw-r--r--arch/sh/kernel/idle.c14
-rw-r--r--arch/sh/kernel/machine_kexec.c8
-rw-r--r--arch/sh/kernel/process_32.c48
-rw-r--r--arch/sh/kernel/process_64.c25
-rw-r--r--arch/sh/kernel/reboot.c98
-rw-r--r--arch/sh/kernel/smp.c9
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 00000000000..b3da0c63fc3
--- /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
6struct pt_regs;
7
8struct 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
16extern struct machine_ops machine_ops;
17
18/* arch/sh/kernel/machine_kexec.c */
19void 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 62e4fc1e440..de2fc3963c1 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;
143void per_cpu_trap_init(void); 143void per_cpu_trap_init(void);
144void default_idle(void); 144void default_idle(void);
145void cpu_idle_wait(void); 145void cpu_idle_wait(void);
146void 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 06814f5b59c..34bd2bac9a5 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)
216int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs, 217int 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
220static 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
219asmlinkage void do_address_error(struct pt_regs *regs, 231asmlinkage 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 ab1dd917ea8..604ba7802cc 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
51extern void phys_stext(void);
52
53static 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
53static inline void set_bl_bit(void) 60static inline void set_bl_bit(void)
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 56704a6d723..02fd3ae8b0e 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -14,7 +14,8 @@ CFLAGS_REMOVE_return_address.o = -pg
14obj-y := debugtraps.o dma-nommu.o dumpstack.o \ 14obj-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 6b3d706deac..0fd7b41f0a2 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
23static int hlt_counter;
24void (*pm_idle)(void) = NULL; 23void (*pm_idle)(void) = NULL;
25void (*pm_power_off)(void); 24
26EXPORT_SYMBOL(pm_power_off); 25static int hlt_counter;
27 26
28static int __init nohlt_setup(char *__unused) 27static int __init nohlt_setup(char *__unused)
29{ 28{
@@ -131,6 +130,15 @@ static void do_nothing(void *unused)
131{ 130{
132} 131}
133 132
133void 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 f52d8ed69e1..7672141c841 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
26typedef void (*relocate_new_kernel_t)(unsigned long indirection_page, 27typedef 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[];
31extern const unsigned int relocate_new_kernel_size; 32extern const unsigned int relocate_new_kernel_size;
32extern void *vbr_base; 33extern void *vbr_base;
33 34
34void machine_shutdown(void) 35void native_machine_crash_shutdown(struct pt_regs *regs)
35{
36}
37
38void 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 856010f9ebc..b6f43f0ea74 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
38static void watchdog_trigger_immediate(void)
39{
40 sh_wdt_write_cnt(0xFF);
41 sh_wdt_write_csr(0xC2);
42}
43
44void 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
55void 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
63void machine_halt(void)
64{
65 local_irq_disable();
66
67 while (1)
68 cpu_sleep();
69}
70
71void machine_power_off(void)
72{
73 if (pm_power_off)
74 pm_power_off();
75}
76 28
77void show_regs(struct pt_regs * regs) 29void 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 c9554a70bd0..6ae5987230f 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -32,30 +32,7 @@
32 32
33struct task_struct *last_task_used_math = NULL; 33struct task_struct *last_task_used_math = NULL;
34 34
35void machine_restart(char * __unused) 35void show_regs(struct pt_regs *regs)
36{
37 extern void phys_stext(void);
38
39 phys_stext();
40}
41
42void machine_halt(void)
43{
44 for (;;);
45}
46
47void 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
58void 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 00000000000..b1fca66bb92
--- /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
13void (*pm_power_off)(void);
14EXPORT_SYMBOL(pm_power_off);
15
16#ifdef CONFIG_SUPERH32
17static void watchdog_trigger_immediate(void)
18{
19 sh_wdt_write_cnt(0xFF);
20 sh_wdt_write_csr(0xC2);
21}
22#endif
23
24static 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
43static void native_machine_shutdown(void)
44{
45 smp_send_stop();
46}
47
48static void native_machine_power_off(void)
49{
50 if (pm_power_off)
51 pm_power_off();
52}
53
54static 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
63struct 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
73void machine_power_off(void)
74{
75 machine_ops.power_off();
76}
77
78void machine_shutdown(void)
79{
80 machine_ops.shutdown();
81}
82
83void machine_restart(char *cmd)
84{
85 machine_ops.restart(cmd);
86}
87
88void machine_halt(void)
89{
90 machine_ops.halt();
91}
92
93#ifdef CONFIG_KEXEC
94void 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 983e0792d5f..e124cf7008d 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
164static 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
173void smp_send_stop(void) 164void smp_send_stop(void)
174{ 165{
175 smp_call_function(stop_this_cpu, 0, 0); 166 smp_call_function(stop_this_cpu, 0, 0);