drv_gpio.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Email: opensource_embedded@phytium.com.cn
  7. *
  8. * Change Logs:
  9. * Date Author Notes
  10. * 2023/7/24 liqiaozhong first add, support intr
  11. *
  12. */
  13. #include "rtconfig.h"
  14. #include <rtthread.h>
  15. #include <rtdevice.h>
  16. #include "interrupt.h"
  17. #define LOG_TAG "gpio_drv"
  18. #include "drv_log.h"
  19. #ifdef RT_USING_SMART
  20. #include "ioremap.h"
  21. #endif
  22. #include <string.h>
  23. #if defined(TARGET_E2000)
  24. #include "fparameters.h"
  25. #endif
  26. #include "fkernel.h"
  27. #include "fcpu_info.h"
  28. #include "ftypes.h"
  29. #include "fio_mux.h"
  30. #include "board.h"
  31. #include "fiopad.h"
  32. #include "fgpio.h"
  33. #include "drv_gpio.h"
  34. /**************************** Type Definitions *******************************/
  35. typedef void (*FGpioOpsIrqHandler)(s32 vector, void *param);
  36. typedef struct
  37. {
  38. FGpioDirection direction;
  39. boolean en_irq;
  40. FGpioIrqType irq_type;
  41. FGpioOpsIrqHandler irq_handler;
  42. void *irq_args;
  43. } FGpioOpsPinConfig;
  44. typedef struct
  45. {
  46. FGpio ctrl;
  47. FGpioPin pins[FGPIO_PORT_NUM][FGPIO_PIN_NUM];
  48. FGpioOpsPinConfig pin_config[FGPIO_PORT_NUM][FGPIO_PIN_NUM];
  49. boolean init_ok;
  50. } FGpioOps;
  51. /***************** Macros (Inline Functions) Definitions *********************/
  52. #if defined(TARGET_E2000)
  53. #define FGPIO_VERSION_2
  54. #endif
  55. /************************** Variable Definitions *****************************/
  56. static FGpioOps gpio[FGPIO_NUM];
  57. extern FIOPadCtrl iopad_ctrl;
  58. /*******************************Api Functions*********************************/
  59. static void FGpioOpsSetupCtrlIRQ(FGpio *ctrl)
  60. {
  61. rt_uint32_t cpu_id = rt_hw_cpu_id();
  62. u32 irq_num = ctrl->config.irq_num[0];
  63. LOG_D("In FGpioOpsSetupCtrlIRQ() -> cpu_id %d, irq_num %d\r\n", cpu_id, irq_num);
  64. rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
  65. rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
  66. rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, ctrl, NULL); /* register intr handler */
  67. rt_hw_interrupt_umask(irq_num);
  68. return;
  69. }
  70. /* setup gpio pin interrupt */
  71. static void FGpioOpsSetupPinIRQ(FGpio *ctrl, FGpioPin *const pin, FGpioOpsPinConfig *config)
  72. {
  73. rt_uint32_t cpu_id = rt_hw_cpu_id();
  74. u32 irq_num = ctrl->config.irq_num[pin->index.pin];
  75. LOG_D("in FGpioOpsSetupPinIRQ() -> cpu_id %d, irq_num %d", cpu_id, irq_num);
  76. rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
  77. rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
  78. rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, config->irq_args, NULL); /* register intr handler */
  79. rt_hw_interrupt_umask(irq_num);
  80. return;
  81. }
  82. /* on E2000, if u want use GPIO-4-11, set pin = FGPIO_OPS_PIN_INDEX(4, 0, 11) */
  83. static void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
  84. {
  85. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  86. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  87. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  88. FGpioPinId gpio_pin_id;
  89. FError err = FGPIO_SUCCESS;
  90. FGpio *instance = &gpio[ctrl_id].ctrl;
  91. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  92. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  93. if (ctrl_id >= FGPIO_NUM)
  94. {
  95. LOG_E("ctrl_id too large!!!");
  96. return;
  97. }
  98. if (FALSE == gpio[ctrl_id].init_ok) /* init ctrl if needed */
  99. {
  100. FGpioConfig input_cfg = *FGpioLookupConfig(ctrl_id);
  101. memset(instance, 0, sizeof(*instance));
  102. #ifdef RT_USING_SMART
  103. input_cfg.base_addr = (uintptr)rt_ioremap((void *)input_cfg.base_addr, 0x1000);
  104. #endif
  105. err = FGpioCfgInitialize(instance, &input_cfg);
  106. if (FGPIO_SUCCESS != err)
  107. {
  108. LOG_E("Ctrl: %d init fail!!!\n", ctrl_id);
  109. return;
  110. }
  111. gpio[ctrl_id].init_ok = TRUE;
  112. }
  113. FIOPadSetGpioMux(ctrl_id, pin_id);
  114. if (FT_COMPONENT_IS_READY == pin_instance->is_ready)
  115. {
  116. FGpioPinDeInitialize(pin_instance);
  117. }
  118. gpio_pin_id.ctrl = ctrl_id;
  119. gpio_pin_id.port = port_id;
  120. gpio_pin_id.pin = pin_id;
  121. err = FGpioPinInitialize(instance, pin_instance, gpio_pin_id);
  122. if (FGPIO_SUCCESS != err)
  123. {
  124. LOG_E("Pin %d-%c-%d init fail!!!\n",
  125. ctrl_id,
  126. port_id == 0 ? 'a' : 'b',
  127. pin_id);
  128. return;
  129. }
  130. switch (mode)
  131. {
  132. case PIN_MODE_OUTPUT:
  133. pin_config->direction = FGPIO_DIR_OUTPUT;
  134. pin_config->en_irq = FALSE;
  135. break;
  136. case PIN_MODE_INPUT:
  137. pin_config->direction = FGPIO_DIR_INPUT;
  138. pin_config->en_irq = TRUE;
  139. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
  140. break;
  141. default:
  142. rt_kprintf("Not support mode %d!!!\n", mode);
  143. break;
  144. }
  145. FGpioSetDirection(pin_instance, pin_config->direction);
  146. rt_kprintf("Init GPIO-%d-%c-%d as an %sput pin\r\n",
  147. ctrl_id,
  148. port_id,
  149. pin_id, pin_config->direction == FGPIO_DIR_OUTPUT ? "out" : "in");
  150. }
  151. void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
  152. {
  153. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  154. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  155. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  156. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  157. if (pin_instance == RT_NULL)
  158. {
  159. rt_kprintf("Pin %d-%c-%d not set mode\n",
  160. ctrl_id,
  161. port_id == 0 ? 'a' : 'b',
  162. pin_id);
  163. return;
  164. }
  165. FGpioSetOutputValue(pin_instance, (value == PIN_HIGH) ? FGPIO_PIN_HIGH : FGPIO_PIN_LOW);
  166. }
  167. rt_ssize_t drv_pin_read(struct rt_device *device, rt_base_t pin)
  168. {
  169. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  170. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  171. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  172. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  173. if (pin_instance == RT_NULL)
  174. {
  175. return -RT_EINVAL;
  176. }
  177. return FGpioGetInputValue(pin_instance) == FGPIO_PIN_HIGH ? PIN_HIGH : PIN_LOW;
  178. }
  179. rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_base_t pin,
  180. rt_uint8_t mode, void (*hdr)(void *args), void *args)
  181. {
  182. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  183. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  184. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  185. rt_base_t level;
  186. FGpio *instance = &gpio[ctrl_id].ctrl;
  187. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  188. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  189. level = rt_hw_interrupt_disable();
  190. pin_config->irq_handler = (FGpioOpsIrqHandler)hdr;
  191. pin_config->irq_args = args;
  192. if (pin_instance == RT_NULL)
  193. {
  194. LOG_E("GPIO%d-%c-%d not init yet.\n", ctrl_id, port_id == 0 ? 'a' : 'b', pin_id);
  195. return -RT_ERROR;
  196. }
  197. if (pin_config->en_irq)
  198. {
  199. FGpioSetInterruptMask(pin_instance, FALSE);
  200. if (FGPIO_IRQ_BY_CONTROLLER == FGpioGetPinIrqSourceType(*pin_instance)) /* setup for ctrl report interrupt */
  201. {
  202. FGpioOpsSetupCtrlIRQ(instance);
  203. LOG_I("GPIO-%d report irq by controller", ctrl_id);
  204. }
  205. else if (FGPIO_IRQ_BY_PIN == FGpioGetPinIrqSourceType(*pin_instance))
  206. {
  207. FGpioOpsSetupPinIRQ(instance, pin_instance, pin_config);
  208. LOG_I("GPIO-%d report irq by pin", ctrl_id);
  209. }
  210. switch (mode)
  211. {
  212. case PIN_IRQ_MODE_RISING:
  213. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
  214. break;
  215. case PIN_IRQ_MODE_FALLING:
  216. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_FALLING;
  217. break;
  218. case PIN_IRQ_MODE_LOW_LEVEL:
  219. pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_LOW;
  220. break;
  221. case PIN_IRQ_MODE_HIGH_LEVEL:
  222. pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_HIGH;
  223. break;
  224. default:
  225. LOG_E("Do not spport irq_mode: %d\n", mode);
  226. break;
  227. }
  228. FGpioSetInterruptType(pin_instance, pin_config->irq_type);
  229. FGpioRegisterInterruptCB(pin_instance, pin_config->irq_handler,
  230. pin_config->irq_args, TRUE); /* register intr callback */
  231. }
  232. rt_hw_interrupt_enable(level);
  233. return RT_EOK;
  234. }
  235. rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_base_t pin)
  236. {
  237. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  238. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  239. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  240. rt_base_t level;
  241. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  242. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  243. if (pin_instance == RT_NULL)
  244. {
  245. rt_kprintf("pin %d-%c-%d not set mode\n",
  246. ctrl_id,
  247. port_id == 0 ? 'a' : 'b',
  248. pin_id);
  249. return -RT_ERROR;
  250. }
  251. level = rt_hw_interrupt_disable();
  252. pin_config->irq_handler = RT_NULL;
  253. pin_config->irq_args = RT_NULL;
  254. rt_hw_interrupt_enable(level);
  255. return RT_EOK;
  256. }
  257. rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  258. {
  259. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  260. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  261. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  262. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  263. if (pin_instance == RT_NULL)
  264. {
  265. rt_kprintf("Pin %d-%c-%d not set mode\n",
  266. ctrl_id,
  267. port_id == 0 ? 'a' : 'b',
  268. pin_id);
  269. return -RT_ERROR;
  270. }
  271. FGpioSetInterruptMask(pin_instance, enabled);
  272. return RT_EOK;
  273. }
  274. const struct rt_pin_ops drv_pin_ops =
  275. {
  276. .pin_mode = drv_pin_mode,
  277. .pin_write = drv_pin_write,
  278. .pin_read = drv_pin_read,
  279. .pin_attach_irq = drv_pin_attach_irq,
  280. .pin_detach_irq = drv_pin_detach_irq,
  281. .pin_irq_enable = drv_pin_irq_enable,
  282. .pin_get = RT_NULL
  283. };
  284. int ft_pin_init(void)
  285. {
  286. rt_err_t ret = RT_EOK;
  287. ret = rt_device_pin_register("pin", &drv_pin_ops, RT_NULL);
  288. rt_kprintf("Register pin with return: %d\n", ret);
  289. return ret;
  290. }
  291. INIT_DEVICE_EXPORT(ft_pin_init);