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