linux/arch/sh/kernel/reboot.c
Paul Mundt 59615ecdb5 sh: Provide a global TLB flush for U/I-TLB clear.
This provides a sledgehammer approach for clearing the TLBs, only to be
used in cases where we know we will never want to use the mappings again
and have no interest in preserving state. This also destroys wired
entries.

The primary use for this is when we are either entering or exiting the
kernel completely, in the latter case as a precursor for CPU reset by
MMU.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
2010-07-02 15:44:09 +09:00

102 lines
1.7 KiB
C

#include <linux/pm.h>
#include <linux/kexec.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/module.h>
#ifdef CONFIG_SUPERH32
#include <asm/watchdog.h>
#endif
#include <asm/addrspace.h>
#include <asm/reboot.h>
#include <asm/system.h>
#include <asm/tlbflush.h>
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
#ifdef CONFIG_SUPERH32
static void watchdog_trigger_immediate(void)
{
sh_wdt_write_cnt(0xFF);
sh_wdt_write_csr(0xC2);
}
#endif
static void native_machine_restart(char * __unused)
{
local_irq_disable();
/* Destroy all of the TLBs in preparation for reset by MMU */
__flush_tlb_global();
/* Address error with SR.BL=1 first. */
trigger_address_error();
#ifdef CONFIG_SUPERH32
/* If that fails or is unsupported, go for the watchdog next. */
watchdog_trigger_immediate();
#endif
/*
* Give up and sleep.
*/
while (1)
cpu_sleep();
}
static void native_machine_shutdown(void)
{
smp_send_stop();
}
static void native_machine_power_off(void)
{
if (pm_power_off)
pm_power_off();
}
static void native_machine_halt(void)
{
/* stop other cpus */
machine_shutdown();
/* stop this cpu */
stop_this_cpu(NULL);
}
struct machine_ops machine_ops = {
.power_off = native_machine_power_off,
.shutdown = native_machine_shutdown,
.restart = native_machine_restart,
.halt = native_machine_halt,
#ifdef CONFIG_KEXEC
.crash_shutdown = native_machine_crash_shutdown,
#endif
};
void machine_power_off(void)
{
machine_ops.power_off();
}
void machine_shutdown(void)
{
machine_ops.shutdown();
}
void machine_restart(char *cmd)
{
machine_ops.restart(cmd);
}
void machine_halt(void)
{
machine_ops.halt();
}
#ifdef CONFIG_KEXEC
void machine_crash_shutdown(struct pt_regs *regs)
{
machine_ops.crash_shutdown(regs);
}
#endif