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