1/*
2 * This program is free software; you can redistribute	it and/or modify it
3 * under  the terms of	the GNU General	 Public License as published by the
4 * Free Software Foundation;  either version 2 of the  License, or (at your
5 * option) any later version.
6 *
7 * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
8 * Author: Fuxin Zhang, zhangfx@lemote.com
9 * Copyright (C) 2009 Lemote, Inc.
10 * Author: Zhangjin Wu, wuzhangjin@gmail.com
11 */
12#include <linux/init.h>
13#include <linux/pm.h>
14
15#include <asm/idle.h>
16#include <asm/reboot.h>
17
18#include <loongson.h>
19#include <boot_param.h>
20
21static inline void loongson_reboot(void)
22{
23#ifndef CONFIG_CPU_JUMP_WORKAROUNDS
24	((void (*)(void))ioremap_nocache(LOONGSON_BOOT_BASE, 4)) ();
25#else
26	void (*func)(void);
27
28	func = (void *)ioremap_nocache(LOONGSON_BOOT_BASE, 4);
29
30	__asm__ __volatile__(
31	"	.set	noat						\n"
32	"	jr	%[func]						\n"
33	"	.set	at						\n"
34	: /* No outputs */
35	: [func] "r" (func));
36#endif
37}
38
39static void loongson_restart(char *command)
40{
41#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
42	/* do preparation for reboot */
43	mach_prepare_reboot();
44
45	/* reboot via jumping to boot base address */
46	loongson_reboot();
47#else
48	void (*fw_restart)(void) = (void *)loongson_sysconf.restart_addr;
49
50	fw_restart();
51	while (1) {
52		if (cpu_wait)
53			cpu_wait();
54	}
55#endif
56}
57
58static void loongson_poweroff(void)
59{
60#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
61	mach_prepare_shutdown();
62	unreachable();
63#else
64	void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
65
66	fw_poweroff();
67	while (1) {
68		if (cpu_wait)
69			cpu_wait();
70	}
71#endif
72}
73
74static void loongson_halt(void)
75{
76	pr_notice("\n\n** You can safely turn off the power now **\n\n");
77	while (1) {
78		if (cpu_wait)
79			cpu_wait();
80	}
81}
82
83static int __init mips_reboot_setup(void)
84{
85	_machine_restart = loongson_restart;
86	_machine_halt = loongson_halt;
87	pm_power_off = loongson_poweroff;
88
89	return 0;
90}
91
92arch_initcall(mips_reboot_setup);
93