1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2020-12-27     iysheng           first version
9  * 2021-01-01     iysheng           support exti interrupt
10  * 2021-09-07     FuC               Suit for Vango V85xx
11  * 2021-09-09     ZhuXW             Add GPIO interrupt
12  */
13 
14 #include <board.h>
15 #include "drv_gpio.h"
16 
17 #ifdef RT_USING_PIN
18 
19 #if defined(GPIOF)
20 #define __V85XX_PORT_MAX 6u
21 #elif defined(GPIOE)
22 #define __V85XX_PORT_MAX 5u
23 #elif defined(GPIOD)
24 #define __V85XX_PORT_MAX 4u
25 #elif defined(GPIOC)
26 #define __V85XX_PORT_MAX 3u
27 #elif defined(GPIOB)
28 #define __V85XX_PORT_MAX 2u
29 #elif defined(GPIOA)
30 #define __V85XX_PORT_MAX 1u
31 #else
32 #define __V85XX_PORT_MAX 0u
33 #error Unsupported V85XX GPIO peripheral.
34 #endif
35 
36 #define PIN_V85XXPORT_MAX __V85XX_PORT_MAX
37 #define PIN_V85XXPORT_A   0u
38 
39 static const struct pin_irq_map pin_irq_map[] =
40 {
41 #if defined(SOC_SERIES_V85XX)
42     {GPIO_Pin_0,  PMU_IRQn},
43     {GPIO_Pin_1,  PMU_IRQn},
44     {GPIO_Pin_2,  PMU_IRQn},
45     {GPIO_Pin_3,  PMU_IRQn},
46     {GPIO_Pin_4,  PMU_IRQn},
47     {GPIO_Pin_5,  PMU_IRQn},
48     {GPIO_Pin_6,  PMU_IRQn},
49     {GPIO_Pin_7,  PMU_IRQn},
50     {GPIO_Pin_8,  PMU_IRQn},
51     {GPIO_Pin_9,  PMU_IRQn},
52     {GPIO_Pin_10, PMU_IRQn},
53     {GPIO_Pin_11, PMU_IRQn},
54     {GPIO_Pin_12, PMU_IRQn},
55     {GPIO_Pin_13, PMU_IRQn},
56     {GPIO_Pin_14, PMU_IRQn},
57     {GPIO_Pin_15, PMU_IRQn},
58 #else
59 #error "Unsupported soc series"
60 #endif
61 };
62 
63 static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
64 {
65     {-1, 0, RT_NULL, RT_NULL},
66     {-1, 0, RT_NULL, RT_NULL},
67     {-1, 0, RT_NULL, RT_NULL},
68     {-1, 0, RT_NULL, RT_NULL},
69     {-1, 0, RT_NULL, RT_NULL},
70     {-1, 0, RT_NULL, RT_NULL},
71     {-1, 0, RT_NULL, RT_NULL},
72     {-1, 0, RT_NULL, RT_NULL},
73     {-1, 0, RT_NULL, RT_NULL},
74     {-1, 0, RT_NULL, RT_NULL},
75     {-1, 0, RT_NULL, RT_NULL},
76     {-1, 0, RT_NULL, RT_NULL},
77     {-1, 0, RT_NULL, RT_NULL},
78     {-1, 0, RT_NULL, RT_NULL},
79     {-1, 0, RT_NULL, RT_NULL},
80     {-1, 0, RT_NULL, RT_NULL},
81 };
82 static uint32_t pin_irq_enable_mask = 0;
83 
84 #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
85 
v85xx_pin_get(const char * name)86 static rt_base_t v85xx_pin_get(const char *name)
87 {
88     rt_base_t pin = 0;
89     int hw_port_num, hw_pin_num = 0;
90     int i, name_len;
91 
92     name_len = rt_strlen(name);
93 
94     if ((name_len < 4) || (name_len >= 6))
95     {
96         return -RT_EINVAL;
97     }
98     if ((name[0] != 'P') || (name[2] != '.'))
99     {
100         return -RT_EINVAL;
101     }
102 
103     if ((name[1] >= 'A') && (name[1] <= 'F'))
104     {
105         hw_port_num = (int)(name[1] - 'A');
106     }
107     else
108     {
109         return -RT_EINVAL;
110     }
111 
112     for (i = 3; i < name_len; i++)
113     {
114         hw_pin_num *= 10;
115         hw_pin_num += name[i] - '0';
116     }
117 
118     pin = PIN_NUM(hw_port_num, hw_pin_num);
119 
120     return pin;
121 }
122 
v85xx_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)123 static void v85xx_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
124 {
125     GPIO_TypeDef *gpio_port;
126     uint16_t gpio_pin;
127 
128     if (PIN_PORT(pin) == PIN_V85XXPORT_A)
129     {
130         gpio_pin = PIN_V85XXPIN(pin);
131 
132         GPIOA_WriteBit(GPIOA, gpio_pin, (BitState)value);
133     }
134     else if (PIN_PORT(pin) < PIN_V85XXPORT_MAX)
135     {
136         gpio_port = PIN_V85XXPORT(pin);
137         gpio_pin = PIN_V85XXPIN(pin);
138 
139         GPIOBToF_WriteBit(gpio_port, gpio_pin, (BitState)value);
140     }
141 }
142 
v85xx_pin_read(rt_device_t dev,rt_base_t pin)143 static rt_ssize_t v85xx_pin_read(rt_device_t dev, rt_base_t pin)
144 {
145     GPIO_TypeDef *gpio_port;
146     uint16_t gpio_pin;
147     rt_ssize_t value = PIN_LOW;
148 
149     if (PIN_PORT(pin) == PIN_V85XXPORT_A)
150     {
151         gpio_pin = PIN_V85XXPIN(pin);
152         value = GPIOA_ReadInputDataBit(GPIOA, gpio_pin);
153     }
154     else if (PIN_PORT(pin) < PIN_V85XXPORT_MAX)
155     {
156         gpio_port = PIN_V85XXPORT(pin);
157         gpio_pin = PIN_V85XXPIN(pin);
158         value = GPIOBToF_ReadInputDataBit(gpio_port, gpio_pin);
159     }
160     else
161     {
162         return -RT_EINVAL;
163     }
164 
165     return value;
166 }
167 
v85xx_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)168 static void v85xx_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
169 {
170     GPIO_InitType GPIO_InitStruct = {0};
171 
172     if (PIN_PORT(pin) >= PIN_V85XXPORT_MAX)
173     {
174         return;
175     }
176 
177     /* Configure GPIO_InitStructure */
178     GPIO_InitStruct.GPIO_Pin  = PIN_V85XXPIN(pin);
179     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
180 
181     switch (mode)
182     {
183         case PIN_MODE_OUTPUT:
184             GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUTPUT_CMOS;
185             break;
186         case PIN_MODE_INPUT:
187             GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
188             break;
189         case PIN_MODE_INPUT_PULLUP:
190             GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INOUT_CMOS;
191             break;
192         case PIN_MODE_INPUT_PULLDOWN:
193             GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INOUT_OD;
194             break;
195         case PIN_MODE_OUTPUT_OD:
196             GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INOUT_OD;
197             break;
198         default:
199             break;
200     }
201 
202     if (PIN_PORT(pin) == PIN_V85XXPORT_A)
203     {
204         GPIOA_Init(GPIOA, &GPIO_InitStruct);
205     }
206     else if (PIN_PORT(pin) < PIN_V85XXPORT_MAX)
207     {
208         GPIOBToF_Init(PIN_V85XXPORT(pin), &GPIO_InitStruct);
209     }
210 }
211 
bit2bitno(rt_uint32_t bit)212 rt_inline rt_int32_t bit2bitno(rt_uint32_t bit)
213 {
214     int i;
215     for (i = 0; i < 32; i++)
216     {
217         if ((0x01 << i) == bit)
218         {
219             return i;
220         }
221     }
222     return -1;
223 }
224 
225 
v85xx_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)226 static rt_err_t v85xx_pin_attach_irq(struct rt_device *device, rt_base_t pin,
227                     rt_uint8_t mode, void (*hdr)(void *args), void *args)
228 {
229     rt_base_t level;
230     rt_int32_t irqindex = -1;
231 
232     if (PIN_PORT(pin) > PIN_V85XXPORT_A)
233     {
234         return -RT_ENOSYS;
235     }
236 
237     irqindex = bit2bitno(PIN_V85XXPIN(pin));
238     if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
239     {
240         return -RT_ENOSYS;
241     }
242 
243     level = rt_hw_interrupt_disable();
244     if (pin_irq_hdr_tab[irqindex].pin == pin &&
245         pin_irq_hdr_tab[irqindex].hdr == hdr &&
246         pin_irq_hdr_tab[irqindex].mode == mode &&
247         pin_irq_hdr_tab[irqindex].args == args)
248     {
249         rt_hw_interrupt_enable(level);
250         return RT_EOK;
251     }
252     if (pin_irq_hdr_tab[irqindex].pin != -1)
253     {
254         rt_hw_interrupt_enable(level);
255         return -RT_EBUSY;
256     }
257     pin_irq_hdr_tab[irqindex].pin = pin;
258     pin_irq_hdr_tab[irqindex].hdr = hdr;
259     pin_irq_hdr_tab[irqindex].mode = mode;
260     pin_irq_hdr_tab[irqindex].args = args;
261     rt_hw_interrupt_enable(level);
262 
263     return RT_EOK;
264 }
v85xx_pin_detach_irq(struct rt_device * device,rt_base_t pin)265 static rt_err_t v85xx_pin_detach_irq(struct rt_device *device, rt_base_t pin)
266 {
267     rt_base_t level;
268     rt_int32_t irqindex = -1;
269 
270     if (PIN_PORT(pin) > PIN_V85XXPORT_A)
271     {
272         return -RT_ENOSYS;
273     }
274 
275     irqindex = bit2bitno(PIN_V85XXPIN(pin));
276     if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
277     {
278         return -RT_ENOSYS;
279     }
280 
281     level = rt_hw_interrupt_disable();
282     if (pin_irq_hdr_tab[irqindex].pin == -1)
283     {
284         rt_hw_interrupt_enable(level);
285         return RT_EOK;
286     }
287     pin_irq_hdr_tab[irqindex].pin = -1;
288     pin_irq_hdr_tab[irqindex].hdr = RT_NULL;
289     pin_irq_hdr_tab[irqindex].mode = 0;
290     pin_irq_hdr_tab[irqindex].args = RT_NULL;
291     rt_hw_interrupt_enable(level);
292 
293     return RT_EOK;
294 }
v85xx_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)295 static rt_err_t v85xx_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
296 {
297     const struct pin_irq_map *irqmap;
298     rt_base_t level;
299     rt_int32_t irqindex = -1;
300     GPIO_InitType GPIO_InitStruct = {0};
301 
302     if (PIN_PORT(pin) > PIN_V85XXPORT_A)
303     {
304         return -RT_ENOSYS;
305     }
306 
307     GPIO_InitStruct.GPIO_Pin = PIN_V85XXPIN(pin);
308     if (enabled == PIN_IRQ_ENABLE)
309     {
310         irqindex = bit2bitno(PIN_V85XXPIN(pin));
311         if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
312         {
313             return -RT_ENOSYS;
314         }
315 
316         level = rt_hw_interrupt_disable();
317 
318         if (pin_irq_hdr_tab[irqindex].pin == -1)
319         {
320             rt_hw_interrupt_enable(level);
321             return -RT_ENOSYS;
322         }
323 
324         GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
325         GPIO_InitStruct.GPIO_Pin  = PIN_V85XXPIN(pin);
326         GPIOA_Init(GPIOA, &GPIO_InitStruct);
327 
328         irqmap = &pin_irq_map[irqindex];
329 
330         switch (pin_irq_hdr_tab[irqindex].mode)
331         {
332         case PIN_IRQ_MODE_RISING:
333             PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_RISING);
334             break;
335         case PIN_IRQ_MODE_FALLING:
336             PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_FALLING);
337             break;
338         case PIN_IRQ_MODE_RISING_FALLING:
339             PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_EDGEBOTH);
340             break;
341         case PIN_IRQ_MODE_HIGH_LEVEL:
342             PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_HIGH);
343             break;
344         case PIN_IRQ_MODE_LOW_LEVEL:
345             PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_LOW);
346             break;
347         default:
348             break;
349         }
350         PMU_INTConfig(PMU_INT_IOAEN, ENABLE);
351 
352         NVIC_SetPriority(irqmap->irqno, 0);
353         NVIC_EnableIRQ(irqmap->irqno);
354         pin_irq_enable_mask |= irqmap->pinbit;
355 
356         rt_hw_interrupt_enable(level);
357     }
358     else if (enabled == PIN_IRQ_DISABLE)
359     {
360 
361         level = rt_hw_interrupt_disable();
362 
363         PMU_INTConfig(PMU_INT_IOAEN, DISABLE);
364 
365         NVIC_DisableIRQ(irqmap->irqno);
366 
367         rt_hw_interrupt_enable(level);
368     }
369     else
370     {
371         return -RT_ENOSYS;
372     }
373     return RT_EOK;
374 }
375 
376 
377 
378 const static struct rt_pin_ops _v85xx_pin_ops =
379 {
380     v85xx_pin_mode,
381     v85xx_pin_write,
382     v85xx_pin_read,
383     v85xx_pin_attach_irq,
384     v85xx_pin_detach_irq,
385     v85xx_pin_irq_enable,
386     v85xx_pin_get,
387 };
388 
pin_irq_hdr(int irqno)389 rt_inline void pin_irq_hdr(int irqno)
390 {
391     if (pin_irq_hdr_tab[irqno].hdr)
392     {
393         pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args);
394     }
395 }
396 
397 
v85xx_pin_exti_irqhandler()398 void v85xx_pin_exti_irqhandler()
399 {
400     rt_base_t intsts=0;
401     int i=0;
402 
403     intsts = PMU_GetIOAAllINTStatus();
404     for(i=0; i<16; i++)
405     {
406         if((1<<i) & intsts)
407         {
408             PMU_ClearIOAINTStatus(1<<i);
409             pin_irq_hdr(bit2bitno(1<<i));
410             return;
411         }
412     }
413 }
414 
PMU_IRQHandler()415 void PMU_IRQHandler()
416 {
417     rt_interrupt_enter();
418     v85xx_pin_exti_irqhandler();
419     rt_interrupt_leave();
420 }
421 
422 
rt_hw_pin_init(void)423 int rt_hw_pin_init(void)
424 {
425   GPIO_InitType GPIO_InitStruct;
426   GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
427   GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All;
428 
429 #if defined(GPIOF)
430     GPIOBToF_Init(GPIOF, &GPIO_InitStruct);
431 #endif
432 #if defined(GPIOE)
433     GPIOBToF_Init(GPIOE, &GPIO_InitStruct);
434 #endif
435 #if defined(GPIOD)
436     GPIOBToF_Init(GPIOD, &GPIO_InitStruct);
437 #endif
438 #if defined(GPIOC)
439     GPIOBToF_Init(GPIOC, &GPIO_InitStruct);
440 #endif
441 #if defined(GPIOB)
442     GPIOBToF_Init(GPIOB, &GPIO_InitStruct);
443 #endif
444 #if defined(GPIOA)
445     GPIOA_Init(GPIOA, &GPIO_InitStruct);
446 #endif
447 
448     return rt_device_pin_register("pin", &_v85xx_pin_ops, RT_NULL);
449 }
450 INIT_BOARD_EXPORT(rt_hw_pin_init);
451 #endif /* RT_USING_PIN */
452