1 /* 2 * PowerNV OPAL power control for graceful shutdown handling 3 * 4 * Copyright 2015 IBM Corp. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/kernel.h> 13 #include <linux/reboot.h> 14 #include <linux/notifier.h> 15 16 #include <asm/opal.h> 17 #include <asm/machdep.h> 18 19 #define SOFT_OFF 0x00 20 #define SOFT_REBOOT 0x01 21 22 static int opal_power_control_event(struct notifier_block *nb, 23 unsigned long msg_type, void *msg) 24 { 25 struct opal_msg *power_msg = msg; 26 uint64_t type; 27 28 type = be64_to_cpu(power_msg->params[0]); 29 30 switch (type) { 31 case SOFT_REBOOT: 32 pr_info("OPAL: reboot requested\n"); 33 orderly_reboot(); 34 break; 35 case SOFT_OFF: 36 pr_info("OPAL: poweroff requested\n"); 37 orderly_poweroff(true); 38 break; 39 default: 40 pr_err("OPAL: power control type unexpected %016llx\n", type); 41 } 42 43 return 0; 44 } 45 46 static struct notifier_block opal_power_control_nb = { 47 .notifier_call = opal_power_control_event, 48 .next = NULL, 49 .priority = 0, 50 }; 51 52 static int __init opal_power_control_init(void) 53 { 54 int ret; 55 56 ret = opal_message_notifier_register(OPAL_MSG_SHUTDOWN, 57 &opal_power_control_nb); 58 if (ret) { 59 pr_err("%s: Can't register OPAL event notifier (%d)\n", 60 __func__, ret); 61 return ret; 62 } 63 64 return 0; 65 } 66 machine_subsys_initcall(powernv, opal_power_control_init); 67