gpio.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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. * 2015-06-19 ItsEddy add gpio driver support
  9. * 2022-09-14 YangZhongQing full gpio driver support
  10. * I referred AM335X_StarterWare_02_00_01_01
  11. */
  12. #include <ctype.h>
  13. #include <rthw.h>
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include <am33xx.h>
  17. #include <interrupt.h>
  18. #include "gpio.h"
  19. #ifdef RT_USING_PIN
  20. #define reg(base) *(int*)(base)
  21. #define GPIO_PIN_LOW (0x0)
  22. #define GPIO_PIN_HIGH (0x1)
  23. /* Values denoting the Interrupt Line number to be used. */
  24. #define GPIO_INT_LINE_1 (0x0)
  25. #define GPIO_INT_LINE_2 (0x1)
  26. #define GPIO_REVISION (0x0)
  27. #define GPIO_SYSCONFIG (0x10)
  28. #define GPIO_IRQSTATUS_RAW(n) (0x24 + (n * 4))
  29. #define GPIO_IRQSTATUS(n) (0x2C + (n * 4))
  30. #define GPIO_IRQSTATUS_SET(n) (0x34 + (n * 4))
  31. #define GPIO_IRQSTATUS_CLR(n) (0x3C + (n * 4))
  32. #define GPIO_IRQWAKEN(n) (0x44 + (n * 4))
  33. #define GPIO_SYSSTATUS (0x114)
  34. #define GPIO_CTRL (0x130)
  35. #define GPIO_OE (0x134)
  36. #define GPIO_DATAIN (0x138)
  37. #define GPIO_DATAOUT (0x13C)
  38. #define GPIO_LEVELDETECT(n) (0x140 + (n * 4))
  39. #define GPIO_RISINGDETECT (0x148)
  40. #define GPIO_FALLINGDETECT (0x14C)
  41. #define GPIO_DEBOUNCENABLE (0x150)
  42. #define GPIO_DEBOUNCINGTIME (0x154)
  43. #define GPIO_CLEARDATAOUT (0x190)
  44. #define GPIO_SETDATAOUT (0x194)
  45. static const rt_base_t GPIO_BASE[] =
  46. {
  47. AM33XX_GPIO_0_REGS,
  48. AM33XX_GPIO_1_REGS,
  49. AM33XX_GPIO_2_REGS,
  50. AM33XX_GPIO_3_REGS
  51. };
  52. #define GPIO_INT0x GPIO_INT0A
  53. #define GPIO_INT1x GPIO_INT1A
  54. #define GPIO_INT2x GPIO_INT2A
  55. #define GPIO_INT3x GPIO_INT3A
  56. static const rt_uint8_t GPIO_INTx[] = {GPIO_INT0x, GPIO_INT1x, GPIO_INT2x, GPIO_INT3x};
  57. // auto determine which int line
  58. #define GPIO_INT0_LINE ((GPIO_INT0x == GPIO_INT0A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
  59. #define GPIO_INT1_LINE ((GPIO_INT1x == GPIO_INT1A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
  60. #define GPIO_INT2_LINE ((GPIO_INT2x == GPIO_INT2A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
  61. #define GPIO_INT3_LINE ((GPIO_INT3x == GPIO_INT3A) ? GPIO_INT_LINE_1 : GPIO_INT_LINE_2)
  62. static const rt_uint8_t GPIO_INT_LINEx[] = {GPIO_INT0_LINE, GPIO_INT1_LINE, GPIO_INT2_LINE, GPIO_INT3_LINE};
  63. struct am33xx_pin_irq_hdr
  64. {
  65. void (*hdr)(void *args);
  66. void *args;
  67. };
  68. struct am33xx_gpio_irq_param
  69. {
  70. struct am33xx_pin_irq_hdr hdr_tab[32];
  71. };
  72. static struct am33xx_gpio_irq_param GPIO_PARAMx[sizeof(GPIO_BASE) / sizeof(GPIO_BASE[0])];
  73. rt_inline void am33xx_gpio_hdr(rt_base_t base, rt_base_t int_line, void *param)
  74. {
  75. struct am33xx_gpio_irq_param *irq_param = param;
  76. struct am33xx_pin_irq_hdr *irq_hdr;
  77. int pinNumber;
  78. rt_ubase_t irqstatus;
  79. irqstatus = REG32(base + GPIO_IRQSTATUS(int_line));
  80. REG32(base + GPIO_IRQSTATUS(int_line)) = irqstatus;
  81. for (pinNumber = 0; pinNumber < sizeof(irq_param->hdr_tab); pinNumber++)
  82. {
  83. if (irqstatus & 0x1)
  84. {
  85. irq_hdr = &irq_param->hdr_tab[pinNumber];
  86. if (irq_hdr->hdr)
  87. irq_hdr->hdr(irq_hdr->args);
  88. // if the last one, exit immediately
  89. if (irqstatus == 0x1)
  90. break;
  91. }
  92. irqstatus >>= 1;
  93. }
  94. }
  95. static void am33xx_gpio0_isr(int vector, void *param)
  96. {
  97. am33xx_gpio_hdr(AM33XX_GPIO_0_REGS, GPIO_INT0_LINE, param);
  98. }
  99. static void am33xx_gpio1_isr(int vector, void *param)
  100. {
  101. am33xx_gpio_hdr(AM33XX_GPIO_1_REGS, GPIO_INT1_LINE, param);
  102. }
  103. static void am33xx_gpio2_isr(int vector, void *param)
  104. {
  105. am33xx_gpio_hdr(AM33XX_GPIO_2_REGS, GPIO_INT2_LINE, param);
  106. }
  107. static void am33xx_gpio3_isr(int vector, void *param)
  108. {
  109. am33xx_gpio_hdr(AM33XX_GPIO_3_REGS, GPIO_INT3_LINE, param);
  110. }
  111. static const rt_isr_handler_t GPIO_ISRx[] =
  112. {
  113. am33xx_gpio0_isr,
  114. am33xx_gpio1_isr,
  115. am33xx_gpio2_isr,
  116. am33xx_gpio3_isr,
  117. };
  118. static void am33xx_pin_mode(struct rt_device *device, rt_base_t pin, rt_base_t mode)
  119. {
  120. RT_ASSERT(pin >= 0 && pin < 128);
  121. RT_ASSERT(mode != PIN_MODE_INPUT_PULLUP); /* Mode not supported */
  122. rt_base_t gpiox = pin >> 5;
  123. rt_base_t pinNumber = pin & 0x1F;
  124. if (PIN_MODE_OUTPUT == mode)
  125. {
  126. reg(GPIO_BASE[gpiox] + GPIO_OE) &= ~(1 << pinNumber);
  127. }
  128. else if (PIN_MODE_INPUT == mode)
  129. {
  130. reg(GPIO_BASE[gpiox] + GPIO_OE) |= (1 << pinNumber);
  131. }
  132. }
  133. static void am33xx_pin_write(struct rt_device *device, rt_base_t pin, rt_base_t value)
  134. {
  135. RT_ASSERT(pin >= 0 && pin < 128);
  136. rt_base_t gpiox = pin >> 5;
  137. rt_base_t pinNumber = pin & 0x1F;
  138. if (GPIO_PIN_HIGH == value)
  139. {
  140. reg(GPIO_BASE[gpiox] + GPIO_SETDATAOUT) = (1 << pinNumber);
  141. }
  142. else /* GPIO_PIN_LOW */
  143. {
  144. reg(GPIO_BASE[gpiox] + GPIO_CLEARDATAOUT) = (1 << pinNumber);
  145. }
  146. }
  147. static int am33xx_pin_read(struct rt_device *device, rt_base_t pin)
  148. {
  149. RT_ASSERT(pin >= 0 && pin < 128);
  150. rt_base_t gpiox = pin >> 5;
  151. rt_base_t pinNumber = pin & 0x1F;
  152. return reg(GPIO_BASE[gpiox] + GPIO_DATAIN) & (1 << pinNumber) ? 1 : 0;
  153. }
  154. static rt_err_t am33xx_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
  155. rt_uint32_t mode, void (*hdr)(void *args), void *args)
  156. {
  157. RT_ASSERT(pin >= 0 && pin < 128);
  158. rt_base_t gpiox = pin >> 5;
  159. rt_base_t pinNumber = pin & 0x1F;
  160. rt_base_t baseAdd = GPIO_BASE[gpiox];
  161. struct am33xx_pin_irq_hdr *irq_hdr = &GPIO_PARAMx[gpiox].hdr_tab[pinNumber];
  162. rt_base_t level;
  163. level = rt_hw_interrupt_disable();
  164. if (irq_hdr->hdr != RT_NULL)
  165. {
  166. rt_hw_interrupt_enable(level);
  167. return -RT_EBUSY;
  168. }
  169. irq_hdr->hdr = hdr;
  170. irq_hdr->args = args;
  171. switch (mode)
  172. {
  173. case PIN_IRQ_MODE_RISING:
  174. /* Enabling rising edge detect interrupt generation. */
  175. REG32(baseAdd + GPIO_RISINGDETECT) |= (1 << pinNumber);
  176. /* Disabling falling edge detect interrupt generation. */
  177. REG32(baseAdd + GPIO_FALLINGDETECT) &= ~(1 << pinNumber);
  178. /* Disabling logic LOW level detect interrupt generation. */
  179. REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
  180. /* Disabling logic HIGH level detect interrupt generation. */
  181. REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
  182. break;
  183. case PIN_IRQ_MODE_FALLING:
  184. /* Disabling rising edge detect interrupt generation. */
  185. REG32(baseAdd + GPIO_RISINGDETECT) &= ~(1 << pinNumber);
  186. /* Enabling falling edge detect interrupt generation. */
  187. REG32(baseAdd + GPIO_FALLINGDETECT) |= (1 << pinNumber);
  188. /* Disabling logic LOW level detect interrupt generation. */
  189. REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
  190. /* Disabling logic HIGH level detect interrupt generation. */
  191. REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
  192. break;
  193. case PIN_IRQ_MODE_RISING_FALLING:
  194. /* Enabling rising edge detect interrupt generation. */
  195. REG32(baseAdd + GPIO_RISINGDETECT) |= (1 << pinNumber);
  196. /* Enabling falling edge detect interrupt generation. */
  197. REG32(baseAdd + GPIO_FALLINGDETECT) |= (1 << pinNumber);
  198. /* Disabling logic LOW level detect interrupt generation. */
  199. REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
  200. /* Disabling logic HIGH level detect interrupt generation. */
  201. REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
  202. break;
  203. case PIN_IRQ_MODE_HIGH_LEVEL:
  204. /* Disabling logic LOW level detect interrupt generation. */
  205. REG32(baseAdd + GPIO_LEVELDETECT(0)) &= ~(1 << pinNumber);
  206. /* Enabling logic HIGH level detect interrupt generation. */
  207. REG32(baseAdd + GPIO_LEVELDETECT(1)) |= (1 << pinNumber);
  208. /* Disabling rising edge detect interrupt generation. */
  209. REG32(baseAdd + GPIO_RISINGDETECT) &= ~(1 << pinNumber);
  210. /* Disabling falling edge detect interrupt generation. */
  211. REG32(baseAdd + GPIO_FALLINGDETECT) &= ~(1 << pinNumber);
  212. break;
  213. case PIN_IRQ_MODE_LOW_LEVEL:
  214. /* Enabling logic LOW level detect interrupt geenration. */
  215. REG32(baseAdd + GPIO_LEVELDETECT(0)) |= (1 << pinNumber);
  216. /* Disabling logic HIGH level detect interrupt generation. */
  217. REG32(baseAdd + GPIO_LEVELDETECT(1)) &= ~(1 << pinNumber);
  218. /* Disabling rising edge detect interrupt generation. */
  219. REG32(baseAdd + GPIO_RISINGDETECT) &= ~(1 << pinNumber);
  220. /* Disabling falling edge detect interrupt generation. */
  221. REG32(baseAdd + GPIO_FALLINGDETECT) &= ~(1 << pinNumber);
  222. break;
  223. }
  224. rt_hw_interrupt_enable(level);
  225. return 0;
  226. }
  227. static rt_err_t am33xx_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
  228. {
  229. RT_ASSERT(pin >= 0 && pin < 128);
  230. rt_base_t gpiox = pin >> 5;
  231. rt_base_t pinNumber = pin & 0x1F;
  232. struct am33xx_pin_irq_hdr *irq_hdr = &GPIO_PARAMx[gpiox].hdr_tab[pinNumber];
  233. rt_base_t level;
  234. level = rt_hw_interrupt_disable();
  235. irq_hdr->hdr = RT_NULL;
  236. irq_hdr->args = RT_NULL;
  237. rt_hw_interrupt_enable(level);
  238. return 0;
  239. }
  240. static rt_err_t am33xx_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
  241. {
  242. RT_ASSERT(pin >= 0 && pin < 128);
  243. rt_base_t gpiox = pin >> 5;
  244. rt_base_t pinNumber = pin & 0x1F;
  245. rt_base_t baseAdd = GPIO_BASE[gpiox];
  246. rt_base_t intLine = GPIO_INT_LINEx[gpiox];
  247. if (enabled == PIN_IRQ_ENABLE)
  248. REG32(baseAdd + GPIO_IRQSTATUS_SET(intLine)) = (1 << pinNumber);
  249. else
  250. REG32(baseAdd + GPIO_IRQSTATUS_CLR(intLine)) = (1 << pinNumber);
  251. return 0;
  252. }
  253. // name format: P0.0, range: GPIO0_[31:0] ... GPIO5_[31:0]
  254. static rt_base_t am33xx_pin_get(const char *name)
  255. {
  256. rt_base_t gpiox;
  257. rt_base_t pinNumber;
  258. if (!isdigit((int)name[1]))
  259. return -RT_EINVAL;
  260. gpiox = name[1] - '0';
  261. if (name[2] != '.')
  262. return -RT_EINVAL;
  263. if (!isdigit((int)name[3]))
  264. return -RT_EINVAL;
  265. pinNumber = name[3] - '0';
  266. if (name[4] == '\0')
  267. goto done;
  268. else if (!isdigit((int)name[4]))
  269. return -RT_EINVAL;
  270. pinNumber *= 10;
  271. pinNumber += name[4] - '0';
  272. if (name[5] != '\0')
  273. return -RT_EINVAL;
  274. done:
  275. if (pinNumber > 0x1F)
  276. return -RT_EINVAL;
  277. return GET_PIN(gpiox, pinNumber);
  278. }
  279. static const struct rt_pin_ops am33xx_pin_ops =
  280. {
  281. am33xx_pin_mode,
  282. am33xx_pin_write,
  283. am33xx_pin_read,
  284. am33xx_pin_attach_irq,
  285. am33xx_pin_detach_irq,
  286. am33xx_pin_irq_enable,
  287. am33xx_pin_get,
  288. };
  289. int rt_hw_gpio_init(void)
  290. {
  291. int vector;
  292. rt_base_t gpiox;
  293. char name[RT_NAME_MAX];
  294. for (gpiox = 0; gpiox < 4; gpiox++)
  295. {
  296. rt_snprintf(name, sizeof(name), "%s%d", "gpio", gpiox);
  297. vector = GPIO_INTx[gpiox];
  298. rt_hw_interrupt_install(vector, GPIO_ISRx[gpiox], &GPIO_PARAMx[gpiox], name);
  299. rt_hw_interrupt_control(vector, 0, 0);
  300. rt_hw_interrupt_umask(vector);
  301. }
  302. rt_device_pin_register("gpio", &am33xx_pin_ops, RT_NULL);
  303. return 0;
  304. }
  305. INIT_BOARD_EXPORT(rt_hw_gpio_init);
  306. #endif