drv_gpio.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * Copyright (c) 2021-2023 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. */
  13. #include <rtthread.h>
  14. #ifdef BSP_USING_GPIO
  15. #include <rthw.h>
  16. #include <rtdevice.h>
  17. #include "board.h"
  18. #include "drv_gpio.h"
  19. #include "hpm_gpio_drv.h"
  20. #include "hpm_gpiom_drv.h"
  21. #include "hpm_clock_drv.h"
  22. #include "hpm_soc_feature.h"
  23. typedef struct
  24. {
  25. uint32_t gpio_idx;
  26. uint32_t irq_num;
  27. } gpio_irq_map_t;
  28. static const gpio_irq_map_t hpm_gpio_irq_map[] = {
  29. #ifdef IRQn_GPIO0_A
  30. { GPIO_IE_GPIOA, IRQn_GPIO0_A },
  31. #endif
  32. #ifdef IRQn_GPIO0_B
  33. { GPIO_IE_GPIOB, IRQn_GPIO0_B },
  34. #endif
  35. #ifdef IRQn_GPIO0_C
  36. { GPIO_IE_GPIOC, IRQn_GPIO0_C },
  37. #endif
  38. #ifdef GPIO_IE_GPIOD
  39. { GPIO_IE_GPIOD, IRQn_GPIO0_D },
  40. #endif
  41. #ifdef IRQn_GPIO0_E
  42. { GPIO_IE_GPIOE, IRQn_GPIO0_E },
  43. #endif
  44. #ifdef IRQn_GPIO0_F
  45. { GPIO_IE_GPIOF, IRQn_GPIO0_F },
  46. #endif
  47. #ifdef IRQn_GPIO0_X
  48. { GPIO_IE_GPIOX, IRQn_GPIO0_X },
  49. #endif
  50. #ifdef IRQn_GPIO0_Y
  51. { GPIO_IE_GPIOY, IRQn_GPIO0_Y },
  52. #endif
  53. #ifdef IRQn_GPIO0_Z
  54. { GPIO_IE_GPIOZ, IRQn_GPIO0_Z },
  55. #endif
  56. };
  57. static struct rt_pin_irq_hdr hpm_gpio_pin_hdr_tbl[IOC_SOC_PAD_MAX];
  58. static int hpm_get_gpi_irq_num(uint32_t gpio_idx)
  59. {
  60. int irq_num = -1;
  61. for (uint32_t i = 0; i < sizeof(hpm_gpio_irq_map) / sizeof(hpm_gpio_irq_map[0]); i++)
  62. {
  63. if (hpm_gpio_irq_map[i].gpio_idx == gpio_idx)
  64. {
  65. irq_num = hpm_gpio_irq_map[i].irq_num;
  66. break;
  67. }
  68. }
  69. return irq_num;
  70. }
  71. static void hpm_gpio_isr(uint32_t gpio_index, GPIO_Type *base)
  72. {
  73. uint32_t pin_idx = 0;
  74. for(pin_idx = 0; pin_idx < 32; pin_idx++)
  75. {
  76. if (gpio_check_pin_interrupt_flag(base, gpio_index, pin_idx))
  77. {
  78. uint32_t pin = gpio_index * 32U + pin_idx;
  79. gpio_clear_pin_interrupt_flag(base, gpio_index, pin_idx);
  80. if (hpm_gpio_pin_hdr_tbl[pin].hdr != RT_NULL)
  81. {
  82. hpm_gpio_pin_hdr_tbl[pin].hdr(hpm_gpio_pin_hdr_tbl[pin].args);
  83. }
  84. }
  85. }
  86. }
  87. #ifdef GPIO_IF_GPIOA
  88. void gpioa_isr(void)
  89. {
  90. hpm_gpio_isr(GPIO_IF_GPIOA, HPM_GPIO0);
  91. }
  92. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_A, gpioa_isr)
  93. #endif
  94. #ifdef GPIO_IF_GPIOB
  95. void gpiob_isr(void)
  96. {
  97. hpm_gpio_isr(GPIO_IF_GPIOB, HPM_GPIO0);
  98. }
  99. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_B, gpiob_isr)
  100. #endif
  101. #ifdef GPIO_IF_GPIOC
  102. void gpioc_isr(void)
  103. {
  104. hpm_gpio_isr(GPIO_IF_GPIOC, HPM_GPIO0);
  105. }
  106. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_C, gpioc_isr)
  107. #endif
  108. #ifdef GPIO_IF_GPIOD
  109. void gpiod_isr(void)
  110. {
  111. hpm_gpio_isr(GPIO_IF_GPIOD, HPM_GPIO0);
  112. }
  113. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_D, gpiod_isr)
  114. #endif
  115. #ifdef GPIO_IF_GPIOE
  116. void gpioe_isr(void)
  117. {
  118. hpm_gpio_isr(GPIO_IF_GPIOE, HPM_GPIO0);
  119. }
  120. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_E, gpioe_isr)
  121. #endif
  122. #ifdef GPIO_IF_GPIOF
  123. void gpiof_isr(void)
  124. {
  125. hpm_gpio_isr(GPIO_IF_GPIOF, HPM_GPIO0);
  126. }
  127. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_F, gpiof_isr)
  128. #endif
  129. #ifdef GPIO_IF_GPIOX
  130. void gpiox_isr(void)
  131. {
  132. hpm_gpio_isr(GPIO_IF_GPIOX, HPM_GPIO0);
  133. }
  134. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_X, gpiox_isr)
  135. #endif
  136. #ifdef GPIO_IF_GPIOY
  137. void gpioy_isr(void)
  138. {
  139. hpm_gpio_isr(GPIO_IF_GPIOY, HPM_GPIO0);
  140. }
  141. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_Y, gpioy_isr)
  142. #endif
  143. #ifdef GPIO_IF_GPIOZ
  144. void gpioz_isr(void)
  145. {
  146. hpm_gpio_isr(GPIO_IF_GPIOZ, HPM_GPIO0);
  147. }
  148. SDK_DECLARE_EXT_ISR_M(IRQn_GPIO0_Z, gpioz_isr)
  149. #endif
  150. static void hpm_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
  151. {
  152. /* TODO: Check the validity of the pin value */
  153. uint32_t gpio_idx = pin >> 5;
  154. uint32_t pin_idx = pin & 0x1FU;
  155. gpiom_set_pin_controller(HPM_GPIOM, gpio_idx, pin_idx, gpiom_soc_gpio0);
  156. HPM_IOC->PAD[pin].FUNC_CTL = 0;
  157. switch (gpio_idx)
  158. {
  159. case GPIO_DI_GPIOY :
  160. HPM_PIOC->PAD[pin].FUNC_CTL = 3;
  161. break;
  162. case GPIO_DI_GPIOZ :
  163. HPM_BIOC->PAD[pin].FUNC_CTL = 3;
  164. break;
  165. default :
  166. break;
  167. }
  168. switch (mode)
  169. {
  170. case PIN_MODE_OUTPUT:
  171. gpio_set_pin_output(HPM_GPIO0, gpio_idx, pin_idx);
  172. HPM_IOC->PAD[pin].PAD_CTL &= ~(IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_OD_MASK);
  173. break;
  174. case PIN_MODE_INPUT:
  175. gpio_set_pin_input(HPM_GPIO0, gpio_idx, pin_idx);
  176. HPM_IOC->PAD[pin].PAD_CTL &= ~(IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_PE_MASK);
  177. break;
  178. case PIN_MODE_INPUT_PULLDOWN:
  179. gpio_set_pin_input(HPM_GPIO0, gpio_idx, pin_idx);
  180. 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);
  181. break;
  182. case PIN_MODE_INPUT_PULLUP:
  183. gpio_set_pin_input(HPM_GPIO0, gpio_idx, pin_idx);
  184. HPM_IOC->PAD[pin].PAD_CTL |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
  185. break;
  186. case PIN_MODE_OUTPUT_OD:
  187. gpio_set_pin_output(HPM_GPIO0, gpio_idx, pin_idx);
  188. 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);
  189. break;
  190. default:
  191. /* Invalid mode */
  192. break;
  193. }
  194. HPM_IOC->PAD[pin].FUNC_CTL = IOC_PAD_FUNC_CTL_LOOP_BACK_MASK;
  195. }
  196. static rt_ssize_t hpm_pin_read(rt_device_t dev, rt_base_t pin)
  197. {
  198. /* TODO: Check the validity of the pin value */
  199. uint32_t gpio_idx = pin >> 5;
  200. uint32_t pin_idx = pin & 0x1FU;
  201. return (rt_ssize_t) gpio_read_pin(HPM_GPIO0, gpio_idx, pin_idx);
  202. }
  203. static void hpm_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
  204. {
  205. /* TODO: Check the validity of the pin value */
  206. uint32_t gpio_idx = pin >> 5;
  207. uint32_t pin_idx = pin & 0x1FU;
  208. gpio_write_pin(HPM_GPIO0, gpio_idx, pin_idx, value);
  209. }
  210. static rt_err_t hpm_pin_attach_irq(struct rt_device *device,
  211. rt_base_t pin,
  212. rt_uint8_t mode,
  213. void (*hdr)(void *args),
  214. void *args)
  215. {
  216. rt_base_t level;
  217. level = rt_hw_interrupt_disable();
  218. hpm_gpio_pin_hdr_tbl[pin].pin = pin;
  219. hpm_gpio_pin_hdr_tbl[pin].hdr = hdr;
  220. hpm_gpio_pin_hdr_tbl[pin].mode = mode;
  221. hpm_gpio_pin_hdr_tbl[pin].args = args;
  222. rt_hw_interrupt_enable(level);
  223. return RT_EOK;
  224. }
  225. static rt_err_t hpm_pin_detach_irq(struct rt_device *device, rt_base_t pin)
  226. {
  227. rt_base_t level;
  228. level = rt_hw_interrupt_disable();
  229. hpm_gpio_pin_hdr_tbl[pin].pin = -1;
  230. hpm_gpio_pin_hdr_tbl[pin].hdr = RT_NULL;
  231. hpm_gpio_pin_hdr_tbl[pin].mode = 0;
  232. hpm_gpio_pin_hdr_tbl[pin].args = RT_NULL;
  233. rt_hw_interrupt_enable(level);
  234. return RT_EOK;
  235. }
  236. static rt_err_t hpm_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  237. {
  238. /* TODO: Check the validity of the pin value */
  239. uint32_t gpio_idx = pin >> 5;
  240. uint32_t pin_idx = pin & 0x1FU;
  241. gpio_interrupt_trigger_t trigger;
  242. if (enabled == PIN_IRQ_ENABLE)
  243. {
  244. switch(hpm_gpio_pin_hdr_tbl[pin].mode)
  245. {
  246. case PIN_IRQ_MODE_RISING:
  247. trigger = gpio_interrupt_trigger_edge_rising;
  248. break;
  249. case PIN_IRQ_MODE_FALLING:
  250. trigger = gpio_interrupt_trigger_edge_falling;
  251. break;
  252. case PIN_IRQ_MODE_HIGH_LEVEL:
  253. trigger = gpio_interrupt_trigger_level_high;
  254. break;
  255. case PIN_IRQ_MODE_LOW_LEVEL:
  256. trigger = gpio_interrupt_trigger_level_low;
  257. break;
  258. default:
  259. trigger = gpio_interrupt_trigger_edge_rising;
  260. break;
  261. }
  262. gpio_config_pin_interrupt(HPM_GPIO0, gpio_idx, pin_idx, trigger);
  263. uint32_t irq_num = hpm_get_gpi_irq_num(gpio_idx);
  264. gpio_enable_pin_interrupt(HPM_GPIO0, gpio_idx, pin_idx);
  265. intc_m_enable_irq_with_priority(irq_num, 1);
  266. }
  267. else if (enabled == PIN_IRQ_DISABLE)
  268. {
  269. gpio_disable_pin_interrupt(HPM_GPIO0, gpio_idx, pin_idx);
  270. }
  271. else
  272. {
  273. return RT_EINVAL;
  274. }
  275. return RT_EOK;
  276. }
  277. const static struct rt_pin_ops hpm_pin_ops = {
  278. .pin_mode = hpm_pin_mode,
  279. .pin_write = hpm_pin_write,
  280. .pin_read = hpm_pin_read,
  281. .pin_attach_irq = hpm_pin_attach_irq,
  282. .pin_detach_irq = hpm_pin_detach_irq,
  283. .pin_irq_enable = hpm_pin_irq_enable};
  284. int rt_hw_pin_init(void)
  285. {
  286. int ret = RT_EOK;
  287. ret = rt_device_pin_register("pin", &hpm_pin_ops, RT_NULL);
  288. return ret;
  289. }
  290. INIT_BOARD_EXPORT(rt_hw_pin_init);
  291. #endif /* BSP_USING_GPIO */