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 int8_t pin_state;
37 };
38
39 struct gpio_keys_config {
40 /** Debounce interval in milliseconds from devicetree */
41 uint32_t debounce_interval_ms;
42 const int num_keys;
43 const struct gpio_keys_pin_config *pin_cfg;
44 struct gpio_keys_pin_data *pin_data;
45 k_work_handler_t handler;
46 bool polling_mode;
47 bool no_disconnect;
48 };
49
50 struct gpio_keys_data {
51 #ifdef CONFIG_PM_DEVICE
52 atomic_t suspended;
53 #endif
54 };
55
56 /**
57 * Handle debounced gpio pin state.
58 */
gpio_keys_poll_pin(const struct device * dev,int key_index)59 static void gpio_keys_poll_pin(const struct device *dev, int key_index)
60 {
61 const struct gpio_keys_config *cfg = dev->config;
62 const struct gpio_keys_pin_config *pin_cfg = &cfg->pin_cfg[key_index];
63 struct gpio_keys_pin_data *pin_data = &cfg->pin_data[key_index];
64 int new_pressed;
65 int ret;
66
67 ret = gpio_pin_get_dt(&pin_cfg->spec);
68 if (ret < 0) {
69 LOG_ERR("key_index %d get failed: %d", key_index, ret);
70 return;
71 }
72
73 new_pressed = ret;
74 LOG_DBG("%s: pin_state=%d, new_pressed=%d, key_index=%d", dev->name,
75 pin_data->cb_data.pin_state, new_pressed, key_index);
76
77 /* If gpio changed, report the event */
78 if (new_pressed != pin_data->cb_data.pin_state) {
79 pin_data->cb_data.pin_state = new_pressed;
80 LOG_DBG("Report event %s %d, code=%d", dev->name, new_pressed,
81 pin_cfg->zephyr_code);
82 input_report_key(dev, pin_cfg->zephyr_code, new_pressed, true, K_FOREVER);
83 }
84 }
85
gpio_keys_poll_pins(struct k_work * work)86 static __maybe_unused void gpio_keys_poll_pins(struct k_work *work)
87 {
88 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
89 struct gpio_keys_pin_data *pin_data = CONTAINER_OF(dwork, struct gpio_keys_pin_data, work);
90 const struct device *dev = pin_data->dev;
91 const struct gpio_keys_config *cfg = dev->config;
92
93 #ifdef CONFIG_PM_DEVICE
94 struct gpio_keys_data *data = dev->data;
95
96 if (atomic_get(&data->suspended) == 1) {
97 return;
98 }
99 #endif
100
101 for (int i = 0; i < cfg->num_keys; i++) {
102 gpio_keys_poll_pin(dev, i);
103 }
104
105 k_work_reschedule(dwork, K_MSEC(cfg->debounce_interval_ms));
106 }
107
gpio_keys_change_deferred(struct k_work * work)108 static __maybe_unused void gpio_keys_change_deferred(struct k_work *work)
109 {
110 struct k_work_delayable *dwork = k_work_delayable_from_work(work);
111 struct gpio_keys_pin_data *pin_data = 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 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 ret = gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_BOTH);
271 if (ret < 0) {
272 LOG_ERR("interrupt configuration failed: %d", ret);
273 return ret;
274 }
275 }
276 }
277
278 return 0;
279 default:
280 return -ENOTSUP;
281 }
282 }
283 #endif
284
285 #define GPIO_KEYS_CFG_CHECK(node_id) \
286 BUILD_ASSERT(DT_NODE_HAS_PROP(node_id, zephyr_code), \
287 "zephyr-code must be specified to use the input-gpio-keys driver");
288
289 #define GPIO_KEYS_CFG_DEF(node_id) \
290 { \
291 .spec = GPIO_DT_SPEC_GET(node_id, gpios), \
292 .zephyr_code = DT_PROP(node_id, zephyr_code), \
293 }
294
295 #define GPIO_KEYS_INIT(i) \
296 DT_INST_FOREACH_CHILD_STATUS_OKAY(i, GPIO_KEYS_CFG_CHECK); \
297 \
298 static const struct gpio_keys_pin_config gpio_keys_pin_config_##i[] = { \
299 DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(i, GPIO_KEYS_CFG_DEF, (,))}; \
300 \
301 static struct gpio_keys_pin_data \
302 gpio_keys_pin_data_##i[ARRAY_SIZE(gpio_keys_pin_config_##i)]; \
303 \
304 static const struct gpio_keys_config gpio_keys_config_##i = { \
305 .debounce_interval_ms = DT_INST_PROP(i, debounce_interval_ms), \
306 .num_keys = ARRAY_SIZE(gpio_keys_pin_config_##i), \
307 .pin_cfg = gpio_keys_pin_config_##i, \
308 .pin_data = gpio_keys_pin_data_##i, \
309 .handler = COND_CODE_1(DT_INST_PROP(i, polling_mode), \
310 (gpio_keys_poll_pins), (gpio_keys_change_deferred)), \
311 .polling_mode = DT_INST_PROP(i, polling_mode), \
312 .no_disconnect = DT_INST_PROP(i, no_disconnect), \
313 }; \
314 \
315 static struct gpio_keys_data gpio_keys_data_##i; \
316 \
317 PM_DEVICE_DT_INST_DEFINE(i, gpio_keys_pm_action); \
318 \
319 DEVICE_DT_INST_DEFINE(i, &gpio_keys_init, PM_DEVICE_DT_INST_GET(i), \
320 &gpio_keys_data_##i, &gpio_keys_config_##i, \
321 POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL);
322
323 DT_INST_FOREACH_STATUS_OKAY(GPIO_KEYS_INIT)
324