drv_gpio.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  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. * 2022-6-30 GuEe-GUI first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <board.h>
  14. #include "drv_gpio.h"
  15. #ifdef BSP_USING_PIN
  16. #define GPIODIR 0x400
  17. #define GPIOIS 0x404
  18. #define GPIOIBE 0x408
  19. #define GPIOIEV 0x40c
  20. #define GPIOIE 0x410
  21. #define GPIORIS 0x414
  22. #define GPIOMIS 0x418
  23. #define GPIOIC 0x41c
  24. #define BIT(x) (1UL << (x))
  25. #define PL061_GPIO_NR 8
  26. static struct pl061
  27. {
  28. #ifdef RT_USING_SMP
  29. struct rt_spinlock spinlock;
  30. #endif
  31. void (*(hdr[PL061_GPIO_NR]))(void *args);
  32. void *args[PL061_GPIO_NR];
  33. } _pl061;
  34. static rt_ubase_t pl061_gpio_base = PL061_GPIO_BASE;
  35. rt_inline rt_uint8_t pl061_read8(rt_ubase_t offset)
  36. {
  37. return HWREG8(pl061_gpio_base + offset);
  38. }
  39. rt_inline void pl061_write8(rt_ubase_t offset, rt_uint8_t value)
  40. {
  41. HWREG8(pl061_gpio_base + offset) = value;
  42. }
  43. static void pl061_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
  44. {
  45. int value;
  46. rt_uint8_t gpiodir;
  47. #ifdef RT_USING_SMP
  48. rt_base_t level;
  49. #endif
  50. if (pin < 0 || pin >= PL061_GPIO_NR)
  51. {
  52. return;
  53. }
  54. #ifdef RT_USING_SMP
  55. level = rt_spin_lock_irqsave(&_pl061.spinlock);
  56. #endif
  57. switch (mode)
  58. {
  59. case PIN_MODE_OUTPUT:
  60. value = !!pl061_read8((BIT(pin + 2)));
  61. pl061_write8(BIT(pin + 2), 0 << pin);
  62. gpiodir = pl061_read8(GPIODIR);
  63. gpiodir |= BIT(pin);
  64. pl061_write8(GPIODIR, gpiodir);
  65. /*
  66. * gpio value is set again, because pl061 doesn't allow to set value of
  67. * a gpio pin before configuring it in OUT mode.
  68. */
  69. pl061_write8((BIT(pin + 2)), value << pin);
  70. break;
  71. case PIN_MODE_INPUT:
  72. gpiodir = pl061_read8(GPIODIR);
  73. gpiodir &= ~(BIT(pin));
  74. pl061_write8(GPIODIR, gpiodir);
  75. break;
  76. }
  77. #ifdef RT_USING_SMP
  78. rt_spin_unlock_irqrestore(&_pl061.spinlock, level);
  79. #endif
  80. }
  81. static void pl061_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
  82. {
  83. pl061_write8(BIT(pin + 2), !!value << pin);
  84. }
  85. static rt_int8_t pl061_pin_read(struct rt_device *device, rt_base_t pin)
  86. {
  87. return !!pl061_read8((BIT(pin + 2)));
  88. }
  89. static rt_err_t pl061_pin_attach_irq(struct rt_device *device, rt_base_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args)
  90. {
  91. rt_uint8_t gpiois, gpioibe, gpioiev;
  92. rt_uint8_t bit = BIT(mode);
  93. #ifdef RT_USING_SMP
  94. rt_base_t level;
  95. #endif
  96. if (pin < 0 || pin >= PL061_GPIO_NR)
  97. {
  98. return -RT_EINVAL;
  99. }
  100. #ifdef RT_USING_SMP
  101. level = rt_spin_lock_irqsave(&_pl061.spinlock);
  102. #endif
  103. gpioiev = pl061_read8(GPIOIEV);
  104. gpiois = pl061_read8(GPIOIS);
  105. gpioibe = pl061_read8(GPIOIBE);
  106. if (mode == PIN_IRQ_MODE_HIGH_LEVEL || pin == PIN_IRQ_MODE_LOW_LEVEL)
  107. {
  108. rt_bool_t polarity = (mode == PIN_IRQ_MODE_HIGH_LEVEL);
  109. /* Disable edge detection */
  110. gpioibe &= ~bit;
  111. /* Enable level detection */
  112. gpiois |= bit;
  113. /* Select polarity */
  114. if (polarity)
  115. {
  116. gpioiev |= bit;
  117. }
  118. else
  119. {
  120. gpioiev &= ~bit;
  121. }
  122. }
  123. else if (mode == PIN_IRQ_MODE_RISING_FALLING)
  124. {
  125. /* Disable level detection */
  126. gpiois &= ~bit;
  127. /* Select both edges, setting this makes GPIOEV be ignored */
  128. gpioibe |= bit;
  129. }
  130. else if (mode == PIN_IRQ_MODE_RISING || mode == PIN_IRQ_MODE_FALLING)
  131. {
  132. rt_bool_t rising = (mode == PIN_IRQ_MODE_RISING);
  133. /* Disable level detection */
  134. gpiois &= ~bit;
  135. /* Clear detection on both edges */
  136. gpioibe &= ~bit;
  137. /* Select edge */
  138. if (rising)
  139. {
  140. gpioiev |= bit;
  141. }
  142. else
  143. {
  144. gpioiev &= ~bit;
  145. }
  146. }
  147. else
  148. {
  149. /* No trigger: disable everything */
  150. gpiois &= ~bit;
  151. gpioibe &= ~bit;
  152. gpioiev &= ~bit;
  153. }
  154. pl061_write8(GPIOIS, gpiois);
  155. pl061_write8(GPIOIBE, gpioibe);
  156. pl061_write8(GPIOIEV, gpioiev);
  157. _pl061.hdr[pin] = hdr;
  158. _pl061.args[pin] = args;
  159. #ifdef RT_USING_SMP
  160. rt_spin_unlock_irqrestore(&_pl061.spinlock, level);
  161. #endif
  162. return RT_EOK;
  163. }
  164. static rt_err_t pl061_pin_detach_irq(struct rt_device *device, rt_base_t pin)
  165. {
  166. if (pin < 0 || pin >= PL061_GPIO_NR)
  167. {
  168. return -RT_EINVAL;
  169. }
  170. _pl061.hdr[pin] = RT_NULL;
  171. _pl061.args[pin] = RT_NULL;
  172. return RT_EOK;
  173. }
  174. static rt_err_t pl061_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  175. {
  176. rt_uint8_t mask = BIT(pin);
  177. rt_uint8_t gpioie;
  178. #ifdef RT_USING_SMP
  179. rt_base_t level;
  180. #endif
  181. if (pin < 0 || pin >= PL061_GPIO_NR)
  182. {
  183. return -RT_EINVAL;
  184. }
  185. #ifdef RT_USING_SMP
  186. level = rt_spin_lock_irqsave(&_pl061.spinlock);
  187. #endif
  188. if (enabled)
  189. {
  190. gpioie = pl061_read8(GPIOIE) | mask;
  191. }
  192. else
  193. {
  194. gpioie = pl061_read8(GPIOIE) & ~mask;
  195. }
  196. pl061_write8(GPIOIE, gpioie);
  197. #ifdef RT_USING_SMP
  198. rt_spin_unlock_irqrestore(&_pl061.spinlock, level);
  199. #endif
  200. return RT_EOK;
  201. }
  202. static const struct rt_pin_ops ops =
  203. {
  204. pl061_pin_mode,
  205. pl061_pin_write,
  206. pl061_pin_read,
  207. pl061_pin_attach_irq,
  208. pl061_pin_detach_irq,
  209. pl061_pin_irq_enable,
  210. RT_NULL,
  211. };
  212. static void rt_hw_gpio_isr(int irqno, void *param)
  213. {
  214. rt_uint8_t mask;
  215. unsigned long pending;
  216. #ifdef RT_USING_SMP
  217. rt_base_t level;
  218. #endif
  219. pending = pl061_read8(GPIOMIS);
  220. if (pending)
  221. {
  222. rt_base_t pin;
  223. for (pin = 0; pin < PL061_GPIO_NR; ++pin)
  224. {
  225. if (pending & BIT(pin))
  226. {
  227. mask |= BIT(pin);
  228. if (_pl061.hdr[pin] != RT_NULL)
  229. {
  230. _pl061.hdr[pin](_pl061.args[pin]);
  231. }
  232. }
  233. }
  234. }
  235. #ifdef RT_USING_SMP
  236. level = rt_spin_lock_irqsave(&_pl061.spinlock);
  237. #endif
  238. pl061_write8(GPIOIC, mask);
  239. #ifdef RT_USING_SMP
  240. rt_spin_unlock_irqrestore(&_pl061.spinlock, level);
  241. #endif
  242. }
  243. int rt_hw_gpio_init(void)
  244. {
  245. #ifdef RT_USING_SMP
  246. rt_spin_lock_init(&_pl061.spinlock);
  247. #endif
  248. #ifdef RT_USING_LWP
  249. pl061_gpio_base = (rt_size_t)rt_ioremap((void *)pl061_gpio_base, PL061_GPIO_SIZE);
  250. #endif
  251. rt_device_pin_register("gpio", &ops, RT_NULL);
  252. rt_hw_interrupt_install(PL061_GPIO_IRQNUM, rt_hw_gpio_isr, RT_NULL, "gpio");
  253. rt_hw_interrupt_umask(PL061_GPIO_IRQNUM);
  254. return 0;
  255. }
  256. INIT_DEVICE_EXPORT(rt_hw_gpio_init);
  257. #endif /* BSP_USING_PIN */