Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[cascardo/linux.git] / drivers / input / misc / palmas-pwrbutton.c
1 /*
2  * Texas Instruments' Palmas Power Button Input Driver
3  *
4  * Copyright (C) 2012-2014 Texas Instruments Incorporated - http://www.ti.com/
5  *      Girish S Ghongdemath
6  *      Nishanth Menon
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13  * kind, whether express or implied; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  */
17
18 #include <linux/init.h>
19 #include <linux/input.h>
20 #include <linux/interrupt.h>
21 #include <linux/kernel.h>
22 #include <linux/mfd/palmas.h>
23 #include <linux/module.h>
24 #include <linux/of.h>
25 #include <linux/platform_device.h>
26 #include <linux/slab.h>
27
28 #define PALMAS_LPK_TIME_MASK            0x0c
29 #define PALMAS_PWRON_DEBOUNCE_MASK      0x03
30 #define PALMAS_PWR_KEY_Q_TIME_MS        20
31
32 /**
33  * struct palmas_pwron - Palmas power on data
34  * @palmas:             pointer to palmas device
35  * @input_dev:          pointer to input device
36  * @input_work:         work for detecting release of key
37  * @irq:                irq that we are hooked on to
38  */
39 struct palmas_pwron {
40         struct palmas *palmas;
41         struct input_dev *input_dev;
42         struct delayed_work input_work;
43         int irq;
44 };
45
46 /**
47  * struct palmas_pwron_config - configuration of palmas power on
48  * @long_press_time_val:        value for long press h/w shutdown event
49  * @pwron_debounce_val:         value for debounce of power button
50  */
51 struct palmas_pwron_config {
52         u8 long_press_time_val;
53         u8 pwron_debounce_val;
54 };
55
56 /**
57  * palmas_power_button_work() - Detects the button release event
58  * @work:       work item to detect button release
59  */
60 static void palmas_power_button_work(struct work_struct *work)
61 {
62         struct palmas_pwron *pwron = container_of(work,
63                                                   struct palmas_pwron,
64                                                   input_work.work);
65         struct input_dev *input_dev = pwron->input_dev;
66         unsigned int reg;
67         int error;
68
69         error = palmas_read(pwron->palmas, PALMAS_INTERRUPT_BASE,
70                             PALMAS_INT1_LINE_STATE, &reg);
71         if (error) {
72                 dev_err(input_dev->dev.parent,
73                         "Cannot read palmas PWRON status: %d\n", error);
74         } else if (reg & BIT(1)) {
75                 /* The button is released, report event. */
76                 input_report_key(input_dev, KEY_POWER, 0);
77                 input_sync(input_dev);
78         } else {
79                 /* The button is still depressed, keep checking. */
80                 schedule_delayed_work(&pwron->input_work,
81                                 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS));
82         }
83 }
84
85 /**
86  * pwron_irq() - button press isr
87  * @irq:                irq
88  * @palmas_pwron:       pwron struct
89  *
90  * Return: IRQ_HANDLED
91  */
92 static irqreturn_t pwron_irq(int irq, void *palmas_pwron)
93 {
94         struct palmas_pwron *pwron = palmas_pwron;
95         struct input_dev *input_dev = pwron->input_dev;
96
97         input_report_key(input_dev, KEY_POWER, 1);
98         pm_wakeup_event(input_dev->dev.parent, 0);
99         input_sync(input_dev);
100
101         mod_delayed_work(system_wq, &pwron->input_work,
102                          msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS));
103
104         return IRQ_HANDLED;
105 }
106
107 /**
108  * palmas_pwron_params_ofinit() - device tree parameter parser
109  * @dev:        palmas button device
110  * @config:     configuration params that this fills up
111  */
112 static void palmas_pwron_params_ofinit(struct device *dev,
113                                        struct palmas_pwron_config *config)
114 {
115         struct device_node *np;
116         u32 val;
117         int i, error;
118         u8 lpk_times[] = { 6, 8, 10, 12 };
119         int pwr_on_deb_ms[] = { 15, 100, 500, 1000 };
120
121         memset(config, 0, sizeof(*config));
122
123         /* Default config parameters */
124         config->long_press_time_val = ARRAY_SIZE(lpk_times) - 1;
125
126         np = dev->of_node;
127         if (!np)
128                 return;
129
130         error = of_property_read_u32(np, "ti,palmas-long-press-seconds", &val);
131         if (!error) {
132                 for (i = 0; i < ARRAY_SIZE(lpk_times); i++) {
133                         if (val <= lpk_times[i]) {
134                                 config->long_press_time_val = i;
135                                 break;
136                         }
137                 }
138         }
139
140         error = of_property_read_u32(np,
141                                      "ti,palmas-pwron-debounce-milli-seconds",
142                                      &val);
143         if (!error) {
144                 for (i = 0; i < ARRAY_SIZE(pwr_on_deb_ms); i++) {
145                         if (val <= pwr_on_deb_ms[i]) {
146                                 config->pwron_debounce_val = i;
147                                 break;
148                         }
149                 }
150         }
151
152         dev_info(dev, "h/w controlled shutdown duration=%d seconds\n",
153                  lpk_times[config->long_press_time_val]);
154 }
155
156 /**
157  * palmas_pwron_probe() - probe
158  * @pdev:       platform device for the button
159  *
160  * Return: 0 for successful probe else appropriate error
161  */
162 static int palmas_pwron_probe(struct platform_device *pdev)
163 {
164         struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
165         struct device *dev = &pdev->dev;
166         struct input_dev *input_dev;
167         struct palmas_pwron *pwron;
168         struct palmas_pwron_config config;
169         int val;
170         int error;
171
172         palmas_pwron_params_ofinit(dev, &config);
173
174         pwron = kzalloc(sizeof(*pwron), GFP_KERNEL);
175         if (!pwron)
176                 return -ENOMEM;
177
178         input_dev = input_allocate_device();
179         if (!input_dev) {
180                 dev_err(dev, "Can't allocate power button\n");
181                 error = -ENOMEM;
182                 goto err_free_mem;
183         }
184
185         input_dev->name = "palmas_pwron";
186         input_dev->phys = "palmas_pwron/input0";
187         input_dev->dev.parent = dev;
188
189         input_set_capability(input_dev, EV_KEY, KEY_POWER);
190
191         /*
192          * Setup default hardware shutdown option (long key press)
193          * and debounce.
194          */
195         val = config.long_press_time_val << __ffs(PALMAS_LPK_TIME_MASK);
196         val |= config.pwron_debounce_val << __ffs(PALMAS_PWRON_DEBOUNCE_MASK);
197         error = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
198                                    PALMAS_LONG_PRESS_KEY,
199                                    PALMAS_LPK_TIME_MASK |
200                                         PALMAS_PWRON_DEBOUNCE_MASK,
201                                    val);
202         if (error) {
203                 dev_err(dev, "LONG_PRESS_KEY_UPDATE failed: %d\n", error);
204                 goto err_free_input;
205         }
206
207         pwron->palmas = palmas;
208         pwron->input_dev = input_dev;
209
210         INIT_DELAYED_WORK(&pwron->input_work, palmas_power_button_work);
211
212         pwron->irq = platform_get_irq(pdev, 0);
213         error = request_threaded_irq(pwron->irq, NULL, pwron_irq,
214                                      IRQF_TRIGGER_HIGH |
215                                         IRQF_TRIGGER_LOW |
216                                         IRQF_ONESHOT,
217                                      dev_name(dev), pwron);
218         if (error) {
219                 dev_err(dev, "Can't get IRQ for pwron: %d\n", error);
220                 goto err_free_input;
221         }
222
223         error = input_register_device(input_dev);
224         if (error) {
225                 dev_err(dev, "Can't register power button: %d\n", error);
226                 goto err_free_irq;
227         }
228
229         platform_set_drvdata(pdev, pwron);
230         device_init_wakeup(dev, true);
231
232         return 0;
233
234 err_free_irq:
235         cancel_delayed_work_sync(&pwron->input_work);
236         free_irq(pwron->irq, pwron);
237 err_free_input:
238         input_free_device(input_dev);
239 err_free_mem:
240         kfree(pwron);
241         return error;
242 }
243
244 /**
245  * palmas_pwron_remove() - Cleanup on removal
246  * @pdev:       platform device for the button
247  *
248  * Return: 0
249  */
250 static int palmas_pwron_remove(struct platform_device *pdev)
251 {
252         struct palmas_pwron *pwron = platform_get_drvdata(pdev);
253
254         free_irq(pwron->irq, pwron);
255         cancel_delayed_work_sync(&pwron->input_work);
256
257         input_unregister_device(pwron->input_dev);
258         kfree(pwron);
259
260         return 0;
261 }
262
263 /**
264  * palmas_pwron_suspend() - suspend handler
265  * @dev:        power button device
266  *
267  * Cancel all pending work items for the power button, setup irq for wakeup
268  *
269  * Return: 0
270  */
271 static int __maybe_unused palmas_pwron_suspend(struct device *dev)
272 {
273         struct platform_device *pdev = to_platform_device(dev);
274         struct palmas_pwron *pwron = platform_get_drvdata(pdev);
275
276         cancel_delayed_work_sync(&pwron->input_work);
277
278         if (device_may_wakeup(dev))
279                 enable_irq_wake(pwron->irq);
280
281         return 0;
282 }
283
284 /**
285  * palmas_pwron_resume() - resume handler
286  * @dev:        power button device
287  *
288  * Just disable the wakeup capability of irq here.
289  *
290  * Return: 0
291  */
292 static int __maybe_unused palmas_pwron_resume(struct device *dev)
293 {
294         struct platform_device *pdev = to_platform_device(dev);
295         struct palmas_pwron *pwron = platform_get_drvdata(pdev);
296
297         if (device_may_wakeup(dev))
298                 disable_irq_wake(pwron->irq);
299
300         return 0;
301 }
302
303 static SIMPLE_DEV_PM_OPS(palmas_pwron_pm,
304                          palmas_pwron_suspend, palmas_pwron_resume);
305
306 #ifdef CONFIG_OF
307 static struct of_device_id of_palmas_pwr_match[] = {
308         { .compatible = "ti,palmas-pwrbutton" },
309         { },
310 };
311
312 MODULE_DEVICE_TABLE(of, of_palmas_pwr_match);
313 #endif
314
315 static struct platform_driver palmas_pwron_driver = {
316         .probe  = palmas_pwron_probe,
317         .remove = palmas_pwron_remove,
318         .driver = {
319                 .name   = "palmas_pwrbutton",
320                 .of_match_table = of_match_ptr(of_palmas_pwr_match),
321                 .pm     = &palmas_pwron_pm,
322         },
323 };
324 module_platform_driver(palmas_pwron_driver);
325
326 MODULE_ALIAS("platform:palmas-pwrbutton");
327 MODULE_DESCRIPTION("Palmas Power Button");
328 MODULE_LICENSE("GPL v2");
329 MODULE_AUTHOR("Texas Instruments Inc.");