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,137 @@ 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
+ /* Convert the device into a port ID by checking the address */
135
+ switch ((uintptr_t )config -> regs ) {
136
+ case DT_REG_ADDR (DT_NODELABEL (gpioa )):
137
+ port_id = 0 ;
138
+ break ;
139
+ #if DT_NODE_EXISTS (DT_NODELABEL (gpiob ))
140
+ case DT_REG_ADDR (DT_NODELABEL (gpiob )):
141
+ port_id = 1 ;
142
+ break ;
143
+ #endif
144
+ case DT_REG_ADDR (DT_NODELABEL (gpioc )):
145
+ port_id = 2 ;
146
+ break ;
147
+ case DT_REG_ADDR (DT_NODELABEL (gpiod )):
148
+ port_id = 3 ;
149
+ break ;
150
+ default :
151
+ return - EINVAL ;
152
+ }
153
+
154
+ #if defined(AFIO_EXTICR_EXTI0 )
155
+ /* CH32V003 style with one register with 2 bits per map. */
156
+ BUILD_ASSERT (AFIO_EXTICR_EXTI0 == 0x03 );
157
+
158
+ (void )cr_id ;
159
+ bit0 = pin << 1 ;
160
+ afio -> EXTICR = (afio -> EXTICR & ~(AFIO_EXTICR_EXTI0 << bit0 )) | (port_id << bit0 );
161
+ #elif defined(AFIO_EXTICR1_EXTI0 )
162
+ /*
163
+ * CH32V20x style with multiple registers with 4 pins per register and 4 bits per
164
+ * map.
165
+ */
166
+ BUILD_ASSERT (AFIO_EXTICR1_EXTI0 == 0x0F );
167
+ BUILD_ASSERT (ARRAY_SIZE (afio -> EXTICR ) == 4 );
168
+
169
+ cr_id = pin / 4 ;
170
+ bit0 = (pin % 4 ) << 4 ;
171
+ afio -> EXTICR [cr_id ] =
172
+ (afio -> EXTICR [cr_id ] & ~(AFIO_EXTICR1_EXTI0 << bit0 )) | (port_id << bit0 );
173
+ #else
174
+ #error Unrecognised EXTICR format
175
+ #endif
176
+
177
+ return 0 ;
178
+ }
179
+
180
+ static int gpio_ch32v00x_pin_interrupt_configure (const struct device * dev , gpio_pin_t pin ,
181
+ enum gpio_int_mode mode ,
182
+ enum gpio_int_trig trigger )
183
+ {
184
+ int err ;
185
+
186
+ switch (mode ) {
187
+ case GPIO_INT_MODE_DISABLED :
188
+ wch_exti_disable (pin );
189
+ err = wch_exti_configure (pin , NULL , NULL );
190
+ break ;
191
+ case GPIO_INT_MODE_EDGE :
192
+ err = wch_exti_configure (pin , gpio_ch32v00x_isr , (void * )dev );
193
+ if (err != 0 ) {
194
+ break ;
195
+ }
196
+
197
+ err = gpio_ch32v00x_configure_exti (dev , pin );
198
+ if (err != 0 ) {
199
+ break ;
200
+ }
201
+
202
+ switch (trigger ) {
203
+ case GPIO_INT_TRIG_LOW :
204
+ wch_exti_set_trigger (pin , WCH_EXTI_TRIGGER_FALLING_EDGE );
205
+ break ;
206
+ case GPIO_INT_TRIG_HIGH :
207
+ wch_exti_set_trigger (pin , WCH_EXTI_TRIGGER_RISING_EDGE );
208
+ break ;
209
+ case GPIO_INT_TRIG_BOTH :
210
+ wch_exti_set_trigger (pin , WCH_EXTI_TRIGGER_FALLING_EDGE |
211
+ WCH_EXTI_TRIGGER_RISING_EDGE );
212
+ break ;
213
+ default :
214
+ return - ENOTSUP ;
215
+ }
216
+
217
+ wch_exti_enable (pin );
218
+ break ;
219
+ default :
220
+ return - ENOTSUP ;
221
+ }
222
+
223
+ return err ;
224
+ }
225
+
226
+ static int gpio_ch32v00x_manage_callback (const struct device * dev , struct gpio_callback * callback ,
227
+ bool set )
228
+ {
229
+ struct gpio_ch32v00x_data * data = dev -> data ;
230
+
231
+ return gpio_manage_callback (& data -> callbacks , callback , set );
232
+ }
233
+
234
+ #endif /* CONFIG_GPIO_WCH_GPIO_INTERRUPTS */
235
+
114
236
static DEVICE_API (gpio , gpio_ch32v00x_driver_api ) = {
115
237
.pin_configure = gpio_ch32v00x_configure ,
116
238
.port_get_raw = gpio_ch32v00x_port_get_raw ,
117
239
.port_set_masked_raw = gpio_ch32v00x_port_set_masked_raw ,
118
240
.port_set_bits_raw = gpio_ch32v00x_port_set_bits_raw ,
119
241
.port_clear_bits_raw = gpio_ch32v00x_port_clear_bits_raw ,
120
242
.port_toggle_bits = gpio_ch32v00x_port_toggle_bits ,
243
+ #if defined(CONFIG_GPIO_WCH_GPIO_INTERRUPTS )
244
+ .pin_interrupt_configure = gpio_ch32v00x_pin_interrupt_configure ,
245
+ .manage_callback = gpio_ch32v00x_manage_callback ,
246
+ #endif
121
247
};
122
248
123
249
static int gpio_ch32v00x_init (const struct device * dev )
0 commit comments