18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology 58c2ecf20Sopenharmony_ci * Author: Fuxin Zhang, zhangfx@lemote.com 68c2ecf20Sopenharmony_ci * Copyright (C) 2009 Lemote, Inc. 78c2ecf20Sopenharmony_ci * Author: Zhangjin Wu, wuzhangjin@gmail.com 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/pm.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/idle.h> 138c2ecf20Sopenharmony_ci#include <asm/reboot.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <loongson.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic inline void loongson_reboot(void) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci#ifndef CONFIG_CPU_JUMP_WORKAROUNDS 208c2ecf20Sopenharmony_ci ((void (*)(void))ioremap(LOONGSON_BOOT_BASE, 4)) (); 218c2ecf20Sopenharmony_ci#else 228c2ecf20Sopenharmony_ci void (*func)(void); 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci func = (void *)ioremap(LOONGSON_BOOT_BASE, 4); 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci __asm__ __volatile__( 278c2ecf20Sopenharmony_ci " .set noat \n" 288c2ecf20Sopenharmony_ci " jr %[func] \n" 298c2ecf20Sopenharmony_ci " .set at \n" 308c2ecf20Sopenharmony_ci : /* No outputs */ 318c2ecf20Sopenharmony_ci : [func] "r" (func)); 328c2ecf20Sopenharmony_ci#endif 338c2ecf20Sopenharmony_ci} 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic void loongson_restart(char *command) 368c2ecf20Sopenharmony_ci{ 378c2ecf20Sopenharmony_ci /* do preparation for reboot */ 388c2ecf20Sopenharmony_ci mach_prepare_reboot(); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* reboot via jumping to boot base address */ 418c2ecf20Sopenharmony_ci loongson_reboot(); 428c2ecf20Sopenharmony_ci} 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic void loongson_poweroff(void) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci mach_prepare_shutdown(); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* 498c2ecf20Sopenharmony_ci * It needs a wait loop here, but mips/kernel/reset.c already calls 508c2ecf20Sopenharmony_ci * a generic delay loop, machine_hang(), so simply return. 518c2ecf20Sopenharmony_ci */ 528c2ecf20Sopenharmony_ci return; 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic void loongson_halt(void) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci pr_notice("\n\n** You can safely turn off the power now **\n\n"); 588c2ecf20Sopenharmony_ci while (1) { 598c2ecf20Sopenharmony_ci if (cpu_wait) 608c2ecf20Sopenharmony_ci cpu_wait(); 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic int __init mips_reboot_setup(void) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci _machine_restart = loongson_restart; 678c2ecf20Sopenharmony_ci _machine_halt = loongson_halt; 688c2ecf20Sopenharmony_ci pm_power_off = loongson_poweroff; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return 0; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ciarch_initcall(mips_reboot_setup); 74