0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/platform_device.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/reboot.h>
0020 #include <linux/kernel.h>
0021 #include <linux/module.h>
0022 #include <linux/of_irq.h>
0023 #include <linux/input.h>
0024 #include <linux/slab.h>
0025
0026
0027 #define MAX_HELD_TIME (4 * MSEC_PER_SEC)
0028
0029 static irqreturn_t hi65xx_power_press_isr(int irq, void *q)
0030 {
0031 struct input_dev *input = q;
0032
0033 pm_wakeup_event(input->dev.parent, MAX_HELD_TIME);
0034 input_report_key(input, KEY_POWER, 1);
0035 input_sync(input);
0036
0037 return IRQ_HANDLED;
0038 }
0039
0040 static irqreturn_t hi65xx_power_release_isr(int irq, void *q)
0041 {
0042 struct input_dev *input = q;
0043
0044 pm_wakeup_event(input->dev.parent, MAX_HELD_TIME);
0045 input_report_key(input, KEY_POWER, 0);
0046 input_sync(input);
0047
0048 return IRQ_HANDLED;
0049 }
0050
0051 static irqreturn_t hi65xx_restart_toggle_isr(int irq, void *q)
0052 {
0053 struct input_dev *input = q;
0054 int value = test_bit(KEY_RESTART, input->key);
0055
0056 pm_wakeup_event(input->dev.parent, MAX_HELD_TIME);
0057 input_report_key(input, KEY_RESTART, !value);
0058 input_sync(input);
0059
0060 return IRQ_HANDLED;
0061 }
0062
0063 static const struct {
0064 const char *name;
0065 irqreturn_t (*handler)(int irq, void *q);
0066 } hi65xx_irq_info[] = {
0067 { "down", hi65xx_power_press_isr },
0068 { "up", hi65xx_power_release_isr },
0069 { "hold 4s", hi65xx_restart_toggle_isr },
0070 };
0071
0072 static int hi65xx_powerkey_probe(struct platform_device *pdev)
0073 {
0074 struct device *dev = &pdev->dev;
0075 struct input_dev *input;
0076 int irq, i, error;
0077
0078 input = devm_input_allocate_device(dev);
0079 if (!input) {
0080 dev_err(dev, "failed to allocate input device\n");
0081 return -ENOMEM;
0082 }
0083
0084 input->phys = "hisi_on/input0";
0085 input->name = "HISI 65xx PowerOn Key";
0086
0087 input_set_capability(input, EV_KEY, KEY_POWER);
0088 input_set_capability(input, EV_KEY, KEY_RESTART);
0089
0090 for (i = 0; i < ARRAY_SIZE(hi65xx_irq_info); i++) {
0091
0092 irq = platform_get_irq_byname(pdev, hi65xx_irq_info[i].name);
0093 if (irq < 0)
0094 return irq;
0095
0096 error = devm_request_any_context_irq(dev, irq,
0097 hi65xx_irq_info[i].handler,
0098 IRQF_ONESHOT,
0099 hi65xx_irq_info[i].name,
0100 input);
0101 if (error < 0) {
0102 dev_err(dev, "couldn't request irq %s: %d\n",
0103 hi65xx_irq_info[i].name, error);
0104 return error;
0105 }
0106 }
0107
0108 error = input_register_device(input);
0109 if (error) {
0110 dev_err(dev, "failed to register input device: %d\n", error);
0111 return error;
0112 }
0113
0114 device_init_wakeup(dev, 1);
0115
0116 return 0;
0117 }
0118
0119 static struct platform_driver hi65xx_powerkey_driver = {
0120 .driver = {
0121 .name = "hi65xx-powerkey",
0122 },
0123 .probe = hi65xx_powerkey_probe,
0124 };
0125 module_platform_driver(hi65xx_powerkey_driver);
0126
0127 MODULE_AUTHOR("Zhiliang Xue <xuezhiliang@huawei.com");
0128 MODULE_DESCRIPTION("Hisi PMIC Power key driver");
0129 MODULE_LICENSE("GPL v2");