1 // SPDX-License-Identifier: GPL-2.0+
5 #include <linux/device.h>
7 #include <linux/init.h>
8 #include <linux/input.h>
9 #include <linux/interrupt.h>
11 #include <linux/jiffies.h>
12 #include <linux/kernel.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
16 #include <linux/of_address.h>
17 #include <linux/platform_device.h>
18 #include <linux/pm_wakeirq.h>
19 #include <linux/regmap.h>
21 #define BBNSM_CTRL 0x8
22 #define BBNSM_INT_EN 0x10
23 #define BBNSM_EVENTS 0x14
24 #define BBNSM_PAD_CTRL 0x24
26 #define BBNSM_BTN_PRESSED BIT(7)
27 #define BBNSM_PWR_ON BIT(6)
28 #define BBNSM_BTN_OFF BIT(5)
29 #define BBNSM_EMG_OFF BIT(4)
30 #define BBNSM_PWRKEY_EVENTS (BBNSM_PWR_ON | BBNSM_BTN_OFF | BBNSM_EMG_OFF)
31 #define BBNSM_DP_EN BIT(24)
33 #define DEBOUNCE_TIME 30
34 #define REPEAT_INTERVAL 60
37 struct regmap
*regmap
;
40 int keystate
; /* 1:pressed */
42 struct timer_list check_timer
;
43 struct input_dev
*input
;
46 static void bbnsm_pwrkey_check_for_events(struct timer_list
*t
)
48 struct bbnsm_pwrkey
*bbnsm
= from_timer(bbnsm
, t
, check_timer
);
49 struct input_dev
*input
= bbnsm
->input
;
52 regmap_read(bbnsm
->regmap
, BBNSM_EVENTS
, &state
);
54 state
= state
& BBNSM_BTN_PRESSED
? 1 : 0;
56 /* only report new event if status changed */
57 if (state
^ bbnsm
->keystate
) {
58 bbnsm
->keystate
= state
;
59 input_event(input
, EV_KEY
, bbnsm
->keycode
, state
);
61 pm_relax(bbnsm
->input
->dev
.parent
);
64 /* repeat check if pressed long */
66 mod_timer(&bbnsm
->check_timer
,
67 jiffies
+ msecs_to_jiffies(REPEAT_INTERVAL
));
70 static irqreturn_t
bbnsm_pwrkey_interrupt(int irq
, void *dev_id
)
72 struct platform_device
*pdev
= dev_id
;
73 struct bbnsm_pwrkey
*bbnsm
= platform_get_drvdata(pdev
);
74 struct input_dev
*input
= bbnsm
->input
;
77 regmap_read(bbnsm
->regmap
, BBNSM_EVENTS
, &event
);
78 if (!(event
& BBNSM_BTN_OFF
))
81 pm_wakeup_event(bbnsm
->input
->dev
.parent
, 0);
84 * Directly report key event after resume to make sure key press
85 * event is never missed.
87 if (bbnsm
->suspended
) {
89 input_event(input
, EV_KEY
, bbnsm
->keycode
, 1);
91 /* Fire at most once per suspend/resume cycle */
92 bbnsm
->suspended
= false;
95 mod_timer(&bbnsm
->check_timer
,
96 jiffies
+ msecs_to_jiffies(DEBOUNCE_TIME
));
99 regmap_write(bbnsm
->regmap
, BBNSM_EVENTS
, BBNSM_BTN_OFF
);
104 static void bbnsm_pwrkey_act(void *pdata
)
106 struct bbnsm_pwrkey
*bbnsm
= pdata
;
108 timer_shutdown_sync(&bbnsm
->check_timer
);
111 static int bbnsm_pwrkey_probe(struct platform_device
*pdev
)
113 struct bbnsm_pwrkey
*bbnsm
;
114 struct input_dev
*input
;
115 struct device_node
*np
= pdev
->dev
.of_node
;
118 bbnsm
= devm_kzalloc(&pdev
->dev
, sizeof(*bbnsm
), GFP_KERNEL
);
122 bbnsm
->regmap
= syscon_node_to_regmap(np
->parent
);
123 if (IS_ERR(bbnsm
->regmap
)) {
124 dev_err(&pdev
->dev
, "bbnsm pwerkey get regmap failed\n");
125 return PTR_ERR(bbnsm
->regmap
);
128 if (device_property_read_u32(&pdev
->dev
, "linux,code",
130 bbnsm
->keycode
= KEY_POWER
;
131 dev_warn(&pdev
->dev
, "key code is not specified, using default KEY_POWER\n");
134 bbnsm
->irq
= platform_get_irq(pdev
, 0);
138 /* config the BBNSM power related register */
139 regmap_update_bits(bbnsm
->regmap
, BBNSM_CTRL
, BBNSM_DP_EN
, BBNSM_DP_EN
);
141 /* clear the unexpected interrupt before driver ready */
142 regmap_write_bits(bbnsm
->regmap
, BBNSM_EVENTS
, BBNSM_PWRKEY_EVENTS
,
143 BBNSM_PWRKEY_EVENTS
);
145 timer_setup(&bbnsm
->check_timer
, bbnsm_pwrkey_check_for_events
, 0);
147 input
= devm_input_allocate_device(&pdev
->dev
);
149 dev_err(&pdev
->dev
, "failed to allocate the input device\n");
153 input
->name
= pdev
->name
;
154 input
->phys
= "bbnsm-pwrkey/input0";
155 input
->id
.bustype
= BUS_HOST
;
157 input_set_capability(input
, EV_KEY
, bbnsm
->keycode
);
159 /* input customer action to cancel release timer */
160 error
= devm_add_action(&pdev
->dev
, bbnsm_pwrkey_act
, bbnsm
);
162 dev_err(&pdev
->dev
, "failed to register remove action\n");
166 bbnsm
->input
= input
;
167 platform_set_drvdata(pdev
, bbnsm
);
169 error
= devm_request_irq(&pdev
->dev
, bbnsm
->irq
, bbnsm_pwrkey_interrupt
,
170 IRQF_SHARED
, pdev
->name
, pdev
);
172 dev_err(&pdev
->dev
, "interrupt not available.\n");
176 error
= input_register_device(input
);
178 dev_err(&pdev
->dev
, "failed to register input device\n");
182 device_init_wakeup(&pdev
->dev
, true);
183 error
= dev_pm_set_wake_irq(&pdev
->dev
, bbnsm
->irq
);
185 dev_warn(&pdev
->dev
, "irq wake enable failed.\n");
190 static int __maybe_unused
bbnsm_pwrkey_suspend(struct device
*dev
)
192 struct platform_device
*pdev
= to_platform_device(dev
);
193 struct bbnsm_pwrkey
*bbnsm
= platform_get_drvdata(pdev
);
195 bbnsm
->suspended
= true;
200 static int __maybe_unused
bbnsm_pwrkey_resume(struct device
*dev
)
202 struct platform_device
*pdev
= to_platform_device(dev
);
203 struct bbnsm_pwrkey
*bbnsm
= platform_get_drvdata(pdev
);
205 bbnsm
->suspended
= false;
210 static SIMPLE_DEV_PM_OPS(bbnsm_pwrkey_pm_ops
, bbnsm_pwrkey_suspend
,
211 bbnsm_pwrkey_resume
);
213 static const struct of_device_id bbnsm_pwrkey_ids
[] = {
214 { .compatible
= "nxp,imx93-bbnsm-pwrkey" },
217 MODULE_DEVICE_TABLE(of
, bbnsm_pwrkey_ids
);
219 static struct platform_driver bbnsm_pwrkey_driver
= {
221 .name
= "bbnsm_pwrkey",
222 .pm
= &bbnsm_pwrkey_pm_ops
,
223 .of_match_table
= bbnsm_pwrkey_ids
,
225 .probe
= bbnsm_pwrkey_probe
,
227 module_platform_driver(bbnsm_pwrkey_driver
);
229 MODULE_AUTHOR("Jacky Bai <ping.bai@nxp.com>");
230 MODULE_DESCRIPTION("NXP bbnsm power key Driver");
231 MODULE_LICENSE("GPL");