drv_gpio.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * File : drv_gpio.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2008 - 2016, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2015-11-19 Urey the first version
  23. */
  24. #include <rthw.h>
  25. #include <rtthread.h>
  26. #include <rtdevice.h>
  27. #include "board.h"
  28. #include "drv_gpio.h"
  29. #define GPIO_DEBUG 0
  30. #if GPIO_DEBUG
  31. #define GPIO_DBG(...) rt_kprintf(__VA_ARGS__)
  32. #else
  33. #define GPIO_DBG(...)
  34. #endif
  35. struct jz_gpio_irq_def _g_gpio_irq_tbl[GPIO_NR_PORTS] = {0};
  36. rt_inline int _fls(int x)
  37. {
  38. __asm__("clz %0, %1" : "=r" (x) : "r" (x));
  39. return 32 - x;
  40. }
  41. void gpio_set_func(enum gpio_port port, uint32_t pins, enum gpio_function func)
  42. {
  43. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  44. writel(func & 0x8 ? pins : 0, GPIO_PXINTS(port));
  45. writel(func & 0x4 ? pins : 0, GPIO_PXMSKS(port));
  46. writel(func & 0x2 ? pins : 0, GPIO_PXPAT1S(port));
  47. writel(func & 0x1 ? pins : 0, GPIO_PXPAT0S(port));
  48. writel(func & 0x8 ? 0 : pins, GPIO_PXINTC(port));
  49. writel(func & 0x4 ? 0 : pins, GPIO_PXMSKC(port));
  50. writel(func & 0x2 ? 0 : pins, GPIO_PXPAT1C(port));
  51. writel(func & 0x1 ? 0 : pins, GPIO_PXPAT0C(port));
  52. writel(func & 0x10 ? pins : 0, GPIO_PXPENC(port));
  53. writel(func & 0x10 ? 0 : pins, GPIO_PXPENS(port));
  54. }
  55. void gpio_set_value(enum gpio_port port,enum gpio_pin pin,int value)
  56. {
  57. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  58. if (value)
  59. writel(pin, GPIO_PXPAT0S(port));
  60. else
  61. writel(pin, GPIO_PXPAT0C(port));
  62. }
  63. void gpio_enable_pull(enum gpio_port port, enum gpio_pin pin)
  64. {
  65. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  66. writel(pin, GPIO_PXPENC(port));
  67. }
  68. void gpio_disable_pull(enum gpio_port port, enum gpio_pin pin)
  69. {
  70. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  71. writel(pin, GPIO_PXPENS(port));
  72. }
  73. void gpio_ctrl_pull(enum gpio_port port, uint32_t pins,int enable)
  74. {
  75. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  76. if (enable)
  77. writel(pins, GPIO_PXPENC(port));
  78. else
  79. writel(pins, GPIO_PXPENS(port));
  80. }
  81. int gpio_get_value(enum gpio_port port, enum gpio_pin pin)
  82. {
  83. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  84. return !!(readl(GPIO_PXPIN(port)) & pin);
  85. }
  86. int gpio_get_flag(enum gpio_port port, enum gpio_pin pin)
  87. {
  88. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  89. return (readl(GPIO_PXFLG(port)) & pin);
  90. }
  91. void gpio_clear_flag(enum gpio_port port, enum gpio_pin pin)
  92. {
  93. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  94. writel(pin, GPIO_PXFLGC(port));
  95. }
  96. void gpio_direction_input(enum gpio_port port, enum gpio_pin pin)
  97. {
  98. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  99. gpio_set_func(port,pin,GPIO_INPUT);
  100. }
  101. void gpio_direction_output(enum gpio_port port, enum gpio_pin pin,int value)
  102. {
  103. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  104. gpio_set_func(port, pin, value ? GPIO_OUTPUT1 : GPIO_OUTPUT0);
  105. }
  106. /*********************************************************************************************************
  107. ** IRQ
  108. *********************************************************************************************************/
  109. void gpio_unmask_irq(enum gpio_port port, enum gpio_pin pin)
  110. {
  111. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  112. writel(pin, GPIO_PXMSKC(port));
  113. }
  114. void gpio_mask_irq(enum gpio_port port, enum gpio_pin pin)
  115. {
  116. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  117. writel(BIT(pin), GPIO_PXMSKS(port));
  118. }
  119. int gpio_set_irq_type(enum gpio_port port, enum gpio_pin pin, enum gpio_irq_type irq_type)
  120. {
  121. enum gpio_function func;
  122. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  123. if (irq_type & IRQ_TYPE_PROBE)
  124. return 0;
  125. switch (irq_type & IRQ_TYPE_SENSE_MASK)
  126. {
  127. case IRQ_TYPE_LEVEL_HIGH:
  128. func = GPIO_INT_HI;
  129. break;
  130. case IRQ_TYPE_LEVEL_LOW:
  131. func = GPIO_INT_LO;
  132. break;
  133. case IRQ_TYPE_EDGE_RISING:
  134. func = GPIO_INT_RE;
  135. break;
  136. case IRQ_TYPE_EDGE_FALLING:
  137. func = GPIO_INT_FE;
  138. break;
  139. case IRQ_TYPE_EDGE_BOTH:
  140. if (gpio_get_value(port, pin))
  141. func = GPIO_INT_FE;
  142. else
  143. func = GPIO_INT_RE;
  144. break;
  145. default:
  146. return -1;
  147. }
  148. gpio_set_func(port,pin, func);
  149. return 0;
  150. }
  151. void gpio_ack_irq(enum gpio_port port, enum gpio_pin pin)
  152. {
  153. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  154. writel(pin, GPIO_PXFLGC(port));
  155. }
  156. void gpio_set_irq_callback(enum gpio_port port, enum gpio_pin pin, void (*irq_cb)(void *),void *irq_arg)
  157. {
  158. uint32_t pin_id;
  159. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  160. pin_id = _fls(pin) - 1;
  161. GPIO_DBG("port = %d,pin = %d \n",port,pin_id);
  162. _g_gpio_irq_tbl[port].irq_cb[pin_id] = irq_cb;
  163. _g_gpio_irq_tbl[port].irq_arg[pin_id] = irq_arg;
  164. GPIO_DBG("set irq callback end... \n");
  165. }
  166. void gpio_irq_handler(int irq, void *param)
  167. {
  168. struct jz_gpio_irq_def *irq_def = (struct jz_gpio_irq_def *)param;
  169. uint32_t pend,mask;
  170. uint32_t pin_id;
  171. enum gpio_port port = (IRQ_GPIO0 - irq);
  172. enum gpio_pin pin;
  173. RT_ASSERT(param != RT_NULL);
  174. GPIO_DBG("GPIO irq handler,irq=%d\n",irq);
  175. pend = readl(GPIO_PXFLG(port));
  176. mask = readl(GPIO_PXMSK(port));
  177. GPIO_DBG("port =%d pend =%08x mask =%08x\n",port,pend,mask);
  178. pend = pend & ~mask;
  179. while(pend)
  180. {
  181. pin_id = _fls(pend) - 1;
  182. pin = 0x01 << pin_id;
  183. GPIO_DBG("PORT%d PIN%d interrupt happened..\n",port,pin_id);
  184. if(irq_def->irq_cb[pin_id] != RT_NULL)
  185. {
  186. GPIO_DBG("do irq callback...\n",port,pin);
  187. irq_def->irq_cb[pin_id](irq_def->irq_arg[pin_id]);
  188. }
  189. pend &= ~(0x01 << pin_id);
  190. gpio_ack_irq(port, pin);
  191. }
  192. }
  193. int rt_hw_gpio_init(void)
  194. {
  195. GPIO_DBG("Install gpio interrupt source...\n");
  196. /* install ISR */
  197. rt_hw_interrupt_install(IRQ_GPIO0,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_A],"GPIOAINT");
  198. rt_hw_interrupt_umask(IRQ_GPIO0);
  199. rt_hw_interrupt_install(IRQ_GPIO1,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_B],"GPIOBINT");
  200. rt_hw_interrupt_umask(IRQ_GPIO1);
  201. rt_hw_interrupt_install(IRQ_GPIO2,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_C],"GPIOCINT");
  202. rt_hw_interrupt_umask(IRQ_GPIO2);
  203. rt_hw_interrupt_install(IRQ_GPIO3,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_D],"GPIODINT");
  204. rt_hw_interrupt_umask(IRQ_GPIO3);
  205. return 0;
  206. }
  207. INIT_BOARD_EXPORT(rt_hw_gpio_init);