fgpio.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fgpio.c
  15. * Date: 2022-02-10 14:53:42
  16. * LastEditTime: 2022-02-18 08:25:29
  17. * Description:  This files is for GPIO user API implmentation
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.0 zhugengyu 2022-3-1 init commit
  23. */
  24. /***************************** Include Files *********************************/
  25. #include "fdebug.h"
  26. #include "fparameters.h"
  27. #include "fgpio_hw.h"
  28. #include "fgpio.h"
  29. /************************** Constant Definitions *****************************/
  30. /**************************** Type Definitions *******************************/
  31. /***************** Macros (Inline Functions) Definitions *********************/
  32. #define FGPIO_DEBUG_TAG "FGPIO"
  33. #define FGPIO_ERROR(format, ...) FT_DEBUG_PRINT_E(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
  34. #define FGPIO_WARN(format, ...) FT_DEBUG_PRINT_W(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
  35. #define FGPIO_INFO(format, ...) FT_DEBUG_PRINT_I(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
  36. #define FGPIO_DEBUG(format, ...) FT_DEBUG_PRINT_D(FGPIO_DEBUG_TAG, format, ##__VA_ARGS__)
  37. /************************** Function Prototypes ******************************/
  38. /************************** Variable Definitions *****************************/
  39. /*****************************************************************************/
  40. /**
  41. * @name: FGpioCfgInitialize
  42. * @msg: 初始化GPIO控制器实例
  43. * @return {FError} FGPIO_SUCCESS 表示初始化成功
  44. * @param {FGpio} *instance, GPIO控制器实例
  45. * @param {FGpioConfig} *config, GPIO控制器配置
  46. */
  47. FError FGpioCfgInitialize(FGpio *const instance, const FGpioConfig *const config)
  48. {
  49. FASSERT(instance && config);
  50. if (0 == config->base_addr)
  51. {
  52. FGPIO_ERROR("invalid base address !!!");
  53. return FGPIO_ERR_INVALID_PARA;
  54. }
  55. if (config != &instance->config)
  56. {
  57. instance->config = *config;
  58. }
  59. instance->is_ready = FT_COMPONENT_IS_READY;
  60. return FGPIO_SUCCESS;
  61. }
  62. /**
  63. * @name: FGpioDeInitialize
  64. * @msg: 去初始化GPIO控制器实例
  65. * @return {*}
  66. * @param {FGpio} *instance, GPIO控制器实例
  67. */
  68. void FGpioDeInitialize(FGpio *const instance)
  69. {
  70. FASSERT(instance);
  71. u32 port_id;
  72. u32 pin_id;
  73. FGpioPin *pin = NULL;
  74. for (port_id = FGPIO_PORT_A; port_id < FGPIO_PORT_NUM; port_id++)
  75. {
  76. for (pin_id = FGPIO_PIN_0; pin_id < FGPIO_PIN_NUM; pin_id++)
  77. {
  78. pin = instance->pins[port_id][pin_id];
  79. if (NULL != pin)
  80. {
  81. FGpioPinDeInitialize(pin);
  82. }
  83. }
  84. }
  85. instance->is_ready = 0;
  86. return;
  87. }
  88. /**
  89. * @name: FGpioPinInitialize
  90. * @msg: 初始化GPIO引脚实例
  91. * @return {FError} FGPIO_SUCCESS 表示初始化成功
  92. * @param {FGpio} *instance, GPIO控制器实例
  93. * @param {FGpioPin} *pin_instance, GPIO引脚实例
  94. * @param {FGpioPinId} index, GPIO引脚索引
  95. */
  96. FError FGpioPinInitialize(FGpio *const instance, FGpioPin *const pin_instance,
  97. const FGpioPinId index)
  98. {
  99. FASSERT(instance && pin_instance);
  100. FASSERT_MSG(index.port < FGPIO_PORT_NUM, "invalid gpio port %d", index);
  101. FASSERT_MSG(index.pin < FGPIO_PIN_NUM, "invalid gpio pin %d", index);
  102. if (FT_COMPONENT_IS_READY != instance->is_ready)
  103. {
  104. FGPIO_ERROR("gpio instance not yet init !!!");
  105. return FGPIO_ERR_NOT_INIT;
  106. }
  107. if (FT_COMPONENT_IS_READY == pin_instance->is_ready)
  108. {
  109. FGPIO_ERROR("gpio pin already inited !!!");
  110. return FGPIO_ERR_ALREADY_INIT;
  111. }
  112. pin_instance->index = index;
  113. instance->pins[index.port][index.pin] = pin_instance;
  114. pin_instance->instance = instance;
  115. pin_instance->irq_cb = NULL;
  116. pin_instance->irq_cb_params = NULL;
  117. pin_instance->irq_one_time = FALSE;
  118. pin_instance->is_ready = FT_COMPONENT_IS_READY;
  119. return FGPIO_SUCCESS;
  120. }
  121. /**
  122. * @name: FGpioPinDeInitialize
  123. * @msg: 去初始化GPIO引脚实例
  124. * @return {NONE}
  125. * @param {FGpioPin} *pin, GPIO引脚实例
  126. */
  127. void FGpioPinDeInitialize(FGpioPin *const pin)
  128. {
  129. FASSERT(pin);
  130. FGpio *const instance = pin->instance;
  131. if ((NULL == instance) || (FT_COMPONENT_IS_READY != instance->is_ready) ||
  132. (FT_COMPONENT_IS_READY != pin->is_ready))
  133. {
  134. FGPIO_ERROR("gpio instance not yet init !!!");
  135. return;
  136. }
  137. if (FGPIO_DIR_INPUT == FGpioGetDirection(pin))
  138. FGpioSetInterruptMask(pin, FALSE); /* 关闭引脚中断 */
  139. FGpioPinId index = pin->index;
  140. FASSERT_MSG(instance->pins[index.port][index.pin] == pin, "invalid pin instance");
  141. instance->pins[index.port][index.pin] = NULL;
  142. pin->instance = NULL;
  143. pin->is_ready = 0U;
  144. return;
  145. }
  146. /**
  147. * @name: FGpioGetPinIrqSourceType
  148. * @msg: 获取引脚中断的上报方式
  149. * @return {FGpioIrqSourceType} 引脚中断的上报方式
  150. * @param {FGpioPin} *pin, GPIO引脚实例
  151. */
  152. FGpioIrqSourceType FGpioGetPinIrqSourceType(FGpioPinId pin_id)
  153. {
  154. #if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
  155. if (FGPIO_PORT_B == pin_id.port)
  156. {
  157. return FGPIO_IRQ_NOT_SUPPORT;
  158. }
  159. #endif
  160. if (FGPIO_PORT_A == pin_id.port)
  161. {
  162. #if defined(FGPIO_VERSION_2) /* E2000 GPIO 0 ~ 5 */
  163. if (pin_id.ctrl <= FGPIO_WITH_PIN_IRQ) /* 0 ~ 2 中断单独上报 */
  164. {
  165. return FGPIO_IRQ_BY_PIN;
  166. }
  167. #endif
  168. return FGPIO_IRQ_BY_CONTROLLER;
  169. }
  170. return FGPIO_IRQ_NOT_SUPPORT;
  171. }
  172. /**
  173. * @name: FGpioReadRegDir
  174. * @msg: 从寄存器读取GPIO组的输入输出方向
  175. * @return {u32} GPIO组的输入输出方向, bit[8:0]有效
  176. * @param {uintptr} base_addr, GPIO控制器基地址
  177. * @param {FGpioPortIndex} port, GPIO组, A/B
  178. */
  179. static u32 FGpioReadRegDir(uintptr base_addr, const FGpioPortIndex port)
  180. {
  181. u32 reg_val = 0;
  182. if (FGPIO_PORT_A == port)
  183. {
  184. reg_val = FGpioReadReg32(base_addr, FGPIO_SWPORTA_DDR_OFFSET);
  185. }
  186. #if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
  187. else if (FGPIO_PORT_B == port)
  188. {
  189. reg_val = FGpioReadReg32(base_addr, FGPIO_SWPORTB_DDR_OFFSET);
  190. }
  191. #endif
  192. else
  193. {
  194. FASSERT(0);
  195. }
  196. return reg_val;
  197. }
  198. /**
  199. * @name: FGpioWriteRegDir
  200. * @msg: 向寄存器写入GPIO组的输入输出方向
  201. * @return {*}
  202. * @param {uintptr} base_addr, GPIO控制器基地址
  203. * @param {FGpioPortIndex} port, GPIO组, A/B
  204. * @param {u32} reg_val, GPIO组的输入输出方向, bit[8:0]有效
  205. */
  206. static void FGpioWriteRegDir(uintptr base_addr, const FGpioPortIndex port, const u32 reg_val)
  207. {
  208. if (FGPIO_PORT_A == port)
  209. {
  210. FGpioWriteReg32(base_addr, FGPIO_SWPORTA_DDR_OFFSET, reg_val);
  211. }
  212. #if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
  213. else if (FGPIO_PORT_B == port)
  214. {
  215. FGpioWriteReg32(base_addr, FGPIO_SWPORTB_DDR_OFFSET, reg_val);
  216. }
  217. #endif
  218. else
  219. {
  220. FASSERT(0);
  221. }
  222. return;
  223. }
  224. /**
  225. * @name: FGpioSetDirection
  226. * @msg: 设置GPIO引脚的输入输出方向
  227. * @return {*}
  228. * @param {FGpioPin} *instance, GPIO控制器实例
  229. * @param {FGpioDirection} dir, 待设置的GPIO的方向
  230. * @note 初始化 GPIO 实例后使用此函数
  231. */
  232. void FGpioSetDirection(FGpioPin *const pin, FGpioDirection dir)
  233. {
  234. FASSERT(pin);
  235. FGpio *const instance = pin->instance;
  236. FASSERT(instance);
  237. FASSERT_MSG(instance->is_ready == FT_COMPONENT_IS_READY, "gpio instance not yet init !!!");
  238. u32 reg_val;
  239. FGpioPinId index = pin->index;
  240. uintptr base_addr = instance->config.base_addr;
  241. reg_val = FGpioReadRegDir(base_addr, index.port);
  242. if (FGPIO_DIR_INPUT == dir)
  243. {
  244. reg_val &= ~BIT(index.pin); /* 0-Input */
  245. }
  246. else if (FGPIO_DIR_OUTPUT == dir)
  247. {
  248. reg_val |= BIT(index.pin); /* 1-Output */
  249. }
  250. else
  251. {
  252. FASSERT(0);
  253. }
  254. FGpioWriteRegDir(base_addr, index.port, reg_val);
  255. return;
  256. }
  257. /**
  258. * @name: FGpioGetDirection
  259. * @msg: 获取GPIO引脚的输入输出方向
  260. * @return {FGpioDirection} GPIO引脚方向
  261. * @param {FGpioPin} *pin, GPIO引脚实例
  262. * @note 初始化 GPIO 实例后使用此函数
  263. */
  264. FGpioDirection FGpioGetDirection(FGpioPin *const pin)
  265. {
  266. FASSERT(pin);
  267. FGpio *const instance = pin->instance;
  268. FASSERT(instance);
  269. FASSERT(instance->is_ready == FT_COMPONENT_IS_READY);
  270. FGpioPinId index = pin->index;
  271. uintptr base_addr = instance->config.base_addr;
  272. u32 reg_val = FGpioReadRegDir(base_addr, index.port);
  273. return (BIT(index.pin) & reg_val) ? FGPIO_DIR_OUTPUT : FGPIO_DIR_INPUT;
  274. }
  275. /**
  276. * @name: FGpioReadRegVal
  277. * @msg: 获取GPIO组的输出寄存器值
  278. * @return {u32} 输出寄存器值 bit[8:0]有效
  279. * @param {uintptr} base_addr, GPIO控制器基地址
  280. * @param {FGpioPortIndex} port, GPIO组
  281. */
  282. static u32 FGpioReadRegVal(uintptr base_addr, const FGpioPortIndex port)
  283. {
  284. u32 reg_val = 0;
  285. if (FGPIO_PORT_A == port)
  286. {
  287. reg_val = FGpioReadReg32(base_addr, FGPIO_SWPORTA_DR_OFFSET);
  288. }
  289. #if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
  290. else if (FGPIO_PORT_B == port)
  291. {
  292. reg_val = FGpioReadReg32(base_addr, FGPIO_SWPORTB_DR_OFFSET);
  293. }
  294. #endif
  295. else
  296. {
  297. FASSERT(0);
  298. }
  299. return reg_val;
  300. }
  301. /**
  302. * @name: FGpioWriteRegVal
  303. * @msg: 设置GPIO组的输出寄存器值
  304. * @return {*}
  305. * @param {uintptr} base_addr, GPIO控制器基地址
  306. * @param {FGpioPortIndex} port, GPIO组
  307. * @param {u32} reg_val, 输出寄存器值 bit[8:0]有效
  308. */
  309. void FGpioWriteRegVal(uintptr base_addr, const FGpioPortIndex port, const u32 reg_val)
  310. {
  311. if (FGPIO_PORT_A == port)
  312. {
  313. FGpioWriteReg32(base_addr, FGPIO_SWPORTA_DR_OFFSET, reg_val);
  314. }
  315. #if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
  316. else if (FGPIO_PORT_B == port)
  317. {
  318. FGpioWriteReg32(base_addr, FGPIO_SWPORTB_DR_OFFSET, reg_val);
  319. }
  320. #endif
  321. else
  322. {
  323. FASSERT(0);
  324. }
  325. return;
  326. }
  327. /**
  328. * @name: FGpioSetOutputValue
  329. * @msg: 设置GPIO引脚的输出值
  330. * @return {FError} FGPIO_SUCCESS 表示设置成功
  331. * @param {FGpioPin} *pin, GPIO引脚实例
  332. * @param {FGpioPinVal} output, GPIO引脚的输出值
  333. * @note 初始化 GPIO 实例后使用此函数,先设置 GPIO 引脚为输出后调用此函数
  334. */
  335. FError FGpioSetOutputValue(FGpioPin *const pin, const FGpioPinVal output)
  336. {
  337. FASSERT(pin);
  338. FGpio *const instance = pin->instance;
  339. FASSERT(instance);
  340. FASSERT_MSG(instance->is_ready == FT_COMPONENT_IS_READY, "gpio instance not yet init !!!");
  341. FGpioPinId index = pin->index;
  342. u32 base_addr = instance->config.base_addr;
  343. u32 reg_val;
  344. if (FGPIO_DIR_OUTPUT != FGpioGetDirection(pin))
  345. {
  346. FGPIO_ERROR("need to set GPIO direction as OUTPUT first !!!");
  347. return FGPIO_ERR_INVALID_STATE;
  348. }
  349. FGPIO_INFO("pin-%d at port %d", index.pin, index.port);
  350. reg_val = FGpioReadRegVal(base_addr, index.port);
  351. if (FGPIO_PIN_LOW == output)
  352. {
  353. reg_val &= ~BIT(index.pin);
  354. }
  355. else if (FGPIO_PIN_HIGH == output)
  356. {
  357. reg_val |= BIT(index.pin);
  358. }
  359. else
  360. {
  361. FASSERT(0);
  362. }
  363. FGPIO_INFO("output val 0x%x", reg_val);
  364. FGpioWriteRegVal(base_addr, index.port, reg_val);
  365. FGPIO_INFO("output val 0x%x", FGpioReadRegVal(base_addr, index.port));
  366. return FGPIO_SUCCESS;
  367. }
  368. /**
  369. * @name: FGpioGetInputValue
  370. * @msg: 获取GPIO引脚的输入值
  371. * @return {FGpioPinVal} 获取的输入值,高电平/低电平
  372. * @param {FGpioPin} *instance, GPIO引脚实例
  373. * @note 初始化 GPIO 实例后使用此函数,先设置 GPIO 引脚为输入后调用此函数
  374. */
  375. FGpioPinVal FGpioGetInputValue(FGpioPin *const pin)
  376. {
  377. FASSERT(pin);
  378. FGpio *const instance = pin->instance;
  379. FASSERT(instance);
  380. FASSERT(instance->is_ready == FT_COMPONENT_IS_READY);
  381. FGpioPinId index = pin->index;
  382. uintptr base_addr = instance->config.base_addr;
  383. u32 reg_val;
  384. if (FGPIO_DIR_INPUT != FGpioGetDirection(pin))
  385. {
  386. FGPIO_ERROR("need to set GPIO direction as INPUT first !!!");
  387. return FGPIO_PIN_LOW;
  388. }
  389. if (FGPIO_PORT_A == index.port)
  390. {
  391. reg_val = FGpioReadReg32(base_addr, FGPIO_EXT_PORTA_OFFSET);
  392. }
  393. #if defined(FGPIO_VERSION_1) /* FT2000-4, D2000 */
  394. else if (FGPIO_PORT_B == index.port)
  395. {
  396. reg_val = FGpioReadReg32(base_addr, FGPIO_EXT_PORTB_OFFSET);
  397. }
  398. #endif
  399. else
  400. {
  401. FASSERT(0);
  402. }
  403. FGPIO_INFO("input val: 0x%x", reg_val);
  404. return (BIT(index.pin) & reg_val) ? FGPIO_PIN_HIGH : FGPIO_PIN_LOW;
  405. }