1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *
4  * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
5  * Author: Fuxin Zhang, zhangfx@lemote.com
6  * Copyright (C) 2009 Lemote, Inc.
7  * Author: Zhangjin Wu, wuzhangjin@gmail.com
8  */
9 #include <linux/init.h>
10 #include <linux/pm.h>
11 
12 #include <asm/idle.h>
13 #include <asm/reboot.h>
14 
15 #include <loongson.h>
16 
17 static inline void loongson_reboot(void)
18 {
19 #ifndef CONFIG_CPU_JUMP_WORKAROUNDS
20 	((void (*)(void))ioremap(LOONGSON_BOOT_BASE, 4)) ();
21 #else
22 	void (*func)(void);
23 
24 	func = (void *)ioremap(LOONGSON_BOOT_BASE, 4);
25 
26 	__asm__ __volatile__(
27 	"	.set	noat						\n"
28 	"	jr	%[func]						\n"
29 	"	.set	at						\n"
30 	: /* No outputs */
31 	: [func] "r" (func));
32 #endif
33 }
34 
35 static void loongson_restart(char *command)
36 {
37 	/* do preparation for reboot */
38 	mach_prepare_reboot();
39 
40 	/* reboot via jumping to boot base address */
41 	loongson_reboot();
42 }
43 
44 static void loongson_poweroff(void)
45 {
46 	mach_prepare_shutdown();
47 
48 	/*
49 	 * It needs a wait loop here, but mips/kernel/reset.c already calls
50 	 * a generic delay loop, machine_hang(), so simply return.
51 	 */
52 	return;
53 }
54 
55 static void loongson_halt(void)
56 {
57 	pr_notice("\n\n** You can safely turn off the power now **\n\n");
58 	while (1) {
59 		if (cpu_wait)
60 			cpu_wait();
61 	}
62 }
63 
64 static int __init mips_reboot_setup(void)
65 {
66 	_machine_restart = loongson_restart;
67 	_machine_halt = loongson_halt;
68 	pm_power_off = loongson_poweroff;
69 
70 	return 0;
71 }
72 
73 arch_initcall(mips_reboot_setup);
74