1 /*
2 * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT zephyr_gpio_emul
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/gpio.h>
11 #include <zephyr/drivers/gpio/gpio_emul.h>
12 #include <errno.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/pm/device.h>
15
16 #include <zephyr/drivers/gpio/gpio_utils.h>
17
18 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(gpio_emul);
21
22 #define GPIO_EMUL_INT_BITMASK \
23 (GPIO_INT_DISABLE | GPIO_INT_ENABLE | GPIO_INT_LEVELS_LOGICAL | \
24 GPIO_INT_EDGE | GPIO_INT_LOW_0 | GPIO_INT_HIGH_1)
25
26 /**
27 * @brief GPIO Emulator interrupt capabilities
28 *
29 * These enumerations are used as a bitmask and allow the GPIO Emulator to
30 * model GPIO interrupt controllers with varying interrupt trigger support.
31 *
32 * For example, some controllers to not support level interrupts,
33 * some controllers do not support rising and falling edge simultaneously,
34 * etc.
35 *
36 * This primarily affects the behaviour of @ref gpio_pin_interrupt_configure.
37 */
38 enum gpio_emul_interrupt_cap {
39 GPIO_EMUL_INT_CAP_EDGE_RISING = 1,
40 GPIO_EMUL_INT_CAP_EDGE_FALLING = 2,
41 GPIO_EMUL_INT_CAP_LEVEL_HIGH = 16,
42 GPIO_EMUL_INT_CAP_LEVEL_LOW = 32,
43 };
44
45 /**
46 * @brief Emulated GPIO controller configuration data
47 *
48 * This structure contains all of the state for a given emulated GPIO
49 * controller as well as all of the pins associated with it.
50 *
51 * The @a flags member is a pointer to an array which is @a num_pins in size.
52 *
53 * @a num_pins must be in the range [1, @ref GPIO_MAX_PINS_PER_PORT].
54 *
55 * Pin direction as well as other pin properties are set using
56 * specific bits in @a flags. For more details, see @ref gpio_interface.
57 *
58 * Changes are synchronized using @ref gpio_emul_data.mu.
59 */
60 struct gpio_emul_config {
61 /** Common @ref gpio_driver_config */
62 const struct gpio_driver_config common;
63 /** Number of pins available in the given GPIO controller instance */
64 const gpio_pin_t num_pins;
65 /** Supported interrupts */
66 const enum gpio_emul_interrupt_cap interrupt_caps;
67 };
68
69 /**
70 * @brief Emulated GPIO controller data
71 *
72 * This structure contains data structures used by a emulated GPIO
73 * controller.
74 *
75 * If the application wishes to specify a "wiring" for the emulated
76 * GPIO, then a @ref gpio_callback_handler_t should be registered using
77 * @ref gpio_add_callback.
78 *
79 * Changes are to @ref gpio_emul_data and @ref gpio_emul_config are
80 * synchronized using @a k_spinlock.
81 */
82 struct gpio_emul_data {
83 /** Common @ref gpio_driver_data */
84 struct gpio_driver_data common;
85 /** Pointer to an array of flags is @a num_pins in size */
86 gpio_flags_t *flags;
87 /** Input values for each pin */
88 gpio_port_value_t input_vals;
89 /** Output values for each pin */
90 gpio_port_value_t output_vals;
91 /** Interrupt status for each pin */
92 gpio_port_pins_t interrupts;
93 /** Spinlock to synchronize accesses to driver data and config */
94 struct k_spinlock lock;
95 /** Is interrupt enabled for each pin */
96 gpio_port_pins_t enabled_interrupts;
97 /** Singly-linked list of callbacks associated with the controller */
98 sys_slist_t callbacks;
99 };
100
101 /**
102 * @brief Obtain a mask of pins that match all of the provided @p flags
103 *
104 * Use this function to see which pins match the current GPIO configuration.
105 *
106 * The caller must ensure that @ref gpio_emul_data.lock is locked.
107 *
108 * @param port The emulated GPIO device pointer
109 * @param mask A mask of flags to match
110 * @param flags The flags to match
111 *
112 * @return a mask of the pins with matching @p flags
113 */
114 static gpio_port_pins_t
get_pins_with_flags(const struct device * port,gpio_port_pins_t mask,gpio_flags_t flags)115 get_pins_with_flags(const struct device *port, gpio_port_pins_t mask,
116 gpio_flags_t flags)
117 {
118 size_t i;
119 gpio_port_pins_t matched = 0;
120 struct gpio_emul_data *drv_data =
121 (struct gpio_emul_data *)port->data;
122 const struct gpio_emul_config *config =
123 (const struct gpio_emul_config *)port->config;
124
125 for (i = 0; i < config->num_pins; ++i) {
126 if ((drv_data->flags[i] & mask) == flags) {
127 matched |= BIT(i);
128 }
129 }
130
131 return matched;
132 }
133
134 /**
135 * @brief Obtain a mask of pins that are configured as @ref GPIO_INPUT
136 *
137 * The caller must ensure that @ref gpio_emul_data.lock is locked.
138 *
139 * @param port The emulated GPIO device pointer
140 *
141 * @return a mask of pins that are configured as @ref GPIO_INPUT
142 */
get_input_pins(const struct device * port)143 static inline gpio_port_pins_t get_input_pins(const struct device *port)
144 {
145 return get_pins_with_flags(port, GPIO_INPUT, GPIO_INPUT);
146 }
147
148 /**
149 * @brief Obtain a mask of pins that are configured as @ref GPIO_OUTPUT
150 *
151 * The caller must ensure that @ref gpio_emul_data.lock is locked.
152 *
153 * @param port The emulated GPIO device pointer
154 *
155 * @return a mask of pins that are configured as @ref GPIO_OUTPUT
156 */
get_output_pins(const struct device * port)157 static inline gpio_port_pins_t get_output_pins(const struct device *port)
158 {
159 return get_pins_with_flags(port, GPIO_OUTPUT, GPIO_OUTPUT);
160 }
161
162 /**
163 * Check if @p port has capabilities specified in @p caps
164 *
165 * @param port The emulated GPIO device pointer
166 * @param caps A bitmask of @ref gpio_emul_interrupt_cap
167 *
168 * @return true if all @p caps are present, otherwise false
169 */
gpio_emul_config_has_caps(const struct device * port,int caps)170 static inline bool gpio_emul_config_has_caps(const struct device *port,
171 int caps) {
172
173 const struct gpio_emul_config *config =
174 (const struct gpio_emul_config *)port->config;
175
176 return (caps & config->interrupt_caps) == caps;
177 }
178
179 /*
180 * GPIO backend API (for setting input pin values)
181 */
gpio_emul_gen_interrupt_bits(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t prev_values,gpio_port_value_t values,gpio_port_pins_t * interrupts,bool detect_edge)182 static void gpio_emul_gen_interrupt_bits(const struct device *port,
183 gpio_port_pins_t mask,
184 gpio_port_value_t prev_values,
185 gpio_port_value_t values,
186 gpio_port_pins_t *interrupts,
187 bool detect_edge)
188 {
189 size_t i;
190 bool bit;
191 bool prev_bit;
192 struct gpio_emul_data *drv_data =
193 (struct gpio_emul_data *)port->data;
194 const struct gpio_emul_config *config =
195 (const struct gpio_emul_config *)port->config;
196
197 for (i = 0, *interrupts = 0; mask && i < config->num_pins;
198 ++i, mask >>= 1, prev_values >>= 1, values >>= 1) {
199 if ((mask & 1) == 0) {
200 continue;
201 }
202
203 prev_bit = ((prev_values & 1) != 0);
204 bit = ((values & 1) != 0);
205
206 switch (drv_data->flags[i] & GPIO_EMUL_INT_BITMASK) {
207 case GPIO_INT_EDGE_RISING:
208 if (gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_EDGE_RISING)) {
209 if (detect_edge && !prev_bit && bit) {
210 drv_data->interrupts |= BIT(i);
211 *interrupts |= (BIT(i) & drv_data->enabled_interrupts);
212 }
213 }
214 break;
215 case GPIO_INT_EDGE_FALLING:
216 if (gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_EDGE_FALLING)) {
217 if (detect_edge && prev_bit && !bit) {
218 drv_data->interrupts |= BIT(i);
219 *interrupts |= (BIT(i) & drv_data->enabled_interrupts);
220 }
221 }
222 break;
223 case GPIO_INT_EDGE_BOTH:
224 if (gpio_emul_config_has_caps(port,
225 GPIO_EMUL_INT_CAP_EDGE_RISING | GPIO_EMUL_INT_CAP_EDGE_FALLING)) {
226 if (detect_edge && prev_bit != bit) {
227 drv_data->interrupts |= BIT(i);
228 *interrupts |= (BIT(i) & drv_data->enabled_interrupts);
229 }
230 }
231 break;
232 case GPIO_INT_LEVEL_LOW:
233 if (gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_LEVEL_LOW)) {
234 if (!bit) {
235 drv_data->interrupts |= BIT(i);
236 *interrupts |= (BIT(i) & drv_data->enabled_interrupts);
237 }
238 }
239 break;
240 case GPIO_INT_LEVEL_HIGH:
241 if (gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_LEVEL_HIGH)) {
242 if (bit) {
243 drv_data->interrupts |= BIT(i);
244 *interrupts |= (BIT(i) & drv_data->enabled_interrupts);
245 }
246 }
247 break;
248 case 0:
249 case GPIO_INT_DISABLE:
250 break;
251 default:
252 LOG_DBG("unhandled case %u",
253 drv_data->flags[i] & GPIO_EMUL_INT_BITMASK);
254 break;
255 }
256 }
257 }
258
259 /**
260 * @brief Trigger possible interrupt events after an input pin has changed
261 *
262 * For more information, see @ref gpio_interface.
263 *
264 * The caller must ensure that @ref gpio_emul_data.lock is locked.
265 *
266 * @param port The emulated GPIO port
267 * @param mask The mask of pins that have changed
268 * @param prev_values Previous pin values
269 * @param values Current pin values
270 */
gpio_emul_pend_interrupt(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t prev_values,gpio_port_value_t values)271 static void gpio_emul_pend_interrupt(const struct device *port, gpio_port_pins_t mask,
272 gpio_port_value_t prev_values,
273 gpio_port_value_t values)
274 {
275 gpio_port_pins_t interrupts;
276 struct gpio_emul_data *drv_data =
277 (struct gpio_emul_data *)port->data;
278 k_spinlock_key_t key;
279
280 key = k_spin_lock(&drv_data->lock);
281 gpio_emul_gen_interrupt_bits(port, mask, prev_values, values,
282 &interrupts, true);
283 while (interrupts != 0) {
284 k_spin_unlock(&drv_data->lock, key);
285 gpio_fire_callbacks(&drv_data->callbacks, port, interrupts);
286 key = k_spin_lock(&drv_data->lock);
287 /* Clear handled interrupts */
288 drv_data->interrupts &= ~interrupts;
289 gpio_emul_gen_interrupt_bits(port, mask, prev_values, values,
290 &interrupts, false);
291 }
292
293 k_spin_unlock(&drv_data->lock, key);
294 }
295
gpio_emul_input_set_masked_int(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t values)296 int gpio_emul_input_set_masked_int(const struct device *port,
297 gpio_port_pins_t mask,
298 gpio_port_value_t values)
299 {
300 gpio_port_pins_t input_mask;
301 gpio_port_pins_t prev_values;
302 struct gpio_emul_data *drv_data =
303 (struct gpio_emul_data *)port->data;
304 const struct gpio_emul_config *config =
305 (const struct gpio_emul_config *)port->config;
306
307 if (mask == 0) {
308 return 0;
309 }
310
311 if (~config->common.port_pin_mask & mask) {
312 LOG_ERR("Pin not supported port_pin_mask=%x mask=%x",
313 config->common.port_pin_mask, mask);
314 return -EINVAL;
315 }
316
317 input_mask = get_input_pins(port);
318 if (~input_mask & mask) {
319 LOG_ERR("Not input pin input_mask=%x mask=%x", input_mask,
320 mask);
321 return -EINVAL;
322 }
323
324 prev_values = drv_data->input_vals;
325 drv_data->input_vals &= ~mask;
326 drv_data->input_vals |= values & mask;
327
328 return 0;
329 }
330
331 /* documented in drivers/gpio/gpio_emul.h */
gpio_emul_input_set_masked(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t values)332 int gpio_emul_input_set_masked(const struct device *port, gpio_port_pins_t mask,
333 gpio_port_value_t values)
334 {
335 struct gpio_emul_data *drv_data = (struct gpio_emul_data *)port->data;
336 gpio_port_pins_t prev_input_values;
337 gpio_port_pins_t input_values;
338 k_spinlock_key_t key;
339 int rv;
340
341 key = k_spin_lock(&drv_data->lock);
342 prev_input_values = drv_data->input_vals;
343 rv = gpio_emul_input_set_masked_int(port, mask, values);
344 input_values = drv_data->input_vals;
345 k_spin_unlock(&drv_data->lock, key);
346 if (rv) {
347 return rv;
348 }
349
350 gpio_emul_pend_interrupt(port, mask, prev_input_values, input_values);
351 return 0;
352 }
353
354 /* documented in drivers/gpio/gpio_emul.h */
gpio_emul_output_get_masked(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t * values)355 int gpio_emul_output_get_masked(const struct device *port, gpio_port_pins_t mask,
356 gpio_port_value_t *values)
357 {
358 struct gpio_emul_data *drv_data =
359 (struct gpio_emul_data *)port->data;
360 const struct gpio_emul_config *config =
361 (const struct gpio_emul_config *)port->config;
362 k_spinlock_key_t key;
363
364 if (mask == 0) {
365 return 0;
366 }
367
368 if (~config->common.port_pin_mask & mask) {
369 return -EINVAL;
370 }
371
372 key = k_spin_lock(&drv_data->lock);
373 *values = drv_data->output_vals & get_output_pins(port);
374 k_spin_unlock(&drv_data->lock, key);
375
376 return 0;
377 }
378
379 /* documented in drivers/gpio/gpio_emul.h */
gpio_emul_flags_get(const struct device * port,gpio_pin_t pin,gpio_flags_t * flags)380 int gpio_emul_flags_get(const struct device *port, gpio_pin_t pin, gpio_flags_t *flags)
381 {
382 struct gpio_emul_data *drv_data =
383 (struct gpio_emul_data *)port->data;
384 const struct gpio_emul_config *config =
385 (const struct gpio_emul_config *)port->config;
386 k_spinlock_key_t key;
387
388 if (flags == NULL) {
389 return -EINVAL;
390 }
391
392 if ((config->common.port_pin_mask & BIT(pin)) == 0) {
393 return -EINVAL;
394 }
395
396 key = k_spin_lock(&drv_data->lock);
397 *flags = drv_data->flags[pin];
398 k_spin_unlock(&drv_data->lock, key);
399
400 return 0;
401 }
402
403 /*
404 * GPIO Driver API
405 *
406 * API is documented at drivers/gpio.h
407 */
408
gpio_emul_pin_configure(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)409 static int gpio_emul_pin_configure(const struct device *port, gpio_pin_t pin,
410 gpio_flags_t flags)
411 {
412 struct gpio_emul_data *drv_data =
413 (struct gpio_emul_data *)port->data;
414 const struct gpio_emul_config *config =
415 (const struct gpio_emul_config *)port->config;
416 k_spinlock_key_t key;
417 int rv;
418
419 if (flags & GPIO_OPEN_DRAIN) {
420 return -ENOTSUP;
421 }
422
423 if (flags & GPIO_OPEN_SOURCE) {
424 return -ENOTSUP;
425 }
426
427 if ((config->common.port_pin_mask & BIT(pin)) == 0) {
428 return -EINVAL;
429 }
430
431 key = k_spin_lock(&drv_data->lock);
432 drv_data->flags[pin] = flags;
433 if (flags & GPIO_OUTPUT) {
434 if (flags & GPIO_OUTPUT_INIT_LOW) {
435 drv_data->output_vals &= ~BIT(pin);
436 if (flags & GPIO_INPUT) {
437 /* for push-pull mode to generate interrupts */
438 rv = gpio_emul_input_set_masked_int(
439 port, BIT(pin), drv_data->output_vals);
440 __ASSERT_NO_MSG(rv == 0);
441 }
442 } else if (flags & GPIO_OUTPUT_INIT_HIGH) {
443 drv_data->output_vals |= BIT(pin);
444 if (flags & GPIO_INPUT) {
445 /* for push-pull mode to generate interrupts */
446 rv = gpio_emul_input_set_masked_int(
447 port, BIT(pin), drv_data->output_vals);
448 __ASSERT_NO_MSG(rv == 0);
449 }
450 }
451 } else if (flags & GPIO_INPUT) {
452 if (flags & GPIO_PULL_UP) {
453 rv = gpio_emul_input_set_masked_int(port, BIT(pin), BIT(pin));
454 __ASSERT_NO_MSG(rv == 0);
455 } else if (flags & GPIO_PULL_DOWN) {
456 rv = gpio_emul_input_set_masked_int(
457 port, BIT(pin), 0);
458 __ASSERT_NO_MSG(rv == 0);
459 }
460 }
461
462 k_spin_unlock(&drv_data->lock, key);
463 gpio_fire_callbacks(&drv_data->callbacks, port, BIT(pin));
464 /* GPIO pin configuration changed so clear the pending interrupt. */
465 drv_data->interrupts &= ~((gpio_port_pins_t)BIT(pin));
466
467 return 0;
468 }
469
470 #ifdef CONFIG_GPIO_GET_CONFIG
gpio_emul_pin_get_config(const struct device * port,gpio_pin_t pin,gpio_flags_t * out_flags)471 static int gpio_emul_pin_get_config(const struct device *port, gpio_pin_t pin,
472 gpio_flags_t *out_flags)
473 {
474 struct gpio_emul_data *drv_data =
475 (struct gpio_emul_data *)port->data;
476 k_spinlock_key_t key;
477
478 key = k_spin_lock(&drv_data->lock);
479
480 *out_flags = drv_data->flags[pin] &
481 ~(GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH
482 | GPIO_OUTPUT_INIT_LOGICAL);
483 if (drv_data->flags[pin] & GPIO_OUTPUT) {
484 if (drv_data->output_vals & BIT(pin)) {
485 *out_flags |= GPIO_OUTPUT_HIGH;
486 } else {
487 *out_flags |= GPIO_OUTPUT_LOW;
488 }
489 }
490
491 k_spin_unlock(&drv_data->lock, key);
492
493 return 0;
494 }
495 #endif
496
gpio_emul_port_get_raw(const struct device * port,gpio_port_value_t * values)497 static int gpio_emul_port_get_raw(const struct device *port, gpio_port_value_t *values)
498 {
499 struct gpio_emul_data *drv_data =
500 (struct gpio_emul_data *)port->data;
501 k_spinlock_key_t key;
502
503 if (values == NULL) {
504 return -EINVAL;
505 }
506
507 key = k_spin_lock(&drv_data->lock);
508 *values = drv_data->input_vals & get_input_pins(port);
509 k_spin_unlock(&drv_data->lock, key);
510
511 return 0;
512 }
513
gpio_emul_port_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t values)514 static int gpio_emul_port_set_masked_raw(const struct device *port,
515 gpio_port_pins_t mask,
516 gpio_port_value_t values)
517 {
518 gpio_port_pins_t output_mask;
519 gpio_port_pins_t prev_values;
520 gpio_port_pins_t prev_input_values;
521 gpio_port_pins_t input_values;
522 gpio_port_pins_t input_mask;
523 struct gpio_emul_data *drv_data =
524 (struct gpio_emul_data *)port->data;
525 k_spinlock_key_t key;
526 int rv;
527
528 key = k_spin_lock(&drv_data->lock);
529 output_mask = get_output_pins(port);
530 mask &= output_mask;
531 prev_values = drv_data->output_vals;
532 prev_values &= output_mask;
533 values &= mask;
534 drv_data->output_vals &= ~mask;
535 drv_data->output_vals |= values;
536 /* in push-pull, set input values & fire interrupts */
537 prev_input_values = drv_data->input_vals;
538 input_mask = mask & get_input_pins(port);
539 rv = gpio_emul_input_set_masked_int(port, input_mask,
540 drv_data->output_vals);
541 input_values = drv_data->input_vals;
542 k_spin_unlock(&drv_data->lock, key);
543 __ASSERT_NO_MSG(rv == 0);
544 gpio_emul_pend_interrupt(port, input_mask, prev_input_values, input_values);
545
546 /* for output-wiring, so the user can take action based on output */
547 if (prev_values ^ values) {
548 gpio_fire_callbacks(&drv_data->callbacks, port, mask & ~get_input_pins(port));
549 }
550
551 return 0;
552 }
553
gpio_emul_port_set_bits_raw(const struct device * port,gpio_port_pins_t pins)554 static int gpio_emul_port_set_bits_raw(const struct device *port,
555 gpio_port_pins_t pins)
556 {
557 struct gpio_emul_data *drv_data =
558 (struct gpio_emul_data *)port->data;
559 k_spinlock_key_t key;
560 gpio_port_pins_t prev_input_values;
561 gpio_port_pins_t input_values;
562 gpio_port_pins_t input_mask;
563 int rv;
564
565 key = k_spin_lock(&drv_data->lock);
566 pins &= get_output_pins(port);
567 drv_data->output_vals |= pins;
568 prev_input_values = drv_data->input_vals;
569 input_mask = pins & get_input_pins(port);
570 rv = gpio_emul_input_set_masked_int(port, input_mask,
571 drv_data->output_vals);
572 input_values = drv_data->input_vals;
573 k_spin_unlock(&drv_data->lock, key);
574 __ASSERT_NO_MSG(rv == 0);
575 gpio_emul_pend_interrupt(port, input_mask, prev_input_values, input_values);
576 /* for output-wiring, so the user can take action based on output */
577 gpio_fire_callbacks(&drv_data->callbacks, port, pins & ~get_input_pins(port));
578
579 return 0;
580 }
581
gpio_emul_port_clear_bits_raw(const struct device * port,gpio_port_pins_t pins)582 static int gpio_emul_port_clear_bits_raw(const struct device *port,
583 gpio_port_pins_t pins)
584 {
585 struct gpio_emul_data *drv_data =
586 (struct gpio_emul_data *)port->data;
587 k_spinlock_key_t key;
588 gpio_port_pins_t prev_input_values;
589 gpio_port_pins_t input_values;
590 gpio_port_pins_t input_mask;
591 int rv;
592
593 key = k_spin_lock(&drv_data->lock);
594 pins &= get_output_pins(port);
595 drv_data->output_vals &= ~pins;
596 prev_input_values = drv_data->input_vals;
597 input_mask = pins & get_input_pins(port);
598 rv = gpio_emul_input_set_masked_int(port, input_mask, drv_data->output_vals);
599 input_values = drv_data->input_vals;
600 k_spin_unlock(&drv_data->lock, key);
601 __ASSERT_NO_MSG(rv == 0);
602 gpio_emul_pend_interrupt(port, input_mask, prev_input_values, input_values);
603 /* for output-wiring, so the user can take action based on output */
604 gpio_fire_callbacks(&drv_data->callbacks, port, pins & ~get_input_pins(port));
605
606 return 0;
607 }
608
gpio_emul_port_toggle_bits(const struct device * port,gpio_port_pins_t pins)609 static int gpio_emul_port_toggle_bits(const struct device *port, gpio_port_pins_t pins)
610 {
611 struct gpio_emul_data *drv_data =
612 (struct gpio_emul_data *)port->data;
613 k_spinlock_key_t key;
614 int rv;
615
616 key = k_spin_lock(&drv_data->lock);
617 drv_data->output_vals ^= (pins & get_output_pins(port));
618 /* in push-pull, set input values but do not fire interrupts (yet) */
619 rv = gpio_emul_input_set_masked_int(port, pins & get_input_pins(port),
620 drv_data->output_vals);
621 k_spin_unlock(&drv_data->lock, key);
622 __ASSERT_NO_MSG(rv == 0);
623 /* for output-wiring, so the user can take action based on output */
624 gpio_fire_callbacks(&drv_data->callbacks, port, pins);
625
626 return 0;
627 }
628
gpio_emul_level_trigger_supported(const struct device * port,enum gpio_int_trig trig)629 static bool gpio_emul_level_trigger_supported(const struct device *port,
630 enum gpio_int_trig trig)
631 {
632 switch (trig) {
633 case GPIO_INT_TRIG_LOW:
634 return gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_LEVEL_LOW);
635 case GPIO_INT_TRIG_HIGH:
636 return gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_LEVEL_HIGH);
637 case GPIO_INT_TRIG_BOTH:
638 return gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_LEVEL_LOW
639 | GPIO_EMUL_INT_CAP_LEVEL_HIGH);
640 default:
641 return false;
642 }
643 }
644
gpio_emul_edge_trigger_supported(const struct device * port,enum gpio_int_trig trig)645 static bool gpio_emul_edge_trigger_supported(const struct device *port,
646 enum gpio_int_trig trig)
647 {
648 switch (trig) {
649 case GPIO_INT_TRIG_LOW:
650 return gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_EDGE_FALLING);
651 case GPIO_INT_TRIG_HIGH:
652 return gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_EDGE_RISING);
653 case GPIO_INT_TRIG_BOTH:
654 return gpio_emul_config_has_caps(port, GPIO_EMUL_INT_CAP_EDGE_FALLING
655 | GPIO_EMUL_INT_CAP_EDGE_RISING);
656 default:
657 return false;
658 }
659 }
660
gpio_emul_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)661 static int gpio_emul_pin_interrupt_configure(const struct device *port, gpio_pin_t pin,
662 enum gpio_int_mode mode,
663 enum gpio_int_trig trig)
664 {
665 int ret;
666 struct gpio_emul_data *drv_data =
667 (struct gpio_emul_data *)port->data;
668 const struct gpio_emul_config *config =
669 (const struct gpio_emul_config *)port->config;
670 k_spinlock_key_t key;
671
672 if ((BIT(pin) & config->common.port_pin_mask) == 0) {
673 return -EINVAL;
674 }
675
676 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
677 if (mode != GPIO_INT_MODE_DISABLED && !(mode & GPIO_INT_ENABLE_DISABLE_ONLY)) {
678 #else
679 if (mode != GPIO_INT_MODE_DISABLED) {
680 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
681 switch (trig) {
682 case GPIO_INT_TRIG_LOW:
683 case GPIO_INT_TRIG_HIGH:
684 case GPIO_INT_TRIG_BOTH:
685 break;
686 default:
687 return -EINVAL;
688 }
689 }
690
691 if (mode == GPIO_INT_MODE_LEVEL) {
692 if (!gpio_emul_level_trigger_supported(port, trig)) {
693 return -ENOTSUP;
694 }
695 }
696
697 if (mode == GPIO_INT_MODE_EDGE) {
698 if (!gpio_emul_edge_trigger_supported(port, trig)) {
699 return -ENOTSUP;
700 }
701 }
702
703 key = k_spin_lock(&drv_data->lock);
704
705 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
706 /* According to the GPIO interrupt configuration flag documentation,
707 * changes to the interrupt trigger properties should clear pending
708 * interrupts.
709 */
710 if (!(mode & GPIO_INT_ENABLE_DISABLE_ONLY)) {
711 drv_data->interrupts &= ~((gpio_port_pins_t)BIT(pin));
712 }
713 #else
714 drv_data->interrupts &= ~((gpio_port_pins_t)BIT(pin));
715 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
716
717 switch (mode) {
718 case GPIO_INT_MODE_DISABLED:
719 drv_data->flags[pin] &= ~GPIO_EMUL_INT_BITMASK;
720 drv_data->flags[pin] |= GPIO_INT_DISABLE;
721 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
722 __fallthrough;
723 case GPIO_INT_MODE_DISABLE_ONLY:
724 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
725 drv_data->enabled_interrupts &= ~((gpio_port_pins_t)BIT(pin));
726 break;
727 case GPIO_INT_MODE_LEVEL:
728 case GPIO_INT_MODE_EDGE:
729 drv_data->flags[pin] &= ~GPIO_EMUL_INT_BITMASK;
730 drv_data->flags[pin] |= (mode | trig);
731 #ifdef CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT
732 __fallthrough;
733 case GPIO_INT_MODE_ENABLE_ONLY:
734 #endif /* CONFIG_GPIO_ENABLE_DISABLE_INTERRUPT */
735 drv_data->enabled_interrupts |= BIT(pin);
736 break;
737 default:
738 ret = -EINVAL;
739 goto unlock;
740 }
741
742 ret = 0;
743
744 unlock:
745 k_spin_unlock(&drv_data->lock, key);
746
747 /* Trigger callback if this pin has pending interrupt */
748 if (BIT(pin) & (drv_data->interrupts & drv_data->enabled_interrupts)) {
749 gpio_fire_callbacks(&drv_data->callbacks, port, BIT(pin));
750 drv_data->interrupts &= ~((gpio_port_pins_t)BIT(pin));
751 }
752
753 return ret;
754 }
755
756 static int gpio_emul_manage_callback(const struct device *port,
757 struct gpio_callback *cb, bool set)
758 {
759 struct gpio_emul_data *drv_data =
760 (struct gpio_emul_data *)port->data;
761
762 return gpio_manage_callback(&drv_data->callbacks, cb, set);
763 }
764
765 static gpio_port_pins_t gpio_emul_get_pending_int(const struct device *dev)
766 {
767 struct gpio_emul_data *drv_data =
768 (struct gpio_emul_data *)dev->data;
769
770 return drv_data->interrupts;
771 }
772
773 #ifdef CONFIG_GPIO_GET_DIRECTION
774 static int gpio_emul_port_get_direction(const struct device *port, gpio_port_pins_t map,
775 gpio_port_pins_t *inputs, gpio_port_pins_t *outputs)
776 {
777 int i;
778 gpio_port_pins_t ip = 0;
779 gpio_port_pins_t op = 0;
780 struct gpio_emul_data *const drv_data = (struct gpio_emul_data *)port->data;
781 const struct gpio_emul_config *config = (const struct gpio_emul_config *)port->config;
782
783 map &= config->common.port_pin_mask;
784
785 if (inputs != NULL) {
786 for (i = find_lsb_set(map) - 1; map;
787 map &= ~BIT(i), i = find_lsb_set(map) - 1) {
788 ip |= !!(drv_data->flags[i] & GPIO_INPUT) * BIT(i);
789 }
790
791 *inputs = ip;
792 }
793
794 if (outputs != NULL) {
795 for (i = find_lsb_set(map) - 1; map;
796 map &= ~BIT(i), i = find_lsb_set(map) - 1) {
797 op |= !!(drv_data->flags[i] & GPIO_OUTPUT) * BIT(i);
798 }
799
800 *outputs = op;
801 }
802
803 return 0;
804 }
805 #endif /* CONFIG_GPIO_GET_DIRECTION */
806
807 static const struct gpio_driver_api gpio_emul_driver = {
808 .pin_configure = gpio_emul_pin_configure,
809 #ifdef CONFIG_GPIO_GET_CONFIG
810 .pin_get_config = gpio_emul_pin_get_config,
811 #endif
812 .port_get_raw = gpio_emul_port_get_raw,
813 .port_set_masked_raw = gpio_emul_port_set_masked_raw,
814 .port_set_bits_raw = gpio_emul_port_set_bits_raw,
815 .port_clear_bits_raw = gpio_emul_port_clear_bits_raw,
816 .port_toggle_bits = gpio_emul_port_toggle_bits,
817 .pin_interrupt_configure = gpio_emul_pin_interrupt_configure,
818 .manage_callback = gpio_emul_manage_callback,
819 .get_pending_int = gpio_emul_get_pending_int,
820 #ifdef CONFIG_GPIO_GET_DIRECTION
821 .port_get_direction = gpio_emul_port_get_direction,
822 #endif /* CONFIG_GPIO_GET_DIRECTION */
823 };
824
825 static int gpio_emul_init(const struct device *dev)
826 {
827 struct gpio_emul_data *drv_data =
828 (struct gpio_emul_data *)dev->data;
829
830 sys_slist_init(&drv_data->callbacks);
831 return 0;
832 }
833
834 #ifdef CONFIG_PM_DEVICE
835 static int gpio_emul_pm_device_pm_action(const struct device *dev,
836 enum pm_device_action action)
837 {
838 ARG_UNUSED(dev);
839 ARG_UNUSED(action);
840
841 return 0;
842 }
843 #endif
844
845 /*
846 * Device Initialization
847 */
848
849 #define GPIO_EMUL_INT_CAPS(_num) (0 \
850 + DT_INST_PROP(_num, rising_edge) \
851 * GPIO_EMUL_INT_CAP_EDGE_RISING \
852 + DT_INST_PROP(_num, falling_edge) \
853 * GPIO_EMUL_INT_CAP_EDGE_FALLING \
854 + DT_INST_PROP(_num, high_level) \
855 * GPIO_EMUL_INT_CAP_LEVEL_HIGH \
856 + DT_INST_PROP(_num, low_level) \
857 * GPIO_EMUL_INT_CAP_LEVEL_LOW \
858 )
859
860 #define DEFINE_GPIO_EMUL(_num) \
861 \
862 static gpio_flags_t \
863 gpio_emul_flags_##_num[DT_INST_PROP(_num, ngpios)]; \
864 \
865 static const struct gpio_emul_config gpio_emul_config_##_num = {\
866 .common = { \
867 .port_pin_mask = \
868 GPIO_PORT_PIN_MASK_FROM_DT_INST(_num), \
869 }, \
870 .num_pins = DT_INST_PROP(_num, ngpios), \
871 .interrupt_caps = GPIO_EMUL_INT_CAPS(_num) \
872 }; \
873 BUILD_ASSERT( \
874 DT_INST_PROP(_num, ngpios) <= GPIO_MAX_PINS_PER_PORT, \
875 "Too many ngpios"); \
876 \
877 static struct gpio_emul_data gpio_emul_data_##_num = { \
878 .flags = gpio_emul_flags_##_num, \
879 }; \
880 \
881 PM_DEVICE_DT_INST_DEFINE(_num, gpio_emul_pm_device_pm_action); \
882 \
883 DEVICE_DT_INST_DEFINE(_num, gpio_emul_init, \
884 PM_DEVICE_DT_INST_GET(_num), \
885 &gpio_emul_data_##_num, \
886 &gpio_emul_config_##_num, POST_KERNEL, \
887 CONFIG_GPIO_INIT_PRIORITY, \
888 &gpio_emul_driver);
889
890 DT_INST_FOREACH_STATUS_OKAY(DEFINE_GPIO_EMUL)
891