Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: add support for PowerOn button on the AB8500 MFD

Add the PowerOn (PonKey) button support to detect power on/off events.

Acked-by: Linus Walleij <linus.walleij@stericsson.com>
Signed-off-by: Sundar R Iyer <sundar.iyer@stericsson.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Sundar R Iyer and committed by
Dmitry Torokhov
77686517 144c0f88

+188
+10
drivers/input/misc/Kconfig
··· 22 22 To compile this driver as a module, choose M here: the module 23 23 will be called 88pm860x_onkey. 24 24 25 + config INPUT_AB8500_PONKEY 26 + tristate "AB8500 Pon (PowerOn) Key" 27 + depends on AB8500_CORE 28 + help 29 + Say Y here to use the PowerOn Key for ST-Ericsson's AB8500 30 + Mix-Sig PMIC. 31 + 32 + To compile this driver as a module, choose M here: the module 33 + will be called ab8500-ponkey. 34 + 25 35 config INPUT_AD714X 26 36 tristate "Analog Devices AD714x Capacitance Touch Sensor" 27 37 help
+1
drivers/input/misc/Makefile
··· 5 5 # Each configuration option enables a list of files. 6 6 7 7 obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o 8 + obj-$(CONFIG_INPUT_AB8500_PONKEY) += ab8500-ponkey.o 8 9 obj-$(CONFIG_INPUT_AD714X) += ad714x.o 9 10 obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o 10 11 obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o
+157
drivers/input/misc/ab8500-ponkey.c
··· 1 + /* 2 + * Copyright (C) ST-Ericsson SA 2010 3 + * 4 + * License Terms: GNU General Public License v2 5 + * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson 6 + * 7 + * AB8500 Power-On Key handler 8 + */ 9 + 10 + #include <linux/kernel.h> 11 + #include <linux/module.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/input.h> 14 + #include <linux/interrupt.h> 15 + #include <linux/mfd/ab8500.h> 16 + #include <linux/slab.h> 17 + 18 + /** 19 + * struct ab8500_ponkey - ab8500 ponkey information 20 + * @input_dev: pointer to input device 21 + * @ab8500: ab8500 parent 22 + * @irq_dbf: irq number for falling transition 23 + * @irq_dbr: irq number for rising transition 24 + */ 25 + struct ab8500_ponkey { 26 + struct input_dev *idev; 27 + struct ab8500 *ab8500; 28 + int irq_dbf; 29 + int irq_dbr; 30 + }; 31 + 32 + /* AB8500 gives us an interrupt when ONKEY is held */ 33 + static irqreturn_t ab8500_ponkey_handler(int irq, void *data) 34 + { 35 + struct ab8500_ponkey *ponkey = data; 36 + 37 + if (irq == ponkey->irq_dbf) 38 + input_report_key(ponkey->idev, KEY_POWER, true); 39 + else if (irq == ponkey->irq_dbr) 40 + input_report_key(ponkey->idev, KEY_POWER, false); 41 + 42 + input_sync(ponkey->idev); 43 + 44 + return IRQ_HANDLED; 45 + } 46 + 47 + static int __devinit ab8500_ponkey_probe(struct platform_device *pdev) 48 + { 49 + struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); 50 + struct ab8500_ponkey *ponkey; 51 + struct input_dev *input; 52 + int irq_dbf, irq_dbr; 53 + int error; 54 + 55 + irq_dbf = platform_get_irq_byname(pdev, "ONKEY_DBF"); 56 + if (irq_dbf < 0) { 57 + dev_err(&pdev->dev, "No IRQ for ONKEY_DBF, error=%d\n", irq_dbf); 58 + return irq_dbf; 59 + } 60 + 61 + irq_dbr = platform_get_irq_byname(pdev, "ONKEY_DBR"); 62 + if (irq_dbr < 0) { 63 + dev_err(&pdev->dev, "No IRQ for ONKEY_DBR, error=%d\n", irq_dbr); 64 + return irq_dbr; 65 + } 66 + 67 + ponkey = kzalloc(sizeof(struct ab8500_ponkey), GFP_KERNEL); 68 + input = input_allocate_device(); 69 + if (!ponkey || !input) { 70 + error = -ENOMEM; 71 + goto err_free_mem; 72 + } 73 + 74 + ponkey->idev = input; 75 + ponkey->ab8500 = ab8500; 76 + ponkey->irq_dbf = irq_dbf; 77 + ponkey->irq_dbr = irq_dbr; 78 + 79 + input->name = "AB8500 POn(PowerOn) Key"; 80 + input->dev.parent = &pdev->dev; 81 + 82 + input_set_capability(input, EV_KEY, KEY_POWER); 83 + 84 + error = request_any_context_irq(ponkey->irq_dbf, ab8500_ponkey_handler, 85 + 0, "ab8500-ponkey-dbf", ponkey); 86 + if (error < 0) { 87 + dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n", 88 + ponkey->irq_dbf, error); 89 + goto err_free_mem; 90 + } 91 + 92 + error = request_any_context_irq(ponkey->irq_dbr, ab8500_ponkey_handler, 93 + 0, "ab8500-ponkey-dbr", ponkey); 94 + if (error < 0) { 95 + dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n", 96 + ponkey->irq_dbr, error); 97 + goto err_free_dbf_irq; 98 + } 99 + 100 + error = input_register_device(ponkey->idev); 101 + if (error) { 102 + dev_err(ab8500->dev, "Can't register input device: %d\n", error); 103 + goto err_free_dbr_irq; 104 + } 105 + 106 + platform_set_drvdata(pdev, ponkey); 107 + return 0; 108 + 109 + err_free_dbr_irq: 110 + free_irq(ponkey->irq_dbf, ponkey); 111 + err_free_dbf_irq: 112 + free_irq(ponkey->irq_dbf, ponkey); 113 + err_free_mem: 114 + input_free_device(input); 115 + kfree(ponkey); 116 + 117 + return error; 118 + } 119 + 120 + static int __devexit ab8500_ponkey_remove(struct platform_device *pdev) 121 + { 122 + struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev); 123 + 124 + free_irq(ponkey->irq_dbf, ponkey); 125 + free_irq(ponkey->irq_dbr, ponkey); 126 + input_unregister_device(ponkey->idev); 127 + kfree(ponkey); 128 + 129 + platform_set_drvdata(pdev, NULL); 130 + 131 + return 0; 132 + } 133 + 134 + static struct platform_driver ab8500_ponkey_driver = { 135 + .driver = { 136 + .name = "ab8500-poweron-key", 137 + .owner = THIS_MODULE, 138 + }, 139 + .probe = ab8500_ponkey_probe, 140 + .remove = __devexit_p(ab8500_ponkey_remove), 141 + }; 142 + 143 + static int __init ab8500_ponkey_init(void) 144 + { 145 + return platform_driver_register(&ab8500_ponkey_driver); 146 + } 147 + module_init(ab8500_ponkey_init); 148 + 149 + static void __exit ab8500_ponkey_exit(void) 150 + { 151 + platform_driver_unregister(&ab8500_ponkey_driver); 152 + } 153 + module_exit(ab8500_ponkey_exit); 154 + 155 + MODULE_LICENSE("GPL v2"); 156 + MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>"); 157 + MODULE_DESCRIPTION("ST-Ericsson AB8500 Power-ON(Pon) Key driver");
+20
drivers/mfd/ab8500-core.c
··· 338 338 }, 339 339 }; 340 340 341 + static struct resource ab8500_poweronkey_db_resources[] = { 342 + { 343 + .name = "ONKEY_DBF", 344 + .start = AB8500_INT_PON_KEY1DB_F, 345 + .end = AB8500_INT_PON_KEY1DB_F, 346 + .flags = IORESOURCE_IRQ, 347 + }, 348 + { 349 + .name = "ONKEY_DBR", 350 + .start = AB8500_INT_PON_KEY1DB_R, 351 + .end = AB8500_INT_PON_KEY1DB_R, 352 + .flags = IORESOURCE_IRQ, 353 + }, 354 + }; 355 + 341 356 static struct mfd_cell ab8500_devs[] = { 342 357 { 343 358 .name = "ab8500-gpadc", ··· 369 354 { .name = "ab8500-usb", }, 370 355 { .name = "ab8500-pwm", }, 371 356 { .name = "ab8500-regulator", }, 357 + { 358 + .name = "ab8500-poweron-key", 359 + .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources), 360 + .resources = ab8500_poweronkey_db_resources, 361 + }, 372 362 }; 373 363 374 364 int __devinit ab8500_init(struct ab8500 *ab8500)