Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* NXP PCF50633 Input Driver
0003  *
0004  * (C) 2006-2008 by Openmoko, Inc.
0005  * Author: Balaji Rao <balajirrao@openmoko.org>
0006  * All rights reserved.
0007  *
0008  * Broken down from monstrous PCF50633 driver mainly by
0009  * Harald Welte, Andy Green and Werner Almesberger
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/device.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/input.h>
0017 #include <linux/slab.h>
0018 
0019 #include <linux/mfd/pcf50633/core.h>
0020 
0021 #define PCF50633_OOCSTAT_ONKEY  0x01
0022 #define PCF50633_REG_OOCSTAT    0x12
0023 #define PCF50633_REG_OOCMODE    0x10
0024 
0025 struct pcf50633_input {
0026     struct pcf50633 *pcf;
0027     struct input_dev *input_dev;
0028 };
0029 
0030 static void
0031 pcf50633_input_irq(int irq, void *data)
0032 {
0033     struct pcf50633_input *input;
0034     int onkey_released;
0035 
0036     input = data;
0037 
0038     /* We report only one event depending on the key press status */
0039     onkey_released = pcf50633_reg_read(input->pcf, PCF50633_REG_OOCSTAT)
0040                         & PCF50633_OOCSTAT_ONKEY;
0041 
0042     if (irq == PCF50633_IRQ_ONKEYF && !onkey_released)
0043         input_report_key(input->input_dev, KEY_POWER, 1);
0044     else if (irq == PCF50633_IRQ_ONKEYR && onkey_released)
0045         input_report_key(input->input_dev, KEY_POWER, 0);
0046 
0047     input_sync(input->input_dev);
0048 }
0049 
0050 static int pcf50633_input_probe(struct platform_device *pdev)
0051 {
0052     struct pcf50633_input *input;
0053     struct input_dev *input_dev;
0054     int ret;
0055 
0056 
0057     input = kzalloc(sizeof(*input), GFP_KERNEL);
0058     if (!input)
0059         return -ENOMEM;
0060 
0061     input_dev = input_allocate_device();
0062     if (!input_dev) {
0063         kfree(input);
0064         return -ENOMEM;
0065     }
0066 
0067     platform_set_drvdata(pdev, input);
0068     input->pcf = dev_to_pcf50633(pdev->dev.parent);
0069     input->input_dev = input_dev;
0070 
0071     input_dev->name = "PCF50633 PMU events";
0072     input_dev->id.bustype = BUS_I2C;
0073     input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
0074     set_bit(KEY_POWER, input_dev->keybit);
0075 
0076     ret = input_register_device(input_dev);
0077     if (ret) {
0078         input_free_device(input_dev);
0079         kfree(input);
0080         return ret;
0081     }
0082     pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR,
0083                 pcf50633_input_irq, input);
0084     pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF,
0085                 pcf50633_input_irq, input);
0086 
0087     return 0;
0088 }
0089 
0090 static int pcf50633_input_remove(struct platform_device *pdev)
0091 {
0092     struct pcf50633_input *input  = platform_get_drvdata(pdev);
0093 
0094     pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYR);
0095     pcf50633_free_irq(input->pcf, PCF50633_IRQ_ONKEYF);
0096 
0097     input_unregister_device(input->input_dev);
0098     kfree(input);
0099 
0100     return 0;
0101 }
0102 
0103 static struct platform_driver pcf50633_input_driver = {
0104     .driver = {
0105         .name = "pcf50633-input",
0106     },
0107     .probe = pcf50633_input_probe,
0108     .remove = pcf50633_input_remove,
0109 };
0110 module_platform_driver(pcf50633_input_driver);
0111 
0112 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
0113 MODULE_DESCRIPTION("PCF50633 input driver");
0114 MODULE_LICENSE("GPL");
0115 MODULE_ALIAS("platform:pcf50633-input");