drv_gpio.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023/10/19 xiunian first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <board.h>
  14. #include <ioremap.h>
  15. #ifdef RT_USING_PIN
  16. #include "drv_gpio.h"
  17. #define GPIO_SWPORTA_DR 0x00
  18. #define GPIO_SWPORTA_DDR 0x04
  19. #define GPIO_INTEN 0x30
  20. #define GPIO_INTTYPE_LEVEL 0x38
  21. #define GPIO_INT_POLARITY 0x3c
  22. #define GPIO_INTSTATUS 0x40
  23. #define GPIO_PORTA_EOI 0x4c
  24. #define GPIO_EXT_PORTA 0x50
  25. #define DWAPB_DRIVER_NAME "gpio-dwapb"
  26. #define DWAPB_GPIOA_BASE 0x03020000
  27. #define DWAPB_GPIOE_BASE 0x05021000
  28. #define DWAPB_GPIO_SIZE 0x1000
  29. #define DWAPB_GPIOA_IRQNUM 0x3c
  30. #define DWAPB_GPIOE_IRQNUM 0x46
  31. #define DWAPB_GPIO_PORT_NR 5
  32. #define DWAPB_GPIO_NR 32
  33. #define PIN_NUM(port, no) (((((port) & 0xFu) << 8) | ((no) & 0xFFu)))
  34. #define PIN_PORT(pin) ((uint8_t)(((pin) >> 8) & 0xFu))
  35. #define PIN_NO(pin) ((uint8_t)((pin) & 0xFFu))
  36. #define BIT(x) (1UL << (x))
  37. rt_inline rt_uint32_t dwapb_read32(rt_ubase_t addr)
  38. {
  39. return HWREG32(addr);
  40. }
  41. rt_inline void dwapb_write32(rt_ubase_t addr, rt_uint32_t value)
  42. {
  43. HWREG32(addr) = value;
  44. }
  45. static rt_ubase_t dwapb_gpio_base = DWAPB_GPIOA_BASE;
  46. static rt_ubase_t dwapb_gpio_base_e = DWAPB_GPIOE_BASE;
  47. static struct dwapb_event
  48. {
  49. void (*(hdr[DWAPB_GPIO_NR]))(void *args);
  50. void *args[DWAPB_GPIO_NR];
  51. rt_uint8_t is_both_edge[DWAPB_GPIO_NR];
  52. } _dwapb_events[DWAPB_GPIO_PORT_NR];
  53. static void dwapb_toggle_trigger(rt_uint8_t port, rt_uint8_t bit)
  54. {
  55. rt_uint8_t val;
  56. rt_ubase_t base_addr;
  57. rt_uint32_t pol;
  58. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  59. pol = dwapb_read32(base_addr + GPIO_INT_POLARITY);
  60. /* Just read the current value right out of the data register */
  61. val = (rt_uint8_t)((dwapb_read32(base_addr + GPIO_EXT_PORTA) >> (bit)) & 1);
  62. if (val)
  63. pol &= ~BIT(bit);
  64. else
  65. pol |= BIT(bit);
  66. dwapb_write32(base_addr + GPIO_INT_POLARITY, pol);
  67. }
  68. static void dwapb_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
  69. {
  70. rt_uint8_t bit, port;
  71. rt_ubase_t base_addr;
  72. rt_uint32_t reg_val;
  73. bit = PIN_NO(pin);
  74. port = PIN_PORT(pin);
  75. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  76. reg_val = dwapb_read32(base_addr + GPIO_SWPORTA_DDR);
  77. switch (mode)
  78. {
  79. case PIN_MODE_OUTPUT:
  80. reg_val |= BIT(bit);
  81. break;
  82. case PIN_MODE_INPUT:
  83. reg_val &= ~BIT(bit);
  84. break;
  85. }
  86. dwapb_write32(base_addr + GPIO_SWPORTA_DDR, reg_val);
  87. }
  88. static void dwapb_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
  89. {
  90. rt_uint8_t bit, port;
  91. rt_ubase_t base_addr;
  92. rt_uint32_t reg_val;
  93. bit = PIN_NO(pin);
  94. port = PIN_PORT(pin);
  95. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  96. reg_val = dwapb_read32(base_addr + GPIO_SWPORTA_DR);
  97. reg_val = (value ? (reg_val | BIT(bit)) : (reg_val & (~BIT(bit))));
  98. dwapb_write32(base_addr + GPIO_SWPORTA_DR, reg_val);
  99. }
  100. static rt_int8_t dwapb_pin_read(struct rt_device *device, rt_base_t pin)
  101. {
  102. rt_uint8_t bit, port;
  103. rt_ubase_t base_addr;
  104. bit = PIN_NO(pin);
  105. port = PIN_PORT(pin);
  106. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  107. rt_uint32_t reg_val = dwapb_read32(GPIO_EXT_PORTA + base_addr);
  108. return ((reg_val >> (bit)) & 1);
  109. }
  110. static rt_base_t dwapb_pin_get(const char *name)
  111. {
  112. rt_base_t pin = 0;
  113. int port_num, pin_num = 0;
  114. int i, name_len;
  115. name_len = rt_strlen(name);
  116. if ((name_len < 2) || (name_len > 3))
  117. {
  118. goto out;
  119. }
  120. if ((name[0] >= 'A') && (name[0] <= 'E'))
  121. {
  122. port_num = (int)(name[0] - 'A');
  123. }
  124. else
  125. {
  126. goto out;
  127. }
  128. for (i = 1; i < name_len; i++)
  129. {
  130. pin_num *= 10;
  131. pin_num += name[i] - '0';
  132. }
  133. pin = PIN_NUM(port_num, pin_num);
  134. return pin;
  135. out:
  136. rt_kprintf("xy x:A~E y:0~31, e.g. C24\n");
  137. return -RT_EINVAL;
  138. }
  139. static rt_err_t dwapb_pin_attach_irq(struct rt_device *device, rt_base_t pin, rt_uint8_t mode, void (*hdr)(void *args), void *args)
  140. {
  141. rt_uint8_t bit, port;
  142. rt_ubase_t base_addr;
  143. rt_uint32_t it_val, ip_val;
  144. bit = PIN_NO(pin);
  145. port = PIN_PORT(pin);
  146. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  147. it_val = dwapb_read32(base_addr + GPIO_INTTYPE_LEVEL);
  148. ip_val = dwapb_read32(base_addr + GPIO_INT_POLARITY);
  149. if (mode == PIN_IRQ_MODE_HIGH_LEVEL || mode == PIN_IRQ_MODE_LOW_LEVEL)
  150. {
  151. rt_bool_t polarity = (mode == PIN_IRQ_MODE_HIGH_LEVEL);
  152. /* Enable level detection */
  153. it_val = (it_val & (~BIT(bit)));
  154. /* Select polarity */
  155. ip_val = (polarity ? (ip_val | BIT(bit)) : (ip_val & (~BIT(bit))));
  156. }
  157. else if (mode == PIN_IRQ_MODE_RISING_FALLING)
  158. {
  159. /* Disable level detection */
  160. it_val = (it_val | BIT(bit));
  161. /* Select both edges */
  162. dwapb_toggle_trigger(port, bit);
  163. }
  164. else if (mode == PIN_IRQ_MODE_RISING || mode == PIN_IRQ_MODE_FALLING)
  165. {
  166. rt_bool_t rising = (mode == PIN_IRQ_MODE_RISING);
  167. /* Disable level detection */
  168. it_val = (it_val | BIT(bit));
  169. /* Select edge */
  170. ip_val = (rising ? (ip_val | BIT(bit)) : (ip_val & (~BIT(bit))));
  171. }
  172. else
  173. {
  174. /* No trigger: disable everything */
  175. it_val = (it_val & (~BIT(bit)));
  176. ip_val = (ip_val & (~BIT(bit)));
  177. }
  178. dwapb_write32(base_addr + GPIO_INTTYPE_LEVEL, it_val);
  179. if (mode != PIN_IRQ_MODE_RISING_FALLING)
  180. dwapb_write32(base_addr + GPIO_INT_POLARITY, ip_val);
  181. _dwapb_events[PIN_PORT(pin)].hdr[PIN_NO(pin)] = hdr;
  182. _dwapb_events[PIN_PORT(pin)].args[PIN_NO(pin)] = args;
  183. _dwapb_events[PIN_PORT(pin)].is_both_edge[PIN_NO(pin)] = (mode == PIN_IRQ_MODE_RISING_FALLING);
  184. return RT_EOK;
  185. }
  186. static rt_err_t dwapb_pin_detach_irq(struct rt_device *device, rt_base_t pin)
  187. {
  188. _dwapb_events[PIN_PORT(pin)].hdr[PIN_NO(pin)] = RT_NULL;
  189. _dwapb_events[PIN_PORT(pin)].args[PIN_NO(pin)] = RT_NULL;
  190. _dwapb_events[PIN_PORT(pin)].is_both_edge[PIN_NO(pin)] = 0;
  191. return RT_EOK;
  192. }
  193. static rt_err_t dwapb_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  194. {
  195. rt_uint8_t bit, port;
  196. rt_ubase_t base_addr;
  197. bit = PIN_NO(pin);
  198. port = PIN_PORT(pin);
  199. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  200. rt_uint32_t reg_val = dwapb_read32(base_addr + GPIO_INTEN);
  201. reg_val = (enabled ? (reg_val | BIT(bit)) : (reg_val & (~BIT(bit))));
  202. dwapb_write32(base_addr + GPIO_INTEN, reg_val);
  203. return RT_EOK;
  204. }
  205. static const struct rt_pin_ops _dwapb_ops =
  206. {
  207. dwapb_pin_mode,
  208. dwapb_pin_write,
  209. dwapb_pin_read,
  210. dwapb_pin_attach_irq,
  211. dwapb_pin_detach_irq,
  212. dwapb_pin_irq_enable,
  213. dwapb_pin_get,
  214. };
  215. static void rt_hw_gpio_isr(int irqno, void *param)
  216. {
  217. rt_uint8_t port;
  218. rt_ubase_t base_addr;
  219. rt_uint32_t pending, mask;
  220. mask = 0;
  221. port = (irqno == DWAPB_GPIOE_IRQNUM ? 4 : (irqno - DWAPB_GPIOA_IRQNUM));
  222. base_addr = (port == 4 ? dwapb_gpio_base_e : (dwapb_gpio_base + DWAPB_GPIO_SIZE * port));
  223. pending = dwapb_read32(base_addr + GPIO_INTSTATUS);
  224. if (pending)
  225. {
  226. rt_base_t bit;
  227. for (bit = 0; bit < DWAPB_GPIO_NR; ++bit)
  228. {
  229. if (pending & BIT(bit))
  230. {
  231. mask = (mask | (BIT(bit)));
  232. if (_dwapb_events[port].hdr[bit] != RT_NULL)
  233. {
  234. _dwapb_events[port].hdr[bit](_dwapb_events[port].args[bit]);
  235. }
  236. if (_dwapb_events[port].is_both_edge[bit]) {
  237. dwapb_toggle_trigger(port, bit);
  238. }
  239. }
  240. }
  241. }
  242. dwapb_write32(base_addr + GPIO_PORTA_EOI, mask);
  243. }
  244. int rt_hw_gpio_init(void)
  245. {
  246. #ifdef RT_USING_LWP
  247. #define BSP_IOREMAP_GPIO_DEVICE(no) \
  248. rt_ioremap((void *)(DWAPB_GPIOA_BASE + (no) * DWAPB_GPIO_SIZE), DWAPB_GPIO_SIZE);
  249. dwapb_gpio_base = (rt_size_t)BSP_IOREMAP_GPIO_DEVICE(0);
  250. BSP_IOREMAP_GPIO_DEVICE(1);
  251. BSP_IOREMAP_GPIO_DEVICE(2);
  252. BSP_IOREMAP_GPIO_DEVICE(3);
  253. dwapb_gpio_base_e = (rt_size_t)rt_ioremap((void *)DWAPB_GPIOE_BASE, DWAPB_GPIO_SIZE);
  254. #endif
  255. rt_device_pin_register("gpio", &_dwapb_ops, RT_NULL);
  256. #define INT_INSTALL_GPIO_DEVICE(no) \
  257. rt_hw_interrupt_install(DWAPB_GPIOA_IRQNUM + (no), rt_hw_gpio_isr, RT_NULL, "gpio"); \
  258. rt_hw_interrupt_umask(DWAPB_GPIOA_IRQNUM + (no));
  259. INT_INSTALL_GPIO_DEVICE(0);
  260. INT_INSTALL_GPIO_DEVICE(1);
  261. INT_INSTALL_GPIO_DEVICE(2);
  262. INT_INSTALL_GPIO_DEVICE(3);
  263. rt_hw_interrupt_install(DWAPB_GPIOE_IRQNUM, rt_hw_gpio_isr, RT_NULL, "gpio");
  264. rt_hw_interrupt_umask(DWAPB_GPIOE_IRQNUM);
  265. return 0;
  266. }
  267. INIT_DEVICE_EXPORT(rt_hw_gpio_init);
  268. #endif /* RT_USING_PIN */