drv_gpio.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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. // Write to shadow register
  45. writel(func & 0x8 ? pins : 0, GPIO_PXINTS(GPIO_PORT_Z));
  46. writel(func & 0x4 ? pins : 0, GPIO_PXMSKS(GPIO_PORT_Z));
  47. writel(func & 0x2 ? pins : 0, GPIO_PXPAT1S(GPIO_PORT_Z));
  48. writel(func & 0x1 ? pins : 0, GPIO_PXPAT0S(GPIO_PORT_Z));
  49. writel(func & 0x8 ? 0 : pins, GPIO_PXINTC(GPIO_PORT_Z));
  50. writel(func & 0x4 ? 0 : pins, GPIO_PXMSKC(GPIO_PORT_Z));
  51. writel(func & 0x2 ? 0 : pins, GPIO_PXPAT1C(GPIO_PORT_Z));
  52. writel(func & 0x1 ? 0 : pins, GPIO_PXPAT0C(GPIO_PORT_Z));
  53. //Load shadown reigster
  54. writel(port,GPIO_PZGID2LD(GPIO_PORT_Z));
  55. writel(func & 0x10 ? pins : 0, GPIO_PXPENC(port));
  56. writel(func & 0x10 ? 0 : pins, GPIO_PXPENS(port));
  57. }
  58. void gpio_set_value(enum gpio_port port,enum gpio_pin pin,int value)
  59. {
  60. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  61. if (value)
  62. writel(pin, GPIO_PXPAT0S(port));
  63. else
  64. writel(pin, GPIO_PXPAT0C(port));
  65. }
  66. void gpio_enable_pull(enum gpio_port port, enum gpio_pin pin)
  67. {
  68. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  69. writel(pin, GPIO_PXPENC(port));
  70. }
  71. void gpio_disable_pull(enum gpio_port port, enum gpio_pin pin)
  72. {
  73. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  74. writel(pin, GPIO_PXPENS(port));
  75. }
  76. void gpio_ctrl_pull(enum gpio_port port, uint32_t pins,int enable)
  77. {
  78. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  79. if (enable)
  80. writel(pins, GPIO_PXPENC(port));
  81. else
  82. writel(pins, GPIO_PXPENS(port));
  83. }
  84. int gpio_get_value(enum gpio_port port, enum gpio_pin pin)
  85. {
  86. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  87. return !!(readl(GPIO_PXPIN(port)) & pin);
  88. }
  89. int gpio_get_flag(enum gpio_port port, enum gpio_pin pin)
  90. {
  91. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  92. return (readl(GPIO_PXFLG(port)) & pin);
  93. }
  94. void gpio_clear_flag(enum gpio_port port, enum gpio_pin pin)
  95. {
  96. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  97. writel(pin, GPIO_PXFLGC(port));
  98. }
  99. void gpio_direction_input(enum gpio_port port, enum gpio_pin pin)
  100. {
  101. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  102. gpio_set_func(port,pin,GPIO_INPUT);
  103. }
  104. void gpio_direction_output(enum gpio_port port, enum gpio_pin pin,int value)
  105. {
  106. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  107. gpio_set_func(port, pin, value ? GPIO_OUTPUT1 : GPIO_OUTPUT0);
  108. }
  109. /*********************************************************************************************************
  110. ** IRQ
  111. *********************************************************************************************************/
  112. void gpio_unmask_irq(enum gpio_port port, enum gpio_pin pin)
  113. {
  114. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  115. writel(pin, GPIO_PXMSKC(port));
  116. }
  117. void gpio_mask_irq(enum gpio_port port, enum gpio_pin pin)
  118. {
  119. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  120. writel(pin, GPIO_PXMSKS(port));
  121. }
  122. int gpio_set_irq_type(enum gpio_port port, enum gpio_pin pin, enum gpio_irq_type irq_type)
  123. {
  124. enum gpio_function func;
  125. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  126. if (irq_type & IRQ_TYPE_PROBE)
  127. return 0;
  128. switch (irq_type & IRQ_TYPE_SENSE_MASK)
  129. {
  130. case IRQ_TYPE_LEVEL_HIGH:
  131. func = GPIO_INT_HI;
  132. break;
  133. case IRQ_TYPE_LEVEL_LOW:
  134. func = GPIO_INT_LO;
  135. break;
  136. case IRQ_TYPE_EDGE_RISING:
  137. func = GPIO_INT_RE;
  138. break;
  139. case IRQ_TYPE_EDGE_FALLING:
  140. func = GPIO_INT_FE;
  141. break;
  142. case IRQ_TYPE_EDGE_BOTH:
  143. if (gpio_get_value(port, pin))
  144. func = GPIO_INT_FE;
  145. else
  146. func = GPIO_INT_RE;
  147. break;
  148. default:
  149. return -1;
  150. }
  151. gpio_set_func(port,pin, func);
  152. return 0;
  153. }
  154. void gpio_ack_irq(enum gpio_port port, enum gpio_pin pin)
  155. {
  156. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  157. writel(pin, GPIO_PXFLGC(port));
  158. }
  159. void gpio_set_irq_callback(enum gpio_port port, enum gpio_pin pin, void (*irq_cb)(void *),void *irq_arg)
  160. {
  161. uint32_t pin_id;
  162. RT_ASSERT(IS_GPIO_ALL_PORT(port));
  163. pin_id = _fls(pin) - 1;
  164. GPIO_DBG("port = %d,pin = %d \n",port,pin_id);
  165. _g_gpio_irq_tbl[port].irq_cb[pin_id] = irq_cb;
  166. _g_gpio_irq_tbl[port].irq_arg[pin_id] = irq_arg;
  167. GPIO_DBG("set irq callback end... \n");
  168. }
  169. void gpio_irq_handler(int irq, void *param)
  170. {
  171. struct jz_gpio_irq_def *irq_def = (struct jz_gpio_irq_def *)param;
  172. uint32_t pend,mask;
  173. uint32_t pin_id;
  174. enum gpio_port port = (IRQ_GPIO0 - irq);
  175. enum gpio_pin pin;
  176. RT_ASSERT(param != RT_NULL);
  177. GPIO_DBG("GPIO irq handler,irq=%d\n",irq);
  178. pend = readl(GPIO_PXFLG(port));
  179. mask = readl(GPIO_PXMSK(port));
  180. GPIO_DBG("port =%d pend =%08x mask =%08x\n",port,pend,mask);
  181. pend = pend & ~mask;
  182. while(pend)
  183. {
  184. pin_id = _fls(pend) - 1;
  185. pin = 0x01 << pin_id;
  186. GPIO_DBG("PORT%d PIN%d interrupt happened..\n",port,pin_id);
  187. if(irq_def->irq_cb[pin_id] != RT_NULL)
  188. {
  189. GPIO_DBG("do irq callback...\n",port,pin);
  190. irq_def->irq_cb[pin_id](irq_def->irq_arg[pin_id]);
  191. }
  192. pend &= ~(0x01 << pin_id);
  193. gpio_ack_irq(port, pin);
  194. }
  195. }
  196. int rt_hw_gpio_init(void)
  197. {
  198. GPIO_DBG("Install gpio interrupt source...\n");
  199. /* install ISR */
  200. rt_hw_interrupt_install(IRQ_GPIO0,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_A],"GPIOAINT");
  201. rt_hw_interrupt_umask(IRQ_GPIO0);
  202. rt_hw_interrupt_install(IRQ_GPIO1,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_B],"GPIOBINT");
  203. rt_hw_interrupt_umask(IRQ_GPIO1);
  204. rt_hw_interrupt_install(IRQ_GPIO2,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_C],"GPIOCINT");
  205. rt_hw_interrupt_umask(IRQ_GPIO2);
  206. rt_hw_interrupt_install(IRQ_GPIO3,gpio_irq_handler,&_g_gpio_irq_tbl[GPIO_PORT_D],"GPIODINT");
  207. rt_hw_interrupt_umask(IRQ_GPIO3);
  208. return 0;
  209. }
  210. INIT_BOARD_EXPORT(rt_hw_gpio_init);