346 lines
9.0 KiB
C
346 lines
9.0 KiB
C
/*
|
||
* 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: fspim_hw.c
|
||
* Date: 2022-02-10 14:53:42
|
||
* LastEditTime: 2022-02-18 09:08:00
|
||
* Description: This file is for providing spim Hardware interaction func.
|
||
*
|
||
* Modify History:
|
||
* Ver Who Date Changes
|
||
* ----- ------ -------- --------------------------------------
|
||
* 1.0 zhugengyu 2021/12/3 init commit
|
||
* 1.1 zhugengyu 2022/4/15 support test mode
|
||
* 1.2 liqiaozhong 2023/1/4 add data get func
|
||
*/
|
||
|
||
|
||
#include "fassert.h"
|
||
#include "fdebug.h"
|
||
#include "fspim_hw.h"
|
||
#include "fspim.h"
|
||
|
||
/***************************** Include Files *********************************/
|
||
|
||
/************************** Constant Definitions *****************************/
|
||
|
||
/**************************** Type Definitions *******************************/
|
||
|
||
/************************** Variable Definitions *****************************/
|
||
|
||
/***************** Macros (Inline Functions) Definitions *********************/
|
||
#define FSPIM_DEBUG_TAG "SPIM-HW"
|
||
#define FSPIM_ERROR(format, ...) FT_DEBUG_PRINT_E(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
|
||
#define FSPIM_WARN(format, ...) FT_DEBUG_PRINT_W(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
|
||
#define FSPIM_INFO(format, ...) FT_DEBUG_PRINT_I(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
|
||
#define FSPIM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__)
|
||
|
||
/************************** Function Prototypes ******************************/
|
||
|
||
/**
|
||
* @name: FSpimGetTxFifoDepth
|
||
* @msg: 获取TX Fifo可以设置的最大深度
|
||
* @return {u32} TX Fifo的深度
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
*/
|
||
u32 FSpimGetTxFifoDepth(uintptr base_addr)
|
||
{
|
||
u32 fifo_depth;
|
||
for (fifo_depth = 1; fifo_depth < FSPIM_MAX_FIFO_DEPTH; fifo_depth++)
|
||
{
|
||
FSpimSetTxFifoThreshold(base_addr, fifo_depth);
|
||
if (fifo_depth != FSpimGetTxFifoThreshold(base_addr))
|
||
{
|
||
FSPIM_INFO("The Tx fifo threshold is %d", fifo_depth);
|
||
break;
|
||
}
|
||
}
|
||
|
||
FSpimSetTxFifoThreshold(base_addr, 0);
|
||
return fifo_depth;
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimGetRxFifoDepth
|
||
* @msg: 获取RX Fifo可以设置的最大深度
|
||
* @return {u32} Rx Fifo的深度
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
*/
|
||
u32 FSpimGetRxFifoDepth(uintptr base_addr)
|
||
{
|
||
u32 fifo_depth = FSPIM_MIN_FIFO_DEPTH;
|
||
while (FSPIM_MAX_FIFO_DEPTH >= fifo_depth)
|
||
{
|
||
FSpimSetRxFifoThreshold(base_addr, fifo_depth);
|
||
if (fifo_depth != FSpimGetRxFifoThreshold(base_addr))
|
||
{
|
||
FSPIM_INFO("The Rx fifo threshold is %d", fifo_depth);
|
||
break;
|
||
}
|
||
|
||
fifo_depth++;
|
||
}
|
||
|
||
return fifo_depth;
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimSelSlaveDev
|
||
* @msg: 选择SPI从设备
|
||
* @return {无}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {u32} slave_dev_id, 从设备ID
|
||
*/
|
||
void FSpimSelSlaveDev(uintptr base_addr, u32 slave_dev_id)
|
||
{
|
||
FASSERT(slave_dev_id < FSPIM_NUM_OF_SLAVE_DEV);
|
||
u32 reg_val;
|
||
|
||
reg_val = (FSPIM_SER_SELECT << slave_dev_id);
|
||
FSPIM_WRITE_REG32(base_addr, FSPIM_SER_OFFSET, reg_val);
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimSetSpeed
|
||
* @msg: 设置SPI传输速度
|
||
* @return {FError}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {u32} speed, SPI传输速度设置
|
||
*/
|
||
FError FSpimSetSpeed(uintptr base_addr, u32 speed)
|
||
{
|
||
FASSERT(speed != 0);
|
||
u32 clk_div;
|
||
boolean enabled = FSpimGetEnable(base_addr);
|
||
|
||
if (enabled)
|
||
{
|
||
FSpimSetEnable(base_addr, FALSE);
|
||
}
|
||
|
||
clk_div = FSPI_CLK_FREQ_HZ / speed;
|
||
if (clk_div < FSPIM_BAUD_R_SCKDV_MIN || clk_div > FSPIM_BAUD_R_SCKDV_MAX)
|
||
{
|
||
FSPIM_ERROR("Clk div is %d => do not support, this parameter should be set as an even from 2 to 65534.", clk_div);
|
||
return FSPIM_ERR_NOT_SUPPORT;
|
||
}
|
||
FSPIM_INFO("Set clk div as %d", clk_div);
|
||
FSPIM_WRITE_REG32(base_addr, FSPIM_BAUD_R_OFFSET, clk_div);
|
||
|
||
if (enabled)
|
||
{
|
||
FSpimSetEnable(base_addr, TRUE);
|
||
}
|
||
|
||
return FSPIM_SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimGetSpeed
|
||
* @msg: 获取SPI传输速度
|
||
* @return {u32}FSPIM传输频率
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {u32} speed, SPI传输速度设置
|
||
*/
|
||
u32 FSpimGetSpeed(uintptr base_addr)
|
||
{
|
||
u32 clk_div;
|
||
u32 spim_speed;
|
||
|
||
return FSPIM_READ_REG32(base_addr, FSPIM_BAUD_R_OFFSET);
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimSetTransMode
|
||
* @msg: 设置SPI传输模式
|
||
* @return {无}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {u32} trans_mode, SPI传输模式设置
|
||
*/
|
||
void FSpimSetTransMode(uintptr base_addr, u32 trans_mode)
|
||
{
|
||
FASSERT(trans_mode < FSPIM_TRANS_MODE_MAX);
|
||
u32 reg_val;
|
||
boolean enabled = FSpimGetEnable(base_addr);
|
||
|
||
if (enabled)
|
||
{
|
||
FSpimSetEnable(base_addr, FALSE);
|
||
}
|
||
|
||
reg_val = FSpimGetCtrlR0(base_addr);
|
||
reg_val &= ~FSPIM_CTRL_R0_TMOD_MASK; /* clear trans mode bits */
|
||
switch (trans_mode)
|
||
{
|
||
case FSPIM_TRANS_MODE_RX_TX:
|
||
reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_TX);
|
||
break;
|
||
case FSPIM_TRANS_MODE_TX_ONLY:
|
||
reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_TX_ONLY);
|
||
break;
|
||
case FSPIM_TRANS_MODE_RX_ONLY:
|
||
reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RX_ONLY);
|
||
break;
|
||
case FSPIM_TRANS_MODE_READ_EEPROM:
|
||
reg_val |= FSPIM_CTRL_R0_TMOD(FSPIM_TMOD_RD_EEPROM);
|
||
break;
|
||
default:
|
||
FASSERT(0);
|
||
break;
|
||
}
|
||
|
||
FSpimSetCtrlR0(base_addr, reg_val);
|
||
|
||
if (enabled)
|
||
{
|
||
FSpimSetEnable(base_addr, TRUE);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimSetCpha
|
||
* @msg: 设置串行时钟相位
|
||
* @return {无}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {u32} cpha_mode, SPI控制器的相位设置
|
||
*/
|
||
void FSpimSetCpha(uintptr base_addr, u32 cpha_mode)
|
||
{
|
||
u32 reg_val = FSpimGetCtrlR0(base_addr);
|
||
|
||
reg_val &= ~FSPIM_CTRL_R0_SCPHA_MASK; /* clear bits */
|
||
if (FSPIM_CPHA_1_EDGE == cpha_mode)
|
||
{
|
||
reg_val |= FSPIM_CTRL_R0_SCPHA(FSPIM_SCPHA_SWITCH_DATA_MID);
|
||
}
|
||
else if (FSPIM_CPHA_2_EDGE == cpha_mode)
|
||
{
|
||
reg_val |= FSPIM_CTRL_R0_SCPHA(FSPIM_SCPHA_SWITCH_DATA_BEG);
|
||
}
|
||
else
|
||
{
|
||
FASSERT(0);
|
||
}
|
||
|
||
FSpimSetCtrlR0(base_addr, reg_val);
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimGetCpha
|
||
* @msg: 获取串行时钟相位
|
||
* @return {FSpimCphaType}串行时钟相位
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
*/
|
||
FSpimCphaType FSpimGetCpha(uintptr base_addr)
|
||
{
|
||
u32 reg_val = FSpimGetCtrlR0(base_addr);
|
||
|
||
if (reg_val &= FSPIM_CTRL_R0_SCPHA(FSPIM_SCPHA_SWITCH_DATA_BEG))
|
||
{
|
||
return FSPIM_CPHA_2_EDGE;
|
||
}
|
||
else
|
||
{
|
||
return FSPIM_CPHA_1_EDGE;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimSetCpol
|
||
* @msg: 设置串行时钟极性
|
||
* @return {无}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {u32} cpol_mode, SPI控制器的极性设置
|
||
*/
|
||
void FSpimSetCpol(uintptr base_addr, u32 cpol_mode)
|
||
{
|
||
u32 reg_val = FSpimGetCtrlR0(base_addr);
|
||
|
||
reg_val &= ~FSPIM_CTRL_R0_SCPOL_MASK; /* clear bits */
|
||
if (FSPIM_CPOL_LOW == cpol_mode)
|
||
{
|
||
reg_val |= FSPIM_CTRL_R0_SCPOL(FSPIM_SCPOL_INACTIVE_LOW);
|
||
}
|
||
else if (FSPIM_CPOL_HIGH == cpol_mode)
|
||
{
|
||
reg_val |= FSPIM_CTRL_R0_SCPOL(FSPIM_SCPOL_INACTIVE_HIGH);
|
||
}
|
||
else
|
||
{
|
||
FASSERT(0);
|
||
}
|
||
|
||
FSpimSetCtrlR0(base_addr, reg_val);
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimGetCpol
|
||
* @msg: 获取串行时钟极性
|
||
* @return {无}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
*/
|
||
FSpimCpolType FSpimGetCpol(uintptr base_addr)
|
||
{
|
||
u32 reg_val = FSpimGetCtrlR0(base_addr);
|
||
|
||
if (reg_val &= FSPIM_CTRL_R0_SCPOL(FSPIM_SCPOL_INACTIVE_HIGH))
|
||
{
|
||
return FSPIM_CPOL_HIGH;
|
||
}
|
||
else
|
||
{
|
||
return FSPIM_CPOL_LOW;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @name: FSpimSetSlaveEnable
|
||
* @msg: 使能/去使能和从设备的连接
|
||
* @return {无}
|
||
* @param {uintptr} base_addr, SPI控制器基地址
|
||
* @param {boolean} enable, TRUE: 使能从设备, FALSE: 去使能从设备
|
||
*/
|
||
void FSpimSetSlaveEnable(uintptr base_addr, boolean enable)
|
||
{
|
||
u32 reg_val;
|
||
boolean enabled = FSpimGetEnable(base_addr);
|
||
|
||
if (enabled)
|
||
{
|
||
FSpimSetEnable(base_addr, FALSE);
|
||
}
|
||
|
||
reg_val = FSpimGetCtrlR0(base_addr);
|
||
|
||
reg_val &= ~FSPIM_CTRL_R0_SLV_OE_MASK;
|
||
if (enable)
|
||
{
|
||
reg_val |= FSPIM_CTRL_R0_SLV_OE(FSPIM_SLAVE_TX_ENABLE);
|
||
}
|
||
else
|
||
{
|
||
reg_val |= FSPIM_CTRL_R0_SLV_OE(FSPIM_SLAVE_TX_DISALE);
|
||
}
|
||
|
||
FSpimSetCtrlR0(base_addr, reg_val);
|
||
|
||
if (enabled)
|
||
{
|
||
FSpimSetEnable(base_addr, TRUE);
|
||
}
|
||
|
||
return;
|
||
} |