1 /* 2 * driver for powerbutton on IBM cell blades 3 * 4 * (C) Copyright IBM Corp. 2005-2008 5 * 6 * Author: Christian Krafft <krafft@de.ibm.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2, or (at your option) 11 * any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 #include <linux/input.h> 24 #include <linux/platform_device.h> 25 #include <asm/pmi.h> 26 #include <asm/prom.h> 27 28 static struct input_dev *button_dev; 29 static struct platform_device *button_pdev; 30 31 static void cbe_powerbutton_handle_pmi(pmi_message_t pmi_msg) 32 { 33 BUG_ON(pmi_msg.type != PMI_TYPE_POWER_BUTTON); 34 35 input_report_key(button_dev, KEY_POWER, 1); 36 input_sync(button_dev); 37 input_report_key(button_dev, KEY_POWER, 0); 38 input_sync(button_dev); 39 } 40 41 static struct pmi_handler cbe_pmi_handler = { 42 .type = PMI_TYPE_POWER_BUTTON, 43 .handle_pmi_message = cbe_powerbutton_handle_pmi, 44 }; 45 46 static int __init cbe_powerbutton_init(void) 47 { 48 int ret = 0; 49 struct input_dev *dev; 50 51 if (!machine_is_compatible("IBM,CBPLUS-1.0")) { 52 printk(KERN_ERR "%s: Not a cell blade.\n", __func__); 53 ret = -ENODEV; 54 goto out; 55 } 56 57 dev = input_allocate_device(); 58 if (!dev) { 59 ret = -ENOMEM; 60 printk(KERN_ERR "%s: Not enough memory.\n", __func__); 61 goto out; 62 } 63 64 set_bit(EV_KEY, dev->evbit); 65 set_bit(KEY_POWER, dev->keybit); 66 67 dev->name = "Power Button"; 68 dev->id.bustype = BUS_HOST; 69 70 /* this makes the button look like an acpi power button 71 * no clue whether anyone relies on that though */ 72 dev->id.product = 0x02; 73 dev->phys = "LNXPWRBN/button/input0"; 74 75 button_pdev = platform_device_register_simple("power_button", 0, NULL, 0); 76 if (IS_ERR(button_pdev)) { 77 ret = PTR_ERR(button_pdev); 78 goto out_free_input; 79 } 80 81 dev->dev.parent = &button_pdev->dev; 82 ret = input_register_device(dev); 83 if (ret) { 84 printk(KERN_ERR "%s: Failed to register device\n", __func__); 85 goto out_free_pdev; 86 } 87 88 button_dev = dev; 89 90 ret = pmi_register_handler(&cbe_pmi_handler); 91 if (ret) { 92 printk(KERN_ERR "%s: Failed to register with pmi.\n", __func__); 93 goto out_free_pdev; 94 } 95 96 goto out; 97 98 out_free_pdev: 99 platform_device_unregister(button_pdev); 100 out_free_input: 101 input_free_device(dev); 102 out: 103 return ret; 104 } 105 106 static void __exit cbe_powerbutton_exit(void) 107 { 108 pmi_unregister_handler(&cbe_pmi_handler); 109 platform_device_unregister(button_pdev); 110 input_free_device(button_dev); 111 } 112 113 module_init(cbe_powerbutton_init); 114 module_exit(cbe_powerbutton_exit); 115 116 MODULE_LICENSE("GPL"); 117 MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); 118