256 lines
7.2 KiB
C
256 lines
7.2 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 files is for
|
|||
|
*
|
|||
|
* Modify History:
|
|||
|
* Ver Who Date Changes
|
|||
|
* ----- ------ -------- --------------------------------------
|
|||
|
* 1.0 zhugengyu 2021-12-3 init commit
|
|||
|
* 1.1 zhugengyu 2022-4-15 support test mode
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
#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("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("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)
|
|||
|
{
|
|||
|
u32 clk_div;
|
|||
|
boolean enabled = FSpimGetEnable(base_addr);
|
|||
|
|
|||
|
if (enabled)
|
|||
|
FSpimSetEnable(base_addr, FALSE);
|
|||
|
|
|||
|
clk_div = FSPI_FREQ / speed;
|
|||
|
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: 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: 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: 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;
|
|||
|
}
|