Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Hisilicon PMIC powerkey driver
0003  *
0004  * Copyright (C) 2013 Hisilicon Ltd.
0005  * Copyright (C) 2015, 2016 Linaro Ltd.
0006  *
0007  * This file is subject to the terms and conditions of the GNU General
0008  * Public License. See the file "COPYING" in the main directory of this
0009  * archive for more details.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
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 /* the held interrupt will trigger after 4 seconds */
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");