66 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			66 lines
		
	
	
	
		
			1.5 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /*
 | ||
|  |  * PowerNV OPAL power control for graceful shutdown handling | ||
|  |  * | ||
|  |  * Copyright 2015 IBM Corp. | ||
|  |  * | ||
|  |  * This program is free software; you can redistribute it and/or | ||
|  |  * modify it under the terms of the GNU General Public License | ||
|  |  * as published by the Free Software Foundation; either version | ||
|  |  * 2 of the License, or (at your option) any later version. | ||
|  |  */ | ||
|  | 
 | ||
|  | #include <linux/kernel.h>
 | ||
|  | #include <linux/reboot.h>
 | ||
|  | #include <linux/notifier.h>
 | ||
|  | 
 | ||
|  | #include <asm/opal.h>
 | ||
|  | #include <asm/machdep.h>
 | ||
|  | 
 | ||
|  | #define SOFT_OFF 0x00
 | ||
|  | #define SOFT_REBOOT 0x01
 | ||
|  | 
 | ||
|  | static int opal_power_control_event(struct notifier_block *nb, | ||
|  | 				    unsigned long msg_type, void *msg) | ||
|  | { | ||
|  | 	struct opal_msg *power_msg = msg; | ||
|  | 	uint64_t type; | ||
|  | 
 | ||
|  | 	type = be64_to_cpu(power_msg->params[0]); | ||
|  | 
 | ||
|  | 	switch (type) { | ||
|  | 	case SOFT_REBOOT: | ||
|  | 		/* Fall through. The service processor is responsible for
 | ||
|  | 		 * bringing the machine back up */ | ||
|  | 	case SOFT_OFF: | ||
|  | 		pr_info("OPAL: poweroff requested\n"); | ||
|  | 		orderly_poweroff(true); | ||
|  | 		break; | ||
|  | 	default: | ||
|  | 		pr_err("OPAL: power control type unexpected %016llx\n", type); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } | ||
|  | 
 | ||
|  | static struct notifier_block opal_power_control_nb = { | ||
|  | 	.notifier_call	= opal_power_control_event, | ||
|  | 	.next		= NULL, | ||
|  | 	.priority	= 0, | ||
|  | }; | ||
|  | 
 | ||
|  | static int __init opal_power_control_init(void) | ||
|  | { | ||
|  | 	int ret; | ||
|  | 
 | ||
|  | 	ret = opal_message_notifier_register(OPAL_MSG_SHUTDOWN, | ||
|  | 					     &opal_power_control_nb); | ||
|  | 	if (ret) { | ||
|  | 		pr_err("%s: Can't register OPAL event notifier (%d)\n", | ||
|  | 				__func__, ret); | ||
|  | 		return ret; | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return 0; | ||
|  | } | ||
|  | machine_subsys_initcall(powernv, opal_power_control_init); |