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

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

DEFINITIONS

This source file includes following definitions.
  1. pm80x_onkey_handler
  2. pm80x_onkey_probe
  3. pm80x_onkey_remove

   1 /*
   2  * Marvell 88PM80x ONKEY driver
   3  *
   4  * Copyright (C) 2012 Marvell International Ltd.
   5  * Haojian Zhuang <haojian.zhuang@marvell.com>
   6  * Qiao Zhou <zhouqiao@marvell.com>
   7  *
   8  * This file is subject to the terms and conditions of the GNU General
   9  * Public License. See the file "COPYING" in the main directory of this
  10  * archive for more details.
  11  *
  12  * This program is distributed in the hope that it will be useful,
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  * GNU General Public License for more details.
  16  *
  17  * You should have received a copy of the GNU General Public License
  18  * along with this program; if not, write to the Free Software
  19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20  */
  21 
  22 #include <linux/kernel.h>
  23 #include <linux/module.h>
  24 #include <linux/input.h>
  25 #include <linux/mfd/88pm80x.h>
  26 #include <linux/regmap.h>
  27 #include <linux/slab.h>
  28 
  29 #define PM800_LONG_ONKEY_EN             (1 << 0)
  30 #define PM800_LONG_KEY_DELAY            (8)     /* 1 .. 16 seconds */
  31 #define PM800_LONKEY_PRESS_TIME         ((PM800_LONG_KEY_DELAY-1) << 4)
  32 #define PM800_LONKEY_PRESS_TIME_MASK    (0xF0)
  33 #define PM800_SW_PDOWN                  (1 << 5)
  34 
  35 struct pm80x_onkey_info {
  36         struct input_dev *idev;
  37         struct pm80x_chip *pm80x;
  38         struct regmap *map;
  39         int irq;
  40 };
  41 
  42 /* 88PM80x gives us an interrupt when ONKEY is held */
  43 static irqreturn_t pm80x_onkey_handler(int irq, void *data)
  44 {
  45         struct pm80x_onkey_info *info = data;
  46         int ret = 0;
  47         unsigned int val;
  48 
  49         ret = regmap_read(info->map, PM800_STATUS_1, &val);
  50         if (ret < 0) {
  51                 dev_err(info->idev->dev.parent, "failed to read status: %d\n", ret);
  52                 return IRQ_NONE;
  53         }
  54         val &= PM800_ONKEY_STS1;
  55 
  56         input_report_key(info->idev, KEY_POWER, val);
  57         input_sync(info->idev);
  58 
  59         return IRQ_HANDLED;
  60 }
  61 
  62 static SIMPLE_DEV_PM_OPS(pm80x_onkey_pm_ops, pm80x_dev_suspend,
  63                          pm80x_dev_resume);
  64 
  65 static int pm80x_onkey_probe(struct platform_device *pdev)
  66 {
  67 
  68         struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
  69         struct pm80x_onkey_info *info;
  70         int err;
  71 
  72         info = kzalloc(sizeof(struct pm80x_onkey_info), GFP_KERNEL);
  73         if (!info)
  74                 return -ENOMEM;
  75 
  76         info->pm80x = chip;
  77 
  78         info->irq = platform_get_irq(pdev, 0);
  79         if (info->irq < 0) {
  80                 err = -EINVAL;
  81                 goto out;
  82         }
  83 
  84         info->map = info->pm80x->regmap;
  85         if (!info->map) {
  86                 dev_err(&pdev->dev, "no regmap!\n");
  87                 err = -EINVAL;
  88                 goto out;
  89         }
  90 
  91         info->idev = input_allocate_device();
  92         if (!info->idev) {
  93                 dev_err(&pdev->dev, "Failed to allocate input dev\n");
  94                 err = -ENOMEM;
  95                 goto out;
  96         }
  97 
  98         info->idev->name = "88pm80x_on";
  99         info->idev->phys = "88pm80x_on/input0";
 100         info->idev->id.bustype = BUS_I2C;
 101         info->idev->dev.parent = &pdev->dev;
 102         info->idev->evbit[0] = BIT_MASK(EV_KEY);
 103         __set_bit(KEY_POWER, info->idev->keybit);
 104 
 105         err = pm80x_request_irq(info->pm80x, info->irq, pm80x_onkey_handler,
 106                                             IRQF_ONESHOT, "onkey", info);
 107         if (err < 0) {
 108                 dev_err(&pdev->dev, "Failed to request IRQ: #%d: %d\n",
 109                         info->irq, err);
 110                 goto out_reg;
 111         }
 112 
 113         err = input_register_device(info->idev);
 114         if (err) {
 115                 dev_err(&pdev->dev, "Can't register input device: %d\n", err);
 116                 goto out_irq;
 117         }
 118 
 119         platform_set_drvdata(pdev, info);
 120 
 121         /* Enable long onkey detection */
 122         regmap_update_bits(info->map, PM800_RTC_MISC4, PM800_LONG_ONKEY_EN,
 123                            PM800_LONG_ONKEY_EN);
 124         /* Set 8-second interval */
 125         regmap_update_bits(info->map, PM800_RTC_MISC3,
 126                            PM800_LONKEY_PRESS_TIME_MASK,
 127                            PM800_LONKEY_PRESS_TIME);
 128 
 129         device_init_wakeup(&pdev->dev, 1);
 130         return 0;
 131 
 132 out_irq:
 133         pm80x_free_irq(info->pm80x, info->irq, info);
 134 out_reg:
 135         input_free_device(info->idev);
 136 out:
 137         kfree(info);
 138         return err;
 139 }
 140 
 141 static int pm80x_onkey_remove(struct platform_device *pdev)
 142 {
 143         struct pm80x_onkey_info *info = platform_get_drvdata(pdev);
 144 
 145         pm80x_free_irq(info->pm80x, info->irq, info);
 146         input_unregister_device(info->idev);
 147         kfree(info);
 148         return 0;
 149 }
 150 
 151 static struct platform_driver pm80x_onkey_driver = {
 152         .driver = {
 153                    .name = "88pm80x-onkey",
 154                    .pm = &pm80x_onkey_pm_ops,
 155                    },
 156         .probe = pm80x_onkey_probe,
 157         .remove = pm80x_onkey_remove,
 158 };
 159 
 160 module_platform_driver(pm80x_onkey_driver);
 161 
 162 MODULE_LICENSE("GPL");
 163 MODULE_DESCRIPTION("Marvell 88PM80x ONKEY driver");
 164 MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>");
 165 MODULE_ALIAS("platform:88pm80x-onkey");

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