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