drv_gpio.c 9.0 KB

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