root/drivers/input/misc/88pm860x_onkey.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pm860x_onkey_handler
  2. pm860x_onkey_probe
  3. pm860x_onkey_suspend
  4. pm860x_onkey_resume

   1 /*
   2  * 88pm860x_onkey.c - Marvell 88PM860x ONKEY driver
   3  *
   4  * Copyright (C) 2009-2010 Marvell International Ltd.
   5  *      Haojian Zhuang <haojian.zhuang@marvell.com>
   6  *
   7  * This file is subject to the terms and conditions of the GNU General
   8  * Public License. See the file "COPYING" in the main directory of this
   9  * archive for more details.
  10  *
  11  * This program is distributed in the hope that it will be useful,
  12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  * GNU General Public License for more details.
  15  *
  16  * You should have received a copy of the GNU General Public License
  17  * along with this program; if not, write to the Free Software
  18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19  */
  20 
  21 #include <linux/kernel.h>
  22 #include <linux/module.h>
  23 #include <linux/platform_device.h>
  24 #include <linux/i2c.h>
  25 #include <linux/input.h>
  26 #include <linux/interrupt.h>
  27 #include <linux/mfd/88pm860x.h>
  28 #include <linux/slab.h>
  29 #include <linux/device.h>
  30 
  31 #define PM8607_WAKEUP           0x0b
  32 
  33 #define LONG_ONKEY_EN           (1 << 1)
  34 #define ONKEY_STATUS            (1 << 0)
  35 
  36 struct pm860x_onkey_info {
  37         struct input_dev        *idev;
  38         struct pm860x_chip      *chip;
  39         struct i2c_client       *i2c;
  40         struct device           *dev;
  41         int                     irq;
  42 };
  43 
  44 /* 88PM860x gives us an interrupt when ONKEY is held */
  45 static irqreturn_t pm860x_onkey_handler(int irq, void *data)
  46 {
  47         struct pm860x_onkey_info *info = data;
  48         int ret;
  49 
  50         ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
  51         ret &= ONKEY_STATUS;
  52         input_report_key(info->idev, KEY_POWER, ret);
  53         input_sync(info->idev);
  54 
  55         /* Enable 8-second long onkey detection */
  56         pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
  57         return IRQ_HANDLED;
  58 }
  59 
  60 static int pm860x_onkey_probe(struct platform_device *pdev)
  61 {
  62         struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
  63         struct pm860x_onkey_info *info;
  64         int irq, ret;
  65 
  66         irq = platform_get_irq(pdev, 0);
  67         if (irq < 0)
  68                 return -EINVAL;
  69 
  70         info = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_onkey_info),
  71                             GFP_KERNEL);
  72         if (!info)
  73                 return -ENOMEM;
  74         info->chip = chip;
  75         info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
  76         info->dev = &pdev->dev;
  77         info->irq = irq;
  78 
  79         info->idev = devm_input_allocate_device(&pdev->dev);
  80         if (!info->idev) {
  81                 dev_err(chip->dev, "Failed to allocate input dev\n");
  82                 return -ENOMEM;
  83         }
  84 
  85         info->idev->name = "88pm860x_on";
  86         info->idev->phys = "88pm860x_on/input0";
  87         info->idev->id.bustype = BUS_I2C;
  88         info->idev->dev.parent = &pdev->dev;
  89         info->idev->evbit[0] = BIT_MASK(EV_KEY);
  90         info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
  91 
  92         ret = input_register_device(info->idev);
  93         if (ret) {
  94                 dev_err(chip->dev, "Can't register input device: %d\n", ret);
  95                 return ret;
  96         }
  97 
  98         ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
  99                                         pm860x_onkey_handler, IRQF_ONESHOT,
 100                                         "onkey", info);
 101         if (ret < 0) {
 102                 dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
 103                         info->irq, ret);
 104                 return ret;
 105         }
 106 
 107         platform_set_drvdata(pdev, info);
 108         device_init_wakeup(&pdev->dev, 1);
 109 
 110         return 0;
 111 }
 112 
 113 static int __maybe_unused pm860x_onkey_suspend(struct device *dev)
 114 {
 115         struct platform_device *pdev = to_platform_device(dev);
 116         struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 117 
 118         if (device_may_wakeup(dev))
 119                 chip->wakeup_flag |= 1 << PM8607_IRQ_ONKEY;
 120         return 0;
 121 }
 122 static int __maybe_unused pm860x_onkey_resume(struct device *dev)
 123 {
 124         struct platform_device *pdev = to_platform_device(dev);
 125         struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
 126 
 127         if (device_may_wakeup(dev))
 128                 chip->wakeup_flag &= ~(1 << PM8607_IRQ_ONKEY);
 129         return 0;
 130 }
 131 
 132 static SIMPLE_DEV_PM_OPS(pm860x_onkey_pm_ops, pm860x_onkey_suspend, pm860x_onkey_resume);
 133 
 134 static struct platform_driver pm860x_onkey_driver = {
 135         .driver         = {
 136                 .name   = "88pm860x-onkey",
 137                 .pm     = &pm860x_onkey_pm_ops,
 138         },
 139         .probe          = pm860x_onkey_probe,
 140 };
 141 module_platform_driver(pm860x_onkey_driver);
 142 
 143 MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver");
 144 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
 145 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */