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