linux/arch/mips/kernel/reset.c
<<
>>
Prefs
   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 */
  26void (*_machine_restart)(char *command);
  27void (*_machine_halt)(void);
  28void (*pm_power_off)(void);
  29
  30EXPORT_SYMBOL(pm_power_off);
  31
  32static 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
  88void 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
 103void 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
 115void machine_power_off(void)
 116{
 117        if (pm_power_off)
 118                pm_power_off();
 119
 120#ifdef CONFIG_SMP
 121        preempt_disable();
 122        smp_send_stop();
 123#endif
 124        machine_hang();
 125}
 126