drv_gpio.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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 <rtthread.h>
  14. #include <rtdevice.h>
  15. #include "interrupt.h"
  16. #include "rtdbg.h"
  17. #ifdef RT_USING_SMART
  18. #include "ioremap.h"
  19. #endif
  20. #include <string.h>
  21. #if defined(TARGET_E2000)
  22. #include "fparameters.h"
  23. #endif
  24. #include "fkernel.h"
  25. #include "fpinctrl.h"
  26. #include "fcpu_info.h"
  27. #include "ftypes.h"
  28. #include "board.h"
  29. #ifdef RT_USING_PIN
  30. #include "fiopad.h"
  31. #include "fgpio.h"
  32. #include "drv_gpio.h"
  33. /**************************** Type Definitions *******************************/
  34. typedef void (*FGpioOpsIrqHandler)(s32 vector, void *param);
  35. typedef struct
  36. {
  37. FGpioDirection direction;
  38. boolean en_irq;
  39. FGpioIrqType irq_type;
  40. FGpioOpsIrqHandler irq_handler;
  41. void *irq_args;
  42. } FGpioOpsPinConfig;
  43. typedef struct
  44. {
  45. FGpio ctrl;
  46. FGpioPin pins[FGPIO_PORT_NUM][FGPIO_PIN_NUM];
  47. FGpioOpsPinConfig pin_config[FGPIO_PORT_NUM][FGPIO_PIN_NUM];
  48. boolean init_ok;
  49. } FGpioOps;
  50. /***************** Macros (Inline Functions) Definitions *********************/
  51. #if defined(TARGET_E2000)
  52. #define FGPIO_VERSION_2
  53. #endif
  54. /************************** Variable Definitions *****************************/
  55. static FGpioOps gpio[FGPIO_NUM];
  56. extern FIOPadCtrl iopad_ctrl;
  57. /*******************************Api Functions*********************************/
  58. static void FGpioOpsSetupCtrlIRQ(FGpio *ctrl)
  59. {
  60. u32 cpu_id;
  61. u32 irq_num = ctrl->config.irq_num[0];
  62. GetCpuId(&cpu_id);
  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. u32 cpu_id;
  74. u32 irq_num = ctrl->config.irq_num[pin->index.pin];
  75. GetCpuId(&cpu_id);
  76. LOG_D("in FGpioOpsSetupPinIRQ() -> cpu_id %d, irq_num %d", cpu_id, irq_num);
  77. rt_hw_interrupt_set_target_cpus(irq_num, cpu_id);
  78. rt_hw_interrupt_set_priority(irq_num, ctrl->config.irq_priority); /* setup interrupt */
  79. rt_hw_interrupt_install(irq_num, FGpioInterruptHandler, config->irq_args, NULL); /* register intr handler */
  80. rt_hw_interrupt_umask(irq_num);
  81. return;
  82. }
  83. void FIOPadSetGpioMux(u32 ctrl_id_p, u32 pin_id_p)
  84. {
  85. #if defined(TARGET_E2000D)
  86. if (ctrl_id_p == FGPIO4_ID)
  87. {
  88. switch (pin_id_p)
  89. {
  90. case 11: /* gpio 4-a-11 */
  91. FIOPadSetFunc(&iopad_ctrl, FIOPAD_AC45_REG0_OFFSET, FIOPAD_FUNC6);
  92. break;
  93. case 12: /* gpio 4-a-12 */
  94. FIOPadSetFunc(&iopad_ctrl, FIOPAD_AE43_REG0_OFFSET, FIOPAD_FUNC6);
  95. break;
  96. default:
  97. LOG_E("Unsupported ctrl pin.");
  98. RT_ASSERT(0);
  99. break;
  100. }
  101. }
  102. else
  103. {
  104. LOG_E("Unsupported ctrl.");
  105. RT_ASSERT(0);
  106. }
  107. #endif
  108. #if defined(TARGET_E2000Q) || defined(TARGET_PHYTIUMPI)
  109. if (ctrl_id_p == FGPIO4_ID)
  110. {
  111. switch (pin_id_p)
  112. {
  113. case 11: /* gpio 4-a-11 */
  114. FIOPadSetFunc(&iopad_ctrl, FIOPAD_AC49_REG0_OFFSET, FIOPAD_FUNC6);
  115. break;
  116. case 12: /* gpio 4-a-12 */
  117. FIOPadSetFunc(&iopad_ctrl, FIOPAD_AE47_REG0_OFFSET, FIOPAD_FUNC6);
  118. break;
  119. default:
  120. LOG_E("Unsupported ctrl pin.");
  121. RT_ASSERT(0);
  122. break;
  123. }
  124. }
  125. else
  126. {
  127. LOG_E("Unsupported ctrl.");
  128. RT_ASSERT(0);
  129. }
  130. #endif
  131. }
  132. /* on E2000, if u want use GPIO-4-11, set pin = FGPIO_OPS_PIN_INDEX(4, 0, 11) */
  133. static void drv_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
  134. {
  135. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  136. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  137. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  138. FGpioPinId gpio_pin_id;
  139. FError err = FGPIO_SUCCESS;
  140. FGpio *instance = &gpio[ctrl_id].ctrl;
  141. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  142. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  143. if (ctrl_id >= FGPIO_NUM)
  144. {
  145. LOG_E("ctrl_id too large!!!");
  146. return;
  147. }
  148. if (FALSE == gpio[ctrl_id].init_ok) /* init ctrl if needed */
  149. {
  150. FGpioConfig input_cfg = *FGpioLookupConfig(ctrl_id);
  151. memset(instance, 0, sizeof(*instance));
  152. #ifdef RT_USING_SMART
  153. input_cfg.base_addr = (uintptr)rt_ioremap((void *)input_cfg.base_addr, 0x1000);
  154. #endif
  155. err = FGpioCfgInitialize(instance, &input_cfg);
  156. if (FGPIO_SUCCESS != err)
  157. {
  158. LOG_E("Ctrl: %d init fail!!!\n", ctrl_id);
  159. return;
  160. }
  161. gpio[ctrl_id].init_ok = TRUE;
  162. }
  163. FIOPadSetGpioMux(ctrl_id, pin_id);
  164. if (FT_COMPONENT_IS_READY == pin_instance->is_ready)
  165. {
  166. FGpioPinDeInitialize(pin_instance);
  167. }
  168. gpio_pin_id.ctrl = ctrl_id;
  169. gpio_pin_id.port = port_id;
  170. gpio_pin_id.pin = pin_id;
  171. err = FGpioPinInitialize(instance, pin_instance, gpio_pin_id);
  172. if (FGPIO_SUCCESS != err)
  173. {
  174. LOG_E("Pin %d-%c-%d init fail!!!\n",
  175. ctrl_id,
  176. port_id == 0 ? 'a' : 'b',
  177. pin_id);
  178. return;
  179. }
  180. switch (mode)
  181. {
  182. case PIN_MODE_OUTPUT:
  183. pin_config->direction = FGPIO_DIR_OUTPUT;
  184. pin_config->en_irq = FALSE;
  185. break;
  186. case PIN_MODE_INPUT:
  187. pin_config->direction = FGPIO_DIR_INPUT;
  188. pin_config->en_irq = TRUE;
  189. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
  190. break;
  191. default:
  192. rt_kprintf("Not support mode %d!!!\n", mode);
  193. break;
  194. }
  195. FGpioSetDirection(pin_instance, pin_config->direction);
  196. rt_kprintf("Init GPIO-%d-%c-%d as an %sput pin\r\n",
  197. ctrl_id,
  198. port_id,
  199. pin_id, pin_config->direction == FGPIO_DIR_OUTPUT ? "out" : "in");
  200. }
  201. void drv_pin_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
  202. {
  203. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  204. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  205. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  206. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  207. if (pin_instance == RT_NULL)
  208. {
  209. rt_kprintf("Pin %d-%c-%d not set mode\n",
  210. ctrl_id,
  211. port_id == 0 ? 'a' : 'b',
  212. pin_id);
  213. return;
  214. }
  215. FGpioSetOutputValue(pin_instance, (value == PIN_HIGH) ? FGPIO_PIN_HIGH : FGPIO_PIN_LOW);
  216. }
  217. rt_int8_t drv_pin_read(struct rt_device *device, rt_base_t pin)
  218. {
  219. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  220. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  221. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  222. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  223. if (pin_instance == RT_NULL)
  224. {
  225. rt_kprintf("Pin %d-%c-%d not set mode\n",
  226. ctrl_id,
  227. port_id == 0 ? 'a' : 'b',
  228. pin_id);
  229. return RT_ERROR;
  230. }
  231. return FGpioGetInputValue(pin_instance) == FGPIO_PIN_HIGH ? PIN_HIGH : PIN_LOW;
  232. }
  233. rt_err_t drv_pin_attach_irq(struct rt_device *device, rt_base_t pin,
  234. rt_uint8_t mode, void (*hdr)(void *args), void *args)
  235. {
  236. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  237. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  238. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  239. rt_base_t level;
  240. FGpio *instance = &gpio[ctrl_id].ctrl;
  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. level = rt_hw_interrupt_disable();
  244. pin_config->irq_handler = (FGpioOpsIrqHandler)hdr;
  245. pin_config->irq_args = args;
  246. if (pin_instance == RT_NULL)
  247. {
  248. LOG_E("GPIO%d-%c-%d not init yet.\n", ctrl_id, port_id == 0 ? 'a' : 'b', pin_id);
  249. return RT_ERROR;
  250. }
  251. if (pin_config->en_irq)
  252. {
  253. FGpioSetInterruptMask(pin_instance, FALSE);
  254. FGpioPinId pin_of_ctrl =
  255. {
  256. .ctrl = ctrl_id,
  257. .port = FGPIO_PORT_A,
  258. .pin = FGPIO_PIN_0
  259. };
  260. if (FGPIO_IRQ_BY_CONTROLLER == FGpioGetPinIrqSourceType(pin_of_ctrl)) /* setup for ctrl report interrupt */
  261. {
  262. FGpioOpsSetupCtrlIRQ(instance);
  263. LOG_I("GPIO-%d report irq by controller", ctrl_id);
  264. }
  265. else if (FGPIO_IRQ_BY_PIN == FGpioGetPinIrqSourceType(pin_of_ctrl))
  266. {
  267. FGpioOpsSetupPinIRQ(instance, pin_instance, pin_config);
  268. LOG_I("GPIO-%d report irq by pin", ctrl_id);
  269. }
  270. switch (mode)
  271. {
  272. case PIN_IRQ_MODE_RISING:
  273. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_RISING;
  274. break;
  275. case PIN_IRQ_MODE_FALLING:
  276. pin_config->irq_type = FGPIO_IRQ_TYPE_EDGE_FALLING;
  277. break;
  278. case PIN_IRQ_MODE_LOW_LEVEL:
  279. pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_LOW;
  280. break;
  281. case PIN_IRQ_MODE_HIGH_LEVEL:
  282. pin_config->irq_type = FGPIO_IRQ_TYPE_LEVEL_HIGH;
  283. break;
  284. default:
  285. LOG_E("Do not spport irq_mode: %d\n", mode);
  286. break;
  287. }
  288. FGpioSetInterruptType(pin_instance, pin_config->irq_type);
  289. FGpioRegisterInterruptCB(pin_instance, pin_config->irq_handler,
  290. pin_config->irq_args, TRUE); /* register intr callback */
  291. }
  292. rt_hw_interrupt_enable(level);
  293. return RT_EOK;
  294. }
  295. rt_err_t drv_pin_detach_irq(struct rt_device *device, rt_base_t pin)
  296. {
  297. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  298. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  299. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  300. rt_base_t level;
  301. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  302. FGpioOpsPinConfig *pin_config = &gpio[ctrl_id].pin_config[port_id][pin_id];
  303. if (pin_instance == RT_NULL)
  304. {
  305. rt_kprintf("pin %d-%c-%d not set mode\n",
  306. ctrl_id,
  307. port_id == 0 ? 'a' : 'b',
  308. pin_id);
  309. return RT_ERROR;
  310. }
  311. level = rt_hw_interrupt_disable();
  312. pin_config->irq_handler = RT_NULL;
  313. pin_config->irq_args = RT_NULL;
  314. rt_hw_interrupt_enable(level);
  315. return RT_EOK;
  316. }
  317. rt_err_t drv_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
  318. {
  319. u32 ctrl_id = FGPIO_OPS_PIN_CTRL_ID(pin);
  320. u32 port_id = FGPIO_OPS_PIN_PORT_ID(pin);
  321. u32 pin_id = FGPIO_OPS_PIN_ID(pin);
  322. FGpioPin *pin_instance = &gpio[ctrl_id].pins[port_id][pin_id];
  323. if (pin_instance == RT_NULL)
  324. {
  325. rt_kprintf("Pin %d-%c-%d not set mode\n",
  326. ctrl_id,
  327. port_id == 0 ? 'a' : 'b',
  328. pin_id);
  329. return RT_ERROR;
  330. }
  331. FGpioSetInterruptMask(pin_instance, enabled);
  332. return RT_EOK;
  333. }
  334. const struct rt_pin_ops drv_pin_ops =
  335. {
  336. .pin_mode = drv_pin_mode,
  337. .pin_write = drv_pin_write,
  338. .pin_read = drv_pin_read,
  339. .pin_attach_irq = drv_pin_attach_irq,
  340. .pin_detach_irq = drv_pin_detach_irq,
  341. .pin_irq_enable = drv_pin_irq_enable,
  342. .pin_get = RT_NULL
  343. };
  344. int ft_pin_init(void)
  345. {
  346. rt_err_t ret = RT_EOK;
  347. ret = rt_device_pin_register("pin", &drv_pin_ops, RT_NULL);
  348. rt_kprintf("Register pin with return: %d\n", ret);
  349. return ret;
  350. }
  351. INIT_DEVICE_EXPORT(ft_pin_init);
  352. #endif /* RT_USING_PIN */