1 /*
2 * Copyright (c) 2022 Google LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT gpio_keys
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/input/input.h>
12 #include <zephyr/kernel.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/pm/device.h>
15 #include <zephyr/pm/device_runtime.h>
16 #include <zephyr/sys/atomic.h>
17
18 LOG_MODULE_REGISTER(gpio_keys, CONFIG_INPUT_LOG_LEVEL);
19
20 struct gpio_keys_callback {
21 struct gpio_callback gpio_cb;
22 int8_t pin_state;
23 };
24
25 struct gpio_keys_pin_config {
26 /** GPIO specification from devicetree */
27 struct gpio_dt_spec spec;
28 /** Zephyr code from devicetree */
29 uint32_t zephyr_code;
30 };
31
32 struct gpio_keys_pin_data {
33 const struct device *dev;
34 struct gpio_keys_callback cb_data;
35 struct k_work_delayable work;
36 };
37
38 struct gpio_keys_config {
39 /** Debounce interval in milliseconds from devicetree */
40 uint32_t debounce_interval_ms;
41 const int num_keys;
42 const struct gpio_keys_pin_config *pin_cfg;
43 struct gpio_keys_pin_data *pin_data;
44 k_work_handler_t handler;
45 bool polling_mode;
46 bool no_disconnect;
47 };
48
49 struct gpio_keys_data {
50 #ifdef CONFIG_PM_DEVICE
51 atomic_t suspended;
52 #endif
53 };
54
55 /**
56 * Handle debounced gpio pin state.
57 */
gpio_keys_poll_pin(const struct device * dev,int key_index)58 static void gpio_keys_poll_pin(const struct device *dev, int key_index)
59 {
60 const struct gpio_keys_config *cfg = dev->config;
61 const struct gpio_keys_pin_config *pin_cfg = &cfg->pin_cfg[key_index];
62 struct gpio_keys_pin_data *pin_data = &cfg->pin_data[key_index];
63 int new_pressed;
64 int ret;
65
66 ret = gpio_pin_get_dt(&pin_cfg->spec);
67 if (ret < 0) {
68 LOG_ERR("key_index %d get failed: %d", key_index, ret);
69 return;
70 }
71
72 new_pressed = ret;
73 LOG_DBG("%s: pin_state=%d, new_pressed=%d, key_index=%d", dev->name,
74 pin_data->cb_data.pin_state, new_pressed, key_index);
75
76 /* If gpio changed, report the event */
77 if (new_pressed != pin_data->cb_data.pin_state) {
78 pin_data->cb_data.pin_state = new_pressed;
79 LOG_DBG("Report event %s %d, code=%d", dev->name, new_pressed,
80 pin_cfg->zephyr_code);
81 input_report_key(dev, pin_cfg->zephyr_code, new_pressed, true, K_FOREVER);
82 }
83 }
84
gpio_keys_poll_pins(struct k_work * work)85 static __maybe_unused void gpio_keys_poll_pins(struct k_work *work)
86 {
87 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
88 struct gpio_keys_pin_data *pin_data = CONTAINER_OF(dwork, struct gpio_keys_pin_data, work);
89 const struct device *dev = pin_data->dev;
90 const struct gpio_keys_config *cfg = dev->config;
91
92 #ifdef CONFIG_PM_DEVICE
93 struct gpio_keys_data *data = dev->data;
94
95 if (atomic_get(&data->suspended) == 1) {
96 return;
97 }
98 #endif
99
100 for (int i = 0; i < cfg->num_keys; i++) {
101 gpio_keys_poll_pin(dev, i);
102 }
103
104 k_work_reschedule(dwork, K_MSEC(cfg->debounce_interval_ms));
105 }
106
gpio_keys_change_deferred(struct k_work * work)107 static __maybe_unused void gpio_keys_change_deferred(struct k_work *work)
108 {
109 const struct k_work_delayable *dwork = k_work_delayable_from_work(work);
110 const struct gpio_keys_pin_data *pin_data =
111 CONTAINER_OF(dwork, struct gpio_keys_pin_data, work);
112 const struct device *dev = pin_data->dev;
113 const struct gpio_keys_config *cfg = dev->config;
114 const int key_index = pin_data - (struct gpio_keys_pin_data *)cfg->pin_data;
115
116 #ifdef CONFIG_PM_DEVICE
117 struct gpio_keys_data *data = dev->data;
118
119 if (atomic_get(&data->suspended) == 1) {
120 return;
121 }
122 #endif
123
124 gpio_keys_poll_pin(dev, key_index);
125 }
126
gpio_keys_interrupt(const struct device * dev,struct gpio_callback * cbdata,uint32_t pins)127 static void gpio_keys_interrupt(const struct device *dev, struct gpio_callback *cbdata,
128 uint32_t pins)
129 {
130 struct gpio_keys_callback *keys_cb = CONTAINER_OF(
131 cbdata, struct gpio_keys_callback, gpio_cb);
132 struct gpio_keys_pin_data *pin_data = CONTAINER_OF(
133 keys_cb, struct gpio_keys_pin_data, cb_data);
134 const struct gpio_keys_config *cfg = pin_data->dev->config;
135
136 ARG_UNUSED(dev); /* GPIO device pointer. */
137 ARG_UNUSED(pins);
138
139 k_work_reschedule(&pin_data->work, K_MSEC(cfg->debounce_interval_ms));
140 }
141
gpio_keys_interrupt_configure(const struct gpio_dt_spec * gpio_spec,struct gpio_keys_callback * cb,uint32_t zephyr_code)142 static int gpio_keys_interrupt_configure(const struct gpio_dt_spec *gpio_spec,
143 struct gpio_keys_callback *cb, uint32_t zephyr_code)
144 {
145 int ret;
146
147 gpio_init_callback(&cb->gpio_cb, gpio_keys_interrupt, BIT(gpio_spec->pin));
148
149 ret = gpio_add_callback(gpio_spec->port, &cb->gpio_cb);
150 if (ret < 0) {
151 LOG_ERR("Could not set gpio callback");
152 return ret;
153 }
154
155 cb->pin_state = gpio_pin_get_dt(gpio_spec);
156
157 LOG_DBG("port=%s, pin=%d", gpio_spec->port->name, gpio_spec->pin);
158
159 ret = gpio_pin_interrupt_configure_dt(gpio_spec, GPIO_INT_EDGE_BOTH);
160 if (ret < 0) {
161 LOG_ERR("interrupt configuration failed: %d", ret);
162 return ret;
163 }
164
165 return 0;
166 }
167
gpio_keys_init(const struct device * dev)168 static int gpio_keys_init(const struct device *dev)
169 {
170 const struct gpio_keys_config *cfg = dev->config;
171 struct gpio_keys_pin_data *pin_data = cfg->pin_data;
172 int ret;
173
174 for (int i = 0; i < cfg->num_keys; i++) {
175 const struct gpio_dt_spec *gpio = &cfg->pin_cfg[i].spec;
176
177 if (!gpio_is_ready_dt(gpio)) {
178 LOG_ERR("%s is not ready", gpio->port->name);
179 return -ENODEV;
180 }
181
182 ret = gpio_pin_configure_dt(gpio, GPIO_INPUT);
183 if (ret != 0) {
184 LOG_ERR("Pin %d configuration failed: %d", i, ret);
185 return ret;
186 }
187
188 pin_data[i].dev = dev;
189 k_work_init_delayable(&pin_data[i].work, cfg->handler);
190
191 if (cfg->polling_mode) {
192 continue;
193 }
194
195 ret = gpio_keys_interrupt_configure(&cfg->pin_cfg[i].spec,
196 &pin_data[i].cb_data,
197 cfg->pin_cfg[i].zephyr_code);
198 if (ret != 0) {
199 LOG_ERR("Pin %d interrupt configuration failed: %d", i, ret);
200 return ret;
201 }
202 }
203
204 if (cfg->polling_mode) {
205 /* use pin 0 work to poll all the pins periodically */
206 k_work_reschedule(&pin_data[0].work, K_MSEC(cfg->debounce_interval_ms));
207 }
208
209 ret = pm_device_runtime_enable(dev);
210 if (ret < 0) {
211 LOG_ERR("Failed to enable runtime power management");
212 return ret;
213 }
214
215 return 0;
216 }
217
218 #ifdef CONFIG_PM_DEVICE
gpio_keys_pm_action(const struct device * dev,enum pm_device_action action)219 static int gpio_keys_pm_action(const struct device *dev,
220 enum pm_device_action action)
221 {
222 const struct gpio_keys_config *cfg = dev->config;
223 struct gpio_keys_data *data = dev->data;
224 struct gpio_keys_pin_data *pin_data = cfg->pin_data;
225 int ret;
226
227 switch (action) {
228 case PM_DEVICE_ACTION_SUSPEND:
229 atomic_set(&data->suspended, 1);
230
231 for (int i = 0; i < cfg->num_keys; i++) {
232 const struct gpio_dt_spec *gpio = &cfg->pin_cfg[i].spec;
233
234 if (!cfg->polling_mode) {
235 ret = gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_DISABLE);
236 if (ret < 0) {
237 LOG_ERR("interrupt configuration failed: %d", ret);
238 return ret;
239 }
240 }
241
242 if (!cfg->no_disconnect) {
243 ret = gpio_pin_configure_dt(gpio, GPIO_DISCONNECTED);
244 if (ret != 0) {
245 LOG_ERR("Pin %d configuration failed: %d", i, ret);
246 return ret;
247 }
248 }
249 }
250
251 return 0;
252 case PM_DEVICE_ACTION_RESUME:
253 atomic_set(&data->suspended, 0);
254
255 for (int i = 0; i < cfg->num_keys; i++) {
256 const struct gpio_dt_spec *gpio = &cfg->pin_cfg[i].spec;
257
258 if (!cfg->no_disconnect) {
259 ret = gpio_pin_configure_dt(gpio, GPIO_INPUT);
260 if (ret != 0) {
261 LOG_ERR("Pin %d configuration failed: %d", i, ret);
262 return ret;
263 }
264 }
265
266 if (cfg->polling_mode) {
267 k_work_reschedule(&pin_data[0].work,
268 K_MSEC(cfg->debounce_interval_ms));
269 } else {
270 pin_data[i].cb_data.pin_state = gpio_pin_get_dt(gpio);
271 ret = gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_BOTH);
272 if (ret < 0) {
273 LOG_ERR("interrupt configuration failed: %d", ret);
274 return ret;
275 }
276 }
277 }
278
279 return 0;
280 default:
281 return -ENOTSUP;
282 }
283 }
284 #endif
285
286 #define GPIO_KEYS_CFG_CHECK(node_id) \
287 BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, zephyr_code), \
288 "zephyr-code must be specified to use the input-gpio-keys driver");
289
290 #define GPIO_KEYS_CFG_DEF(node_id) \
291 { \
292 .spec = GPIO_DT_SPEC_GET(node_id, gpios), \
293 .zephyr_code = DT_PROP(node_id, zephyr_code), \
294 }
295
296 #define GPIO_KEYS_INIT(i) \
297 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, GPIO_KEYS_CFG_CHECK); \
298 \
299 static const struct gpio_keys_pin_config gpio_keys_pin_config_##i[] = { \
300 DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(i, GPIO_KEYS_CFG_DEF, (,))}; \
301 \
302 static struct gpio_keys_pin_data \
303 gpio_keys_pin_data_##i[ARRAY_SIZE(gpio_keys_pin_config_##i)]; \
304 \
305 static const struct gpio_keys_config gpio_keys_config_##i = { \
306 .debounce_interval_ms = DT_INST_PROP(i, debounce_interval_ms), \
307 .num_keys = ARRAY_SIZE(gpio_keys_pin_config_##i), \
308 .pin_cfg = gpio_keys_pin_config_##i, \
309 .pin_data = gpio_keys_pin_data_##i, \
310 .handler = COND_CODE_1(DT_INST_PROP(i, polling_mode), \
311 (gpio_keys_poll_pins), (gpio_keys_change_deferred)), \
312 .polling_mode = DT_INST_PROP(i, polling_mode), \
313 .no_disconnect = DT_INST_PROP(i, no_disconnect), \
314 }; \
315 \
316 static struct gpio_keys_data gpio_keys_data_##i; \
317 \
318 PM_DEVICE_DT_INST_DEFINE(i, gpio_keys_pm_action); \
319 \
320 DEVICE_DT_INST_DEFINE(i, &gpio_keys_init, PM_DEVICE_DT_INST_GET(i), \
321 &gpio_keys_data_##i, &gpio_keys_config_##i, \
322 POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL);
323
324 DT_INST_FOREACH_STATUS_OKAY(GPIO_KEYS_INIT)
325