2 * Texas Instruments' Palmas Power Button Input Driver
4 * Copyright (C) 2012-2014 Texas Instruments Incorporated - http://www.ti.com/
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.
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.
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>
25 #include <linux/platform_device.h>
26 #include <linux/slab.h>
28 #define PALMAS_LPK_TIME_MASK 0x0c
29 #define PALMAS_PWRON_DEBOUNCE_MASK 0x03
30 #define PALMAS_PWR_KEY_Q_TIME_MS 20
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
40 struct palmas
*palmas
;
41 struct input_dev
*input_dev
;
42 struct delayed_work input_work
;
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
51 struct palmas_pwron_config
{
52 u8 long_press_time_val
;
53 u8 pwron_debounce_val
;
57 * palmas_power_button_work() - Detects the button release event
58 * @work: work item to detect button release
60 static void palmas_power_button_work(struct work_struct
*work
)
62 struct palmas_pwron
*pwron
= container_of(work
,
65 struct input_dev
*input_dev
= pwron
->input_dev
;
69 error
= palmas_read(pwron
->palmas
, PALMAS_INTERRUPT_BASE
,
70 PALMAS_INT1_LINE_STATE
, ®
);
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
);
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
));
86 * pwron_irq() - button press isr
88 * @palmas_pwron: pwron struct
92 static irqreturn_t
pwron_irq(int irq
, void *palmas_pwron
)
94 struct palmas_pwron
*pwron
= palmas_pwron
;
95 struct input_dev
*input_dev
= pwron
->input_dev
;
97 input_report_key(input_dev
, KEY_POWER
, 1);
98 pm_wakeup_event(input_dev
->dev
.parent
, 0);
99 input_sync(input_dev
);
101 mod_delayed_work(system_wq
, &pwron
->input_work
,
102 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS
));
108 * palmas_pwron_params_ofinit() - device tree parameter parser
109 * @dev: palmas button device
110 * @config: configuration params that this fills up
112 static void palmas_pwron_params_ofinit(struct device
*dev
,
113 struct palmas_pwron_config
*config
)
115 struct device_node
*np
;
118 u8 lpk_times
[] = { 6, 8, 10, 12 };
119 int pwr_on_deb_ms
[] = { 15, 100, 500, 1000 };
121 memset(config
, 0, sizeof(*config
));
123 /* Default config parameters */
124 config
->long_press_time_val
= ARRAY_SIZE(lpk_times
) - 1;
130 error
= of_property_read_u32(np
, "ti,palmas-long-press-seconds", &val
);
132 for (i
= 0; i
< ARRAY_SIZE(lpk_times
); i
++) {
133 if (val
<= lpk_times
[i
]) {
134 config
->long_press_time_val
= i
;
140 error
= of_property_read_u32(np
,
141 "ti,palmas-pwron-debounce-milli-seconds",
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
;
152 dev_info(dev
, "h/w controlled shutdown duration=%d seconds\n",
153 lpk_times
[config
->long_press_time_val
]);
157 * palmas_pwron_probe() - probe
158 * @pdev: platform device for the button
160 * Return: 0 for successful probe else appropriate error
162 static int palmas_pwron_probe(struct platform_device
*pdev
)
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
;
172 palmas_pwron_params_ofinit(dev
, &config
);
174 pwron
= kzalloc(sizeof(*pwron
), GFP_KERNEL
);
178 input_dev
= input_allocate_device();
180 dev_err(dev
, "Can't allocate power button\n");
185 input_dev
->name
= "palmas_pwron";
186 input_dev
->phys
= "palmas_pwron/input0";
187 input_dev
->dev
.parent
= dev
;
189 input_set_capability(input_dev
, EV_KEY
, KEY_POWER
);
192 * Setup default hardware shutdown option (long key press)
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
,
203 dev_err(dev
, "LONG_PRESS_KEY_UPDATE failed: %d\n", error
);
207 pwron
->palmas
= palmas
;
208 pwron
->input_dev
= input_dev
;
210 INIT_DELAYED_WORK(&pwron
->input_work
, palmas_power_button_work
);
212 pwron
->irq
= platform_get_irq(pdev
, 0);
213 error
= request_threaded_irq(pwron
->irq
, NULL
, pwron_irq
,
217 dev_name(dev
), pwron
);
219 dev_err(dev
, "Can't get IRQ for pwron: %d\n", error
);
223 error
= input_register_device(input_dev
);
225 dev_err(dev
, "Can't register power button: %d\n", error
);
229 platform_set_drvdata(pdev
, pwron
);
230 device_init_wakeup(dev
, true);
235 cancel_delayed_work_sync(&pwron
->input_work
);
236 free_irq(pwron
->irq
, pwron
);
238 input_free_device(input_dev
);
245 * palmas_pwron_remove() - Cleanup on removal
246 * @pdev: platform device for the button
250 static int palmas_pwron_remove(struct platform_device
*pdev
)
252 struct palmas_pwron
*pwron
= platform_get_drvdata(pdev
);
254 free_irq(pwron
->irq
, pwron
);
255 cancel_delayed_work_sync(&pwron
->input_work
);
257 input_unregister_device(pwron
->input_dev
);
264 * palmas_pwron_suspend() - suspend handler
265 * @dev: power button device
267 * Cancel all pending work items for the power button, setup irq for wakeup
271 static int __maybe_unused
palmas_pwron_suspend(struct device
*dev
)
273 struct platform_device
*pdev
= to_platform_device(dev
);
274 struct palmas_pwron
*pwron
= platform_get_drvdata(pdev
);
276 cancel_delayed_work_sync(&pwron
->input_work
);
278 if (device_may_wakeup(dev
))
279 enable_irq_wake(pwron
->irq
);
285 * palmas_pwron_resume() - resume handler
286 * @dev: power button device
288 * Just disable the wakeup capability of irq here.
292 static int __maybe_unused
palmas_pwron_resume(struct device
*dev
)
294 struct platform_device
*pdev
= to_platform_device(dev
);
295 struct palmas_pwron
*pwron
= platform_get_drvdata(pdev
);
297 if (device_may_wakeup(dev
))
298 disable_irq_wake(pwron
->irq
);
303 static SIMPLE_DEV_PM_OPS(palmas_pwron_pm
,
304 palmas_pwron_suspend
, palmas_pwron_resume
);
307 static const struct of_device_id of_palmas_pwr_match
[] = {
308 { .compatible
= "ti,palmas-pwrbutton" },
312 MODULE_DEVICE_TABLE(of
, of_palmas_pwr_match
);
315 static struct platform_driver palmas_pwron_driver
= {
316 .probe
= palmas_pwron_probe
,
317 .remove
= palmas_pwron_remove
,
319 .name
= "palmas_pwrbutton",
320 .of_match_table
= of_match_ptr(of_palmas_pwr_match
),
321 .pm
= &palmas_pwron_pm
,
324 module_platform_driver(palmas_pwron_driver
);
326 MODULE_ALIAS("platform:palmas-pwrbutton");
327 MODULE_DESCRIPTION("Palmas Power Button");
328 MODULE_LICENSE("GPL v2");
329 MODULE_AUTHOR("Texas Instruments Inc.");