drv_gpio.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. * 1. Redistributions of source code must retain the above copyright
  6. * notice, this list of conditions and the following disclaimer.
  7. * 2. Redistributions in binary form must reproduce the above copyright
  8. * notice, this list of conditions and the following disclaimer in the
  9. * documentation and/or other materials provided with the distribution.
  10. *
  11. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  12. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  13. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  16. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  17. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  18. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. /*
  26. * Copyright (c) 2006-2025, RT-Thread Development Team
  27. *
  28. * SPDX-License-Identifier: Apache-2.0
  29. */
  30. #include <rtthread.h>
  31. #include <rthw.h>
  32. #include <rtdevice.h>
  33. #include <riscv_io.h>
  34. #include <rtdef.h>
  35. #include "ioremap.h"
  36. #include "drv_gpio.h"
  37. #include "drv_hardlock.h"
  38. #include "board.h"
  39. #include <dfs_posix.h>
  40. #include <lwp_user_mm.h>
  41. #include <sys/ioctl.h>
  42. #include <rtdbg.h>
  43. #define DBG_TAG "GPIO"
  44. #ifdef RT_DEBUG
  45. #define DBG_LVL DBG_LOG
  46. #else
  47. #define DBG_LVL DBG_WARNING
  48. #endif
  49. #define DBG_COLOR
  50. struct kd_gpio_device {
  51. struct rt_device dev;
  52. void* base[2];
  53. int hardlock;
  54. };
  55. static struct kd_gpio_device gpio_dev;
  56. static struct
  57. {
  58. void (*hdr)(void* args);
  59. void* args;
  60. gpio_pin_edge_t edge;
  61. int debounce;
  62. struct rt_work debounce_work;
  63. struct rt_work send_sig_work;
  64. struct rt_lwp* lwp;
  65. int lwp_ref_cnt;
  66. int signo;
  67. void* sigval;
  68. } irq_table[GPIO_MAX_NUM];
  69. static void kd_gpio_reg_writel(void* reg, rt_size_t offset, rt_uint32_t value)
  70. {
  71. while (0 != kd_hardlock_lock(gpio_dev.hardlock))
  72. ;
  73. rt_uint32_t val = readl(reg);
  74. val &= ~(1 << offset);
  75. val |= (value << offset);
  76. writel(val, reg);
  77. kd_hardlock_unlock(gpio_dev.hardlock);
  78. }
  79. static rt_uint32_t kd_gpio_reg_readl(void* reg, rt_size_t offset)
  80. {
  81. rt_uint32_t val = readl(reg);
  82. return (val & (1 << offset)) >> offset;
  83. }
  84. static int check_pin_valid(rt_base_t pin)
  85. {
  86. if ((rt_uint16_t)pin < 0 || (rt_uint16_t)pin > GPIO_MAX_NUM)
  87. {
  88. LOG_E("pin %d is not valid\n", pin);
  89. return -RT_EINVAL;
  90. }
  91. return pin;
  92. }
  93. rt_err_t kd_pin_mode(rt_base_t pin, rt_base_t mode)
  94. {
  95. void* reg;
  96. uint32_t dir;
  97. if (check_pin_valid(pin) < 0)
  98. return -RT_EINVAL;
  99. switch (mode)
  100. {
  101. case GPIO_DM_INPUT:
  102. dir = 0;
  103. break;
  104. case GPIO_DM_OUTPUT:
  105. dir = 1;
  106. break;
  107. default:
  108. LOG_E("GPIO drive mode is not supported.");
  109. return -RT_EINVAL;
  110. }
  111. if (pin < 32)
  112. {
  113. reg = gpio_dev.base[0] + DIRECTION;
  114. } else {
  115. pin -= 32;
  116. if (pin < 32)
  117. {
  118. reg = gpio_dev.base[1] + DIRECTION;
  119. } else {
  120. reg = gpio_dev.base[1] + DIRECTION + DIRECTION_STRIDE;
  121. pin -= 32;
  122. }
  123. }
  124. kd_gpio_reg_writel(reg, pin, dir);
  125. return RT_EOK;
  126. }
  127. int kd_pin_mode_get(rt_base_t pin)
  128. {
  129. void* reg;
  130. if (check_pin_valid(pin) < 0)
  131. return -RT_EINVAL;
  132. if (pin < 32)
  133. {
  134. reg = gpio_dev.base[0] + DIRECTION;
  135. } else {
  136. pin -= 32;
  137. if (pin < 32)
  138. {
  139. reg = gpio_dev.base[1] + DIRECTION;
  140. } else {
  141. reg = gpio_dev.base[1] + DIRECTION + DIRECTION_STRIDE;
  142. pin -= 32;
  143. }
  144. }
  145. return kd_gpio_reg_readl(reg, pin) ? GPIO_DM_OUTPUT : GPIO_DM_INPUT;
  146. }
  147. rt_err_t kd_pin_write(rt_base_t pin, rt_base_t value)
  148. {
  149. void* reg;
  150. if (check_pin_valid(pin) < 0)
  151. return -RT_EINVAL;
  152. if (pin < 32)
  153. {
  154. reg = gpio_dev.base[0] + DATA_OUTPUT;
  155. } else {
  156. pin -= 32;
  157. if (pin < 32)
  158. {
  159. reg = gpio_dev.base[1] + DATA_OUTPUT;
  160. } else {
  161. reg = gpio_dev.base[1] + DATA_OUTPUT + DATA_INPUT_STRIDE;
  162. pin -= 32;
  163. }
  164. }
  165. kd_gpio_reg_writel(reg, pin, value ? GPIO_PV_HIGH : GPIO_PV_LOW);
  166. return RT_EOK;
  167. }
  168. int kd_pin_read(rt_base_t pin)
  169. {
  170. void* reg;
  171. if (check_pin_valid(pin) < 0)
  172. return -RT_EINVAL;
  173. if (pin < 32)
  174. {
  175. reg = gpio_dev.base[0] + DATA_INPUT;
  176. } else {
  177. pin -= 32;
  178. if (pin < 32)
  179. {
  180. reg = gpio_dev.base[1] + DATA_INPUT;
  181. } else {
  182. reg = gpio_dev.base[1] + DATA_INPUT + DATA_INPUT_STRIDE;
  183. pin -= 32;
  184. }
  185. }
  186. return kd_gpio_reg_readl(reg, pin) ? GPIO_PV_HIGH : GPIO_PV_LOW;
  187. }
  188. static int kd_set_pin_edge(rt_int32_t pin, gpio_pin_edge_t edge)
  189. {
  190. void* reg;
  191. reg = gpio_dev.base[pin >> 5];
  192. pin = pin & 0x1f;
  193. switch (edge)
  194. {
  195. case GPIO_PE_RISING:
  196. kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x1);
  197. kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x1);
  198. kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
  199. break;
  200. case GPIO_PE_FALLING:
  201. kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x1);
  202. kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x0);
  203. kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
  204. break;
  205. case GPIO_PE_BOTH:
  206. kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x1);
  207. break;
  208. case GPIO_PE_LOW:
  209. kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x0);
  210. kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x0);
  211. kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
  212. break;
  213. case GPIO_PE_HIGH:
  214. kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x0);
  215. kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x1);
  216. kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
  217. break;
  218. default:
  219. break;
  220. }
  221. kd_gpio_reg_writel(reg + INT_ENABLE, pin, 0x1);
  222. return RT_EOK;
  223. }
  224. static void debounce_work(struct rt_work* work, void* param)
  225. {
  226. void* reg;
  227. rt_size_t pin = (rt_size_t)param;
  228. reg = gpio_dev.base[pin >> 5];
  229. pin = pin & 0x1f;
  230. rt_base_t level = rt_hw_interrupt_disable();
  231. kd_gpio_reg_writel(reg + INT_MASK, pin, 0x0);
  232. rt_hw_interrupt_enable(level);
  233. }
  234. static void pin_irq(int vector, void* param)
  235. {
  236. void* reg;
  237. long pin = vector - IRQN_GPIO0_INTERRUPT;
  238. gpio_pin_edge_t edge = irq_table[pin].edge;
  239. long pin_offset;
  240. reg = gpio_dev.base[pin >> 5];
  241. pin_offset = pin & 0x1f;
  242. switch (edge)
  243. {
  244. case GPIO_PE_RISING:
  245. case GPIO_PE_FALLING:
  246. case GPIO_PE_BOTH:
  247. kd_gpio_reg_writel(reg + INT_CLEAR, pin_offset, 0x1);
  248. break;
  249. case GPIO_PE_LOW:
  250. case GPIO_PE_HIGH:
  251. kd_gpio_reg_writel(reg + INT_MASK, pin_offset, 0x1);
  252. rt_work_init(&irq_table[pin].debounce_work, debounce_work, (void *)pin);
  253. rt_work_submit(&irq_table[pin].debounce_work, irq_table[pin].debounce);
  254. break;
  255. default:
  256. break;
  257. }
  258. if (irq_table[pin].hdr)
  259. irq_table[pin].hdr(irq_table[pin].args);
  260. }
  261. static void gpio_irq_to_user(void* args)
  262. {
  263. }
  264. rt_err_t kd_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void* args), void* args)
  265. {
  266. char irq_name[10];
  267. if (check_pin_valid(pin) < 0)
  268. return -RT_EINVAL;
  269. if (pin >= GPIO_IRQ_MAX_NUM)
  270. {
  271. LOG_E("pin %d not support interrupt", pin);
  272. return -RT_EINVAL;
  273. }
  274. irq_table[pin].hdr = hdr;
  275. irq_table[pin].args = args;
  276. if (hdr != gpio_irq_to_user)
  277. {
  278. irq_table[pin].lwp = NULL;
  279. irq_table[pin].lwp_ref_cnt = 0;
  280. }
  281. if (mode < 0 || mode > 4)
  282. return -RT_EINVAL;
  283. irq_table[pin].edge = mode;
  284. irq_table[pin].debounce = rt_tick_from_millisecond(10);
  285. kd_set_pin_edge(pin, irq_table[pin].edge);
  286. rt_snprintf(irq_name, sizeof irq_name, "pin%d", pin);
  287. rt_hw_interrupt_install(IRQN_GPIO0_INTERRUPT + pin, pin_irq, RT_NULL, irq_name);
  288. return RT_EOK;
  289. }
  290. rt_err_t kd_pin_detach_irq(rt_int32_t pin)
  291. {
  292. void* reg;
  293. if (check_pin_valid(pin) < 0)
  294. return -RT_EINVAL;
  295. if (pin >= GPIO_IRQ_MAX_NUM)
  296. {
  297. LOG_E("pin %d not support interrupt", pin);
  298. return -RT_EINVAL;
  299. }
  300. irq_table[pin].hdr = RT_NULL;
  301. irq_table[pin].args = RT_NULL;
  302. irq_table[pin].lwp = NULL;
  303. irq_table[pin].lwp_ref_cnt = 0;
  304. irq_table[pin].signo = 0;
  305. irq_table[pin].sigval = 0;
  306. reg = gpio_dev.base[pin >> 5];
  307. pin = pin & 0x1f;
  308. kd_gpio_reg_writel(reg + INT_ENABLE, pin, 0x0);
  309. return RT_EOK;
  310. }
  311. rt_err_t kd_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
  312. {
  313. if (check_pin_valid(pin) < 0)
  314. return -RT_EINVAL;
  315. if (pin >= GPIO_IRQ_MAX_NUM)
  316. {
  317. LOG_E("pin %d not support interrupt", pin);
  318. return -RT_EINVAL;
  319. }
  320. if (enabled)
  321. rt_hw_interrupt_umask(IRQN_GPIO0_INTERRUPT + pin);
  322. else
  323. rt_hw_interrupt_mask(IRQN_GPIO0_INTERRUPT + pin);
  324. return RT_EOK;
  325. }
  326. int rt_hw_gpio_init(void)
  327. {
  328. rt_err_t ret;
  329. gpio_dev.base[0] = rt_ioremap((void*)GPIO0_BASE_ADDR, GPIO0_IO_SIZE);
  330. gpio_dev.base[1] = rt_ioremap((void*)GPIO1_BASE_ADDR, GPIO1_IO_SIZE);
  331. if (kd_request_lock(HARDLOCK_GPIO))
  332. {
  333. rt_kprintf("fail to request hardlock-%d\n", HARDLOCK_GPIO);
  334. return -RT_ERROR;
  335. }
  336. gpio_dev.hardlock = HARDLOCK_GPIO;
  337. ret = rt_device_register(&gpio_dev.dev, "gpio", RT_DEVICE_FLAG_RDWR);
  338. return ret;
  339. }
  340. INIT_BOARD_EXPORT(rt_hw_gpio_init);