1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2024 NXP. 4 */ 5 6 #include <linux/input.h> 7 #include <linux/jiffies.h> 8 #include <linux/module.h> 9 #include <linux/of.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> 15 16 #define DEBOUNCE_TIME 30 17 #define REPEAT_INTERVAL 60 18 19 struct scmi_imx_bbm { 20 struct scmi_protocol_handle *ph; 21 const struct scmi_imx_bbm_proto_ops *ops; 22 struct notifier_block nb; 23 int keycode; 24 int keystate; /* 1:pressed */ 25 bool suspended; 26 struct delayed_work check_work; 27 struct input_dev *input; 28 }; 29 30 static void scmi_imx_bbm_pwrkey_check_for_events(struct work_struct *work) 31 { 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; 36 u32 state = 0; 37 int ret; 38 39 ret = bbnsm->ops->button_get(ph, &state); 40 if (ret) { 41 pr_err("%s: %d\n", __func__, ret); 42 return; 43 } 44 45 pr_debug("%s: state: %d, keystate %d\n", __func__, state, bbnsm->keystate); 46 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); 51 input_sync(input); 52 pm_relax(bbnsm->input->dev.parent); 53 pr_debug("EV_KEY: %x\n", bbnsm->keycode); 54 } 55 56 /* repeat check if pressed long */ 57 if (state) 58 schedule_delayed_work(&bbnsm->check_work, msecs_to_jiffies(REPEAT_INTERVAL)); 59 } 60 61 static int scmi_imx_bbm_pwrkey_event(struct scmi_imx_bbm *bbnsm) 62 { 63 struct input_dev *input = bbnsm->input; 64 65 pm_wakeup_event(input->dev.parent, 0); 66 67 /* 68 * Directly report key event after resume to make no key press 69 * event is missed. 70 */ 71 if (READ_ONCE(bbnsm->suspended)) { 72 bbnsm->keystate = 1; 73 input_event(input, EV_KEY, bbnsm->keycode, 1); 74 input_sync(input); 75 WRITE_ONCE(bbnsm->suspended, false); 76 } 77 78 schedule_delayed_work(&bbnsm->check_work, msecs_to_jiffies(DEBOUNCE_TIME)); 79 80 return 0; 81 } 82 83 static void scmi_imx_bbm_pwrkey_act(void *pdata) 84 { 85 struct scmi_imx_bbm *bbnsm = pdata; 86 87 cancel_delayed_work_sync(&bbnsm->check_work); 88 } 89 90 static int scmi_imx_bbm_key_notifier(struct notifier_block *nb, unsigned long event, void *data) 91 { 92 struct scmi_imx_bbm *bbnsm = container_of(nb, struct scmi_imx_bbm, nb); 93 struct scmi_imx_bbm_notif_report *r = data; 94 95 if (r->is_button) { 96 pr_debug("BBM Button Power key pressed\n"); 97 scmi_imx_bbm_pwrkey_event(bbnsm); 98 } else { 99 /* Should never reach here */ 100 pr_err("Unexpected BBM event: %s\n", __func__); 101 } 102 103 return 0; 104 } 105 106 static int scmi_imx_bbm_pwrkey_init(struct scmi_device *sdev) 107 { 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; 112 int ret; 113 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"); 117 } 118 119 INIT_DELAYED_WORK(&bbnsm->check_work, scmi_imx_bbm_pwrkey_check_for_events); 120 121 input = devm_input_allocate_device(dev); 122 if (!input) { 123 dev_err(dev, "failed to allocate the input device for SCMI IMX BBM\n"); 124 return -ENOMEM; 125 } 126 127 input->name = dev_name(dev); 128 input->phys = "bbnsm-pwrkey/input0"; 129 input->id.bustype = BUS_HOST; 130 131 input_set_capability(input, EV_KEY, bbnsm->keycode); 132 133 ret = devm_add_action_or_reset(dev, scmi_imx_bbm_pwrkey_act, bbnsm); 134 if (ret) { 135 dev_err(dev, "failed to register remove action\n"); 136 return ret; 137 } 138 139 bbnsm->input = input; 140 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, 144 NULL, &bbnsm->nb); 145 146 if (ret) 147 dev_err(dev, "Failed to register BBM Button Events %d:", ret); 148 149 ret = input_register_device(input); 150 if (ret) { 151 dev_err(dev, "failed to register input device\n"); 152 return ret; 153 } 154 155 return 0; 156 } 157 158 static int scmi_imx_bbm_key_probe(struct scmi_device *sdev) 159 { 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; 164 int ret; 165 166 if (!handle) 167 return -ENODEV; 168 169 bbnsm = devm_kzalloc(dev, sizeof(*bbnsm), GFP_KERNEL); 170 if (!bbnsm) 171 return -ENOMEM; 172 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); 176 177 bbnsm->ph = ph; 178 179 device_init_wakeup(dev, true); 180 181 dev_set_drvdata(dev, bbnsm); 182 183 ret = scmi_imx_bbm_pwrkey_init(sdev); 184 if (ret) 185 device_init_wakeup(dev, false); 186 187 return ret; 188 } 189 190 static int __maybe_unused scmi_imx_bbm_key_suspend(struct device *dev) 191 { 192 struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); 193 194 WRITE_ONCE(bbnsm->suspended, true); 195 196 return 0; 197 } 198 199 static int __maybe_unused scmi_imx_bbm_key_resume(struct device *dev) 200 { 201 return 0; 202 } 203 204 static SIMPLE_DEV_PM_OPS(scmi_imx_bbm_pm_key_ops, scmi_imx_bbm_key_suspend, 205 scmi_imx_bbm_key_resume); 206 207 static const struct scmi_device_id scmi_id_table[] = { 208 { SCMI_PROTOCOL_IMX_BBM, "imx-bbm-key" }, 209 { }, 210 }; 211 MODULE_DEVICE_TABLE(scmi, scmi_id_table); 212 213 static struct scmi_driver scmi_imx_bbm_key_driver = { 214 .driver = { 215 .pm = &scmi_imx_bbm_pm_key_ops, 216 }, 217 .name = "scmi-imx-bbm-key", 218 .probe = scmi_imx_bbm_key_probe, 219 .id_table = scmi_id_table, 220 }; 221 module_scmi_driver(scmi_imx_bbm_key_driver); 222 223 MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); 224 MODULE_DESCRIPTION("IMX SM BBM Key driver"); 225 MODULE_LICENSE("GPL"); 226