0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <linux/module.h>
0024 #include <linux/init.h>
0025 #include <linux/kernel.h>
0026 #include <linux/errno.h>
0027 #include <linux/input.h>
0028 #include <linux/interrupt.h>
0029 #include <linux/platform_device.h>
0030 #include <linux/mfd/twl.h>
0031
0032 #define PWR_PWRON_IRQ (1 << 0)
0033
0034 #define STS_HW_CONDITIONS 0xf
0035
0036 static irqreturn_t powerbutton_irq(int irq, void *_pwr)
0037 {
0038 struct input_dev *pwr = _pwr;
0039 int err;
0040 u8 value;
0041
0042 err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS);
0043 if (!err) {
0044 pm_wakeup_event(pwr->dev.parent, 0);
0045 input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ);
0046 input_sync(pwr);
0047 } else {
0048 dev_err(pwr->dev.parent, "twl4030: i2c error %d while reading"
0049 " TWL4030 PM_MASTER STS_HW_CONDITIONS register\n", err);
0050 }
0051
0052 return IRQ_HANDLED;
0053 }
0054
0055 static int twl4030_pwrbutton_probe(struct platform_device *pdev)
0056 {
0057 struct input_dev *pwr;
0058 int irq = platform_get_irq(pdev, 0);
0059 int err;
0060
0061 pwr = devm_input_allocate_device(&pdev->dev);
0062 if (!pwr) {
0063 dev_err(&pdev->dev, "Can't allocate power button\n");
0064 return -ENOMEM;
0065 }
0066
0067 input_set_capability(pwr, EV_KEY, KEY_POWER);
0068 pwr->name = "twl4030_pwrbutton";
0069 pwr->phys = "twl4030_pwrbutton/input0";
0070 pwr->dev.parent = &pdev->dev;
0071
0072 err = devm_request_threaded_irq(&pdev->dev, irq, NULL, powerbutton_irq,
0073 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
0074 IRQF_ONESHOT,
0075 "twl4030_pwrbutton", pwr);
0076 if (err < 0) {
0077 dev_err(&pdev->dev, "Can't get IRQ for pwrbutton: %d\n", err);
0078 return err;
0079 }
0080
0081 err = input_register_device(pwr);
0082 if (err) {
0083 dev_err(&pdev->dev, "Can't register power button: %d\n", err);
0084 return err;
0085 }
0086
0087 device_init_wakeup(&pdev->dev, true);
0088
0089 return 0;
0090 }
0091
0092 #ifdef CONFIG_OF
0093 static const struct of_device_id twl4030_pwrbutton_dt_match_table[] = {
0094 { .compatible = "ti,twl4030-pwrbutton" },
0095 {},
0096 };
0097 MODULE_DEVICE_TABLE(of, twl4030_pwrbutton_dt_match_table);
0098 #endif
0099
0100 static struct platform_driver twl4030_pwrbutton_driver = {
0101 .probe = twl4030_pwrbutton_probe,
0102 .driver = {
0103 .name = "twl4030_pwrbutton",
0104 .of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table),
0105 },
0106 };
0107 module_platform_driver(twl4030_pwrbutton_driver);
0108
0109 MODULE_ALIAS("platform:twl4030_pwrbutton");
0110 MODULE_DESCRIPTION("Triton2 Power Button");
0111 MODULE_LICENSE("GPL");
0112 MODULE_AUTHOR("Peter De Schrijver <peter.de-schrijver@nokia.com>");
0113 MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
0114