1 /* 2 * This file is subject to the terms and conditions of the GNU General Public 3 * License. See the file "COPYING" in the main directory of this archive 4 * for more details. 5 * 6 * Copyright (C) 2001, 06 by Ralf Baechle (ralf@linux-mips.org) 7 * Copyright (C) 2001 MIPS Technologies, Inc. 8 */ 9 #include <linux/kernel.h> 10 #include <linux/export.h> 11 #include <linux/pm.h> 12 #include <linux/types.h> 13 #include <linux/reboot.h> 14 #include <linux/delay.h> 15 16 #include <asm/compiler.h> 17 #include <asm/idle.h> 18 #include <asm/mipsregs.h> 19 #include <asm/reboot.h> 20 21 /* 22 * Urgs ... Too many MIPS machines to handle this in a generic way. 23 * So handle all using function pointers to machine specific 24 * functions. 25 */ 26 void (*_machine_restart)(char *command); 27 void (*_machine_halt)(void); 28 void (*pm_power_off)(void); 29 30 EXPORT_SYMBOL(pm_power_off); 31 32 static void machine_hang(void) 33 { 34 /* 35 * We're hanging the system so we don't want to be interrupted anymore. 36 * Any interrupt handlers that ran would at best be useless & at worst 37 * go awry because the system isn't in a functional state. 38 */ 39 local_irq_disable(); 40 41 /* 42 * Mask all interrupts, giving us a better chance of remaining in the 43 * low power wait state. 44 */ 45 clear_c0_status(ST0_IM); 46 47 while (true) { 48 if (cpu_has_mips_r) { 49 /* 50 * We know that the wait instruction is supported so 51 * make use of it directly, leaving interrupts 52 * disabled. 53 */ 54 asm volatile( 55 ".set push\n\t" 56 ".set " MIPS_ISA_ARCH_LEVEL "\n\t" 57 "wait\n\t" 58 ".set pop"); 59 } else if (cpu_wait) { 60 /* 61 * Try the cpu_wait() callback. This isn't ideal since 62 * it'll re-enable interrupts, but that ought to be 63 * harmless given that they're all masked. 64 */ 65 cpu_wait(); 66 local_irq_disable(); 67 } else { 68 /* 69 * We're going to burn some power running round the 70 * loop, but we don't really have a choice. This isn't 71 * a path we should expect to run for long during 72 * typical use anyway. 73 */ 74 } 75 76 /* 77 * In most modern MIPS CPUs interrupts will cause the wait 78 * instruction to graduate even when disabled, and in some 79 * cases even when masked. In order to prevent a timer 80 * interrupt from continuously taking us out of the low power 81 * wait state, we clear any pending timer interrupt here. 82 */ 83 if (cpu_has_counter) 84 write_c0_compare(0); 85 } 86 } 87 88 void machine_restart(char *command) 89 { 90 if (_machine_restart) 91 _machine_restart(command); 92 93 #ifdef CONFIG_SMP 94 preempt_disable(); 95 smp_send_stop(); 96 #endif 97 do_kernel_restart(command); 98 mdelay(1000); 99 pr_emerg("Reboot failed -- System halted\n"); 100 machine_hang(); 101 } 102 103 void machine_halt(void) 104 { 105 if (_machine_halt) 106 _machine_halt(); 107 108 #ifdef CONFIG_SMP 109 preempt_disable(); 110 smp_send_stop(); 111 #endif 112 machine_hang(); 113 } 114 115 void machine_power_off(void) 116 { 117 do_kernel_power_off(); 118 119 #ifdef CONFIG_SMP 120 preempt_disable(); 121 smp_send_stop(); 122 #endif 123 machine_hang(); 124 } 125