1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) STMicroelectronics 2018
3 // Author: Pascal Paillet <p.paillet@st.com> for STMicroelectronics.
5 #include <linux/input.h>
6 #include <linux/interrupt.h>
7 #include <linux/mfd/stpmic1.h>
8 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/property.h>
12 #include <linux/regmap.h>
15 * struct stpmic1_onkey - OnKey data
16 * @input_dev: pointer to input device
17 * @irq_falling: irq that we are hooked on to
18 * @irq_rising: irq that we are hooked on to
20 struct stpmic1_onkey
{
21 struct input_dev
*input_dev
;
26 static irqreturn_t
onkey_falling_irq(int irq
, void *ponkey
)
28 struct stpmic1_onkey
*onkey
= ponkey
;
29 struct input_dev
*input_dev
= onkey
->input_dev
;
31 input_report_key(input_dev
, KEY_POWER
, 1);
32 pm_wakeup_event(input_dev
->dev
.parent
, 0);
33 input_sync(input_dev
);
38 static irqreturn_t
onkey_rising_irq(int irq
, void *ponkey
)
40 struct stpmic1_onkey
*onkey
= ponkey
;
41 struct input_dev
*input_dev
= onkey
->input_dev
;
43 input_report_key(input_dev
, KEY_POWER
, 0);
44 pm_wakeup_event(input_dev
->dev
.parent
, 0);
45 input_sync(input_dev
);
50 static int stpmic1_onkey_probe(struct platform_device
*pdev
)
52 struct stpmic1
*pmic
= dev_get_drvdata(pdev
->dev
.parent
);
53 struct device
*dev
= &pdev
->dev
;
54 struct input_dev
*input_dev
;
55 struct stpmic1_onkey
*onkey
;
56 unsigned int val
, reg
= 0;
59 onkey
= devm_kzalloc(dev
, sizeof(*onkey
), GFP_KERNEL
);
63 onkey
->irq_falling
= platform_get_irq_byname(pdev
, "onkey-falling");
64 if (onkey
->irq_falling
< 0) {
65 dev_err(dev
, "failed: request IRQ onkey-falling %d\n",
67 return onkey
->irq_falling
;
70 onkey
->irq_rising
= platform_get_irq_byname(pdev
, "onkey-rising");
71 if (onkey
->irq_rising
< 0) {
72 dev_err(dev
, "failed: request IRQ onkey-rising %d\n",
74 return onkey
->irq_rising
;
77 if (!device_property_read_u32(dev
, "power-off-time-sec", &val
)) {
78 if (val
> 0 && val
<= 16) {
79 dev_dbg(dev
, "power-off-time=%d seconds\n", val
);
80 reg
|= PONKEY_PWR_OFF
;
81 reg
|= ((16 - val
) & PONKEY_TURNOFF_TIMER_MASK
);
83 dev_err(dev
, "power-off-time-sec out of range\n");
88 if (device_property_present(dev
, "st,onkey-clear-cc-flag"))
89 reg
|= PONKEY_CC_FLAG_CLEAR
;
91 error
= regmap_update_bits(pmic
->regmap
, PKEY_TURNOFF_CR
,
92 PONKEY_TURNOFF_MASK
, reg
);
94 dev_err(dev
, "PKEY_TURNOFF_CR write failed: %d\n", error
);
98 if (device_property_present(dev
, "st,onkey-pu-inactive")) {
99 error
= regmap_update_bits(pmic
->regmap
, PADS_PULL_CR
,
103 dev_err(dev
, "ONKEY Pads configuration failed: %d\n",
109 input_dev
= devm_input_allocate_device(dev
);
111 dev_err(dev
, "Can't allocate Pwr Onkey Input Device\n");
115 input_dev
->name
= "pmic_onkey";
116 input_dev
->phys
= "pmic_onkey/input0";
118 input_set_capability(input_dev
, EV_KEY
, KEY_POWER
);
120 onkey
->input_dev
= input_dev
;
122 /* interrupt is nested in a thread */
123 error
= devm_request_threaded_irq(dev
, onkey
->irq_falling
, NULL
,
124 onkey_falling_irq
, IRQF_ONESHOT
,
125 dev_name(dev
), onkey
);
127 dev_err(dev
, "Can't get IRQ Onkey Falling: %d\n", error
);
131 error
= devm_request_threaded_irq(dev
, onkey
->irq_rising
, NULL
,
132 onkey_rising_irq
, IRQF_ONESHOT
,
133 dev_name(dev
), onkey
);
135 dev_err(dev
, "Can't get IRQ Onkey Rising: %d\n", error
);
139 error
= input_register_device(input_dev
);
141 dev_err(dev
, "Can't register power button: %d\n", error
);
145 platform_set_drvdata(pdev
, onkey
);
146 device_init_wakeup(dev
, true);
151 static int __maybe_unused
stpmic1_onkey_suspend(struct device
*dev
)
153 struct platform_device
*pdev
= to_platform_device(dev
);
154 struct stpmic1_onkey
*onkey
= platform_get_drvdata(pdev
);
156 if (device_may_wakeup(dev
)) {
157 enable_irq_wake(onkey
->irq_falling
);
158 enable_irq_wake(onkey
->irq_rising
);
163 static int __maybe_unused
stpmic1_onkey_resume(struct device
*dev
)
165 struct platform_device
*pdev
= to_platform_device(dev
);
166 struct stpmic1_onkey
*onkey
= platform_get_drvdata(pdev
);
168 if (device_may_wakeup(dev
)) {
169 disable_irq_wake(onkey
->irq_falling
);
170 disable_irq_wake(onkey
->irq_rising
);
175 static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm
,
176 stpmic1_onkey_suspend
,
177 stpmic1_onkey_resume
);
179 static const struct of_device_id of_stpmic1_onkey_match
[] = {
180 { .compatible
= "st,stpmic1-onkey" },
184 MODULE_DEVICE_TABLE(of
, of_stpmic1_onkey_match
);
186 static struct platform_driver stpmic1_onkey_driver
= {
187 .probe
= stpmic1_onkey_probe
,
189 .name
= "stpmic1_onkey",
190 .of_match_table
= of_match_ptr(of_stpmic1_onkey_match
),
191 .pm
= &stpmic1_onkey_pm
,
194 module_platform_driver(stpmic1_onkey_driver
);
196 MODULE_DESCRIPTION("Onkey driver for STPMIC1");
197 MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
198 MODULE_LICENSE("GPL v2");