1 /* 2 * Driver for keys on GPIO lines capable of generating interrupts. 3 * 4 * Copyright 2005 Phil Blundell 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/module.h> 12 #include <linux/version.h> 13 14 #include <linux/init.h> 15 #include <linux/fs.h> 16 #include <linux/interrupt.h> 17 #include <linux/irq.h> 18 #include <linux/sched.h> 19 #include <linux/pm.h> 20 #include <linux/sysctl.h> 21 #include <linux/proc_fs.h> 22 #include <linux/delay.h> 23 #include <linux/platform_device.h> 24 #include <linux/input.h> 25 #include <linux/irq.h> 26 27 #include <asm/arch/pxa-regs.h> 28 #include <asm/arch/hardware.h> 29 30 #include <asm/hardware/gpio_keys.h> 31 32 static irqreturn_t gpio_keys_isr(int irq, void *dev_id) 33 { 34 int i; 35 struct platform_device *pdev = dev_id; 36 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 37 struct input_dev *input = platform_get_drvdata(pdev); 38 39 for (i = 0; i < pdata->nbuttons; i++) { 40 int gpio = pdata->buttons[i].gpio; 41 if (irq == IRQ_GPIO(gpio)) { 42 int state = ((GPLR(gpio) & GPIO_bit(gpio)) ? 1 : 0) ^ (pdata->buttons[i].active_low); 43 44 input_report_key(input, pdata->buttons[i].keycode, state); 45 input_sync(input); 46 } 47 } 48 49 return IRQ_HANDLED; 50 } 51 52 static int __devinit gpio_keys_probe(struct platform_device *pdev) 53 { 54 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 55 struct input_dev *input; 56 int i, error; 57 58 input = input_allocate_device(); 59 if (!input) 60 return -ENOMEM; 61 62 platform_set_drvdata(pdev, input); 63 64 input->evbit[0] = BIT(EV_KEY); 65 66 input->name = pdev->name; 67 input->phys = "gpio-keys/input0"; 68 input->cdev.dev = &pdev->dev; 69 input->private = pdata; 70 71 input->id.bustype = BUS_HOST; 72 input->id.vendor = 0x0001; 73 input->id.product = 0x0001; 74 input->id.version = 0x0100; 75 76 for (i = 0; i < pdata->nbuttons; i++) { 77 int code = pdata->buttons[i].keycode; 78 int irq = IRQ_GPIO(pdata->buttons[i].gpio); 79 80 set_irq_type(irq, IRQ_TYPE_EDGE_BOTH); 81 error = request_irq(irq, gpio_keys_isr, SA_SAMPLE_RANDOM, 82 pdata->buttons[i].desc ? pdata->buttons[i].desc : "gpio_keys", 83 pdev); 84 if (error) { 85 printk(KERN_ERR "gpio-keys: unable to claim irq %d; error %d\n", irq, ret); 86 goto fail; 87 } 88 set_bit(code, input->keybit); 89 } 90 91 error = input_register_device(input); 92 if (error) { 93 printk(KERN_ERR "Unable to register gpio-keys input device\n"); 94 goto fail; 95 } 96 97 return 0; 98 99 fail: 100 for (i = i - 1; i >= 0; i--) 101 free_irq(IRQ_GPIO(pdata->buttons[i].gpio), pdev); 102 103 input_free_device(input); 104 105 return error; 106 } 107 108 static int __devexit gpio_keys_remove(struct platform_device *pdev) 109 { 110 struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; 111 struct input_dev *input = platform_get_drvdata(pdev); 112 int i; 113 114 for (i = 0; i < pdata->nbuttons; i++) { 115 int irq = IRQ_GPIO(pdata->buttons[i].gpio); 116 free_irq(irq, pdev); 117 } 118 119 input_unregister_device(input); 120 121 return 0; 122 } 123 124 struct platform_driver gpio_keys_device_driver = { 125 .probe = gpio_keys_probe, 126 .remove = __devexit_p(gpio_keys_remove), 127 .driver = { 128 .name = "gpio-keys", 129 } 130 }; 131 132 static int __init gpio_keys_init(void) 133 { 134 return platform_driver_register(&gpio_keys_device_driver); 135 } 136 137 static void __exit gpio_keys_exit(void) 138 { 139 platform_driver_unregister(&gpio_keys_device_driver); 140 } 141 142 module_init(gpio_keys_init); 143 module_exit(gpio_keys_exit); 144 145 MODULE_LICENSE("GPL"); 146 MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); 147 MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); 148