Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * wm831x-on.c - WM831X ON pin driver
0003  *
0004  * Copyright (C) 2009 Wolfson Microelectronics plc
0005  *
0006  * This file is subject to the terms and conditions of the GNU General
0007  * Public License. See the file "COPYING" in the main directory of this
0008  * archive for more details.
0009  *
0010  * This program is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  * GNU General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU General Public License
0016  * along with this program; if not, write to the Free Software
0017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0018  */
0019 
0020 #include <linux/module.h>
0021 #include <linux/slab.h>
0022 #include <linux/kernel.h>
0023 #include <linux/errno.h>
0024 #include <linux/input.h>
0025 #include <linux/interrupt.h>
0026 #include <linux/platform_device.h>
0027 #include <linux/workqueue.h>
0028 #include <linux/mfd/wm831x/core.h>
0029 
0030 struct wm831x_on {
0031     struct input_dev *dev;
0032     struct delayed_work work;
0033     struct wm831x *wm831x;
0034 };
0035 
0036 /*
0037  * The chip gives us an interrupt when the ON pin is asserted but we
0038  * then need to poll to see when the pin is deasserted.
0039  */
0040 static void wm831x_poll_on(struct work_struct *work)
0041 {
0042     struct wm831x_on *wm831x_on = container_of(work, struct wm831x_on,
0043                            work.work);
0044     struct wm831x *wm831x = wm831x_on->wm831x;
0045     int poll, ret;
0046 
0047     ret = wm831x_reg_read(wm831x, WM831X_ON_PIN_CONTROL);
0048     if (ret >= 0) {
0049         poll = !(ret & WM831X_ON_PIN_STS);
0050 
0051         input_report_key(wm831x_on->dev, KEY_POWER, poll);
0052         input_sync(wm831x_on->dev);
0053     } else {
0054         dev_err(wm831x->dev, "Failed to read ON status: %d\n", ret);
0055         poll = 1;
0056     }
0057 
0058     if (poll)
0059         schedule_delayed_work(&wm831x_on->work, 100);
0060 }
0061 
0062 static irqreturn_t wm831x_on_irq(int irq, void *data)
0063 {
0064     struct wm831x_on *wm831x_on = data;
0065 
0066     schedule_delayed_work(&wm831x_on->work, 0);
0067 
0068     return IRQ_HANDLED;
0069 }
0070 
0071 static int wm831x_on_probe(struct platform_device *pdev)
0072 {
0073     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
0074     struct wm831x_on *wm831x_on;
0075     int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
0076     int ret;
0077 
0078     wm831x_on = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_on),
0079                  GFP_KERNEL);
0080     if (!wm831x_on) {
0081         dev_err(&pdev->dev, "Can't allocate data\n");
0082         return -ENOMEM;
0083     }
0084 
0085     wm831x_on->wm831x = wm831x;
0086     INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on);
0087 
0088     wm831x_on->dev = devm_input_allocate_device(&pdev->dev);
0089     if (!wm831x_on->dev) {
0090         dev_err(&pdev->dev, "Can't allocate input dev\n");
0091         ret = -ENOMEM;
0092         goto err;
0093     }
0094 
0095     wm831x_on->dev->evbit[0] = BIT_MASK(EV_KEY);
0096     wm831x_on->dev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
0097     wm831x_on->dev->name = "wm831x_on";
0098     wm831x_on->dev->phys = "wm831x_on/input0";
0099     wm831x_on->dev->dev.parent = &pdev->dev;
0100 
0101     ret = request_threaded_irq(irq, NULL, wm831x_on_irq,
0102                    IRQF_TRIGGER_RISING | IRQF_ONESHOT,
0103                    "wm831x_on",
0104                    wm831x_on);
0105     if (ret < 0) {
0106         dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret);
0107         goto err_input_dev;
0108     }
0109     ret = input_register_device(wm831x_on->dev);
0110     if (ret) {
0111         dev_dbg(&pdev->dev, "Can't register input device: %d\n", ret);
0112         goto err_irq;
0113     }
0114 
0115     platform_set_drvdata(pdev, wm831x_on);
0116 
0117     return 0;
0118 
0119 err_irq:
0120     free_irq(irq, wm831x_on);
0121 err_input_dev:
0122 err:
0123     return ret;
0124 }
0125 
0126 static int wm831x_on_remove(struct platform_device *pdev)
0127 {
0128     struct wm831x_on *wm831x_on = platform_get_drvdata(pdev);
0129     int irq = platform_get_irq(pdev, 0);
0130 
0131     free_irq(irq, wm831x_on);
0132     cancel_delayed_work_sync(&wm831x_on->work);
0133 
0134     return 0;
0135 }
0136 
0137 static struct platform_driver wm831x_on_driver = {
0138     .probe      = wm831x_on_probe,
0139     .remove     = wm831x_on_remove,
0140     .driver     = {
0141         .name   = "wm831x-on",
0142     },
0143 };
0144 module_platform_driver(wm831x_on_driver);
0145 
0146 MODULE_ALIAS("platform:wm831x-on");
0147 MODULE_DESCRIPTION("WM831x ON pin");
0148 MODULE_LICENSE("GPL");
0149 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0150