fioctrl.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  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: fioctrl.c
  15. * Date: 2022-02-10 14:53:42
  16. * LastEditTime: 2022-02-18 08:25:29
  17. * Description:  This files is for io-ctrl function implementation (io-mux/io-config/io-delay)
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. * 1.0 zhugengyu 2022/2/22 init commit
  23. */
  24. /***************************** Include Files *********************************/
  25. #include "fparameters.h"
  26. #include "fio.h"
  27. #include "fkernel.h"
  28. #include "fassert.h"
  29. #include "fdebug.h"
  30. #include "fioctrl.h"
  31. #include "fpinctrl.h"
  32. /************************** Constant Definitions *****************************/
  33. /* Bit[0] : 输入延迟功能使能 */
  34. #define FIOCTRL_DELAY_EN(delay_beg) BIT(delay_beg)
  35. #define FIOCTRL_INPUT_DELAY_OFF 0
  36. /* Bit[3:1] : 输入延迟精调档位选择 */
  37. #define FIOCTRL_DELICATE_DELAY_MASK(delay_beg) GENMASK((delay_beg + 3), (delay_beg + 1))
  38. #define FIOCTRL_DELICATE_DELAY_GET(reg_val, delay_beg) GET_REG32_BITS((reg_val), (delay_beg + 3), (delay_beg + 1))
  39. #define FIOCTRL_DELICATE_DELAY_SET(val, delay_beg) SET_REG32_BITS((val), (delay_beg + 3), (delay_beg + 1))
  40. /* Bit[6:4] : 输入延迟粗调档位选择 */
  41. #define FIOCTRL_ROUGH_DELAY_MASK(delay_beg) GENMASK((delay_beg + 6), (delay_beg + 4))
  42. #define FIOCTRL_ROUGH_DELAY_GET(reg_val, delay_beg) GET_REG32_BITS((reg_val), (delay_beg + 6), (delay_beg + 4))
  43. #define FIOCTRL_ROUGH_DELAY_SET(val, delay_beg) SET_REG32_BITS((val), (delay_beg + 6), (delay_beg + 4))
  44. /* Bit[7] : 保留 */
  45. /* Bit[8] : 输出延迟功能使能 */
  46. /* Bit[11:9] : 输出延迟精调档位选择 */
  47. /* Bit [14:12] : 输出延迟粗调档位选择 */
  48. /* Bit [15] : 保留 */
  49. #define FIOCTRL_FUNC_BEG_OFF(reg_bit) ((reg_bit) + 0)
  50. #define FIOCTRL_FUNC_END_OFF(reg_bit) ((reg_bit) + 1) /* bit[1:0] 复用功能占2个位 */
  51. #define FIOCTRL_PULL_BEG_OFF(reg_bit) ((reg_bit) + 2)
  52. #define FIOCTRL_PULL_END_OFF(reg_bit) ((reg_bit) + 3) /* bit[3:2] 上下拉功能占2个位 */
  53. #define FIOCTRL_DELAY_IN_BEG_OFF(reg_bit) ((reg_bit) + 0)
  54. #define FIOCTRL_DELAY_IN_END_OFF(reg_bit) ((reg_bit) + 7) /* bit[8:1] 输入延时占7个位 */
  55. #define FIOCTRL_DELAY_OUT_BEG_OFF(reg_bit) ((reg_bit) + 8)
  56. #define FIOCTRL_DELAY_OUT_END_OFF(reg_bit) ((reg_bit) + 15) /* bit[15:9] 输出延时占7个位 */
  57. /* 芯片引脚控制寄存器的起止位置 */
  58. #define FIOCTRL_REG_OFFSET_MIN 0x200
  59. #define FIOCTRL_REG_OFFSET_MAX 0x22c
  60. /* 芯片引脚延时寄存器的起止位置 */
  61. #define FIOCTRL_DELAY_REG_OFFSET_MIN 0x400
  62. #define FIOCTRL_DELAY_REG_OFFSET_MAX 0x404
  63. /**************************** Type Definitions *******************************/
  64. /***************** Macros (Inline Functions) Definitions *********************/
  65. #define FIOCTRL_DEBUG_TAG "FIOCTRL"
  66. #define FIOCTRL_ERROR(format, ...) FT_DEBUG_PRINT_E(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
  67. #define FIOCTRL_WARN(format, ...) FT_DEBUG_PRINT_W(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
  68. #define FIOCTRL_INFO(format, ...) FT_DEBUG_PRINT_I(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
  69. #define FIOCTRL_DEBUG(format, ...) FT_DEBUG_PRINT_D(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
  70. #define FIOCTRL_ASSERT_REG_OFF(pin) FASSERT_MSG(((pin.reg_off >= FIOCTRL_REG_OFFSET_MIN) && (pin.reg_off <= FIOCTRL_REG_OFFSET_MAX)), "invalid pin register off @%d", (pin.reg_off))
  71. #define FIOCTRL_ASSERT_FUNC(func) FASSERT_MSG((func < FPIN_NUM_OF_FUNC), "invalid func as %d", (func))
  72. #define FIOCTRL_ASSERT_PULL(pull) FASSERT_MSG((pull < FPIN_NUM_OF_PULL), "invalid pull as %d", (pull))
  73. #define FIOCTRL_ASSERT_DELAY_REG_OFF(pin) FASSERT_MSG(((pin.reg_off >= FIOCTRL_DELAY_REG_OFFSET_MIN) && (pin.reg_off <= FIOCTRL_DELAY_REG_OFFSET_MAX)), "invalid delay pin register off @%d", (pin.reg_off))
  74. #define FIOCTRL_ASSERT_DELAY(delay) FASSERT_MSG(((delay) < FPIN_NUM_OF_DELAY), "invalid delay as %d", (delay));
  75. /************************** Function Prototypes ******************************/
  76. /************************** Variable Definitions *****************************/
  77. /*****************************************************************************/
  78. /**
  79. * @name: FPinGetFunc
  80. * @msg: 获取IO引脚当前的复用功能
  81. * @return {FPinFunc} 当前的复用功能
  82. * @param {FPinIndex} pin IO引脚索引
  83. * @note 参考编程手册,使用 FIOCTRL_INDEX 宏定义index的值
  84. */
  85. FPinFunc FPinGetFunc(const FPinIndex pin)
  86. {
  87. FIOCTRL_ASSERT_REG_OFF(pin);
  88. u32 func_beg = FIOCTRL_FUNC_BEG_OFF(pin.reg_bit);
  89. u32 func_end = FIOCTRL_FUNC_END_OFF(pin.reg_bit);
  90. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  91. u32 func = GET_REG32_BITS(reg_val, func_end, func_beg);
  92. FIOCTRL_ASSERT_FUNC(func);
  93. return (FPinFunc)GET_REG32_BITS(reg_val, func_end, func_beg);
  94. }
  95. /**
  96. * @name: FPinSetFunc
  97. * @msg: 设置IO引脚复用功能
  98. * @return {*}
  99. * @param {FPinIndex} pin IO引脚索引
  100. * @param {FPinFunc} func IO复用功能
  101. * @note 参考编程手册,使用 FIOCTRL_INDEX 宏定义index的值
  102. */
  103. void FPinSetFunc(const FPinIndex pin, FPinFunc func)
  104. {
  105. FIOCTRL_ASSERT_REG_OFF(pin);
  106. FIOCTRL_ASSERT_FUNC(func);
  107. u32 func_beg = FIOCTRL_FUNC_BEG_OFF(pin.reg_bit);
  108. u32 func_end = FIOCTRL_FUNC_END_OFF(pin.reg_bit);
  109. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  110. reg_val &= ~GENMASK(func_end, func_beg);
  111. reg_val |= SET_REG32_BITS(func, func_end, func_beg);
  112. FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
  113. return;
  114. }
  115. /**
  116. * @name: FPinGetPull
  117. * @msg: 获取IO引脚当前的上下拉设置
  118. * @return {*}
  119. * @param {FPinIndex} pin IO引脚索引
  120. * @note 参考编程手册,使用 FIOCTRL_INDEX 宏定义index的值
  121. */
  122. FPinPull FPinGetPull(const FPinIndex pin)
  123. {
  124. FIOCTRL_ASSERT_REG_OFF(pin);
  125. u32 pull_beg = FIOCTRL_PULL_BEG_OFF(pin.reg_bit);
  126. u32 pull_end = FIOCTRL_PULL_END_OFF(pin.reg_bit);
  127. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  128. u32 pull = GET_REG32_BITS(reg_val, pull_end, pull_beg);
  129. FIOCTRL_ASSERT_PULL(pull);
  130. return (FPinPull)pull;
  131. }
  132. /**
  133. * @name: FPinSetPull
  134. * @msg: 设置IO引脚当前的上下拉
  135. * @return {*}
  136. * @param {FPinIndex} pin IO引脚索引
  137. * @param {FPinPull} pull 上下拉设置
  138. */
  139. void FPinSetPull(const FPinIndex pin, FPinPull pull)
  140. {
  141. FIOCTRL_ASSERT_REG_OFF(pin);
  142. FIOCTRL_ASSERT_PULL(pull);
  143. u32 pull_beg = FIOCTRL_PULL_BEG_OFF(pin.reg_bit);
  144. u32 pull_end = FIOCTRL_PULL_END_OFF(pin.reg_bit);
  145. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  146. reg_val &= ~GENMASK(pull_end, pull_beg);
  147. reg_val |= SET_REG32_BITS(pull, pull_end, pull_beg);
  148. FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
  149. return;
  150. }
  151. /**
  152. * @name: FPinGetConfig
  153. * @msg: 获取IO引脚的复用、上下拉和驱动能力设置
  154. * @return {*}
  155. * @param {FPinIndex} pin IO引脚索引
  156. * @param {FPinFunc} *func IO复用功能
  157. * @param {FPinPull} *pull pull 上下拉设置
  158. */
  159. void FPinGetConfig(const FPinIndex pin, FPinFunc *func, FPinPull *pull)
  160. {
  161. FIOCTRL_ASSERT_REG_OFF(pin);
  162. u32 func_beg = FIOCTRL_FUNC_BEG_OFF(pin.reg_bit);
  163. u32 func_end = FIOCTRL_FUNC_END_OFF(pin.reg_bit);
  164. u32 pull_beg = FIOCTRL_PULL_BEG_OFF(pin.reg_bit);
  165. u32 pull_end = FIOCTRL_PULL_END_OFF(pin.reg_bit);
  166. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  167. if (func)
  168. {
  169. *func = GET_REG32_BITS(reg_val, func_end, func_beg);
  170. }
  171. if (pull)
  172. {
  173. *pull = GET_REG32_BITS(reg_val, pull_end, pull_beg);
  174. }
  175. return;
  176. }
  177. /**
  178. * @name: FPinSetConfig
  179. * @msg: 设置IO引脚的复用、上下拉和驱动能力
  180. * @return {*}
  181. * @param {FPinIndex} pin IO引脚索引
  182. * @param {FPinFunc} func IO复用功能
  183. * @param {FPinPull} pull pull 上下拉设置
  184. */
  185. void FPinSetConfig(const FPinIndex pin, FPinFunc func, FPinPull pull)
  186. {
  187. FIOCTRL_ASSERT_REG_OFF(pin);
  188. u32 func_beg = FIOCTRL_FUNC_BEG_OFF(pin.reg_bit);
  189. u32 func_end = FIOCTRL_FUNC_END_OFF(pin.reg_bit);
  190. u32 pull_beg = FIOCTRL_PULL_BEG_OFF(pin.reg_bit);
  191. u32 pull_end = FIOCTRL_PULL_END_OFF(pin.reg_bit);
  192. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  193. reg_val &= ~GENMASK(func_end, func_beg);
  194. reg_val |= SET_REG32_BITS(func, func_end, func_beg);
  195. reg_val &= ~GENMASK(pull_end, pull_beg);
  196. reg_val |= SET_REG32_BITS(pull, pull_end, pull_beg);
  197. FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
  198. return;
  199. }
  200. /**
  201. * @name: FPinGetDelay
  202. * @msg: 获取IO引脚当前的延时设置
  203. * @return {FPinDelay} 当前的延时设置
  204. * @param {FPinIndex} pin IO引脚延时设置索引
  205. * @param {FPinDelayDir} dir 输入/输出延时
  206. * @param {FPinDelayType} type 精调/粗调延时
  207. */
  208. FPinDelay FPinGetDelay(const FPinIndex pin, FPinDelayDir dir, FPinDelayType type)
  209. {
  210. FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
  211. u8 delay = 0;
  212. const u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  213. u32 delay_beg = 0, delay_end = 0;
  214. if (FPIN_OUTPUT_DELAY == dir)
  215. {
  216. delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
  217. }
  218. else if (FPIN_INPUT_DELAY == dir)
  219. {
  220. delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
  221. }
  222. else
  223. {
  224. FASSERT(0);
  225. }
  226. if (FPIN_DELAY_FINE_TUNING == type)
  227. {
  228. delay = FIOCTRL_DELICATE_DELAY_GET(reg_val, delay_beg);
  229. }
  230. else if (FPIN_DELAY_COARSE_TUNING == type)
  231. {
  232. delay = FIOCTRL_ROUGH_DELAY_GET(reg_val, delay_beg);
  233. }
  234. else
  235. {
  236. FASSERT(0);
  237. }
  238. FIOCTRL_ASSERT_DELAY(delay);
  239. return (FPinDelay)delay;
  240. }
  241. /**
  242. * @name: FPinGetDelayEn
  243. * @msg: 获取IO引脚当前的延时使能标志位
  244. * @return {*}
  245. * @param {FPinIndex} pin IO引脚延时设置索引
  246. * @param {FPinDelayDir} dir 输入/输出延时
  247. */
  248. boolean FPinGetDelayEn(const FPinIndex pin, FPinDelayDir dir)
  249. {
  250. FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
  251. boolean enabled = FALSE;
  252. const u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  253. u32 delay_beg = 0, delay_end = 0;
  254. if (FPIN_OUTPUT_DELAY == dir)
  255. {
  256. delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
  257. }
  258. else if (FPIN_INPUT_DELAY == dir)
  259. {
  260. delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
  261. }
  262. else
  263. {
  264. FASSERT(0);
  265. }
  266. if (FIOCTRL_DELAY_EN(delay_beg) & reg_val)
  267. {
  268. enabled = TRUE;
  269. }
  270. return enabled;
  271. }
  272. /**
  273. * @name: FPinSetDelay
  274. * @msg: 设置IO引脚延时
  275. * @return {*}
  276. * @param {FPinIndex} pin IO引脚延时设置索引
  277. * @param {FPinDelayDir} dir 输入/输出延时
  278. * @param {FPinDelayType} type 精调/粗调延时
  279. * @param {FPinDelay} delay 延时档位设置 0 ~ 8 档可用
  280. */
  281. void FPinSetDelay(const FPinIndex pin, FPinDelayDir dir, FPinDelayType type, FPinDelay delay)
  282. {
  283. FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
  284. FIOCTRL_ASSERT_DELAY(delay);
  285. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  286. u32 delay_beg = 0, delay_end = 0;
  287. if (FPIN_OUTPUT_DELAY == dir)
  288. {
  289. delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
  290. }
  291. else if (FPIN_INPUT_DELAY == dir)
  292. {
  293. delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
  294. }
  295. else
  296. {
  297. FASSERT(0);
  298. }
  299. if (FPIN_DELAY_FINE_TUNING == type)
  300. {
  301. reg_val &= ~FIOCTRL_DELICATE_DELAY_MASK(delay_beg);
  302. delay = FIOCTRL_DELICATE_DELAY_GET(reg_val, delay_beg);
  303. }
  304. else if (FPIN_DELAY_COARSE_TUNING == type)
  305. {
  306. reg_val &= ~FIOCTRL_ROUGH_DELAY_MASK(delay_beg);
  307. delay = FIOCTRL_ROUGH_DELAY_GET(reg_val, delay_beg);
  308. }
  309. else
  310. {
  311. FASSERT(0);
  312. }
  313. FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
  314. return;
  315. }
  316. /**
  317. * @name: FPinSetDelayEn
  318. * @msg: 使能/去使能IO引脚延时
  319. * @return {*}
  320. * @param {FPinIndex} pin IO引脚延时设置索引
  321. * @param {FPinDelayDir} dir 输入/输出延时
  322. * @param {boolean} enable TRUE: 使能, FALSE: 去使能
  323. */
  324. void FPinSetDelayEn(const FPinIndex pin, FPinDelayDir dir, boolean enable)
  325. {
  326. FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
  327. u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
  328. u32 delay_beg = 0, delay_end = 0;
  329. if (FPIN_OUTPUT_DELAY == dir)
  330. {
  331. delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
  332. }
  333. else if (FPIN_INPUT_DELAY == dir)
  334. {
  335. delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
  336. }
  337. else
  338. {
  339. FASSERT(0);
  340. }
  341. reg_val &= ~FIOCTRL_DELAY_EN(delay_beg);
  342. if (enable)
  343. {
  344. reg_val |= FIOCTRL_DELAY_EN(delay_beg);
  345. }
  346. FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
  347. return;
  348. }