1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-07-15 Emuzit first version
9 */
10 #include <rthw.h>
11 #include <drivers/dev_pin.h>
12 #include "ch56x_gpio.h"
13 #include "isr_sp.h"
14
15 struct port_info
16 {
17 uint32_t pin_mark;
18 struct gpio_px_regs *regbase;
19 };
20
21 static const struct port_info pin_ports[GPIO_PORTS] =
22 {
23 {GPIO_PA_PIN_MARK, (struct gpio_px_regs *)GPIO_REG_BASE_PA},
24 {GPIO_PB_PIN_MARK, (struct gpio_px_regs *)GPIO_REG_BASE_PB},
25 };
26
27 static struct rt_pin_irq_hdr pin_irq_hdr_table[8] =
28 {
29 {-1, 0, RT_NULL, RT_NULL},
30 {-1, 0, RT_NULL, RT_NULL},
31 {-1, 0, RT_NULL, RT_NULL},
32 {-1, 0, RT_NULL, RT_NULL},
33 {-1, 0, RT_NULL, RT_NULL},
34 {-1, 0, RT_NULL, RT_NULL},
35 {-1, 0, RT_NULL, RT_NULL},
36 {-1, 0, RT_NULL, RT_NULL},
37 };
38
39
40 #if defined(SOC_SERIES_CH569)
_gpio_pin_to_ibit(rt_base_t pin)41 static int _gpio_pin_to_ibit(rt_base_t pin)
42 {
43 /* gpio ext interrupt 7-0 : {PB15,PB12,PB11,PB4,PB3,PA4,PA3,PA2}
44 * not time critical, use linear search
45 */
46 switch (pin)
47 {
48 case GET_PIN(A, 2): return 0;
49 case GET_PIN(A, 3): return 1;
50 case GET_PIN(A, 4): return 2;
51 case GET_PIN(B, 3): return 3;
52 case GET_PIN(B, 4): return 4;
53 case GET_PIN(B, 11): return 5;
54 case GET_PIN(B, 12): return 6;
55 case GET_PIN(B, 15): return 7;
56 }
57 return -1;
58 }
59
60 #else
61
_gpio_pin_to_ibit(rt_base_t pin)62 static int _gpio_pin_to_ibit(rt_base_t pin)
63 {
64 /* gpio ext interrupt 7-0 : {PB10,PB4,PA12,PA11,PA10,PA6,PA4,PA3}
65 * not time critical, use linear search
66 */
67 switch (pin)
68 {
69 case GET_PIN(A, 3): return 0;
70 case GET_PIN(A, 4): return 1;
71 case GET_PIN(A, 6): return 2;
72 case GET_PIN(A, 10): return 3;
73 case GET_PIN(A, 11): return 4;
74 case GET_PIN(A, 12): return 5;
75 case GET_PIN(B, 4): return 6;
76 case GET_PIN(B, 10): return 7;
77 }
78 return -1;
79 }
80 #endif
81
_gpio_px_regbase(rt_base_t pin)82 static struct gpio_px_regs *_gpio_px_regbase(rt_base_t pin)
83 {
84 /* fixed linear mapping : 32 pins per port, for ports A,B,C,D...
85 */
86 uint32_t port = (uint32_t)pin >> 5;
87 uint32_t bitpos = 1 << (pin & 0x1f);
88
89 if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
90 return pin_ports[port].regbase;
91 else
92 return RT_NULL;
93 }
94
gpio_pin_mode(struct rt_device * device,rt_base_t pin,rt_uint8_t mode)95 static void gpio_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
96 {
97 volatile struct gpio_px_regs *px;
98
99 uint32_t port = (uint32_t)pin >> 5;
100 uint32_t bitpos = 1 << (pin & 0x1f);
101
102 if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
103 px = pin_ports[port].regbase;
104 else
105 return;
106
107 switch (mode)
108 {
109 case PIN_MODE_OUTPUT:
110 BITS_CLR(px->PD, bitpos);
111 BITS_SET(px->DIR, bitpos);
112 break;
113 case PIN_MODE_INPUT:
114 BITS_CLR(px->PU, bitpos);
115 BITS_CLR(px->PD, bitpos);
116 BITS_CLR(px->DIR, bitpos);
117 break;
118 case PIN_MODE_INPUT_PULLUP:
119 BITS_SET(px->PU, bitpos);
120 BITS_CLR(px->PD, bitpos);
121 BITS_CLR(px->DIR, bitpos);
122 break;
123 case PIN_MODE_INPUT_PULLDOWN:
124 BITS_CLR(px->PU, bitpos);
125 BITS_SET(px->PD, bitpos);
126 BITS_CLR(px->DIR, bitpos);
127 break;
128 case PIN_MODE_OUTPUT_OD:
129 BITS_SET(px->PD, bitpos);
130 BITS_SET(px->OUT, bitpos);
131 }
132 }
133
gpio_pin_write(struct rt_device * device,rt_base_t pin,rt_uint8_t value)134 static void gpio_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
135 {
136 volatile struct gpio_px_regs *px;
137
138 uint32_t port = (uint32_t)pin >> 5;
139 uint32_t bitpos = 1 << (pin & 0x1f);
140
141 if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
142 px = pin_ports[port].regbase;
143 else
144 return;
145
146 if (value == 0)
147 BITS_CLR(px->OUT, bitpos);
148 else
149 BITS_SET(px->OUT, bitpos);
150 }
151
gpio_pin_read(struct rt_device * device,rt_base_t pin)152 static rt_ssize_t gpio_pin_read(struct rt_device *device, rt_base_t pin)
153 {
154 volatile struct gpio_px_regs *px;
155
156 uint32_t port = (uint32_t)pin >> 5;
157 uint32_t bitpos = 1 << (pin & 0x1f);
158
159 if (port < GPIO_PORTS && (pin_ports[port].pin_mark & bitpos))
160 px = pin_ports[port].regbase;
161 else
162 return PIN_LOW;
163
164 return (px->PIN & bitpos) ? PIN_HIGH : PIN_LOW;
165 }
166
gpio_pin_get(const char * name)167 static rt_base_t gpio_pin_get(const char *name)
168 {
169 int port, pin, sz, n;
170
171 /* pin name is in the form "PX.nn" (X: A,B,C,D...; nn: 0~31)
172 * fixed linear mapping : 32 pins per port, for ports A,B,C,D...
173 */
174 sz = rt_strlen(name);
175 if ((sz == 4 || sz == 5) && name[0] == 'P' && name[2] == '.')
176 {
177 port = name[1] - 'A';
178 pin = name[3] - '0';
179 if (0 <= port && port < GPIO_PORTS && 0 <= pin && pin <= 9)
180 {
181 if (sz == 5)
182 {
183 n = name[4] - '0';
184 pin = (0 <= n && n <= 9) ? (pin * 10 + n) : 32;
185 }
186 if (pin < 32 && (pin_ports[port].pin_mark & (1 << pin)))
187 {
188 return port * 32 + pin;
189 }
190 }
191 }
192
193 out:
194 rt_kprintf("PX.nn X: A,B,C,D... nn: 0~31, e.g. PA.0\n");
195 return -1;
196 }
197
gpio_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)198 static rt_err_t gpio_pin_attach_irq(struct rt_device *device, rt_base_t pin,
199 rt_uint8_t mode, void (*hdr)(void *args), void *args)
200 {
201 rt_base_t level;
202
203 int ibit;
204
205 switch (mode)
206 {
207 case PIN_IRQ_MODE_RISING:
208 case PIN_IRQ_MODE_FALLING:
209 case PIN_IRQ_MODE_HIGH_LEVEL:
210 case PIN_IRQ_MODE_LOW_LEVEL:
211 break;
212 case PIN_IRQ_MODE_RISING_FALLING:
213 /* hardware not supported */
214 default:
215 return -RT_EINVAL;
216 }
217
218 ibit = _gpio_pin_to_ibit(pin);
219 if (ibit < 0)
220 return -RT_EINVAL;
221
222 level = rt_hw_interrupt_disable();
223 if (pin_irq_hdr_table[ibit].pin == pin &&
224 pin_irq_hdr_table[ibit].mode == mode &&
225 pin_irq_hdr_table[ibit].hdr == hdr &&
226 pin_irq_hdr_table[ibit].args == args)
227 {
228 rt_hw_interrupt_enable(level);
229 return RT_EOK;
230 }
231
232 if (pin_irq_hdr_table[ibit].pin >= 0)
233 {
234 rt_hw_interrupt_enable(level);
235 return -RT_EFULL;
236 }
237
238 pin_irq_hdr_table[ibit].pin = pin;
239 pin_irq_hdr_table[ibit].mode = mode;
240 pin_irq_hdr_table[ibit].hdr = hdr;
241 pin_irq_hdr_table[ibit].args = args;
242
243 rt_hw_interrupt_enable(level);
244 return RT_EOK;
245 }
246
gpio_pin_detach_irq(struct rt_device * device,rt_base_t pin)247 static rt_err_t gpio_pin_detach_irq(struct rt_device *device, rt_base_t pin)
248 {
249 rt_base_t level;
250
251 int ibit;
252
253 ibit = _gpio_pin_to_ibit(pin);
254 if (ibit < 0)
255 return -RT_EINVAL;
256
257 level = rt_hw_interrupt_disable();
258 if (pin_irq_hdr_table[ibit].pin < 0)
259 {
260 rt_hw_interrupt_enable(level);
261 return RT_EOK;
262 }
263 pin_irq_hdr_table[ibit].pin = -1;
264 pin_irq_hdr_table[ibit].mode = 0;
265 pin_irq_hdr_table[ibit].hdr = RT_NULL;
266 pin_irq_hdr_table[ibit].args = RT_NULL;
267 rt_hw_interrupt_enable(level);
268 return RT_EOK;
269 }
270
gpio_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)271 static rt_err_t gpio_pin_irq_enable(struct rt_device *device, rt_base_t pin,
272 rt_uint8_t enabled)
273 {
274 volatile struct gpio_registers *gpio;
275
276 rt_base_t level, int_enable;
277
278 int ibit, bitpos;
279
280 ibit = _gpio_pin_to_ibit(pin);
281 if (ibit < 0)
282 return -RT_EINVAL;
283 bitpos = (1 << ibit);
284
285 gpio = (struct gpio_registers *)GPIO_REG_BASE;
286
287 if (enabled == PIN_IRQ_ENABLE)
288 {
289 level = rt_hw_interrupt_disable();
290 if (pin_irq_hdr_table[ibit].pin != pin)
291 {
292 rt_hw_interrupt_enable(level);
293 return -RT_EINVAL;
294 }
295
296 switch (pin_irq_hdr_table[ibit].mode)
297 {
298 case PIN_IRQ_MODE_RISING:
299 BITS_SET(gpio->INT_MODE.reg, bitpos);
300 BITS_SET(gpio->INT_POLAR.reg, bitpos);
301 break;
302 case PIN_IRQ_MODE_FALLING:
303 BITS_SET(gpio->INT_MODE.reg, bitpos);
304 BITS_CLR(gpio->INT_POLAR.reg, bitpos);
305 break;
306 case PIN_IRQ_MODE_HIGH_LEVEL:
307 BITS_CLR(gpio->INT_MODE.reg, bitpos);
308 BITS_SET(gpio->INT_POLAR.reg, bitpos);
309 break;
310 case PIN_IRQ_MODE_LOW_LEVEL:
311 BITS_CLR(gpio->INT_MODE.reg, bitpos);
312 BITS_CLR(gpio->INT_POLAR.reg, bitpos);
313 break;
314 case PIN_IRQ_MODE_RISING_FALLING:
315 default:
316 rt_hw_interrupt_enable(level);
317 return -RT_EINVAL;
318 }
319
320 /* clear possible pending intr, then enable pin intr */
321 int_enable = gpio->INT_ENABLE.reg;
322 gpio->INT_FLAG.reg = bitpos;
323 gpio->INT_ENABLE.reg = int_enable | bitpos;
324 /* enable GPIO_IRQn if this is the first enabled EXTIx */
325 if (int_enable == 0)
326 {
327 rt_hw_interrupt_umask(GPIO_IRQn);
328 }
329 rt_hw_interrupt_enable(level);
330 }
331 else if (enabled == PIN_IRQ_DISABLE)
332 {
333 level = rt_hw_interrupt_disable();
334 int_enable = gpio->INT_ENABLE.reg;
335 BITS_CLR(int_enable, bitpos);
336 gpio->INT_ENABLE.reg = int_enable;
337 /* disable GPIO_IRQn if no EXTIx enabled */
338 if (int_enable == 0)
339 {
340 rt_hw_interrupt_mask(GPIO_IRQn);
341 }
342 rt_hw_interrupt_enable(level);
343 }
344 else
345 {
346 return -RT_EINVAL;
347 }
348
349 return RT_EOK;
350 }
351
352 static const struct rt_pin_ops pin_ops =
353 {
354 .pin_mode = gpio_pin_mode,
355 .pin_write = gpio_pin_write,
356 .pin_read = gpio_pin_read,
357 .pin_attach_irq = gpio_pin_attach_irq,
358 .pin_detach_irq = gpio_pin_detach_irq,
359 .pin_irq_enable = gpio_pin_irq_enable,
360 .pin_get = gpio_pin_get,
361 };
362
rt_hw_pin_init(void)363 static int rt_hw_pin_init(void)
364 {
365 return rt_device_pin_register("pin", &pin_ops, RT_NULL);
366 }
367 INIT_BOARD_EXPORT(rt_hw_pin_init);
368
369 void gpio_irq_handler(void) __attribute__((interrupt()));
gpio_irq_handler(void)370 void gpio_irq_handler(void)
371 {
372 volatile struct gpio_registers *gpio;
373
374 uint8_t iflags;
375
376 int ibit, bitpos;
377
378 isr_sp_enter();
379 rt_interrupt_enter();
380
381 gpio = (struct gpio_registers *)GPIO_REG_BASE;
382 iflags = gpio->INT_FLAG.reg;
383 /* prioritized as pb15 -> pa2 (CH569), or pb10 -> pa3 */
384 for (ibit = 7; ibit >= 0; ibit--)
385 {
386 bitpos = (1 << ibit);
387 if (iflags & bitpos)
388 {
389 if (pin_irq_hdr_table[ibit].hdr)
390 {
391 pin_irq_hdr_table[ibit].hdr(pin_irq_hdr_table[ibit].args);
392 }
393 /* clear interrupt */
394 gpio->INT_FLAG.reg = bitpos;
395 }
396 }
397
398 rt_interrupt_leave();
399 isr_sp_leave();
400 }
401