drv_gpio.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-03-19 ZYH first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <fpioa.h>
  13. #include <gpiohs.h>
  14. #include "drv_gpio.h"
  15. #include "drv_io_config.h"
  16. #include <plic.h>
  17. #include <rthw.h>
  18. #include <utils.h>
  19. #include <string.h>
  20. #define DBG_ENABLE
  21. #define DBG_TAG "PIN"
  22. #define DBG_LVL DBG_WARNING
  23. #define DBG_COLOR
  24. #include <rtdbg.h>
  25. #define FUNC_GPIOHS(n) (FUNC_GPIOHS0 + n)
  26. static short pin_alloc_table[FPIOA_NUM_IO];
  27. static uint32_t free_pin = 0;
  28. static int alloc_pin_channel(rt_base_t pin_index)
  29. {
  30. if(free_pin == 32)
  31. {
  32. LOG_E("no free gpiohs channel to alloc");
  33. return -1;
  34. }
  35. if(pin_alloc_table[pin_index] != -1)
  36. {
  37. LOG_W("already alloc gpiohs channel for pin %d", pin_index);
  38. return pin_alloc_table[pin_index];
  39. }
  40. pin_alloc_table[pin_index] = free_pin;
  41. free_pin++;
  42. fpioa_set_function(pin_index, FUNC_GPIOHS(pin_alloc_table[pin_index]));
  43. return pin_alloc_table[pin_index];
  44. }
  45. int get_pin_channel(rt_base_t pin_index)
  46. {
  47. return pin_alloc_table[pin_index];
  48. }
  49. static void free_pin_channel(rt_base_t pin_index)
  50. {
  51. if(pin_alloc_table[pin_index] == -1)
  52. {
  53. LOG_W("free error:not alloc gpiohs channel for pin %d", pin_index);
  54. return;
  55. }
  56. pin_alloc_table[pin_index] = -1;
  57. free_pin--;
  58. }
  59. static void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode)
  60. {
  61. int pin_channel = get_pin_channel(pin);
  62. if(pin_channel == -1)
  63. {
  64. pin_channel = alloc_pin_channel(pin);
  65. if(pin_channel == -1)
  66. {
  67. return;
  68. }
  69. }
  70. switch (mode)
  71. {
  72. case PIN_MODE_OUTPUT:
  73. gpiohs_set_drive_mode(pin_channel, GPIO_DM_OUTPUT);
  74. break;
  75. case PIN_MODE_INPUT:
  76. gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT);
  77. break;
  78. case PIN_MODE_INPUT_PULLUP:
  79. gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_UP);
  80. break;
  81. case PIN_MODE_INPUT_PULLDOWN:
  82. gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_DOWN);
  83. break;
  84. default:
  85. LOG_E("Not support mode %d", mode);
  86. break;
  87. }
  88. }
  89. static void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_base_t value)
  90. {
  91. int pin_channel = get_pin_channel(pin);
  92. if(pin_channel == -1)
  93. {
  94. LOG_E("pin %d not set mode", pin);
  95. return;
  96. }
  97. gpiohs_set_pin(pin_channel, value == PIN_HIGH ? GPIO_PV_HIGH : GPIO_PV_LOW);
  98. }
  99. static int drv_pin_read(struct rt_device *device, rt_base_t pin)
  100. {
  101. int pin_channel = get_pin_channel(pin);
  102. if(pin_channel == -1)
  103. {
  104. LOG_E("pin %d not set mode", pin);
  105. return -1;
  106. }
  107. return gpiohs_get_pin(pin_channel) == GPIO_PV_HIGH ? PIN_HIGH : PIN_LOW;
  108. }
  109. static struct
  110. {
  111. void (*hdr)(void *args);
  112. void* args;
  113. gpio_pin_edge_t edge;
  114. } irq_table[32];
  115. static void pin_irq(int vector, void *param)
  116. {
  117. int pin_channel = vector - IRQN_GPIOHS0_INTERRUPT;
  118. if(irq_table[pin_channel].edge & GPIO_PE_FALLING)
  119. {
  120. set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 0);
  121. set_gpio_bit(gpiohs->fall_ip.u32, pin_channel, 1);
  122. set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 1);
  123. }
  124. if(irq_table[pin_channel].edge & GPIO_PE_RISING)
  125. {
  126. set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 0);
  127. set_gpio_bit(gpiohs->rise_ip.u32, pin_channel, 1);
  128. set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 1);
  129. }
  130. if(irq_table[pin_channel].edge & GPIO_PE_LOW)
  131. {
  132. set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 0);
  133. set_gpio_bit(gpiohs->low_ip.u32, pin_channel, 1);
  134. set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 1);
  135. }
  136. if(irq_table[pin_channel].edge & GPIO_PE_HIGH)
  137. {
  138. set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 0);
  139. set_gpio_bit(gpiohs->high_ip.u32, pin_channel, 1);
  140. set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 1);
  141. }
  142. if(irq_table[pin_channel].hdr)
  143. {
  144. irq_table[pin_channel].hdr(irq_table[pin_channel].args);
  145. }
  146. }
  147. static rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
  148. rt_uint32_t mode, void (*hdr)(void *args), void *args)
  149. {
  150. int pin_channel = get_pin_channel(pin);
  151. char irq_name[10];
  152. if(pin_channel == -1)
  153. {
  154. LOG_E("pin %d not set mode", pin);
  155. return -RT_ERROR;
  156. }
  157. irq_table[pin_channel].hdr = hdr;
  158. irq_table[pin_channel].args = args;
  159. switch (mode)
  160. {
  161. case PIN_IRQ_MODE_RISING:
  162. irq_table[pin_channel].edge = GPIO_PE_RISING;
  163. break;
  164. case PIN_IRQ_MODE_FALLING:
  165. irq_table[pin_channel].edge = GPIO_PE_FALLING;
  166. break;
  167. case PIN_IRQ_MODE_RISING_FALLING:
  168. irq_table[pin_channel].edge = GPIO_PE_BOTH;
  169. break;
  170. case PIN_IRQ_MODE_HIGH_LEVEL:
  171. irq_table[pin_channel].edge = GPIO_PE_LOW;
  172. break;
  173. case PIN_IRQ_MODE_LOW_LEVEL:
  174. irq_table[pin_channel].edge = GPIO_PE_HIGH;
  175. break;
  176. default:
  177. break;
  178. }
  179. gpiohs_set_pin_edge(pin_channel, irq_table[pin_channel].edge);
  180. rt_snprintf(irq_name, sizeof irq_name, "pin%d", pin);
  181. rt_hw_interrupt_install(IRQN_GPIOHS0_INTERRUPT + pin_channel, pin_irq, RT_NULL, irq_name);
  182. return RT_EOK;
  183. }
  184. static rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
  185. {
  186. rt_err_t ret = RT_EOK;
  187. int pin_channel = get_pin_channel(pin);
  188. if(pin_channel == -1)
  189. {
  190. LOG_E("pin %d not set mode", pin);
  191. return -RT_ERROR;
  192. }
  193. irq_table[pin_channel].hdr = RT_NULL;
  194. irq_table[pin_channel].args = RT_NULL;
  195. return ret;
  196. }
  197. static rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
  198. {
  199. int pin_channel = get_pin_channel(pin);
  200. if(pin_channel == -1)
  201. {
  202. LOG_E("pin %d not set mode", pin);
  203. return -RT_ERROR;
  204. }
  205. if(enabled)
  206. {
  207. rt_hw_interrupt_umask(IRQN_GPIOHS0_INTERRUPT + pin_channel);
  208. }
  209. else
  210. {
  211. rt_hw_interrupt_mask(IRQN_GPIOHS0_INTERRUPT + pin_channel);
  212. }
  213. return RT_EOK;
  214. }
  215. const static struct rt_pin_ops drv_pin_ops =
  216. {
  217. drv_pin_mode,
  218. drv_pin_write,
  219. drv_pin_read,
  220. drv_pin_attach_irq,
  221. drv_pin_detach_irq,
  222. drv_pin_irq_enable
  223. };
  224. int rt_hw_pin_init(void)
  225. {
  226. rt_err_t ret = RT_EOK;
  227. memset(pin_alloc_table, 0xff, sizeof pin_alloc_table);
  228. free_pin = GPIO_ALLOC_START;
  229. ret = rt_device_pin_register("pin", &drv_pin_ops, RT_NULL);
  230. return ret;
  231. }
  232. INIT_BOARD_EXPORT(rt_hw_pin_init);