7
7
#include <zephyr/drivers/clock_control.h>
8
8
#include <zephyr/drivers/gpio.h>
9
9
#include <zephyr/drivers/gpio/gpio_utils.h>
10
+ #include <zephyr/drivers/interrupt_controller/wch_exti.h>
10
11
#include <zephyr/dt-bindings/gpio/gpio.h>
11
12
#include <zephyr/irq.h>
12
13
@@ -23,6 +24,7 @@ struct gpio_ch32v00x_config {
23
24
24
25
struct gpio_ch32v00x_data {
25
26
struct gpio_driver_data common ;
27
+ sys_slist_t callbacks ;
26
28
};
27
29
28
30
static int gpio_ch32v00x_configure (const struct device * dev , gpio_pin_t pin , gpio_flags_t flags )
@@ -111,13 +113,136 @@ static int gpio_ch32v00x_port_toggle_bits(const struct device *dev, uint32_t pin
111
113
return 0 ;
112
114
}
113
115
116
+ #if defined(CONFIG_GPIO_WCH_GPIO_INTERRUPTS )
117
+
118
+ static void gpio_ch32v00x_isr (uint8_t line , void * user )
119
+ {
120
+ const struct device * dev = user ;
121
+ struct gpio_ch32v00x_data * data = dev -> data ;
122
+
123
+ gpio_fire_callbacks (& data -> callbacks , dev , BIT (line ));
124
+ }
125
+
126
+ static int gpio_ch32v00x_configure_exti (const struct device * dev , gpio_pin_t pin )
127
+ {
128
+ const struct gpio_ch32v00x_config * config = dev -> config ;
129
+ AFIO_TypeDef * afio = (AFIO_TypeDef * )DT_REG_ADDR (DT_NODELABEL (pinctrl ));
130
+ uint8_t port_id ;
131
+ uint8_t cr_id ;
132
+ uint8_t bit0 ;
133
+
134
+ switch ((uintptr_t )config -> regs ) {
135
+ case DT_REG_ADDR (DT_NODELABEL (gpioa )):
136
+ port_id = 0 ;
137
+ break ;
138
+ #if DT_NODE_EXISTS (DT_NODELABEL (gpiob ))
139
+ case DT_REG_ADDR (DT_NODELABEL (gpiob )):
140
+ port_id = 1 ;
141
+ break ;
142
+ #endif
143
+ case DT_REG_ADDR (DT_NODELABEL (gpioc )):
144
+ port_id = 2 ;
145
+ break ;
146
+ case DT_REG_ADDR (DT_NODELABEL (gpiod )):
147
+ port_id = 3 ;
148
+ break ;
149
+ default :
150
+ return - EINVAL ;
151
+ }
152
+
153
+ #if defined(AFIO_EXTICR_EXTI0 )
154
+ /* CH32V003 style with one register with 2 bits per map. */
155
+ BUILD_ASSERT (AFIO_EXTICR_EXTI0 == 0x03 );
156
+
157
+ (void )cr_id ;
158
+ bit0 = pin << 1 ;
159
+ afio -> EXTICR = (afio -> EXTICR & ~(AFIO_EXTICR_EXTI0 << bit0 )) | (port_id << bit0 );
160
+ #elif defined(AFIO_EXTICR1_EXTI0 )
161
+ /*
162
+ * CH32V20x style with multiple registers with 4 pins per register and 4 bits per
163
+ * map.
164
+ */
165
+ BUILD_ASSERT (AFIO_EXTICR1_EXTI0 == 0x0F );
166
+ BUILD_ASSERT (ARRAY_SIZE (afio -> EXTICR ) == 4 );
167
+
168
+ cr_id = pin / 4 ;
169
+ bit0 = (pin % 4 ) << 4 ;
170
+ afio -> EXTICR [cr_id ] =
171
+ (afio -> EXTICR [cr_id ] & ~(AFIO_EXTICR1_EXTI0 << bit0 )) | (port_id << bit0 );
172
+ #else
173
+ #error Unrecognised EXTICR format
174
+ #endif
175
+
176
+ return 0 ;
177
+ }
178
+
179
+ static int gpio_ch32v00x_pin_interrupt_configure (const struct device * dev , gpio_pin_t pin ,
180
+ enum gpio_int_mode mode ,
181
+ enum gpio_int_trig trigger )
182
+ {
183
+ int err ;
184
+
185
+ switch (mode ) {
186
+ case GPIO_INT_MODE_DISABLED :
187
+ wch_exti_disable (pin );
188
+ err = wch_exti_configure (pin , NULL , NULL );
189
+ break ;
190
+ case GPIO_INT_MODE_EDGE :
191
+ err = wch_exti_configure (pin , gpio_ch32v00x_isr , (void * )dev );
192
+ if (err != 0 ) {
193
+ break ;
194
+ }
195
+
196
+ err = gpio_ch32v00x_configure_exti (dev , pin );
197
+ if (err != 0 ) {
198
+ break ;
199
+ }
200
+
201
+ switch (trigger ) {
202
+ case GPIO_INT_TRIG_LOW :
203
+ wch_exti_set_trigger (pin , WCH_EXTI_TRIGGER_FALLING_EDGE );
204
+ break ;
205
+ case GPIO_INT_TRIG_HIGH :
206
+ wch_exti_set_trigger (pin , WCH_EXTI_TRIGGER_RISING_EDGE );
207
+ break ;
208
+ case GPIO_INT_TRIG_BOTH :
209
+ wch_exti_set_trigger (pin , WCH_EXTI_TRIGGER_FALLING_EDGE |
210
+ WCH_EXTI_TRIGGER_RISING_EDGE );
211
+ break ;
212
+ default :
213
+ return - ENOTSUP ;
214
+ }
215
+
216
+ wch_exti_enable (pin );
217
+ break ;
218
+ default :
219
+ return - ENOTSUP ;
220
+ }
221
+
222
+ return err ;
223
+ }
224
+
225
+ static int gpio_ch32v00x_manage_callback (const struct device * dev , struct gpio_callback * callback ,
226
+ bool set )
227
+ {
228
+ struct gpio_ch32v00x_data * data = dev -> data ;
229
+
230
+ return gpio_manage_callback (& data -> callbacks , callback , set );
231
+ }
232
+
233
+ #endif /* CONFIG_GPIO_WCH_GPIO_INTERRUPTS */
234
+
114
235
static DEVICE_API (gpio , gpio_ch32v00x_driver_api ) = {
115
236
.pin_configure = gpio_ch32v00x_configure ,
116
237
.port_get_raw = gpio_ch32v00x_port_get_raw ,
117
238
.port_set_masked_raw = gpio_ch32v00x_port_set_masked_raw ,
118
239
.port_set_bits_raw = gpio_ch32v00x_port_set_bits_raw ,
119
240
.port_clear_bits_raw = gpio_ch32v00x_port_clear_bits_raw ,
120
241
.port_toggle_bits = gpio_ch32v00x_port_toggle_bits ,
242
+ #if defined(CONFIG_GPIO_WCH_GPIO_INTERRUPTS )
243
+ .pin_interrupt_configure = gpio_ch32v00x_pin_interrupt_configure ,
244
+ .manage_callback = gpio_ch32v00x_manage_callback ,
245
+ #endif
121
246
};
122
247
123
248
static int gpio_ch32v00x_init (const struct device * dev )
0 commit comments