1 // SPDX-License-Identifier: GPL-2.0+
6 #include <linux/input.h>
7 #include <linux/jiffies.h>
8 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/rtc.h>
12 #include <linux/scmi_protocol.h>
13 #include <linux/scmi_imx_protocol.h>
14 #include <linux/suspend.h>
16 #define DEBOUNCE_TIME 30
17 #define REPEAT_INTERVAL 60
20 struct scmi_protocol_handle
*ph
;
21 const struct scmi_imx_bbm_proto_ops
*ops
;
22 struct notifier_block nb
;
24 int keystate
; /* 1:pressed */
26 struct delayed_work check_work
;
27 struct input_dev
*input
;
30 static void scmi_imx_bbm_pwrkey_check_for_events(struct work_struct
*work
)
32 struct scmi_imx_bbm
*bbnsm
= container_of(to_delayed_work(work
),
33 struct scmi_imx_bbm
, check_work
);
34 struct scmi_protocol_handle
*ph
= bbnsm
->ph
;
35 struct input_dev
*input
= bbnsm
->input
;
39 ret
= bbnsm
->ops
->button_get(ph
, &state
);
41 pr_err("%s: %d\n", __func__
, ret
);
45 pr_debug("%s: state: %d, keystate %d\n", __func__
, state
, bbnsm
->keystate
);
47 /* only report new event if status changed */
48 if (state
^ bbnsm
->keystate
) {
49 bbnsm
->keystate
= state
;
50 input_event(input
, EV_KEY
, bbnsm
->keycode
, state
);
52 pm_relax(bbnsm
->input
->dev
.parent
);
53 pr_debug("EV_KEY: %x\n", bbnsm
->keycode
);
56 /* repeat check if pressed long */
58 schedule_delayed_work(&bbnsm
->check_work
, msecs_to_jiffies(REPEAT_INTERVAL
));
61 static int scmi_imx_bbm_pwrkey_event(struct scmi_imx_bbm
*bbnsm
)
63 struct input_dev
*input
= bbnsm
->input
;
65 pm_wakeup_event(input
->dev
.parent
, 0);
68 * Directly report key event after resume to make no key press
71 if (READ_ONCE(bbnsm
->suspended
)) {
73 input_event(input
, EV_KEY
, bbnsm
->keycode
, 1);
75 WRITE_ONCE(bbnsm
->suspended
, false);
78 schedule_delayed_work(&bbnsm
->check_work
, msecs_to_jiffies(DEBOUNCE_TIME
));
83 static void scmi_imx_bbm_pwrkey_act(void *pdata
)
85 struct scmi_imx_bbm
*bbnsm
= pdata
;
87 cancel_delayed_work_sync(&bbnsm
->check_work
);
90 static int scmi_imx_bbm_key_notifier(struct notifier_block
*nb
, unsigned long event
, void *data
)
92 struct scmi_imx_bbm
*bbnsm
= container_of(nb
, struct scmi_imx_bbm
, nb
);
93 struct scmi_imx_bbm_notif_report
*r
= data
;
96 pr_debug("BBM Button Power key pressed\n");
97 scmi_imx_bbm_pwrkey_event(bbnsm
);
99 /* Should never reach here */
100 pr_err("Unexpected BBM event: %s\n", __func__
);
106 static int scmi_imx_bbm_pwrkey_init(struct scmi_device
*sdev
)
108 const struct scmi_handle
*handle
= sdev
->handle
;
109 struct device
*dev
= &sdev
->dev
;
110 struct scmi_imx_bbm
*bbnsm
= dev_get_drvdata(dev
);
111 struct input_dev
*input
;
114 if (device_property_read_u32(dev
, "linux,code", &bbnsm
->keycode
)) {
115 bbnsm
->keycode
= KEY_POWER
;
116 dev_warn(dev
, "key code is not specified, using default KEY_POWER\n");
119 INIT_DELAYED_WORK(&bbnsm
->check_work
, scmi_imx_bbm_pwrkey_check_for_events
);
121 input
= devm_input_allocate_device(dev
);
123 dev_err(dev
, "failed to allocate the input device for SCMI IMX BBM\n");
127 input
->name
= dev_name(dev
);
128 input
->phys
= "bbnsm-pwrkey/input0";
129 input
->id
.bustype
= BUS_HOST
;
131 input_set_capability(input
, EV_KEY
, bbnsm
->keycode
);
133 ret
= devm_add_action_or_reset(dev
, scmi_imx_bbm_pwrkey_act
, bbnsm
);
135 dev_err(dev
, "failed to register remove action\n");
139 bbnsm
->input
= input
;
141 bbnsm
->nb
.notifier_call
= &scmi_imx_bbm_key_notifier
;
142 ret
= handle
->notify_ops
->devm_event_notifier_register(sdev
, SCMI_PROTOCOL_IMX_BBM
,
143 SCMI_EVENT_IMX_BBM_BUTTON
,
147 dev_err(dev
, "Failed to register BBM Button Events %d:", ret
);
149 ret
= input_register_device(input
);
151 dev_err(dev
, "failed to register input device\n");
158 static int scmi_imx_bbm_key_probe(struct scmi_device
*sdev
)
160 const struct scmi_handle
*handle
= sdev
->handle
;
161 struct device
*dev
= &sdev
->dev
;
162 struct scmi_protocol_handle
*ph
;
163 struct scmi_imx_bbm
*bbnsm
;
169 bbnsm
= devm_kzalloc(dev
, sizeof(*bbnsm
), GFP_KERNEL
);
173 bbnsm
->ops
= handle
->devm_protocol_get(sdev
, SCMI_PROTOCOL_IMX_BBM
, &ph
);
174 if (IS_ERR(bbnsm
->ops
))
175 return PTR_ERR(bbnsm
->ops
);
179 device_init_wakeup(dev
, true);
181 dev_set_drvdata(dev
, bbnsm
);
183 ret
= scmi_imx_bbm_pwrkey_init(sdev
);
185 device_init_wakeup(dev
, false);
190 static int __maybe_unused
scmi_imx_bbm_key_suspend(struct device
*dev
)
192 struct scmi_imx_bbm
*bbnsm
= dev_get_drvdata(dev
);
194 WRITE_ONCE(bbnsm
->suspended
, true);
199 static int __maybe_unused
scmi_imx_bbm_key_resume(struct device
*dev
)
204 static SIMPLE_DEV_PM_OPS(scmi_imx_bbm_pm_key_ops
, scmi_imx_bbm_key_suspend
,
205 scmi_imx_bbm_key_resume
);
207 static const struct scmi_device_id scmi_id_table
[] = {
208 { SCMI_PROTOCOL_IMX_BBM
, "imx-bbm-key" },
211 MODULE_DEVICE_TABLE(scmi
, scmi_id_table
);
213 static struct scmi_driver scmi_imx_bbm_key_driver
= {
215 .pm
= &scmi_imx_bbm_pm_key_ops
,
217 .name
= "scmi-imx-bbm-key",
218 .probe
= scmi_imx_bbm_key_probe
,
219 .id_table
= scmi_id_table
,
221 module_scmi_driver(scmi_imx_bbm_key_driver
);
223 MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
224 MODULE_DESCRIPTION("IMX SM BBM Key driver");
225 MODULE_LICENSE("GPL");