1 /*
2 * Copyright (c) 2021-2024 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-01-11 HPMicro First version
9 * 2022-07-28 HPMicro Fixed compiling warnings
10 * 2023-05-08 HPMicro Adapt RT-Thread V5.0.0
11 * 2023-08-15 HPMicro Enable pad loopback feature
12 * 2024-01-08 HPMicro Implemented pin_get
13 * 2024-04-17 HPMicro Refined pin irq implementation
14 * 2024-05-31 HPMicro Adapt later PIN driver framework
15 * 2024-07-03 HPMicro Determined the existence of GPIO via GPIO_DO_GPIOx macro
16 */
17
18 #include <rtthread.h>
19
20 #ifdef BSP_USING_GPIO
21 #include <rthw.h>
22 #include <rtdevice.h>
23 #include "board.h"
24 #include "drv_gpio.h"
25 #include "hpm_gpio_drv.h"
26 #include "hpm_gpiom_drv.h"
27 #include "hpm_clock_drv.h"
28 #include "hpm_soc_feature.h"
29
30
31 typedef struct
32 {
33 uint32_t gpio_idx;
34 uint32_t irq_num;
35 struct rt_pin_irq_hdr *pin_irq_tbl;
36 } gpio_irq_map_t;
37
38 #ifdef GPIO_DO_GPIOA
39 static struct rt_pin_irq_hdr hpm_gpio0_a_pin_hdr[32];
40 #endif
41 #ifdef GPIO_DO_GPIOB
42 static struct rt_pin_irq_hdr hpm_gpio0_b_pin_hdr[32];
43 #endif
44 #ifdef GPIO_DO_GPIOC
45 static struct rt_pin_irq_hdr hpm_gpio0_c_pin_hdr[32];
46 #endif
47 #ifdef GPIO_DO_GPIOD
48 static struct rt_pin_irq_hdr hpm_gpio0_d_pin_hdr[32];
49 #endif
50 #ifdef GPIO_DO_GPIOE
51 static struct rt_pin_irq_hdr hpm_gpio0_e_pin_hdr[32];
52 #endif
53 #ifdef GPIO_DO_GPIOF
54 static struct rt_pin_irq_hdr hpm_gpio0_f_pin_hdr[32];
55 #endif
56 #ifdef GPIO_DO_GPIOV
57 static struct rt_pin_irq_hdr hpm_gpio0_v_pin_hdr[32];
58 #endif
59 #ifdef GPIO_DO_GPIOW
60 static struct rt_pin_irq_hdr hpm_gpio0_w_pin_hdr[32];
61 #endif
62 #ifdef GPIO_DO_GPIOX
63 static struct rt_pin_irq_hdr hpm_gpio0_x_pin_hdr[32];
64 #endif
65 #ifdef GPIO_DO_GPIOY
66 static struct rt_pin_irq_hdr hpm_gpio0_y_pin_hdr[32];
67 #endif
68 #ifdef GPIO_DO_GPIOZ
69 static struct rt_pin_irq_hdr hpm_gpio0_z_pin_hdr[32];
70 #endif
71
72 static const gpio_irq_map_t hpm_gpio_irq_map[] = {
73 #ifdef GPIO_DO_GPIOA
74 { GPIO_IE_GPIOA, IRQn_GPIO0_A, hpm_gpio0_a_pin_hdr },
75 #endif
76 #ifdef GPIO_DO_GPIOB
77 { GPIO_IE_GPIOB, IRQn_GPIO0_B, hpm_gpio0_b_pin_hdr },
78 #endif
79 #ifdef GPIO_DO_GPIOC
80 { GPIO_IE_GPIOC, IRQn_GPIO0_C, hpm_gpio0_c_pin_hdr },
81 #endif
82 #ifdef GPIO_DO_GPIOD
83 { GPIO_IE_GPIOD, IRQn_GPIO0_D, hpm_gpio0_d_pin_hdr },
84 #endif
85 #ifdef GPIO_DO_GPIOE
86 { GPIO_IE_GPIOE, IRQn_GPIO0_E, hpm_gpio0_e_pin_hdr },
87 #endif
88 #ifdef GPIO_DO_GPIOF
89 { GPIO_IE_GPIOF, IRQn_GPIO0_F, hpm_gpio0_f_pin_hdr },
90 #endif
91 #ifdef GPIO_DO_GPIOV
92 { GPIO_IE_GPIOV, IRQn_GPIO0_V, hpm_gpio0_v_pin_hdr },
93 #endif
94 #ifdef GPIO_DO_GPIOW
95 { GPIO_IE_GPIOW, IRQn_GPIO0_W, hpm_gpio0_w_pin_hdr },
96 #endif
97 #ifdef GPIO_DO_GPIOX
98 { GPIO_IE_GPIOX, IRQn_GPIO0_X, hpm_gpio0_x_pin_hdr },
99 #endif
100 #ifdef GPIO_DO_GPIOY
101 { GPIO_IE_GPIOY, IRQn_GPIO0_Y, hpm_gpio0_y_pin_hdr },
102 #endif
103 #ifdef GPIO_DO_GPIOZ
104 { GPIO_IE_GPIOZ, IRQn_GPIO0_Z, hpm_gpio0_z_pin_hdr },
105 #endif
106 };
107
lookup_pin_irq_hdr_tbl(rt_base_t pin)108 static struct rt_pin_irq_hdr *lookup_pin_irq_hdr_tbl(rt_base_t pin)
109 {
110 struct rt_pin_irq_hdr *pin_irq_hdr_tbl = RT_NULL;
111 uint32_t gpio_idx = pin >> 5;
112
113 for (uint32_t i = 0; i < ARRAY_SIZE(hpm_gpio_irq_map); i++)
114 {
115 if (hpm_gpio_irq_map[i].gpio_idx == gpio_idx)
116 {
117 pin_irq_hdr_tbl = hpm_gpio_irq_map[i].pin_irq_tbl;
118 break;
119 }
120 }
121 return pin_irq_hdr_tbl;
122 }
123
hpm_get_gpio_irq_num(uint32_t gpio_idx)124 static int hpm_get_gpio_irq_num(uint32_t gpio_idx)
125 {
126 int irq_num = -1;
127
128 for (uint32_t i = 0; i < ARRAY_SIZE(hpm_gpio_irq_map); i++)
129 {
130 if (hpm_gpio_irq_map[i].gpio_idx == gpio_idx)
131 {
132 irq_num = hpm_gpio_irq_map[i].irq_num;
133 break;
134 }
135 }
136 return irq_num;
137 }
138
hpm_gpio_isr(uint32_t gpio_idx,GPIO_Type * base)139 static void hpm_gpio_isr(uint32_t gpio_idx, GPIO_Type *base)
140 {
141 /* Lookup the Pin IRQ Header Table */
142 struct rt_pin_irq_hdr *pin_irq_hdr = RT_NULL;
143 for (uint32_t i = 0; i < ARRAY_SIZE(hpm_gpio_irq_map); i++)
144 {
145 if (hpm_gpio_irq_map[i].gpio_idx == gpio_idx)
146 {
147 pin_irq_hdr = hpm_gpio_irq_map[i].pin_irq_tbl;
148 break;
149 }
150 }
151
152 for(uint32_t pin_idx = 0; pin_idx < 32; pin_idx++)
153 {
154 if (gpio_check_pin_interrupt_flag(base, gpio_idx, pin_idx))
155 {
156 gpio_clear_pin_interrupt_flag(base, gpio_idx, pin_idx);
157
158 if (pin_irq_hdr[pin_idx].hdr != RT_NULL)
159 {
160 pin_irq_hdr[pin_idx].hdr(pin_irq_hdr[pin_idx].args);
161 }
162 }
163 }
164 }
165
166 #ifdef GPIO_DO_GPIOA
gpioa_isr(void)167 void gpioa_isr(void)
168 {
169 hpm_gpio_isr(GPIO_IF_GPIOA, HPM_GPIO0);
170 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_A,gpioa_isr)171 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_A, gpioa_isr)
172 #endif
173
174 #ifdef GPIO_DO_GPIOB
175 void gpiob_isr(void)
176 {
177 hpm_gpio_isr(GPIO_IF_GPIOB, HPM_GPIO0);
178 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_B,gpiob_isr)179 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_B, gpiob_isr)
180 #endif
181
182 #ifdef GPIO_DO_GPIOC
183 void gpioc_isr(void)
184 {
185 hpm_gpio_isr(GPIO_IF_GPIOC, HPM_GPIO0);
186 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_C,gpioc_isr)187 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_C, gpioc_isr)
188 #endif
189
190 #ifdef GPIO_DO_GPIOD
191 void gpiod_isr(void)
192 {
193 hpm_gpio_isr(GPIO_IF_GPIOD, HPM_GPIO0);
194 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_D,gpiod_isr)195 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_D, gpiod_isr)
196 #endif
197
198 #ifdef GPIO_DO_GPIOE
199 void gpioe_isr(void)
200 {
201 hpm_gpio_isr(GPIO_IF_GPIOE, HPM_GPIO0);
202 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_E,gpioe_isr)203 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_E, gpioe_isr)
204 #endif
205
206 #ifdef GPIO_DO_GPIOF
207 void gpiof_isr(void)
208 {
209 hpm_gpio_isr(GPIO_IF_GPIOF, HPM_GPIO0);
210 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_F,gpiof_isr)211 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_F, gpiof_isr)
212 #endif
213
214 #ifdef GPIO_DO_GPIOV
215 void gpiov_isr(void)
216 {
217 hpm_gpio_isr(GPIO_IF_GPIOV, HPM_GPIO0);
218 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_V,gpiox_isr)219 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_V, gpiox_isr)
220 #endif
221
222 #ifdef GPIO_DO_GPIOW
223 void gpiow_isr(void)
224 {
225 hpm_gpio_isr(GPIO_IF_GPIOW, HPM_GPIO0);
226 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_W,gpiox_isr)227 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_W, gpiox_isr)
228 #endif
229
230 #ifdef GPIO_DO_GPIOX
231 void gpiox_isr(void)
232 {
233 hpm_gpio_isr(GPIO_IF_GPIOX, HPM_GPIO0);
234 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_X,gpiox_isr)235 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_X, gpiox_isr)
236 #endif
237
238 #ifdef GPIO_DO_GPIOY
239 void gpioy_isr(void)
240 {
241 hpm_gpio_isr(GPIO_IF_GPIOY, HPM_GPIO0);
242 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_Y,gpioy_isr)243 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_Y, gpioy_isr)
244 #endif
245
246 #ifdef GPIO_DO_GPIOZ
247 void gpioz_isr(void)
248 {
249 hpm_gpio_isr(GPIO_IF_GPIOZ, HPM_GPIO0);
250 }
SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_Z,gpioz_isr)251 SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_Z, gpioz_isr)
252 #endif
253
254 /**
255 * @brief Get Pin index from name
256 *
257 * Name rule is : <GPIO NAME><Index>
258 * for example: PA00, PZ03
259 *
260 **/
261 static rt_base_t hpm_pin_get(const char *name)
262 {
263 if (!( (rt_strlen(name) == 4) &&
264 (name[0] == 'P') &&
265 ((('A' <= name[1]) && (name[1] <= 'F')) || (('V' <= name[1]) && (name[1] <= 'Z'))) &&
266 (('0' <= name[2]) && (name[2] <= '9')) &&
267 (('0' <= name[3]) && (name[3] <= '9'))
268 ))
269 {
270 return -RT_EINVAL;
271 }
272
273 uint32_t gpio_idx = (name[1] <= 'F') ? (name[1] - 'A') : (11 + name[1] - 'V');
274 uint32_t pin_idx = (uint32_t)(name[2] - '0') * 10 + (name[3] - '0');
275 return (gpio_idx * 32 + pin_idx);
276 }
277
hpm_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)278 static void hpm_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
279 {
280 /* TODO: Check the validity of the pin value */
281 uint32_t gpio_idx = pin >> 5;
282 uint32_t pin_idx = pin & 0x1FU;
283
284 gpiom_set_pin_controller(HPM_GPIOM, gpio_idx, pin_idx, gpiom_soc_gpio0);
285
286 HPM_IOC->PAD[pin].FUNC_CTL = 0;
287
288 switch (gpio_idx)
289 {
290 case GPIO_DI_GPIOY :
291 HPM_PIOC->PAD[pin].FUNC_CTL = 3;
292 break;
293 #ifdef GPIO_DI_GPIOZ
294 case GPIO_DI_GPIOZ :
295 #ifdef HPM_BIOC
296 HPM_BIOC->PAD[pin].FUNC_CTL = 3;
297 #endif
298 break;
299 #endif
300 default :
301 break;
302 }
303
304 switch (mode)
305 {
306 case PIN_MODE_OUTPUT:
307 gpio_set_pin_output(HPM_GPIO0, gpio_idx, pin_idx);
308 HPM_IOC->PAD[pin].PAD_CTL &= ~(IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_OD_MASK);
309 break;
310 case PIN_MODE_INPUT:
311 gpio_set_pin_input(HPM_GPIO0, gpio_idx, pin_idx);
312 HPM_IOC->PAD[pin].PAD_CTL &= ~(IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_PE_MASK);
313 break;
314 case PIN_MODE_INPUT_PULLDOWN:
315 gpio_set_pin_input(HPM_GPIO0, gpio_idx, pin_idx);
316 HPM_IOC->PAD[pin].PAD_CTL = (HPM_IOC->PAD[pin].PAD_CTL & ~IOC_PAD_PAD_CTL_PS_MASK) | IOC_PAD_PAD_CTL_PE_SET(1);
317 break;
318 case PIN_MODE_INPUT_PULLUP:
319 gpio_set_pin_input(HPM_GPIO0, gpio_idx, pin_idx);
320 HPM_IOC->PAD[pin].PAD_CTL |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
321 break;
322 case PIN_MODE_OUTPUT_OD:
323 gpio_set_pin_output(HPM_GPIO0, gpio_idx, pin_idx);
324 HPM_IOC->PAD[pin].PAD_CTL = (HPM_IOC->PAD[pin].PAD_CTL & ~(IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_PE_MASK)) | IOC_PAD_PAD_CTL_OD_SET(1);
325 break;
326 default:
327 /* Invalid mode */
328 break;
329 }
330 HPM_IOC->PAD[pin].FUNC_CTL = IOC_PAD_FUNC_CTL_LOOP_BACK_MASK;
331 }
332
hpm_pin_read(rt_device_t dev,rt_base_t pin)333 static rt_ssize_t hpm_pin_read(rt_device_t dev, rt_base_t pin)
334 {
335 /* TODO: Check the validity of the pin value */
336 uint32_t gpio_idx = pin >> 5;
337 uint32_t pin_idx = pin & 0x1FU;
338
339 return (rt_ssize_t) gpio_read_pin(HPM_GPIO0, gpio_idx, pin_idx);
340 }
341
hpm_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)342 static void hpm_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
343 {
344 /* TODO: Check the validity of the pin value */
345 uint32_t gpio_idx = pin >> 5;
346 uint32_t pin_idx = pin & 0x1FU;
347
348 gpio_write_pin(HPM_GPIO0, gpio_idx, pin_idx, value);
349 }
350
hpm_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)351 static rt_err_t hpm_pin_attach_irq(struct rt_device *device,
352 rt_base_t pin,
353 rt_uint8_t mode,
354 void (*hdr)(void *args),
355 void *args)
356 {
357 struct rt_pin_irq_hdr *pin_irq_hdr_tbl = lookup_pin_irq_hdr_tbl(pin);
358 if (pin_irq_hdr_tbl == RT_NULL)
359 {
360 return -RT_EINVAL;
361 }
362
363 rt_base_t level = rt_hw_interrupt_disable();
364 uint32_t pin_idx = pin & 0x1FUL;
365 pin_irq_hdr_tbl[pin_idx].pin = pin;
366 pin_irq_hdr_tbl[pin_idx].hdr = hdr;
367 pin_irq_hdr_tbl[pin_idx].mode = mode;
368 pin_irq_hdr_tbl[pin_idx].args = args;
369 rt_hw_interrupt_enable(level);
370
371 return RT_EOK;
372 }
373
hpm_pin_detach_irq(struct rt_device * device,rt_base_t pin)374 static rt_err_t hpm_pin_detach_irq(struct rt_device *device, rt_base_t pin)
375 {
376 struct rt_pin_irq_hdr *pin_irq_hdr_tbl = lookup_pin_irq_hdr_tbl(pin);
377 if (pin_irq_hdr_tbl == RT_NULL)
378 {
379 return -RT_EINVAL;
380 }
381 rt_base_t level = rt_hw_interrupt_disable();
382 uint32_t pin_idx = pin & 0x1FUL;
383 pin_irq_hdr_tbl[pin_idx].pin = -1;
384 pin_irq_hdr_tbl[pin_idx].hdr = RT_NULL;
385 pin_irq_hdr_tbl[pin_idx].mode = 0;
386 pin_irq_hdr_tbl[pin_idx].args = RT_NULL;
387 rt_hw_interrupt_enable(level);
388
389 return RT_EOK;
390 }
391
hpm_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)392 static rt_err_t hpm_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
393 {
394 /* TODO: Check the validity of the pin value */
395 uint32_t gpio_idx = pin >> 5;
396 uint32_t pin_idx = pin & 0x1FU;
397
398 struct rt_pin_irq_hdr *pin_irq_hdr_tbl = lookup_pin_irq_hdr_tbl(pin);
399 if (pin_irq_hdr_tbl == RT_NULL)
400 {
401 return -RT_EINVAL;
402 }
403
404 gpio_interrupt_trigger_t trigger;
405 if (enabled == PIN_IRQ_ENABLE)
406 {
407 switch(pin_irq_hdr_tbl[pin_idx].mode)
408 {
409 case PIN_IRQ_MODE_RISING:
410 trigger = gpio_interrupt_trigger_edge_rising;
411 break;
412 case PIN_IRQ_MODE_FALLING:
413 trigger = gpio_interrupt_trigger_edge_falling;
414 break;
415 case PIN_IRQ_MODE_HIGH_LEVEL:
416 trigger = gpio_interrupt_trigger_level_high;
417 break;
418 case PIN_IRQ_MODE_LOW_LEVEL:
419 trigger = gpio_interrupt_trigger_level_low;
420 break;
421 default:
422 trigger = gpio_interrupt_trigger_edge_rising;
423 break;
424 }
425 gpio_config_pin_interrupt(HPM_GPIO0, gpio_idx, pin_idx, trigger);
426 uint32_t irq_num = hpm_get_gpio_irq_num(gpio_idx);
427 gpio_enable_pin_interrupt(HPM_GPIO0, gpio_idx, pin_idx);
428 intc_m_enable_irq_with_priority(irq_num, 1);
429 }
430 else if (enabled == PIN_IRQ_DISABLE)
431 {
432 gpio_disable_pin_interrupt(HPM_GPIO0, gpio_idx, pin_idx);
433 }
434 else
435 {
436 return -RT_EINVAL;
437 }
438
439 return RT_EOK;
440 }
441
442 const static struct rt_pin_ops hpm_pin_ops = {
443 .pin_mode = hpm_pin_mode,
444 .pin_write = hpm_pin_write,
445 .pin_read = hpm_pin_read,
446 .pin_attach_irq = hpm_pin_attach_irq,
447 .pin_detach_irq = hpm_pin_detach_irq,
448 .pin_irq_enable = hpm_pin_irq_enable,
449 .pin_get = hpm_pin_get,
450 };
451
rt_hw_pin_init(void)452 int rt_hw_pin_init(void)
453 {
454 int ret = RT_EOK;
455
456 ret = rt_device_pin_register("pin", &hpm_pin_ops, RT_NULL);
457
458 return ret;
459 }
460
461 INIT_BOARD_EXPORT(rt_hw_pin_init);
462
463 #endif /* BSP_USING_GPIO */
464