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