1 // SPDX-License-Identifier: GPL-2.0-only
3 * Texas Instruments' Palmas Power Button Input Driver
5 * Copyright (C) 2012-2014 Texas Instruments Incorporated - http://www.ti.com/
10 #include <linux/bitfield.h>
11 #include <linux/init.h>
12 #include <linux/input.h>
13 #include <linux/interrupt.h>
14 #include <linux/kernel.h>
15 #include <linux/mfd/palmas.h>
16 #include <linux/module.h>
18 #include <linux/platform_device.h>
19 #include <linux/slab.h>
21 #define PALMAS_LPK_TIME_MASK 0x0c
22 #define PALMAS_PWRON_DEBOUNCE_MASK 0x03
23 #define PALMAS_PWR_KEY_Q_TIME_MS 20
26 * struct palmas_pwron - Palmas power on data
27 * @palmas: pointer to palmas device
28 * @input_dev: pointer to input device
29 * @input_work: work for detecting release of key
30 * @irq: irq that we are hooked on to
33 struct palmas
*palmas
;
34 struct input_dev
*input_dev
;
35 struct delayed_work input_work
;
40 * struct palmas_pwron_config - configuration of palmas power on
41 * @long_press_time_val: value for long press h/w shutdown event
42 * @pwron_debounce_val: value for debounce of power button
44 struct palmas_pwron_config
{
45 u8 long_press_time_val
;
46 u8 pwron_debounce_val
;
50 * palmas_power_button_work() - Detects the button release event
51 * @work: work item to detect button release
53 static void palmas_power_button_work(struct work_struct
*work
)
55 struct palmas_pwron
*pwron
= container_of(work
,
58 struct input_dev
*input_dev
= pwron
->input_dev
;
62 error
= palmas_read(pwron
->palmas
, PALMAS_INTERRUPT_BASE
,
63 PALMAS_INT1_LINE_STATE
, ®
);
65 dev_err(input_dev
->dev
.parent
,
66 "Cannot read palmas PWRON status: %d\n", error
);
67 } else if (reg
& BIT(1)) {
68 /* The button is released, report event. */
69 input_report_key(input_dev
, KEY_POWER
, 0);
70 input_sync(input_dev
);
72 /* The button is still depressed, keep checking. */
73 schedule_delayed_work(&pwron
->input_work
,
74 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS
));
79 * pwron_irq() - button press isr
81 * @palmas_pwron: pwron struct
85 static irqreturn_t
pwron_irq(int irq
, void *palmas_pwron
)
87 struct palmas_pwron
*pwron
= palmas_pwron
;
88 struct input_dev
*input_dev
= pwron
->input_dev
;
90 input_report_key(input_dev
, KEY_POWER
, 1);
91 pm_wakeup_event(input_dev
->dev
.parent
, 0);
92 input_sync(input_dev
);
94 mod_delayed_work(system_wq
, &pwron
->input_work
,
95 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS
));
101 * palmas_pwron_params_ofinit() - device tree parameter parser
102 * @dev: palmas button device
103 * @config: configuration params that this fills up
105 static void palmas_pwron_params_ofinit(struct device
*dev
,
106 struct palmas_pwron_config
*config
)
108 struct device_node
*np
;
111 static const u8 lpk_times
[] = { 6, 8, 10, 12 };
112 static const int pwr_on_deb_ms
[] = { 15, 100, 500, 1000 };
114 memset(config
, 0, sizeof(*config
));
116 /* Default config parameters */
117 config
->long_press_time_val
= ARRAY_SIZE(lpk_times
) - 1;
123 error
= of_property_read_u32(np
, "ti,palmas-long-press-seconds", &val
);
125 for (i
= 0; i
< ARRAY_SIZE(lpk_times
); i
++) {
126 if (val
<= lpk_times
[i
]) {
127 config
->long_press_time_val
= i
;
133 error
= of_property_read_u32(np
,
134 "ti,palmas-pwron-debounce-milli-seconds",
137 for (i
= 0; i
< ARRAY_SIZE(pwr_on_deb_ms
); i
++) {
138 if (val
<= pwr_on_deb_ms
[i
]) {
139 config
->pwron_debounce_val
= i
;
145 dev_info(dev
, "h/w controlled shutdown duration=%d seconds\n",
146 lpk_times
[config
->long_press_time_val
]);
150 * palmas_pwron_probe() - probe
151 * @pdev: platform device for the button
153 * Return: 0 for successful probe else appropriate error
155 static int palmas_pwron_probe(struct platform_device
*pdev
)
157 struct palmas
*palmas
= dev_get_drvdata(pdev
->dev
.parent
);
158 struct device
*dev
= &pdev
->dev
;
159 struct input_dev
*input_dev
;
160 struct palmas_pwron
*pwron
;
161 struct palmas_pwron_config config
;
165 palmas_pwron_params_ofinit(dev
, &config
);
167 pwron
= kzalloc(sizeof(*pwron
), GFP_KERNEL
);
171 input_dev
= input_allocate_device();
173 dev_err(dev
, "Can't allocate power button\n");
178 input_dev
->name
= "palmas_pwron";
179 input_dev
->phys
= "palmas_pwron/input0";
180 input_dev
->dev
.parent
= dev
;
182 input_set_capability(input_dev
, EV_KEY
, KEY_POWER
);
185 * Setup default hardware shutdown option (long key press)
188 val
= FIELD_PREP(PALMAS_LPK_TIME_MASK
, config
.long_press_time_val
) |
189 FIELD_PREP(PALMAS_PWRON_DEBOUNCE_MASK
, config
.pwron_debounce_val
);
190 error
= palmas_update_bits(palmas
, PALMAS_PMU_CONTROL_BASE
,
191 PALMAS_LONG_PRESS_KEY
,
192 PALMAS_LPK_TIME_MASK
|
193 PALMAS_PWRON_DEBOUNCE_MASK
,
196 dev_err(dev
, "LONG_PRESS_KEY_UPDATE failed: %d\n", error
);
200 pwron
->palmas
= palmas
;
201 pwron
->input_dev
= input_dev
;
203 INIT_DELAYED_WORK(&pwron
->input_work
, palmas_power_button_work
);
205 pwron
->irq
= platform_get_irq(pdev
, 0);
206 if (pwron
->irq
< 0) {
211 error
= request_threaded_irq(pwron
->irq
, NULL
, pwron_irq
,
215 dev_name(dev
), pwron
);
217 dev_err(dev
, "Can't get IRQ for pwron: %d\n", error
);
221 error
= input_register_device(input_dev
);
223 dev_err(dev
, "Can't register power button: %d\n", error
);
227 platform_set_drvdata(pdev
, pwron
);
228 device_init_wakeup(dev
, true);
233 cancel_delayed_work_sync(&pwron
->input_work
);
234 free_irq(pwron
->irq
, pwron
);
236 input_free_device(input_dev
);
243 * palmas_pwron_remove() - Cleanup on removal
244 * @pdev: platform device for the button
248 static void palmas_pwron_remove(struct platform_device
*pdev
)
250 struct palmas_pwron
*pwron
= platform_get_drvdata(pdev
);
252 free_irq(pwron
->irq
, pwron
);
253 cancel_delayed_work_sync(&pwron
->input_work
);
255 input_unregister_device(pwron
->input_dev
);
260 * palmas_pwron_suspend() - suspend handler
261 * @dev: power button device
263 * Cancel all pending work items for the power button, setup irq for wakeup
267 static int palmas_pwron_suspend(struct device
*dev
)
269 struct platform_device
*pdev
= to_platform_device(dev
);
270 struct palmas_pwron
*pwron
= platform_get_drvdata(pdev
);
272 cancel_delayed_work_sync(&pwron
->input_work
);
274 if (device_may_wakeup(dev
))
275 enable_irq_wake(pwron
->irq
);
281 * palmas_pwron_resume() - resume handler
282 * @dev: power button device
284 * Just disable the wakeup capability of irq here.
288 static int palmas_pwron_resume(struct device
*dev
)
290 struct platform_device
*pdev
= to_platform_device(dev
);
291 struct palmas_pwron
*pwron
= platform_get_drvdata(pdev
);
293 if (device_may_wakeup(dev
))
294 disable_irq_wake(pwron
->irq
);
299 static DEFINE_SIMPLE_DEV_PM_OPS(palmas_pwron_pm
,
300 palmas_pwron_suspend
, palmas_pwron_resume
);
303 static const struct of_device_id of_palmas_pwr_match
[] = {
304 { .compatible
= "ti,palmas-pwrbutton" },
308 MODULE_DEVICE_TABLE(of
, of_palmas_pwr_match
);
311 static struct platform_driver palmas_pwron_driver
= {
312 .probe
= palmas_pwron_probe
,
313 .remove
= palmas_pwron_remove
,
315 .name
= "palmas_pwrbutton",
316 .of_match_table
= of_match_ptr(of_palmas_pwr_match
),
317 .pm
= pm_sleep_ptr(&palmas_pwron_pm
),
320 module_platform_driver(palmas_pwron_driver
);
322 MODULE_ALIAS("platform:palmas-pwrbutton");
323 MODULE_DESCRIPTION("Palmas Power Button");
324 MODULE_LICENSE("GPL v2");
325 MODULE_AUTHOR("Texas Instruments Inc.");