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/bitfield.h>
19 #include <linux/init.h>
20 #include <linux/input.h>
21 #include <linux/interrupt.h>
22 #include <linux/kernel.h>
23 #include <linux/mfd/palmas.h>
24 #include <linux/module.h>
26 #include <linux/platform_device.h>
27 #include <linux/slab.h>
29 #define PALMAS_LPK_TIME_MASK 0x0c
30 #define PALMAS_PWRON_DEBOUNCE_MASK 0x03
31 #define PALMAS_PWR_KEY_Q_TIME_MS 20
34 * struct palmas_pwron - Palmas power on data
35 * @palmas: pointer to palmas device
36 * @input_dev: pointer to input device
37 * @input_work: work for detecting release of key
38 * @irq: irq that we are hooked on to
41 struct palmas *palmas;
42 struct input_dev *input_dev;
43 struct delayed_work input_work;
48 * struct palmas_pwron_config - configuration of palmas power on
49 * @long_press_time_val: value for long press h/w shutdown event
50 * @pwron_debounce_val: value for debounce of power button
52 struct palmas_pwron_config {
53 u8 long_press_time_val;
54 u8 pwron_debounce_val;
58 * palmas_power_button_work() - Detects the button release event
59 * @work: work item to detect button release
61 static void palmas_power_button_work(struct work_struct *work)
63 struct palmas_pwron *pwron = container_of(work,
66 struct input_dev *input_dev = pwron->input_dev;
70 error = palmas_read(pwron->palmas, PALMAS_INTERRUPT_BASE,
71 PALMAS_INT1_LINE_STATE, ®);
73 dev_err(input_dev->dev.parent,
74 "Cannot read palmas PWRON status: %d\n", error);
75 } else if (reg & BIT(1)) {
76 /* The button is released, report event. */
77 input_report_key(input_dev, KEY_POWER, 0);
78 input_sync(input_dev);
80 /* The button is still depressed, keep checking. */
81 schedule_delayed_work(&pwron->input_work,
82 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS));
87 * pwron_irq() - button press isr
89 * @palmas_pwron: pwron struct
93 static irqreturn_t pwron_irq(int irq, void *palmas_pwron)
95 struct palmas_pwron *pwron = palmas_pwron;
96 struct input_dev *input_dev = pwron->input_dev;
98 input_report_key(input_dev, KEY_POWER, 1);
99 pm_wakeup_event(input_dev->dev.parent, 0);
100 input_sync(input_dev);
102 mod_delayed_work(system_wq, &pwron->input_work,
103 msecs_to_jiffies(PALMAS_PWR_KEY_Q_TIME_MS));
109 * palmas_pwron_params_ofinit() - device tree parameter parser
110 * @dev: palmas button device
111 * @config: configuration params that this fills up
113 static void palmas_pwron_params_ofinit(struct device *dev,
114 struct palmas_pwron_config *config)
116 struct device_node *np;
119 static const u8 lpk_times[] = { 6, 8, 10, 12 };
120 static const int pwr_on_deb_ms[] = { 15, 100, 500, 1000 };
122 memset(config, 0, sizeof(*config));
124 /* Default config parameters */
125 config->long_press_time_val = ARRAY_SIZE(lpk_times) - 1;
131 error = of_property_read_u32(np, "ti,palmas-long-press-seconds", &val);
133 for (i = 0; i < ARRAY_SIZE(lpk_times); i++) {
134 if (val <= lpk_times[i]) {
135 config->long_press_time_val = i;
141 error = of_property_read_u32(np,
142 "ti,palmas-pwron-debounce-milli-seconds",
145 for (i = 0; i < ARRAY_SIZE(pwr_on_deb_ms); i++) {
146 if (val <= pwr_on_deb_ms[i]) {
147 config->pwron_debounce_val = i;
153 dev_info(dev, "h/w controlled shutdown duration=%d seconds\n",
154 lpk_times[config->long_press_time_val]);
158 * palmas_pwron_probe() - probe
159 * @pdev: platform device for the button
161 * Return: 0 for successful probe else appropriate error
163 static int palmas_pwron_probe(struct platform_device *pdev)
165 struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
166 struct device *dev = &pdev->dev;
167 struct input_dev *input_dev;
168 struct palmas_pwron *pwron;
169 struct palmas_pwron_config config;
173 palmas_pwron_params_ofinit(dev, &config);
175 pwron = kzalloc(sizeof(*pwron), GFP_KERNEL);
179 input_dev = input_allocate_device();
181 dev_err(dev, "Can't allocate power button\n");
186 input_dev->name = "palmas_pwron";
187 input_dev->phys = "palmas_pwron/input0";
188 input_dev->dev.parent = dev;
190 input_set_capability(input_dev, EV_KEY, KEY_POWER);
193 * Setup default hardware shutdown option (long key press)
196 val = FIELD_PREP(PALMAS_LPK_TIME_MASK, config.long_press_time_val) |
197 FIELD_PREP(PALMAS_PWRON_DEBOUNCE_MASK, config.pwron_debounce_val);
198 error = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE,
199 PALMAS_LONG_PRESS_KEY,
200 PALMAS_LPK_TIME_MASK |
201 PALMAS_PWRON_DEBOUNCE_MASK,
204 dev_err(dev, "LONG_PRESS_KEY_UPDATE failed: %d\n", error);
208 pwron->palmas = palmas;
209 pwron->input_dev = input_dev;
211 INIT_DELAYED_WORK(&pwron->input_work, palmas_power_button_work);
213 pwron->irq = platform_get_irq(pdev, 0);
214 if (pwron->irq < 0) {
219 error = request_threaded_irq(pwron->irq, NULL, pwron_irq,
223 dev_name(dev), pwron);
225 dev_err(dev, "Can't get IRQ for pwron: %d\n", error);
229 error = input_register_device(input_dev);
231 dev_err(dev, "Can't register power button: %d\n", error);
235 platform_set_drvdata(pdev, pwron);
236 device_init_wakeup(dev, true);
241 cancel_delayed_work_sync(&pwron->input_work);
242 free_irq(pwron->irq, pwron);
244 input_free_device(input_dev);
251 * palmas_pwron_remove() - Cleanup on removal
252 * @pdev: platform device for the button
256 static int palmas_pwron_remove(struct platform_device *pdev)
258 struct palmas_pwron *pwron = platform_get_drvdata(pdev);
260 free_irq(pwron->irq, pwron);
261 cancel_delayed_work_sync(&pwron->input_work);
263 input_unregister_device(pwron->input_dev);
270 * palmas_pwron_suspend() - suspend handler
271 * @dev: power button device
273 * Cancel all pending work items for the power button, setup irq for wakeup
277 static int __maybe_unused palmas_pwron_suspend(struct device *dev)
279 struct platform_device *pdev = to_platform_device(dev);
280 struct palmas_pwron *pwron = platform_get_drvdata(pdev);
282 cancel_delayed_work_sync(&pwron->input_work);
284 if (device_may_wakeup(dev))
285 enable_irq_wake(pwron->irq);
291 * palmas_pwron_resume() - resume handler
292 * @dev: power button device
294 * Just disable the wakeup capability of irq here.
298 static int __maybe_unused palmas_pwron_resume(struct device *dev)
300 struct platform_device *pdev = to_platform_device(dev);
301 struct palmas_pwron *pwron = platform_get_drvdata(pdev);
303 if (device_may_wakeup(dev))
304 disable_irq_wake(pwron->irq);
309 static SIMPLE_DEV_PM_OPS(palmas_pwron_pm,
310 palmas_pwron_suspend, palmas_pwron_resume);
313 static const struct of_device_id of_palmas_pwr_match[] = {
314 { .compatible = "ti,palmas-pwrbutton" },
318 MODULE_DEVICE_TABLE(of, of_palmas_pwr_match);
321 static struct platform_driver palmas_pwron_driver = {
322 .probe = palmas_pwron_probe,
323 .remove = palmas_pwron_remove,
325 .name = "palmas_pwrbutton",
326 .of_match_table = of_match_ptr(of_palmas_pwr_match),
327 .pm = &palmas_pwron_pm,
330 module_platform_driver(palmas_pwron_driver);
332 MODULE_ALIAS("platform:palmas-pwrbutton");
333 MODULE_DESCRIPTION("Palmas Power Button");
334 MODULE_LICENSE("GPL v2");
335 MODULE_AUTHOR("Texas Instruments Inc.");