Commit 77686517977e77d101c8a7b397717df00a88922b

Authored by Sundar R Iyer
Committed by Dmitry Torokhov
1 parent 144c0f8833

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>

Showing 4 changed files with 188 additions and 0 deletions Side-by-side Diff

drivers/input/misc/Kconfig
... ... @@ -22,6 +22,16 @@
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
drivers/input/misc/Makefile
... ... @@ -5,6 +5,7 @@
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
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");
drivers/mfd/ab8500-core.c
... ... @@ -338,6 +338,21 @@
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",
... ... @@ -354,6 +369,11 @@
354 369 { .name = "ab8500-usb", },
355 370 { .name = "ab8500-pwm", },
356 371 { .name = "ab8500-regulator", },
  372 + {
  373 + .name = "ab8500-poweron-key",
  374 + .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
  375 + .resources = ab8500_poweronkey_db_resources,
  376 + },
357 377 };
358 378  
359 379 int __devinit ab8500_init(struct ab8500 *ab8500)