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 int 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);
262 * palmas_pwron_suspend() - suspend handler
263 * @dev: power button device
265 * Cancel all pending work items for the power button, setup irq for wakeup
269 static int palmas_pwron_suspend(struct device *dev)
271 struct platform_device *pdev = to_platform_device(dev);
272 struct palmas_pwron *pwron = platform_get_drvdata(pdev);
274 cancel_delayed_work_sync(&pwron->input_work);
276 if (device_may_wakeup(dev))
277 enable_irq_wake(pwron->irq);
283 * palmas_pwron_resume() - resume handler
284 * @dev: power button device
286 * Just disable the wakeup capability of irq here.
290 static int palmas_pwron_resume(struct device *dev)
292 struct platform_device *pdev = to_platform_device(dev);
293 struct palmas_pwron *pwron = platform_get_drvdata(pdev);
295 if (device_may_wakeup(dev))
296 disable_irq_wake(pwron->irq);
301 static DEFINE_SIMPLE_DEV_PM_OPS(palmas_pwron_pm,
302 palmas_pwron_suspend, palmas_pwron_resume);
305 static const struct of_device_id of_palmas_pwr_match[] = {
306 { .compatible = "ti,palmas-pwrbutton" },
310 MODULE_DEVICE_TABLE(of, of_palmas_pwr_match);
313 static struct platform_driver palmas_pwron_driver = {
314 .probe = palmas_pwron_probe,
315 .remove = palmas_pwron_remove,
317 .name = "palmas_pwrbutton",
318 .of_match_table = of_match_ptr(of_palmas_pwr_match),
319 .pm = pm_sleep_ptr(&palmas_pwron_pm),
322 module_platform_driver(palmas_pwron_driver);
324 MODULE_ALIAS("platform:palmas-pwrbutton");
325 MODULE_DESCRIPTION("Palmas Power Button");
326 MODULE_LICENSE("GPL v2");
327 MODULE_AUTHOR("Texas Instruments Inc.");