1 /* 2 * Copyright (C) 2020-2021 Alibaba Group Holding Limited 3 */ 4 5 #ifndef AOS_GPIOC_CORE_H 6 #define AOS_GPIOC_CORE_H 7 8 #include <aos/device_core.h> 9 #include <aos/gpioc.h> 10 11 #define AOS_GPIOC_IRQ_EVENT_P ((uint32_t)1 << 0) 12 #define AOS_GPIOC_IRQ_EVENT_N ((uint32_t)1 << 1) 13 14 struct aos_gpioc; 15 16 typedef struct { 17 void (*unregister)(struct aos_gpioc *); 18 aos_status_t (*set_mode)(struct aos_gpioc *, uint32_t); 19 void (*enable_irq)(struct aos_gpioc *, uint32_t); 20 void (*disable_irq)(struct aos_gpioc *, uint32_t); 21 int (*get_value)(struct aos_gpioc *, uint32_t); 22 void (*set_value)(struct aos_gpioc *, uint32_t); 23 } aos_gpioc_ops_t; 24 25 typedef struct { 26 uint32_t id; 27 uint32_t mode; 28 aos_gpio_irq_handler_t irq_handler; 29 void *irq_arg; 30 aos_sem_t irq_sem; 31 aos_event_t irq_event; 32 aos_task_t irq_task; 33 bool hard_irq_en; 34 int value; 35 } aos_gpioc_pin_t; 36 37 typedef struct aos_gpioc { 38 aos_dev_t dev; 39 aos_spinlock_t lock; 40 41 /* must be initialized before registration */ 42 const aos_gpioc_ops_t *ops; 43 uint32_t num_pins; 44 45 aos_gpioc_pin_t pins[0]; 46 } aos_gpioc_t; 47 48 #define aos_gpioc_hard_irq_handler(gpioc, pin, polarity) \ 49 do { \ 50 aos_gpioc_t *_gpioc = (gpioc); \ 51 uint32_t _pin = (pin); \ 52 uint32_t mode; \ 53 uint32_t trig; \ 54 uint32_t mask; \ 55 aos_irqsave_t flags; \ 56 flags = aos_spin_lock_irqsave(&_gpioc->lock); \ 57 if (!_gpioc->pins[_pin].hard_irq_en) { \ 58 aos_spin_unlock_irqrestore(&_gpioc->lock, flags); \ 59 break; \ 60 } \ 61 mode = _gpioc->pins[_pin].mode; \ 62 if ((mode & AOS_GPIO_DIR_MASK) == AOS_GPIO_DIR_INPUT) \ 63 trig = mode & AOS_GPIO_IRQ_TRIG_MASK; \ 64 else \ 65 trig = AOS_GPIO_IRQ_TRIG_NONE; \ 66 if (trig == AOS_GPIO_IRQ_TRIG_LEVEL_HIGH || trig == AOS_GPIO_IRQ_TRIG_LEVEL_LOW) { \ 67 _gpioc->pins[_pin].hard_irq_en = false; \ 68 _gpioc->ops->disable_irq(_gpioc, _pin); \ 69 } \ 70 if (trig == AOS_GPIO_IRQ_TRIG_EDGE_BOTH) { \ 71 mask = (polarity) ? AOS_GPIOC_IRQ_EVENT_P : AOS_GPIOC_IRQ_EVENT_N; \ 72 } else if (trig == AOS_GPIO_IRQ_TRIG_EDGE_RISING || trig == AOS_GPIO_IRQ_TRIG_LEVEL_HIGH) { \ 73 mask = AOS_GPIOC_IRQ_EVENT_P; \ 74 } else if (trig == AOS_GPIO_IRQ_TRIG_EDGE_FALLING || trig == AOS_GPIO_IRQ_TRIG_LEVEL_LOW) { \ 75 mask = AOS_GPIOC_IRQ_EVENT_N; \ 76 } else { \ 77 mask = 0; \ 78 } \ 79 if (mask) \ 80 aos_event_set(&_gpioc->pins[pin].irq_event, mask, AOS_EVENT_OR); \ 81 aos_spin_unlock_irqrestore(&_gpioc->lock, flags); \ 82 } while (0) 83 84 #ifdef __cplusplus 85 extern "C" { 86 #endif 87 88 aos_status_t aos_gpioc_register(aos_gpioc_t *gpioc); 89 aos_status_t aos_gpioc_unregister(uint32_t id); 90 91 #ifdef __cplusplus 92 } 93 #endif 94 95 #endif /* AOS_GPIOC_CORE_H */ 96