0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/input.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/device.h>
0011 #include <linux/mfd/intel_soc_pmic.h>
0012 #include <linux/module.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/pm_wakeirq.h>
0015 #include <linux/slab.h>
0016
0017 #define CHTDC_TI_SIRQ_REG 0x3
0018 #define SIRQ_PWRBTN_REL BIT(0)
0019
0020 static irqreturn_t chtdc_ti_pwrbtn_interrupt(int irq, void *dev_id)
0021 {
0022 struct input_dev *input = dev_id;
0023 struct device *dev = input->dev.parent;
0024 struct regmap *regmap = dev_get_drvdata(dev);
0025 int state;
0026
0027 if (!regmap_read(regmap, CHTDC_TI_SIRQ_REG, &state)) {
0028 dev_dbg(dev, "SIRQ_REG=0x%x\n", state);
0029 input_report_key(input, KEY_POWER, !(state & SIRQ_PWRBTN_REL));
0030 input_sync(input);
0031 }
0032
0033 return IRQ_HANDLED;
0034 }
0035
0036 static int chtdc_ti_pwrbtn_probe(struct platform_device *pdev)
0037 {
0038 struct device *dev = &pdev->dev;
0039 struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent);
0040 struct input_dev *input;
0041 int irq, err;
0042
0043 irq = platform_get_irq(pdev, 0);
0044 if (irq < 0)
0045 return irq;
0046 input = devm_input_allocate_device(dev);
0047 if (!input)
0048 return -ENOMEM;
0049 input->name = pdev->name;
0050 input->phys = "power-button/input0";
0051 input->id.bustype = BUS_HOST;
0052 input_set_capability(input, EV_KEY, KEY_POWER);
0053 err = input_register_device(input);
0054 if (err)
0055 return err;
0056
0057 dev_set_drvdata(dev, pmic->regmap);
0058
0059 err = devm_request_threaded_irq(dev, irq, NULL,
0060 chtdc_ti_pwrbtn_interrupt,
0061 IRQF_ONESHOT, KBUILD_MODNAME, input);
0062 if (err)
0063 return err;
0064
0065 device_init_wakeup(dev, true);
0066 dev_pm_set_wake_irq(dev, irq);
0067 return 0;
0068 }
0069
0070 static int chtdc_ti_pwrbtn_remove(struct platform_device *pdev)
0071 {
0072 dev_pm_clear_wake_irq(&pdev->dev);
0073 device_init_wakeup(&pdev->dev, false);
0074 return 0;
0075 }
0076
0077 static const struct platform_device_id chtdc_ti_pwrbtn_id_table[] = {
0078 { .name = "chtdc_ti_pwrbtn" },
0079 {},
0080 };
0081 MODULE_DEVICE_TABLE(platform, chtdc_ti_pwrbtn_id_table);
0082
0083 static struct platform_driver chtdc_ti_pwrbtn_driver = {
0084 .driver = {
0085 .name = KBUILD_MODNAME,
0086 },
0087 .probe = chtdc_ti_pwrbtn_probe,
0088 .remove = chtdc_ti_pwrbtn_remove,
0089 .id_table = chtdc_ti_pwrbtn_id_table,
0090 };
0091 module_platform_driver(chtdc_ti_pwrbtn_driver);
0092
0093 MODULE_DESCRIPTION("Power-button driver for Dollar Cove TI PMIC");
0094 MODULE_LICENSE("GPL v2");