| 
									
										
										
										
											2007-07-11 18:18:04 -07:00
										 |  |  | /* power.c: Power management driver.
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2008-08-30 01:18:56 -07:00
										 |  |  |  * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							| 
									
										
										
										
											2011-07-22 13:18:16 -04:00
										 |  |  | #include <linux/export.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | #include <linux/init.h>
 | 
					
						
							|  |  |  | #include <linux/interrupt.h>
 | 
					
						
							| 
									
										
										
										
											2007-07-18 13:12:45 -07:00
										 |  |  | #include <linux/reboot.h>
 | 
					
						
							| 
									
										
										
										
											2008-08-07 15:33:36 -07:00
										 |  |  | #include <linux/of_device.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-29 15:22:46 -07:00
										 |  |  | #include <asm/prom.h>
 | 
					
						
							|  |  |  | #include <asm/io.h>
 | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void __iomem *power_reg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-11 18:18:04 -07:00
										 |  |  | static irqreturn_t power_handler(int irq, void *dev_id) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2007-07-18 13:12:45 -07:00
										 |  |  | 	orderly_poweroff(true); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* FIXME: Check registers for status... */ | 
					
						
							|  |  |  | 	return IRQ_HANDLED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-21 14:03:26 -08:00
										 |  |  | static int has_button_interrupt(unsigned int irq, struct device_node *dp) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-07-11 18:18:04 -07:00
										 |  |  | 	if (irq == 0xffffffff) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2006-06-22 19:12:03 -07:00
										 |  |  | 	if (!of_find_property(dp, "button", NULL)) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-21 14:03:26 -08:00
										 |  |  | static int power_probe(struct platform_device *op) | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-06-29 15:22:46 -07:00
										 |  |  | 	struct resource *res = &op->resource[0]; | 
					
						
							| 
									
										
										
										
											2010-06-18 11:09:58 -06:00
										 |  |  | 	unsigned int irq = op->archdata.irqs[0]; | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-29 15:22:46 -07:00
										 |  |  | 	power_reg = of_ioremap(res, 0, 0x4, "power"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-06 13:19:28 -08:00
										 |  |  | 	printk(KERN_INFO "%s: Control reg at %llx\n", | 
					
						
							| 
									
										
										
										
											2010-04-13 16:12:29 -07:00
										 |  |  | 	       op->dev.of_node->name, res->start); | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-13 16:12:29 -07:00
										 |  |  | 	if (has_button_interrupt(irq, op->dev.of_node)) { | 
					
						
							| 
									
										
										
										
											2005-10-06 20:43:54 -07:00
										 |  |  | 		if (request_irq(irq, | 
					
						
							| 
									
										
										
										
											2006-06-29 14:39:11 -07:00
										 |  |  | 				power_handler, 0, "power", NULL) < 0) | 
					
						
							| 
									
										
										
										
											2007-07-11 18:18:04 -07:00
										 |  |  | 			printk(KERN_ERR "power: Cannot setup IRQ handler.\n"); | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-06-29 15:22:46 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2005-04-16 15:20:36 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-30 17:37:56 -07:00
										 |  |  | static const struct of_device_id power_match[] = { | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		.name = "power", | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	{}, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-22 20:01:33 -07:00
										 |  |  | static struct platform_driver power_driver = { | 
					
						
							| 
									
										
										
										
											2006-06-29 15:22:46 -07:00
										 |  |  | 	.probe		= power_probe, | 
					
						
							| 
									
										
										
										
											2010-04-13 16:13:02 -07:00
										 |  |  | 	.driver = { | 
					
						
							|  |  |  | 		.name = "power", | 
					
						
							|  |  |  | 		.owner = THIS_MODULE, | 
					
						
							|  |  |  | 		.of_match_table = power_match, | 
					
						
							| 
									
										
										
										
											2007-10-10 23:27:34 -07:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-30 01:18:56 -07:00
										 |  |  | static int __init power_init(void) | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-02-22 20:01:33 -07:00
										 |  |  | 	return platform_driver_register(&power_driver); | 
					
						
							| 
									
										
										
										
											2006-06-23 01:44:10 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-08-30 01:18:56 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | device_initcall(power_init); |