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 return onkey
->irq_falling
;
67 onkey
->irq_rising
= platform_get_irq_byname(pdev
, "onkey-rising");
68 if (onkey
->irq_rising
< 0)
69 return onkey
->irq_rising
;
71 if (!device_property_read_u32(dev
, "power-off-time-sec", &val
)) {
72 if (val
> 0 && val
<= 16) {
73 dev_dbg(dev
, "power-off-time=%d seconds\n", val
);
74 reg
|= PONKEY_PWR_OFF
;
75 reg
|= ((16 - val
) & PONKEY_TURNOFF_TIMER_MASK
);
77 dev_err(dev
, "power-off-time-sec out of range\n");
82 if (device_property_present(dev
, "st,onkey-clear-cc-flag"))
83 reg
|= PONKEY_CC_FLAG_CLEAR
;
85 error
= regmap_update_bits(pmic
->regmap
, PKEY_TURNOFF_CR
,
86 PONKEY_TURNOFF_MASK
, reg
);
88 dev_err(dev
, "PKEY_TURNOFF_CR write failed: %d\n", error
);
92 if (device_property_present(dev
, "st,onkey-pu-inactive")) {
93 error
= regmap_update_bits(pmic
->regmap
, PADS_PULL_CR
,
97 dev_err(dev
, "ONKEY Pads configuration failed: %d\n",
103 input_dev
= devm_input_allocate_device(dev
);
105 dev_err(dev
, "Can't allocate Pwr Onkey Input Device\n");
109 input_dev
->name
= "pmic_onkey";
110 input_dev
->phys
= "pmic_onkey/input0";
112 input_set_capability(input_dev
, EV_KEY
, KEY_POWER
);
114 onkey
->input_dev
= input_dev
;
116 /* interrupt is nested in a thread */
117 error
= devm_request_threaded_irq(dev
, onkey
->irq_falling
, NULL
,
118 onkey_falling_irq
, IRQF_ONESHOT
,
119 dev_name(dev
), onkey
);
121 dev_err(dev
, "Can't get IRQ Onkey Falling: %d\n", error
);
125 error
= devm_request_threaded_irq(dev
, onkey
->irq_rising
, NULL
,
126 onkey_rising_irq
, IRQF_ONESHOT
,
127 dev_name(dev
), onkey
);
129 dev_err(dev
, "Can't get IRQ Onkey Rising: %d\n", error
);
133 error
= input_register_device(input_dev
);
135 dev_err(dev
, "Can't register power button: %d\n", error
);
139 platform_set_drvdata(pdev
, onkey
);
140 device_init_wakeup(dev
, true);
145 static int __maybe_unused
stpmic1_onkey_suspend(struct device
*dev
)
147 struct platform_device
*pdev
= to_platform_device(dev
);
148 struct stpmic1_onkey
*onkey
= platform_get_drvdata(pdev
);
150 if (device_may_wakeup(dev
)) {
151 enable_irq_wake(onkey
->irq_falling
);
152 enable_irq_wake(onkey
->irq_rising
);
157 static int __maybe_unused
stpmic1_onkey_resume(struct device
*dev
)
159 struct platform_device
*pdev
= to_platform_device(dev
);
160 struct stpmic1_onkey
*onkey
= platform_get_drvdata(pdev
);
162 if (device_may_wakeup(dev
)) {
163 disable_irq_wake(onkey
->irq_falling
);
164 disable_irq_wake(onkey
->irq_rising
);
169 static SIMPLE_DEV_PM_OPS(stpmic1_onkey_pm
,
170 stpmic1_onkey_suspend
,
171 stpmic1_onkey_resume
);
173 static const struct of_device_id of_stpmic1_onkey_match
[] = {
174 { .compatible
= "st,stpmic1-onkey" },
178 MODULE_DEVICE_TABLE(of
, of_stpmic1_onkey_match
);
180 static struct platform_driver stpmic1_onkey_driver
= {
181 .probe
= stpmic1_onkey_probe
,
183 .name
= "stpmic1_onkey",
184 .of_match_table
= of_match_ptr(of_stpmic1_onkey_match
),
185 .pm
= &stpmic1_onkey_pm
,
188 module_platform_driver(stpmic1_onkey_driver
);
190 MODULE_DESCRIPTION("Onkey driver for STPMIC1");
191 MODULE_AUTHOR("Pascal Paillet <p.paillet@st.com>");
192 MODULE_LICENSE("GPL v2");