drv_gpio.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. u32 cpu_id;
  62. u32 irq_num = ctrl->config.irq_num[0];
  63. GetCpuId(&cpu_id);
  64. LOG_D("In FGpioOpsSetupCtrlIRQ() -> cpu_id %d, irq_num %d\r\n", cpu_id, irq_num);
  65. rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
  66. rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
  67. rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, ctrl, NULL); /* register intr handler */
  68. rt_hw_interrupt_umask(irq_num);
  69. return;
  70. }
  71. /* setup gpio pin interrupt */
  72. static void FGpioOpsSetupPinIRQ(FGpio *ctrl, FGpioPin *const pin, FGpioOpsPinConfig *config)
  73. {
  74. u32 cpu_id;
  75. u32 irq_num = ctrl->config.irq_num[pin->index.pin];
  76. GetCpuId(&cpu_id);
  77. LOG_D("in FGpioOpsSetupPinIRQ() -> cpu_id %d, irq_num %d", cpu_id, irq_num);
  78. rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
  79. rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
  80. rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, config->irq_args, NULL); /* register intr handler */
  81. rt_hw_interrupt_umask(irq_num);
  82. return;
  83. }
  84. /* on E2000, if u want use GPIO-4-11, set pin = FGPIO_OPS_PIN_INDEX(4, 0, 11) */
  85. static void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
  86. {
  87. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  88. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  89. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  90. FGpioPinId gpio_pin_id;
  91. FError err = FGPIO_SUCCESS;
  92. FGpio *instance = &gpio[ctrl_id].ctrl;
  93. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  94. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  95. if (ctrl_id >= FGPIO_NUM)
  96. {
  97. LOG_E("ctrl_id too large!!!");
  98. return;
  99. }
  100. if (FALSE == gpio[ctrl_id].init_ok) /* init ctrl if needed */
  101. {
  102. FGpioConfig input_cfg = *FGpioLookupConfig(ctrl_id);
  103. memset(instance, 0, sizeof(*instance));
  104. #ifdef RT_USING_SMART
  105. input_cfg.base_addr = (uintptr)rt_ioremap((void *)input_cfg.base_addr, 0x1000);
  106. #endif
  107. err = FGpioCfgInitialize(instance, &input_cfg);
  108. if (FGPIO_SUCCESS != err)
  109. {
  110. LOG_E("Ctrl: %d init fail!!!\n", ctrl_id);
  111. return;
  112. }
  113. gpio[ctrl_id].init_ok = TRUE;
  114. }
  115. FIOPadSetGpioMux(ctrl_id, pin_id);
  116. if (FT_COMPONENT_IS_READY == pin_instance->is_ready)
  117. {
  118. FGpioPinDeInitialize(pin_instance);
  119. }
  120. gpio_pin_id.ctrl = ctrl_id;
  121. gpio_pin_id.port = port_id;
  122. gpio_pin_id.pin = pin_id;
  123. err = FGpioPinInitialize(instance, pin_instance, gpio_pin_id);
  124. if (FGPIO_SUCCESS != err)
  125. {
  126. LOG_E("Pin %d-%c-%d init fail!!!\n",
  127. ctrl_id,
  128. port_id == 0 ? 'a' : 'b',
  129. pin_id);
  130. return;
  131. }
  132. switch (mode)
  133. {
  134. case PIN_MODE_OUTPUT:
  135. pin_config->direction = FGPIO_DIR_OUTPUT;
  136. pin_config->en_irq = FALSE;
  137. break;
  138. case PIN_MODE_INPUT:
  139. pin_config->direction = FGPIO_DIR_INPUT;
  140. pin_config->en_irq = TRUE;
  141. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
  142. break;
  143. default:
  144. rt_kprintf("Not support mode %d!!!\n", mode);
  145. break;
  146. }
  147. FGpioSetDirection(pin_instance, pin_config->direction);
  148. rt_kprintf("Init GPIO-%d-%c-%d as an %sput pin\r\n",
  149. ctrl_id,
  150. port_id,
  151. pin_id, pin_config->direction == FGPIO_DIR_OUTPUT ? "out" : "in");
  152. }
  153. void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
  154. {
  155. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  156. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  157. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  158. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  159. if (pin_instance == RT_NULL)
  160. {
  161. rt_kprintf("Pin %d-%c-%d not set mode\n",
  162. ctrl_id,
  163. port_id == 0 ? 'a' : 'b',
  164. pin_id);
  165. return;
  166. }
  167. FGpioSetOutputValue(pin_instance, (value == PIN_HIGH) ? FGPIO_PIN_HIGH : FGPIO_PIN_LOW);
  168. }
  169. rt_ssize_t drv_pin_read(struct rt_device *device, rt_base_t pin)
  170. {
  171. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  172. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  173. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  174. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  175. if (pin_instance == RT_NULL)
  176. {
  177. rt_kprintf("Pin %d-%c-%d not set mode\n",
  178. ctrl_id,
  179. port_id == 0 ? 'a' : 'b',
  180. pin_id);
  181. return -RT_ERROR;
  182. }
  183. return FGpioGetInputValue(pin_instance) == FGPIO_PIN_HIGH ? PIN_HIGH : PIN_LOW;
  184. }
  185. rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_base_t pin,
  186. rt_uint8_t mode, void (*hdr)(void *args), void *args)
  187. {
  188. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  189. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  190. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  191. rt_base_t level;
  192. FGpio *instance = &gpio[ctrl_id].ctrl;
  193. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  194. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  195. level = rt_hw_interrupt_disable();
  196. pin_config->irq_handler = (FGpioOpsIrqHandler)hdr;
  197. pin_config->irq_args = args;
  198. if (pin_instance == RT_NULL)
  199. {
  200. LOG_E("GPIO%d-%c-%d not init yet.\n", ctrl_id, port_id == 0 ? 'a' : 'b', pin_id);
  201. return -RT_ERROR;
  202. }
  203. if (pin_config->en_irq)
  204. {
  205. FGpioSetInterruptMask(pin_instance, FALSE);
  206. FGpioPinId pin_of_ctrl =
  207. {
  208. .ctrl = ctrl_id,
  209. .port = FGPIO_PORT_A,
  210. .pin = FGPIO_PIN_0
  211. };
  212. if (FGPIO_IRQ_BY_CONTROLLER == FGpioGetPinIrqSourceType(pin_of_ctrl)) /* setup for ctrl report interrupt */
  213. {
  214. FGpioOpsSetupCtrlIRQ(instance);
  215. LOG_I("GPIO-%d report irq by controller", ctrl_id);
  216. }
  217. else if (FGPIO_IRQ_BY_PIN == FGpioGetPinIrqSourceType(pin_of_ctrl))
  218. {
  219. FGpioOpsSetupPinIRQ(instance, pin_instance, pin_config);
  220. LOG_I("GPIO-%d report irq by pin", ctrl_id);
  221. }
  222. switch (mode)
  223. {
  224. case PIN_IRQ_MODE_RISING:
  225. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
  226. break;
  227. case PIN_IRQ_MODE_FALLING:
  228. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_FALLING;
  229. break;
  230. case PIN_IRQ_MODE_LOW_LEVEL:
  231. pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_LOW;
  232. break;
  233. case PIN_IRQ_MODE_HIGH_LEVEL:
  234. pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_HIGH;
  235. break;
  236. default:
  237. LOG_E("Do not spport irq_mode: %d\n", mode);
  238. break;
  239. }
  240. FGpioSetInterruptType(pin_instance, pin_config->irq_type);
  241. FGpioRegisterInterruptCB(pin_instance, pin_config->irq_handler,
  242. pin_config->irq_args, TRUE); /* register intr callback */
  243. }
  244. rt_hw_interrupt_enable(level);
  245. return RT_EOK;
  246. }
  247. rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_base_t pin)
  248. {
  249. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  250. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  251. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  252. rt_base_t level;
  253. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  254. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  255. if (pin_instance == RT_NULL)
  256. {
  257. rt_kprintf("pin %d-%c-%d not set mode\n",
  258. ctrl_id,
  259. port_id == 0 ? 'a' : 'b',
  260. pin_id);
  261. return -RT_ERROR;
  262. }
  263. level = rt_hw_interrupt_disable();
  264. pin_config->irq_handler = RT_NULL;
  265. pin_config->irq_args = RT_NULL;
  266. rt_hw_interrupt_enable(level);
  267. return RT_EOK;
  268. }
  269. rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  270. {
  271. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  272. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  273. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  274. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  275. if (pin_instance == RT_NULL)
  276. {
  277. rt_kprintf("Pin %d-%c-%d not set mode\n",
  278. ctrl_id,
  279. port_id == 0 ? 'a' : 'b',
  280. pin_id);
  281. return -RT_ERROR;
  282. }
  283. FGpioSetInterruptMask(pin_instance, enabled);
  284. return RT_EOK;
  285. }
  286. const struct rt_pin_ops drv_pin_ops =
  287. {
  288. .pin_mode = drv_pin_mode,
  289. .pin_write = drv_pin_write,
  290. .pin_read = drv_pin_read,
  291. .pin_attach_irq = drv_pin_attach_irq,
  292. .pin_detach_irq = drv_pin_detach_irq,
  293. .pin_irq_enable = drv_pin_irq_enable,
  294. .pin_get = RT_NULL
  295. };
  296. int ft_pin_init(void)
  297. {
  298. rt_err_t ret = RT_EOK;
  299. ret = rt_device_pin_register("pin", &drv_pin_ops, RT_NULL);
  300. rt_kprintf("Register pin with return: %d\n", ret);
  301. return ret;
  302. }
  303. INIT_DEVICE_EXPORT(ft_pin_init);