rt-thread/bsp/phytium/libraries/standalone/board/ft2004/fioctrl.c

348 lines
11 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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: fioctrl.c
* Date: 2022-02-10 14:53:42
* LastEditTime: 2022-02-18 08:25:29
* Description:  This files is for io-ctrl function implementation (io-mux/io-config/io-delay)
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 zhugengyu 2022/2/22 init commit
*/
/***************************** Include Files *********************************/
#include "fparameters.h"
#include "fio.h"
#include "fkernel.h"
#include "fassert.h"
#include "fdebug.h"
#include "fioctrl.h"
#include "fpinctrl.h"
/************************** Constant Definitions *****************************/
/* Bit[0] : 输入延迟功能使能 */
#define FIOCTRL_DELAY_EN(delay_beg) BIT(delay_beg)
#define FIOCTRL_INPUT_DELAY_OFF 0
/* Bit[3:1] : 输入延迟精调档位选择 */
#define FIOCTRL_DELICATE_DELAY_MASK(delay_beg) GENMASK((delay_beg + 3), (delay_beg + 1))
#define FIOCTRL_DELICATE_DELAY_GET(reg_val, delay_beg) GET_REG32_BITS((reg_val), (delay_beg + 3), (delay_beg + 1))
#define FIOCTRL_DELICATE_DELAY_SET(val, delay_beg) SET_REG32_BITS((val), (delay_beg + 3), (delay_beg + 1))
/* Bit[6:4] : 输入延迟粗调档位选择 */
#define FIOCTRL_ROUGH_DELAY_MASK(delay_beg) GENMASK((delay_beg + 6), (delay_beg + 4))
#define FIOCTRL_ROUGH_DELAY_GET(reg_val, delay_beg) GET_REG32_BITS((reg_val), (delay_beg + 6), (delay_beg + 4))
#define FIOCTRL_ROUGH_DELAY_SET(val, delay_beg) SET_REG32_BITS((val), (delay_beg + 6), (delay_beg + 4))
/* Bit[7] : 保留 */
/* Bit[8] : 输出延迟功能使能 */
/* Bit[11:9] : 输出延迟精调档位选择 */
/* Bit [14:12] : 输出延迟粗调档位选择 */
/* Bit [15] : 保留 */
#define FIOCTRL_FUNC_BEG_OFF(reg_bit) ((reg_bit) + 0)
#define FIOCTRL_FUNC_END_OFF(reg_bit) ((reg_bit) + 1) /* bit[1:0] 复用功能占2个位 */
#define FIOCTRL_PULL_BEG_OFF(reg_bit) ((reg_bit) + 2)
#define FIOCTRL_PULL_END_OFF(reg_bit) ((reg_bit) + 3) /* bit[3:2] 上下拉功能占2个位 */
#define FIOCTRL_DELAY_IN_BEG_OFF(reg_bit) ((reg_bit) + 0)
#define FIOCTRL_DELAY_IN_END_OFF(reg_bit) ((reg_bit) + 7) /* bit[8:1] 输入延时占7个位 */
#define FIOCTRL_DELAY_OUT_BEG_OFF(reg_bit) ((reg_bit) + 8)
#define FIOCTRL_DELAY_OUT_END_OFF(reg_bit) ((reg_bit) + 15) /* bit[15:9] 输出延时占7个位 */
/* 芯片引脚控制寄存器的起止位置 */
#define FIOCTRL_REG_OFFSET_MIN 0x200
#define FIOCTRL_REG_OFFSET_MAX 0x22c
/* 芯片引脚延时寄存器的起止位置 */
#define FIOCTRL_DELAY_REG_OFFSET_MIN 0x400
#define FIOCTRL_DELAY_REG_OFFSET_MAX 0x404
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define FIOCTRL_DEBUG_TAG "FIOCTRL"
#define FIOCTRL_ERROR(format, ...) FT_DEBUG_PRINT_E(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FIOCTRL_WARN(format, ...) FT_DEBUG_PRINT_W(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FIOCTRL_INFO(format, ...) FT_DEBUG_PRINT_I(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#define FIOCTRL_DEBUG(format, ...) FT_DEBUG_PRINT_D(FIOCTRL_DEBUG_TAG, format, ##__VA_ARGS__)
#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))
#define FIOCTRL_ASSERT_FUNC(func) FASSERT_MSG((func < FPIN_NUM_OF_FUNC), "invalid func as %d", (func))
#define FIOCTRL_ASSERT_PULL(pull) FASSERT_MSG((pull < FPIN_NUM_OF_PULL), "invalid pull as %d", (pull))
#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))
#define FIOCTRL_ASSERT_DELAY(delay) FASSERT_MSG(((delay) < FPIN_NUM_OF_DELAY), "invalid delay as %d", (delay));
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
* @name: FPinGetFunc
* @msg: 获取IO引脚当前的复用功能
* @return {FPinFunc} 当前的复用功能
* @param {FPinIndex} pin IO引脚索引
* @note 参考编程手册,使用 FIOCTRL_INDEX 宏定义index的值
*/
FPinFunc FPinGetFunc(const FPinIndex pin)
{
FIOCTRL_ASSERT_REG_OFF(pin);
u32 func_beg = FIOCTRL_FUNC_BEG_OFF(pin.reg_bit);
u32 func_end = FIOCTRL_FUNC_END_OFF(pin.reg_bit);
u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
u32 func = GET_REG32_BITS(reg_val, func_end, func_beg);
FIOCTRL_ASSERT_FUNC(func);
return (FPinFunc)GET_REG32_BITS(reg_val, func_end, func_beg);
}
/**
* @name: FPinSetFunc
* @msg: 设置IO引脚复用功能
* @return {*}
* @param {FPinIndex} pin IO引脚索引
* @param {FPinFunc} func IO复用功能
* @note 参考编程手册,使用 FIOCTRL_INDEX 宏定义index的值
*/
void FPinSetFunc(const FPinIndex pin, FPinFunc func)
{
FIOCTRL_ASSERT_REG_OFF(pin);
FIOCTRL_ASSERT_FUNC(func);
u32 func_beg = FIOCTRL_FUNC_BEG_OFF(pin.reg_bit);
u32 func_end = FIOCTRL_FUNC_END_OFF(pin.reg_bit);
u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
reg_val &= ~GENMASK(func_end, func_beg);
reg_val |= SET_REG32_BITS(func, func_end, func_beg);
FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
return;
}
/**
* @name: FPinGetPull
* @msg: 获取IO引脚当前的上下拉设置
* @return {*}
* @param {FPinIndex} pin IO引脚索引
* @note 参考编程手册,使用 FIOCTRL_INDEX 宏定义index的值
*/
FPinPull FPinGetPull(const FPinIndex pin)
{
FIOCTRL_ASSERT_REG_OFF(pin);
u32 pull_beg = FIOCTRL_PULL_BEG_OFF(pin.reg_bit);
u32 pull_end = FIOCTRL_PULL_END_OFF(pin.reg_bit);
u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
u32 pull = GET_REG32_BITS(reg_val, pull_end, pull_beg);
FIOCTRL_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)
{
FIOCTRL_ASSERT_REG_OFF(pin);
FIOCTRL_ASSERT_PULL(pull);
u32 pull_beg = FIOCTRL_PULL_BEG_OFF(pin.reg_bit);
u32 pull_end = FIOCTRL_PULL_END_OFF(pin.reg_bit);
u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
reg_val &= ~GENMASK(pull_end, pull_beg);
reg_val |= SET_REG32_BITS(pull, pull_end, pull_beg);
FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, 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)
{
FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
u8 delay = 0;
const u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
u32 delay_beg = 0, delay_end = 0;
if (FPIN_OUTPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
}
else if (FPIN_INPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
}
else
{
FASSERT(0);
}
if (FPIN_DELAY_FINE_TUNING == type)
{
delay = FIOCTRL_DELICATE_DELAY_GET(reg_val, delay_beg); /* bit[3:1] delicate delay tune */
}
else if (FPIN_DELAY_COARSE_TUNING == type)
{
delay = FIOCTRL_ROUGH_DELAY_GET(reg_val, delay_beg); /* bit[6:4] rough delay adjust */
}
else
{
FASSERT(0);
}
FIOCTRL_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)
{
FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
boolean enabled = FALSE;
const u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
u32 delay_beg = 0, delay_end = 0;
if (FPIN_OUTPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
}
else if (FPIN_INPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
}
else
{
FASSERT(0);
}
if (FIOCTRL_DELAY_EN(delay_beg) & reg_val)
{
enabled = TRUE;
}
return enabled;
}
/**
* @name: FPinSetDelay
* @msg: 设置IO引脚延时
* @return {*}
* @param {FPinIndex} pin IO引脚延时设置索引
* @param {FPinDelayDir} dir 输入/输出延时
* @param {FPinDelayType} type 精调/粗调延时
* @param {FPinDelay} delay 延时档位设置 0 ~ 8 档可用
*/
void FPinSetDelay(const FPinIndex pin, FPinDelayDir dir, FPinDelayType type, FPinDelay delay)
{
FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
FIOCTRL_ASSERT_DELAY(delay);
u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
u32 delay_beg = 0, delay_end = 0;
if (FPIN_OUTPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
}
else if (FPIN_INPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
}
else
{
FASSERT(0);
}
if (FPIN_DELAY_FINE_TUNING == type)
{
reg_val &= ~FIOCTRL_DELICATE_DELAY_MASK(delay_beg);
delay = FIOCTRL_DELICATE_DELAY_GET(reg_val, delay_beg);
}
else if (FPIN_DELAY_COARSE_TUNING == type)
{
reg_val &= ~FIOCTRL_ROUGH_DELAY_MASK(delay_beg);
delay = FIOCTRL_ROUGH_DELAY_GET(reg_val, delay_beg);
}
else
{
FASSERT(0);
}
FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, 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)
{
FIOCTRL_ASSERT_DELAY_REG_OFF(pin);
u32 reg_val = FtIn32(FIOCTRL_REG_BASE_ADDR + pin.reg_off);
u32 delay_beg = 0, delay_end = 0;
if (FPIN_OUTPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_OUT_BEG_OFF(pin.reg_off);
}
else if (FPIN_INPUT_DELAY == dir)
{
delay_beg = FIOCTRL_DELAY_IN_BEG_OFF(pin.reg_off);
}
else
{
FASSERT(0);
}
reg_val &= ~FIOCTRL_DELAY_EN(delay_beg);
if (enable)
{
reg_val |= FIOCTRL_DELAY_EN(delay_beg);
}
FtOut32(FIOCTRL_REG_BASE_ADDR + pin.reg_off, reg_val);
return;
}