drv_gpio.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /*
  2. * Copyright (c) 2006-2024 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-07-1 Rbb666 first version
  9. * 2025-04-24 Passionate0424 fix ifx_pin_irq_enable
  10. */
  11. #include "drv_gpio.h"
  12. #ifdef RT_USING_PIN
  13. #define PIN_GET(pin) ((uint8_t)(((uint8_t)pin) & 0x07U))
  14. #define PORT_GET(pin) ((uint8_t)(((uint8_t)pin) >> 3U))
  15. #if defined(SOC_XMC7200D_E272K8384AA)
  16. #define __IFX_PORT_MAX 35u
  17. #elif defined(SOC_XMC7100D_F144K4160AA)
  18. #define __IFX_PORT_MAX 33u
  19. #else
  20. #define __IFX_PORT_MAX 14u
  21. #endif
  22. #define PIN_IFXPORT_MAX __IFX_PORT_MAX
  23. static cyhal_gpio_callback_data_t irq_cb_data[PIN_IFXPORT_MAX];
  24. static struct pin_irq_map pin_irq_map[] =
  25. {
  26. {CYHAL_PORT_0, ioss_interrupts_gpio_0_IRQn},
  27. #if !defined(SOC_CY8C6245LQI_S3D72) && !defined(SOC_CY8C6244LQI_S4D92)
  28. {CYHAL_PORT_1, ioss_interrupts_gpio_1_IRQn},
  29. #endif
  30. {CYHAL_PORT_2, ioss_interrupts_gpio_2_IRQn},
  31. {CYHAL_PORT_3, ioss_interrupts_gpio_3_IRQn},
  32. #if !defined(SOC_CY8C6245LQI_S3D72) && !defined(SOC_CY8C6244LQI_S4D92)
  33. {CYHAL_PORT_4, ioss_interrupts_gpio_4_IRQn},
  34. #endif
  35. {CYHAL_PORT_5, ioss_interrupts_gpio_5_IRQn},
  36. {CYHAL_PORT_6, ioss_interrupts_gpio_6_IRQn},
  37. {CYHAL_PORT_7, ioss_interrupts_gpio_7_IRQn},
  38. {CYHAL_PORT_8, ioss_interrupts_gpio_8_IRQn},
  39. {CYHAL_PORT_9, ioss_interrupts_gpio_9_IRQn},
  40. {CYHAL_PORT_10, ioss_interrupts_gpio_10_IRQn},
  41. {CYHAL_PORT_11, ioss_interrupts_gpio_11_IRQn},
  42. {CYHAL_PORT_12, ioss_interrupts_gpio_12_IRQn},
  43. #if !defined(SOC_CY8C6245LQI_S3D72) && !defined(SOC_CY8C6244LQI_S4D92)
  44. {CYHAL_PORT_13, ioss_interrupts_gpio_13_IRQn},
  45. #endif
  46. {CYHAL_PORT_14, ioss_interrupts_gpio_14_IRQn},
  47. #if defined(SOC_XMC7200D_E272K8384AA)
  48. {CYHAL_PORT_15, ioss_interrupts_gpio_15_IRQn},
  49. {CYHAL_PORT_16, ioss_interrupts_gpio_16_IRQn},
  50. {CYHAL_PORT_17, ioss_interrupts_gpio_17_IRQn},
  51. {CYHAL_PORT_18, ioss_interrupts_gpio_18_IRQn},
  52. {CYHAL_PORT_19, ioss_interrupts_gpio_19_IRQn},
  53. {CYHAL_PORT_20, ioss_interrupts_gpio_20_IRQn},
  54. {CYHAL_PORT_21, ioss_interrupts_gpio_21_IRQn},
  55. {CYHAL_PORT_22, ioss_interrupts_gpio_22_IRQn},
  56. {CYHAL_PORT_23, ioss_interrupts_gpio_23_IRQn},
  57. {CYHAL_PORT_24, ioss_interrupts_gpio_24_IRQn},
  58. {CYHAL_PORT_25, ioss_interrupts_gpio_25_IRQn},
  59. {CYHAL_PORT_26, ioss_interrupts_gpio_26_IRQn},
  60. {CYHAL_PORT_27, ioss_interrupts_gpio_27_IRQn},
  61. {CYHAL_PORT_28, ioss_interrupts_gpio_28_IRQn},
  62. {CYHAL_PORT_29, ioss_interrupts_gpio_29_IRQn},
  63. {CYHAL_PORT_30, ioss_interrupts_gpio_30_IRQn},
  64. {CYHAL_PORT_31, ioss_interrupts_gpio_31_IRQn},
  65. {CYHAL_PORT_32, ioss_interrupts_gpio_32_IRQn},
  66. {CYHAL_PORT_33, ioss_interrupts_gpio_33_IRQn},
  67. {CYHAL_PORT_34, ioss_interrupts_gpio_34_IRQn},
  68. #endif
  69. #if defined(SOC_XMC7100D_F144K4160AA)
  70. {CYHAL_PORT_15, ioss_interrupts_gpio_15_IRQn},
  71. {CYHAL_PORT_16, ioss_interrupts_gpio_16_IRQn},
  72. {CYHAL_PORT_17, ioss_interrupts_gpio_17_IRQn},
  73. {CYHAL_PORT_18, ioss_interrupts_gpio_18_IRQn},
  74. {CYHAL_PORT_19, ioss_interrupts_gpio_19_IRQn},
  75. {CYHAL_PORT_20, ioss_interrupts_gpio_20_IRQn},
  76. {CYHAL_PORT_21, ioss_interrupts_gpio_21_IRQn},
  77. {CYHAL_PORT_22, ioss_interrupts_gpio_22_IRQn},
  78. {CYHAL_PORT_23, ioss_interrupts_gpio_23_IRQn},
  79. {CYHAL_PORT_24, ioss_interrupts_gpio_24_IRQn},
  80. {CYHAL_PORT_25, ioss_interrupts_gpio_25_IRQn},
  81. {CYHAL_PORT_26, ioss_interrupts_gpio_26_IRQn},
  82. {CYHAL_PORT_27, ioss_interrupts_gpio_27_IRQn},
  83. {CYHAL_PORT_28, ioss_interrupts_gpio_28_IRQn},
  84. {CYHAL_PORT_29, ioss_interrupts_gpio_29_IRQn},
  85. {CYHAL_PORT_30, ioss_interrupts_gpio_30_IRQn},
  86. {CYHAL_PORT_31, ioss_interrupts_gpio_31_IRQn},
  87. {CYHAL_PORT_32, ioss_interrupts_gpio_32_IRQn},
  88. #endif
  89. };
  90. static struct rt_pin_irq_hdr pin_irq_handler_tab[] =
  91. {
  92. {-1, 0, RT_NULL, RT_NULL},
  93. {-1, 0, RT_NULL, RT_NULL},
  94. {-1, 0, RT_NULL, RT_NULL},
  95. {-1, 0, RT_NULL, RT_NULL},
  96. {-1, 0, RT_NULL, RT_NULL},
  97. {-1, 0, RT_NULL, RT_NULL},
  98. {-1, 0, RT_NULL, RT_NULL},
  99. {-1, 0, RT_NULL, RT_NULL},
  100. {-1, 0, RT_NULL, RT_NULL},
  101. {-1, 0, RT_NULL, RT_NULL},
  102. {-1, 0, RT_NULL, RT_NULL},
  103. {-1, 0, RT_NULL, RT_NULL},
  104. {-1, 0, RT_NULL, RT_NULL},
  105. {-1, 0, RT_NULL, RT_NULL},
  106. {-1, 0, RT_NULL, RT_NULL},
  107. {-1, 0, RT_NULL, RT_NULL},
  108. #if defined(SOC_XMC7200D_E272K8384AA)
  109. {-1, 0, RT_NULL, RT_NULL},
  110. {-1, 0, RT_NULL, RT_NULL},
  111. {-1, 0, RT_NULL, RT_NULL},
  112. {-1, 0, RT_NULL, RT_NULL},
  113. {-1, 0, RT_NULL, RT_NULL},
  114. {-1, 0, RT_NULL, RT_NULL},
  115. {-1, 0, RT_NULL, RT_NULL},
  116. {-1, 0, RT_NULL, RT_NULL},
  117. {-1, 0, RT_NULL, RT_NULL},
  118. {-1, 0, RT_NULL, RT_NULL},
  119. {-1, 0, RT_NULL, RT_NULL},
  120. {-1, 0, RT_NULL, RT_NULL},
  121. {-1, 0, RT_NULL, RT_NULL},
  122. {-1, 0, RT_NULL, RT_NULL},
  123. {-1, 0, RT_NULL, RT_NULL},
  124. {-1, 0, RT_NULL, RT_NULL},
  125. {-1, 0, RT_NULL, RT_NULL},
  126. {-1, 0, RT_NULL, RT_NULL},
  127. {-1, 0, RT_NULL, RT_NULL},
  128. #endif
  129. #if defined(SOC_XMC7100D_F144K4160AA)
  130. {-1, 0, RT_NULL, RT_NULL},
  131. {-1, 0, RT_NULL, RT_NULL},
  132. {-1, 0, RT_NULL, RT_NULL},
  133. {-1, 0, RT_NULL, RT_NULL},
  134. {-1, 0, RT_NULL, RT_NULL},
  135. {-1, 0, RT_NULL, RT_NULL},
  136. {-1, 0, RT_NULL, RT_NULL},
  137. {-1, 0, RT_NULL, RT_NULL},
  138. {-1, 0, RT_NULL, RT_NULL},
  139. {-1, 0, RT_NULL, RT_NULL},
  140. {-1, 0, RT_NULL, RT_NULL},
  141. {-1, 0, RT_NULL, RT_NULL},
  142. {-1, 0, RT_NULL, RT_NULL},
  143. {-1, 0, RT_NULL, RT_NULL},
  144. {-1, 0, RT_NULL, RT_NULL},
  145. {-1, 0, RT_NULL, RT_NULL},
  146. {-1, 0, RT_NULL, RT_NULL},
  147. #endif
  148. };
  149. rt_inline void pin_irq_handler(int irqno)
  150. {
  151. Cy_GPIO_ClearInterrupt(CYHAL_GET_PORTADDR(irqno), CYHAL_GET_PIN(irqno));
  152. if (pin_irq_handler_tab[irqno].hdr)
  153. {
  154. pin_irq_handler_tab[irqno].hdr(pin_irq_handler_tab[irqno].args);
  155. }
  156. }
  157. void gpio_exint_handler(uint16_t GPIO_Port)
  158. {
  159. pin_irq_handler(GPIO_Port);
  160. }
  161. /* interrupt callback definition*/
  162. static void irq_callback(void *callback_arg, cyhal_gpio_event_t event)
  163. {
  164. /* To avoid compiler warnings */
  165. (void) callback_arg;
  166. (void) event;
  167. /* enter interrupt */
  168. rt_interrupt_enter();
  169. gpio_exint_handler(*(rt_uint16_t *)callback_arg);
  170. /* leave interrupt */
  171. rt_interrupt_leave();
  172. }
  173. static void ifx_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
  174. {
  175. rt_uint16_t gpio_pin;
  176. if (PORT_GET(pin) < PIN_IFXPORT_MAX)
  177. {
  178. gpio_pin = pin;
  179. }
  180. else
  181. {
  182. return;
  183. }
  184. switch (mode)
  185. {
  186. case PIN_MODE_OUTPUT:
  187. cyhal_gpio_init(gpio_pin, CYHAL_GPIO_DIR_OUTPUT, CYHAL_GPIO_DRIVE_STRONG, true);
  188. break;
  189. case PIN_MODE_INPUT:
  190. cyhal_gpio_init(gpio_pin, CYHAL_GPIO_DIR_INPUT, CYHAL_GPIO_DRIVE_NONE, false);
  191. break;
  192. case PIN_MODE_INPUT_PULLUP:
  193. cyhal_gpio_init(gpio_pin, CYHAL_GPIO_DIR_BIDIRECTIONAL, CYHAL_GPIO_DRIVE_PULLUP, true);
  194. break;
  195. case PIN_MODE_INPUT_PULLDOWN:
  196. cyhal_gpio_init(gpio_pin, CYHAL_GPIO_DIR_BIDIRECTIONAL, CYHAL_GPIO_DRIVE_PULLDOWN, false);
  197. break;
  198. case PIN_MODE_OUTPUT_OD:
  199. cyhal_gpio_init(gpio_pin, CYHAL_GPIO_DIR_BIDIRECTIONAL, CYHAL_GPIO_DRIVE_PULLUP, true);
  200. break;
  201. }
  202. }
  203. static void ifx_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
  204. {
  205. rt_uint16_t gpio_pin;
  206. if (PORT_GET(pin) < PIN_IFXPORT_MAX)
  207. {
  208. gpio_pin = pin;
  209. }
  210. else
  211. {
  212. return;
  213. }
  214. cyhal_gpio_write(gpio_pin, value);
  215. }
  216. static rt_ssize_t ifx_pin_read(struct rt_device *device, rt_base_t pin)
  217. {
  218. rt_uint16_t gpio_pin;
  219. if (PORT_GET(pin) < PIN_IFXPORT_MAX)
  220. {
  221. gpio_pin = pin;
  222. }
  223. else
  224. {
  225. return -RT_EINVAL;
  226. }
  227. return cyhal_gpio_read(gpio_pin);
  228. }
  229. static rt_err_t ifx_pin_attach_irq(struct rt_device *device, rt_base_t pin,
  230. rt_uint8_t mode, void (*hdr)(void *args), void *args)
  231. {
  232. rt_uint16_t gpio_port;
  233. rt_uint16_t gpio_pin;
  234. rt_base_t level;
  235. if (PORT_GET(pin) < PIN_IFXPORT_MAX)
  236. {
  237. gpio_port = PORT_GET(pin);
  238. gpio_pin = pin;
  239. }
  240. else
  241. {
  242. return -RT_ERROR;
  243. }
  244. level = rt_hw_interrupt_disable();
  245. if (pin_irq_handler_tab[gpio_port].pin == pin &&
  246. pin_irq_handler_tab[gpio_port].hdr == hdr &&
  247. pin_irq_handler_tab[gpio_port].mode == mode &&
  248. pin_irq_handler_tab[gpio_port].args == args)
  249. {
  250. rt_hw_interrupt_enable(level);
  251. return RT_EOK;
  252. }
  253. if (pin_irq_handler_tab[gpio_port].pin != -1)
  254. {
  255. rt_hw_interrupt_enable(level);
  256. return -RT_EBUSY;
  257. }
  258. pin_irq_handler_tab[gpio_port].pin = pin;
  259. pin_irq_handler_tab[gpio_port].hdr = hdr;
  260. pin_irq_handler_tab[gpio_port].mode = mode;
  261. pin_irq_handler_tab[gpio_port].args = args;
  262. rt_hw_interrupt_enable(level);
  263. return RT_EOK;
  264. }
  265. static rt_err_t ifx_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
  266. {
  267. rt_uint16_t gpio_port;
  268. rt_uint16_t gpio_pin;
  269. rt_base_t level;
  270. if (PORT_GET(pin) < PIN_IFXPORT_MAX)
  271. {
  272. gpio_port = PORT_GET(pin);
  273. gpio_pin = pin;
  274. }
  275. else
  276. {
  277. return -RT_ERROR;
  278. }
  279. level = rt_hw_interrupt_disable();
  280. if (pin_irq_handler_tab[gpio_port].pin == -1)
  281. {
  282. rt_hw_interrupt_enable(level);
  283. return RT_EOK;
  284. }
  285. pin_irq_handler_tab[gpio_port].pin = -1;
  286. pin_irq_handler_tab[gpio_port].hdr = RT_NULL;
  287. pin_irq_handler_tab[gpio_port].mode = 0;
  288. pin_irq_handler_tab[gpio_port].args = RT_NULL;
  289. rt_hw_interrupt_enable(level);
  290. return RT_EOK;
  291. }
  292. static rt_err_t ifx_pin_irq_enable(struct rt_device *device, rt_base_t pin,
  293. rt_uint8_t enabled)
  294. {
  295. rt_uint16_t gpio_port;
  296. rt_uint16_t gpio_pin;
  297. rt_base_t level;
  298. rt_uint8_t pin_irq_mode;
  299. const struct pin_irq_map *irqmap;
  300. if (PORT_GET(pin) < PIN_IFXPORT_MAX)
  301. {
  302. gpio_port = PORT_GET(pin);
  303. gpio_pin = pin;
  304. }
  305. else
  306. {
  307. return -RT_ERROR;
  308. }
  309. if (enabled == PIN_IRQ_ENABLE)
  310. {
  311. level = rt_hw_interrupt_disable();
  312. if (pin_irq_handler_tab[gpio_port].pin == -1)
  313. {
  314. rt_hw_interrupt_enable(level);
  315. return -RT_EINVAL;
  316. }
  317. irqmap = &pin_irq_map[gpio_port];
  318. #if !defined(COMPONENT_CAT1C)||defined(SOC_XMC7100D_F144K4160AA)
  319. IRQn_Type irqn = irqmap->irqno;
  320. irq_cb_data[irqn].callback = irq_callback;
  321. irq_cb_data[irqn].callback_arg = (rt_uint16_t *)&pin_irq_map[gpio_port].port;
  322. cyhal_gpio_register_callback(gpio_pin, &irq_cb_data[irqn]);
  323. #endif
  324. Cy_GPIO_ClearInterrupt(CYHAL_GET_PORTADDR(gpio_pin), CYHAL_GET_PIN(gpio_pin));
  325. switch (pin_irq_handler_tab[gpio_port].mode)
  326. {
  327. case PIN_IRQ_MODE_RISING:
  328. pin_irq_mode = CYHAL_GPIO_IRQ_RISE;
  329. break;
  330. case PIN_IRQ_MODE_FALLING:
  331. pin_irq_mode = CYHAL_GPIO_IRQ_FALL;
  332. break;
  333. case PIN_IRQ_MODE_RISING_FALLING:
  334. pin_irq_mode = CYHAL_GPIO_IRQ_BOTH;
  335. break;
  336. default:
  337. break;
  338. }
  339. cyhal_gpio_enable_event(gpio_pin, pin_irq_mode, GPIO_INTERRUPT_PRIORITY, RT_TRUE);
  340. rt_hw_interrupt_enable(level);
  341. }
  342. else if (enabled == PIN_IRQ_DISABLE)
  343. {
  344. level = rt_hw_interrupt_disable();
  345. irqmap = &pin_irq_map[gpio_port];
  346. #if !defined(COMPONENT_CAT1C)||defined(SOC_XMC7100D_F144K4160AA)
  347. IRQn_Type irqn = irqmap->irqno;
  348. if (irqn < 0 || irqn >= PIN_IFXPORT_MAX)
  349. {
  350. rt_hw_interrupt_enable(level);
  351. return -RT_EINVAL;
  352. }
  353. _cyhal_irq_disable(irqn);
  354. #endif
  355. rt_hw_interrupt_enable(level);
  356. }
  357. else
  358. {
  359. return -RT_EINVAL;
  360. }
  361. return RT_EOK;
  362. }
  363. const static struct rt_pin_ops _ifx_pin_ops =
  364. {
  365. ifx_pin_mode,
  366. ifx_pin_write,
  367. ifx_pin_read,
  368. ifx_pin_attach_irq,
  369. ifx_pin_dettach_irq,
  370. ifx_pin_irq_enable,
  371. RT_NULL,
  372. };
  373. int rt_hw_pin_init(void)
  374. {
  375. return rt_device_pin_register("pin", &_ifx_pin_ops, RT_NULL);
  376. }
  377. #endif /* RT_USING_PIN */