aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-01-20 02:42:52 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-01-20 02:42:52 -0500
commitfbb82b03653cdb7fd1863b911e7540011259d2ce (patch)
treed5920f46068bb184a5322bc1505fb030adb6bfb6 /arch/sh/kernel
parent2efa53b269ec1e9289a108e1506f53f6f1de440b (diff)
sh: machine_ops based reboot support.
This provides a machine_ops-based reboot interface loosely cloned from x86, and converts the native sh32 and sh64 cases over to it. Necessary both for tying in SMP support and also enabling platforms like SDK7786 to add support for their microcontroller-based power managers. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-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
7 files changed, 115 insertions, 90 deletions
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
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 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
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 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
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 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
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 c9554a70bd0e..6ae5987230f8 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 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
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 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
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);