| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572 |
- /*
- * Copyright : (C) 2022 Phytium Information Technology, Inc.
- * All Rights Reserved.
- *
- * This program is OPEN SOURCE software: you can redistribute it and/or modify it
- * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
- * either version 1.0 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Phytium Public License for more details.
- *
- *
- * FilePath: fiopad_comm.c
- * Date: 2022-02-10 14:53:42
- * LastEditTime: 2022-02-18 08:25:29
- * Description: This files is for io-pad function definition
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ------ -------- --------------------------------------
- * 1.0 huanghe 2021/11/5 init commit
- * 1.1 zhugengyu 2022/3/21 adopt to lastest tech spec.
- */
- /***************************** Include Files *********************************/
- #include "fparameters.h"
- #include "fio.h"
- #include "fkernel.h"
- #include "fassert.h"
- #include "fdebug.h"
- #include "stdio.h"
- #include "fpinctrl.h"
- /************************** Constant Definitions *****************************/
- /** @name IO PAD Control Register
- */
- #define FIOPAD_X_REG0_BEG_OFFSET 0x0 /* 上下拉/驱动能力/复用功能配置 */
- #define FIOPAD_X_REG0_END_OFFSET 0x24c
- #define FIOPAD_X_REG1_BEG_OFFSET 0x1024 /* 输入/输出延时配置 */
- #define FIOPAD_X_REG1_END_OFFSET 0x124c
- /** @name X_reg0 Register
- */
- #define FIOPAD_X_REG0_PULL_MASK GENMASK(9, 8) /* 上下拉配置 */
- #define FIOPAD_X_REG0_PULL_GET(x) GET_REG32_BITS((x), 9, 8)
- #define FIOPAD_X_REG0_PULL_SET(x) SET_REG32_BITS((x), 9, 8)
- #define FIOPAD_X_REG0_DRIVE_MASK GENMASK(7, 4) /* 驱动能力配置 */
- #define FIOPAD_X_REG0_DRIVE_GET(x) GET_REG32_BITS((x), 7, 4)
- #define FIOPAD_X_REG0_DRIVE_SET(x) SET_REG32_BITS((x), 7, 4)
- #define FIOPAD_X_REG0_FUNC_MASK GENMASK(2, 0) /* 引脚复用配置 */
- #define FIOPAD_X_REG0_FUNC_GET(x) GET_REG32_BITS((x), 2, 0)
- #define FIOPAD_X_REG0_FUNC_SET(x) SET_REG32_BITS((x), 2, 0)
- /** @name X_reg1 Register
- */
- #define FIOPAD_X_REG1_OUT_DELAY_EN BIT(8)
- #define FIOPAD_X_REG1_OUT_DELAY_DELICATE_MASK GENMASK(11, 9)
- #define FIOPAD_X_REG1_OUT_DELAY_DELICATE_GET(x) GET_REG32_BITS((x), 11, 9) /* 延时精调 */
- #define FIOPAD_X_REG1_OUT_DELAY_DELICATE_SET(x) SET_REG32_BITS((x), 11, 9)
- #define FIOPAD_X_REG1_OUT_DELAY_ROUGH_MASK GENMASK(14, 12)
- #define FIOPAD_X_REG1_OUT_DELAY_ROUGH_GET(x) GET_REG32_BITS((x), 14, 12) /* 延时粗调 */
- #define FIOPAD_X_REG1_OUT_DELAY_ROUGH_SET(x) SET_REG32_BITS((x), 14, 12)
- #define FIOPAD_X_REG1_IN_DELAY_EN BIT(0)
- #define FIOPAD_X_REG1_IN_DELAY_DELICATE_MASK GENMASK(3, 1)
- #define FIOPAD_X_REG1_IN_DELAY_DELICATE_GET(x) GET_REG32_BITS((x), 3, 1) /* 延时精调 */
- #define FIOPAD_X_REG1_IN_DELAY_DELICATE_SET(x) SET_REG32_BITS((x), 3, 1)
- #define FIOPAD_X_REG1_IN_DELAY_ROUGH_MASK GENMASK(6, 4)
- #define FIOPAD_X_REG1_IN_DELAY_ROUGH_GET(x) GET_REG32_BITS((x), 6, 4) /* 延时粗调 */
- #define FIOPAD_X_REG1_IN_DELAY_ROUGH_SET(x) SET_REG32_BITS((x), 6, 4)
- #define FIOPAD_DELAY_MAX 15
- /**************************** Type Definitions *******************************/
- /***************** Macros (Inline Functions) Definitions *********************/
- static inline u32 FIOPadRead(FPinIndex pin)
- {
- return FtIn32(FIOPAD_BASE_ADDR + pin.reg_off);
- }
- static inline void FIOPadWrite(FPinIndex pin, u32 reg_val)
- {
- FtOut32(FIOPAD_BASE_ADDR + pin.reg_off, reg_val);
- return;
- }
- #define FIOPAD_ASSERT_REG0_OFF(pin) FASSERT_MSG((FIOPAD_X_REG0_END_OFFSET >= pin.reg_off), "invalid reg0 offset @0x%x\r\n", (pin.reg_off))
- #define FIOPAD_ASSERT_FUNC(func) FASSERT_MSG((func < FPIN_NUM_OF_FUNC), "invalid func as %d\r\n", (func))
- #define FIOPAD_ASSERT_PULL(pull) FASSERT_MSG((pull < FPIN_NUM_OF_PULL), "invalid pull as %d\r\n", (pull))
- #define FIOPAD_ASSERT_DRIVE(drive) FASSERT_MSG((drive < FPIN_NUM_OF_DRIVE), "invalid pull as %d\r\n", (drive))
- #define FIOPAD_ASSERT_REG1_OFF(pin) FASSERT_MSG(((FIOPAD_X_REG1_BEG_OFFSET <= pin.reg_off) && (FIOPAD_X_REG1_END_OFFSET >= pin.reg_off)), "invalid reg1 offset @0x%x\r\n", (pin.reg_off))
- #define FIOPAD_ASSERT_DELAY(delay) FASSERT_MSG((delay < FPIN_NUM_OF_DELAY), "invalid delay as %d\r\n", (delay))
- #define FIOPAD_DEBUG_TAG "FIOPAD"
- #define FIOPAD_ERROR(format, ...) FT_DEBUG_PRINT_E(FIOPAD_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FIOPAD_WARN(format, ...) FT_DEBUG_PRINT_W(FIOPAD_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FIOPAD_INFO(format, ...) FT_DEBUG_PRINT_I(FIOPAD_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FIOPAD_DEBUG(format, ...) FT_DEBUG_PRINT_D(FIOPAD_DEBUG_TAG, format, ##__VA_ARGS__)
- /************************** Function Prototypes ******************************/
- /**
- * @name: FPinGetFunc
- * @msg: 获取IO引脚当前的复用功能
- * @return {FPinFunc} 当前的复用功能
- * @param {FPinIndex} pin IO引脚索引
- * @note 参考编程手册,使用 FIOPAD_INDEX 宏定义index的值
- */
- FPinFunc FPinGetFunc(const FPinIndex pin)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- u32 func = FIOPAD_X_REG0_FUNC_GET(FIOPadRead(pin));
- FIOPAD_ASSERT_FUNC(func);
- return (FPinFunc)func;
- }
- /**
- * @name: FPinSetFunc
- * @msg: 设置IO引脚复用功能
- * @return {*}
- * @param {FPinIndex} pin IO引脚索引
- * @param {FPinFunc} func IO复用功能
- * @note 参考编程手册,使用 FIOPAD_INDEX 宏定义index的值
- */
- void FPinSetFunc(const FPinIndex pin, FPinFunc func)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- FIOPAD_ASSERT_FUNC(func);
- u32 reg_val = FIOPadRead(pin);
- u32 test_val = 0;
- reg_val &= ~FIOPAD_X_REG0_FUNC_MASK;
- reg_val |= FIOPAD_X_REG0_FUNC_SET(func);
- FIOPadWrite(pin, reg_val);
- test_val = FIOPadRead(pin);
- if (reg_val != test_val)
- {
- FIOPAD_ERROR("ERROR: FIOPad write is failed ,pin is %x\n, 0x%x != 0x%x",
- pin.reg_off, reg_val, test_val);
- }
- return;
- }
- /**
- * @name: FPinGetDrive
- * @msg: 获取IO引脚的驱动能力
- * @return {FPinDrive} 引脚的当前的驱动能力
- * @param {FPinIndex} pin IO引脚索引
- */
- FPinDrive FPinGetDrive(const FPinIndex pin)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- u32 drive = FIOPAD_X_REG0_DRIVE_GET(FIOPadRead(pin));
- FIOPAD_ASSERT_DRIVE(drive);
- return (FPinDrive)drive;
- }
- /**
- * @name: FPinSetDrive
- * @msg: 设置IO引脚的驱动能力
- * @return {*}
- * @param {FPinIndex} pin, IO引脚索引
- * @param {FPinDrive} drive, 引脚驱动能力设置
- */
- void FPinSetDrive(const FPinIndex pin, FPinDrive drive)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- FIOPAD_ASSERT_DRIVE(drive);
- u32 reg_val = FIOPadRead(pin);
- reg_val &= ~FIOPAD_X_REG0_DRIVE_MASK;
- reg_val |= FIOPAD_X_REG0_DRIVE_SET(drive);
- FIOPadWrite(pin, reg_val);
- return;
- }
- void FPinGetConfig(const FPinIndex pin, FPinFunc *func, FPinPull *pull, FPinDrive *drive)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- u32 reg_val = FIOPadRead(pin);
- if (func)
- {
- *func = FIOPAD_X_REG0_FUNC_GET(reg_val);
- }
- if (pull)
- {
- *pull = FIOPAD_X_REG0_PULL_GET(reg_val);
- }
- if (drive)
- {
- *pull = FIOPAD_X_REG0_DRIVE_GET(reg_val);
- }
- return;
- }
- void FPinSetConfig(const FPinIndex pin, FPinFunc func, FPinPull pull, FPinDrive drive)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- u32 reg_val = FIOPadRead(pin);
- reg_val &= ~FIOPAD_X_REG0_FUNC_MASK;
- reg_val |= FIOPAD_X_REG0_FUNC_SET(func);
- reg_val &= ~FIOPAD_X_REG0_PULL_MASK;
- reg_val |= FIOPAD_X_REG0_PULL_SET(pull);
- reg_val &= ~FIOPAD_X_REG0_DRIVE_MASK;
- reg_val |= FIOPAD_X_REG0_DRIVE_SET(drive);
- FIOPadWrite(pin, reg_val);
- return;
- }
- /**
- * @name: FPinGetPull
- * @msg: 获取IO引脚当前的上下拉设置
- * @return {*}
- * @param {FPinIndex} pin IO引脚索引
- * @note 参考编程手册,使用 FIOPAD_INDEX 宏定义index的值
- */
- FPinPull FPinGetPull(const FPinIndex pin)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- u32 pull = FIOPAD_X_REG0_PULL_GET(FIOPadRead(pin));
- FIOPAD_ASSERT_PULL(pull);
- return (FPinPull)pull;
- }
- /**
- * @name: FPinSetPull
- * @msg: 设置IO引脚当前的上下拉
- * @return {*}
- * @param {FPinIndex} pin IO引脚索引
- * @param {FPinPull} pull 上下拉设置
- */
- void FPinSetPull(const FPinIndex pin, FPinPull pull)
- {
- FIOPAD_ASSERT_REG0_OFF(pin);
- FIOPAD_ASSERT_PULL(pull);
- u32 reg_val = FIOPadRead(pin);
- reg_val &= ~FIOPAD_X_REG0_PULL_MASK;
- reg_val |= FIOPAD_X_REG0_PULL_SET(pull);
- FIOPadWrite(pin, reg_val);
- return;
- }
- /**
- * @name: FPinGetDelay
- * @msg: 获取IO引脚当前的延时设置
- * @return {FPinDelay} 当前的延时设置
- * @param {FPinIndex} pin IO引脚延时设置索引
- * @param {FPinDelayDir} dir 输入/输出延时
- * @param {FPinDelayType} type 精调/粗调延时
- */
- FPinDelay FPinGetDelay(const FPinIndex pin, FPinDelayDir dir, FPinDelayType type)
- {
- FIOPAD_ASSERT_REG1_OFF(pin);
- const u32 reg_val = FIOPadRead(pin);
- u8 delay = 0;
- if (FPIN_OUTPUT_DELAY == dir)
- {
- if (FPIN_DELAY_FINE_TUNING == type)
- {
- delay = FIOPAD_X_REG1_OUT_DELAY_DELICATE_GET(reg_val);
- }
- else if (FPIN_DELAY_COARSE_TUNING == type)
- {
- delay = FIOPAD_X_REG1_OUT_DELAY_ROUGH_GET(reg_val);
- }
- else
- {
- FASSERT(0);
- }
- }
- else if (FPIN_INPUT_DELAY == dir)
- {
- if (FPIN_DELAY_FINE_TUNING == type)
- {
- delay = FIOPAD_X_REG1_IN_DELAY_DELICATE_GET(reg_val);
- }
- else if (FPIN_DELAY_COARSE_TUNING == type)
- {
- delay = FIOPAD_X_REG1_IN_DELAY_ROUGH_GET(reg_val);
- }
- else
- {
- FASSERT(0);
- }
- }
- else
- {
- FASSERT(0);
- }
- FIOPAD_ASSERT_DELAY(delay);
- return (FPinDelay)delay;
- }
- /**
- * @name: FPinGetDelayEn
- * @msg: 获取IO引脚当前的延时使能标志位
- * @return {*}
- * @param {FPinIndex} pin IO引脚延时设置索引
- * @param {FPinDelayDir} dir 输入/输出延时
- */
- boolean FPinGetDelayEn(const FPinIndex pin, FPinDelayDir dir)
- {
- FIOPAD_ASSERT_REG1_OFF(pin);
- const u32 reg_val = FIOPadRead(pin);
- boolean enabled = FALSE;
- if (FPIN_OUTPUT_DELAY == dir)
- {
- if (FIOPAD_X_REG1_OUT_DELAY_EN & reg_val)
- enabled = TRUE;
- else
- enabled = FALSE;
- }
- else if (FPIN_INPUT_DELAY == dir)
- {
- if (FIOPAD_X_REG1_IN_DELAY_EN & reg_val)
- enabled = TRUE;
- else
- enabled = FALSE;
- }
- else
- {
- FASSERT(0);
- }
- return enabled;
- }
- /**
- * @name: FPinSetDelay
- * @msg: 设置IO引脚延时
- * @return {*}
- * @param {FPinIndex} pin IO引脚延时设置索引
- * @param {FPinDelayDir} dir 输入/输出延时
- * @param {FPinDelayType} type 精调/粗调延时
- * @param {FPinDelay} delay 延时设置
- */
- void FPinSetDelay(const FPinIndex pin, FPinDelayDir dir, FPinDelayType type, FPinDelay delay)
- {
- FIOPAD_ASSERT_REG1_OFF(pin);
- FIOPAD_ASSERT_DELAY(delay);
- u32 reg_val = FIOPadRead(pin);
- if (FPIN_OUTPUT_DELAY == dir)
- {
- if (FPIN_DELAY_FINE_TUNING == type)
- {
- reg_val &= ~FIOPAD_X_REG1_OUT_DELAY_DELICATE_MASK;
- reg_val |= FIOPAD_X_REG1_OUT_DELAY_DELICATE_SET(delay);
- }
- else if (FPIN_DELAY_COARSE_TUNING == type)
- {
- reg_val &= ~FIOPAD_X_REG1_OUT_DELAY_ROUGH_MASK;
- reg_val |= FIOPAD_X_REG1_OUT_DELAY_ROUGH_SET(delay);
- }
- else
- {
- FASSERT(0);
- }
- }
- else if (FPIN_INPUT_DELAY == dir)
- {
- if (FPIN_DELAY_FINE_TUNING == type)
- {
- reg_val &= ~FIOPAD_X_REG1_IN_DELAY_DELICATE_MASK;
- reg_val |= FIOPAD_X_REG1_IN_DELAY_DELICATE_SET(delay);
- }
- else if (FPIN_DELAY_COARSE_TUNING == type)
- {
- reg_val &= ~FIOPAD_X_REG1_IN_DELAY_ROUGH_MASK;
- reg_val |= FIOPAD_X_REG1_IN_DELAY_ROUGH_SET(delay);
- }
- else
- {
- FASSERT(0);
- }
- }
- else
- {
- FASSERT(0);
- }
- FIOPadWrite(pin, reg_val);
- return;
- }
- /**
- * @name: FPinSetDelayEn
- * @msg: 使能/去使能IO引脚延时
- * @return {*}
- * @param {FPinIndex} pin IO引脚延时设置索引
- * @param {FPinDelayDir} dir 输入/输出延时
- * @param {boolean} enable TRUE: 使能, FALSE: 去使能
- */
- void FPinSetDelayEn(const FPinIndex pin, FPinDelayDir dir, boolean enable)
- {
- FIOPAD_ASSERT_REG1_OFF(pin);
- u32 reg_val = FIOPadRead(pin);
- if (FPIN_OUTPUT_DELAY == dir)
- {
- if (enable)
- reg_val |= FIOPAD_X_REG1_OUT_DELAY_EN;
- else
- reg_val &= ~FIOPAD_X_REG1_OUT_DELAY_EN;
- }
- else if (FPIN_INPUT_DELAY == dir)
- {
- if (enable)
- reg_val |= FIOPAD_X_REG1_IN_DELAY_EN;
- else
- reg_val &= ~FIOPAD_X_REG1_IN_DELAY_EN;
- }
- else
- {
- FASSERT(0);
- }
- FIOPadWrite(pin, reg_val);
- return;
- }
- /**
- * @name: FPinSetDelayConfig
- * @msg: Update and enable common IO pin delay config
- * @return {NONE}
- * @param {FPinIndex} pin, IO pin index
- * @param {FPinDelayIOType} in_out_type, Select the input and output types ,
- * @param {FPinDelay} roungh_delay, delay rough setting
- * @param {FPinDelay} delicate_delay, delay delicate setting
- * @param {boolean} enable, enable delay
- */
- void FPinSetDelayConfig(const FPinIndex pin, FPinDelayIOType in_out_type, FPinDelay roungh_delay, FPinDelay delicate_delay, boolean enable)
- {
- FIOPAD_ASSERT_REG1_OFF(pin);
- u32 reg_val = FIOPadRead(pin);
- if (in_out_type == FPIN_DELAY_IN_TYPE)
- {
- reg_val = FIOPadRead(pin);
- /* update delicate input delay */
- reg_val &= ~FIOPAD_X_REG1_IN_DELAY_DELICATE_MASK;
- reg_val |= FIOPAD_X_REG1_IN_DELAY_DELICATE_SET(delicate_delay);
- /* update rough input delay */
- reg_val &= ~FIOPAD_X_REG1_IN_DELAY_ROUGH_MASK;
- reg_val |= FIOPAD_X_REG1_IN_DELAY_ROUGH_SET(roungh_delay);
- /* enable input delay */
- if (enable)
- {
- reg_val |= FIOPAD_X_REG1_IN_DELAY_EN;
- }
- else
- {
- reg_val &= ~FIOPAD_X_REG1_IN_DELAY_EN;
- }
- }
- else
- {
- /* update delicate output delay */
- reg_val &= ~FIOPAD_X_REG1_OUT_DELAY_DELICATE_MASK;
- reg_val |= FIOPAD_X_REG1_OUT_DELAY_DELICATE_SET(delicate_delay);
- /* update rough output delay */
- reg_val &= ~FIOPAD_X_REG1_OUT_DELAY_ROUGH_MASK;
- reg_val |= FIOPAD_X_REG1_OUT_DELAY_ROUGH_SET(roungh_delay);
- /* enable output delay */
- if (enable)
- {
- reg_val |= FIOPAD_X_REG1_OUT_DELAY_EN;
- }
- else
- {
- reg_val &= ~FIOPAD_X_REG1_OUT_DELAY_EN;
- }
- }
- FIOPadWrite(pin, reg_val);
- return;
- }
- /**
- * @name: FPinGetDelayConfig
- * @msg: Get current common IO pin delay config
- * @return {NONE}
- * @param {FPinIndex} pin, IO pin index
- * @param {FPinDelay} *in_roungh_delay, input delay rough setting (输入粗调)
- * @param {FPinDelay} *in_delicate_delay, input delay delicate setting (输入精调)
- * @param {FPinDelay} *out_roungh_delay, output delay rough setting (输出粗调)
- * @param {FPinDelay} *out_delicate_delay, output delay delicate setting (输出精调)
- */
- void FPinGetDelayConfig(const FPinIndex pin, FPinDelay *in_roungh_delay, FPinDelay *in_delicate_delay,
- FPinDelay *out_roungh_delay, FPinDelay *out_delicate_delay)
- {
- FIOPAD_ASSERT_REG1_OFF(pin);
- u32 reg_val = FIOPadRead(pin);
- if (out_delicate_delay)
- {
- *out_delicate_delay = FIOPAD_X_REG1_OUT_DELAY_DELICATE_GET(reg_val);
- }
- if (out_roungh_delay)
- {
- *out_roungh_delay = FIOPAD_X_REG1_OUT_DELAY_ROUGH_GET(reg_val);
- }
- if (in_delicate_delay)
- {
- *in_delicate_delay = FIOPAD_X_REG1_IN_DELAY_DELICATE_GET(reg_val);
- }
- if (in_roungh_delay)
- {
- *in_roungh_delay = FIOPAD_X_REG1_IN_DELAY_ROUGH_GET(reg_val);
- }
- return;
- }
- /**
- * @name: FIOPadDumpPadFunc
- * @msg: print information of all iopad
- * @return {*}
- */
- void FIOPadDumpPadFunc(void)
- {
- uintptr beg_off = FIOPAD_0_FUNC_OFFSET;
- uintptr end_off = FIOPAD_147_FUNC_OFFSET;
- uintptr off;
- FPinIndex pin;
- const char *pull_state[FPIN_NUM_OF_PULL] = {"none", "down", "up"};
- FIOPAD_DEBUG("Pad Func Info...");
- for (off = beg_off; off <= end_off; off += 4U)
- {
- pin.reg_off = off;
- FIOPAD_DEBUG(" [0x%x] func: %d, ds: %d, pull: %s ",
- pin.reg_off,
- FPinGetFunc(pin),
- FPinGetDrive(pin),
- pull_state[FPinGetPull(pin)]);
- }
- }
|