Zynq-Linux移植学习笔记之35-BroadCom 5396 Port-Based VLAN破环
1、背景介绍
在使用带有BCM5396交换芯片的板卡时,若存在多个模块含有5396的情况,容易导致出现网络中常见的成环现象,表现为网络异常。下图为一个成环的示意图:
上图中,板1和板2上面均含有一片5396,这两片5396都有Port与背板网络总线相连,很显然,此时两片5396之间网络是相通的,用红色线条表示。当机箱再插入一个模块后,两片5396又都与该模块网络相通,分别用紫色和蓝色线条表示。三条线组成在一起,就形成了一个环。
2、硬件相关资料介绍
查看BCM5396 datasheet能够发现,该芯片支持VLAN形式的虚网划分,从而实现破环功能。
比较容易实现的是基于PORT 的VLAN,最终验证也是这种方法比较可靠。
至于BCM5396中支持的生成树,过于复杂也未考虑。
下面是基于PORT的VLAN划分需要操作的控制寄存器,总共17个port,
3、实现原理
Port-Base VLAN功能是5396提供的一个类似VLAN的功能,主要通过设置5396端口的进出映射使能来决定包转发与否,具体原理如下:
基于端口的VLAN会将各个交换端口分成多个虚拟的私有域,如果数据不适于该私有域,则不被允许转发至该端口所属的私有域。
基于端口的VLAN可以理解为一个过滤器,用于过滤掉流向非私有域的数据流。对于每一个接收的报文,5396会先解析该报文的DA(目的地址),根据ARL(地址解析逻辑表)获得一个端口向量,该向量由该数据包应转发的目的端口集合组成。然后,ARL使用VLAN过滤器来进一步处理之前获得的端口向量,只有端口向量中处于同一私有域的目的端口,该包才允许被转发出去。具体流程如下:
4、实现过程
根据datasheet描述,需要先完成对模块5396端口拓扑结构进行测试确认,设计VLAN的验证方案,再根据VLAN Base过滤器的功能,完成对应端口的配置。
查看5396端口状态可以在uboot中增加对5396端口的0x20寄存器打印,若该值为0x97,则表明该端口已经启用。具体见下图:
以下用一个例子加以说明:
如上图所示,两块5396都通过port5与3槽的某板相连,port6与4槽另一块板相连,port8连接本板zynq,port9连接PHY外接copper出。同时5396之间通过port10互连,图中蓝色标注线条已成环。
在5396正常启动情况下,默认各端口的Port VLAN Base寄存器为0x1ffff,即所有端口均能与其余端口建立包转发关系,上图中3槽分别与两片5396,两片5396之间均能够相互通信。为了避免成环,设计将3槽相连的port5与5396之间互连的port10,分割为两个私有域,不同私有域之间无法通信,从而实现破环。
基于Port Base VLAN寄存器的含义和端口拓扑结构,可以设定相应端口的配置,如下表所示:
Port ID | Page值 | Address值 | 设定值 |
5 | 0x31 | 0x14 | 0x00 00 03 00 |
6 | 0x31 | 0x18 | 0x00 00 03 00 |
8 | 0x31 | 0x20 | 0x00 01 ff ff |
9 | 0x31 | 0x24 | 0x00 01 ff ff |
10 | 0x31 | 0x28 | 0x00 00 03 00 |
根据上表中的设定port5只能将对应的数据包转发给port8和port9,和port10不通,port10也是如此,两者已经属于不同的私有域。而port8和port9不会成环,无需更改。
5、代码实现
在uboot中配置5396时进行配置,前提是需要端口连接情况。比较容易的做法是先确定5396与zynq相连及与phy相连的port,将这两个port的寄存器设置为默认值,其余port设置转发时只转发给这两个port,即寄存器17位中只有2个1,其余为0.
#define XSPIPS_CR_OFFSET 0x00 /**< Configuration */
#define XSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */
#define XSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */
#define XSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */
#define XSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */
#define XSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */
#define XSPIPS_DR_OFFSET 0x18 /**< Delay Register */
#define XSPIPS_TXD_OFFSET 0x1C /**< Data Transmit Register */
#define XSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */
#define XSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */
#define XSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */
#define XSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */
#define XSPIPS_MASTER_OPTION 0x1 /**< Master mode option */
#define XSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */
#define XSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */
#define XSPIPS_DECODE_SSELECT_OPTION 0x8 /**< Select 16 slaves Option */
#define XSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */
#define XSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start mode option */
#define XSPIPS_CR_MODF_GEN_EN_MASK 0x00020000 /**< Modefail Generation
Enable */
#define XSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */
#define XSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start
Enable */
#define XSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */
#define XSPIPS_CR_SSCTRL_MASK 0x00003C00 /**< Slave Select Decode */
#define XSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */
#define XSPIPS_CR_SSCTRL_MAXIMUM 0xF /**< Slave Select maximum value */
#define XSPIPS_CR_SSDECEN_MASK 0x00000200 /**< Slave Select Decode Enable */
#define XSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */
#define XSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */
#define XSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */
#define XSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */
#define XSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */
#define XSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */
#define XSPIPS_CR_RESET_STATE 0x00020000 /**< Mode Fail Generation Enable */
#define XSPIPS_IXR_TXUF_MASK 0x00000040 /**< Tx FIFO Underflow */
#define XSPIPS_IXR_RXFULL_MASK 0x00000020 /**< Rx FIFO Full */
#define XSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< Rx FIFO Not Empty */
#define XSPIPS_IXR_TXFULL_MASK 0x00000008 /**< Tx FIFO Full */
#define XSPIPS_IXR_TXOW_MASK 0x00000004 /**< Tx FIFO Overwater */
#define XSPIPS_IXR_MODF_MASK 0x00000002 /**< Mode Fault */
#define XSPIPS_IXR_RXOVR_MASK 0x00000001 /**< Rx FIFO Overrun */
#define XSPIPS_IXR_DFLT_MASK 0x00000027 /**< Default interrupts
mask */
#define XSPIPS_IXR_WR_TO_CLR_MASK 0x00000043 /**< Interrupts which
need write to clear */
#define XSPIPS_ISR_RESET_STATE 0x04 /**< Default to tx/rx
* reg empty */
#define XSPIPS_IXR_DISABLE_ALL_MASK 0x00000043 /**< Disable all
* interrupts */
#define XSPIPS_FIFO_DEPTH 128 /**< FIFO depth of Tx and Rx */
#define NREAD (0x60)
#define NWRITE (0x61)
#define SIO (0xF0)
#define STS (0xFE)
#define SPG (0xFF)
#define SPIF (0x80)
#define RACK (0x20)
#define RXRDY (0x02)
#define TXRDY (0x01)
#define XST_SUCCESS 0L
#define XST_FAILURE 1L
#define XSpiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \
*(volatile u32 *) ((BaseAddress) + RegOffset) = RegisterValue
#define XSpiPs_ReadReg(BaseAddress, RegOffset) \
(*(volatile u32 * )((BaseAddress) + (RegOffset)))
#define XSpiPs_Enable(InstancePtr) \
*(volatile u32 *)((InstancePtr->Config.BaseAddress) + XSPIPS_ER_OFFSET) = 1
#define XSpiPs_Disable(InstancePtr) \
*(volatile u32 *)((InstancePtr->Config.BaseAddress) + XSPIPS_ER_OFFSET) = 0
typedef void (*XSpiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent,
unsigned ByteCount);
typedef struct {
u32 Option;
u32 Mask;
} OptionsMap;
static OptionsMap OptionsTable[] = {
{XSPIPS_MASTER_OPTION, XSPIPS_CR_MSTREN_MASK},
{XSPIPS_CLK_ACTIVE_LOW_OPTION, XSPIPS_CR_CPOL_MASK},
{XSPIPS_CLK_PHASE_1_OPTION, XSPIPS_CR_CPHA_MASK},
{XSPIPS_DECODE_SSELECT_OPTION, XSPIPS_CR_SSDECEN_MASK},
{XSPIPS_FORCE_SSELECT_OPTION, XSPIPS_CR_SSFORCE_MASK},
{XSPIPS_MANUAL_START_OPTION, XSPIPS_CR_MANSTRTEN_MASK}
};
#define XSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
u32 InputClockHz; /**< Input clock frequency */
} XSpiPs_Config;
typedef struct {
XSpiPs_Config Config; /**< Configuration structure */
u32 IsReady; /**< Device is initialized and ready */
u8 *SendBufferPtr; /**< Buffer to send (state) */
u8 *RecvBufferPtr; /**< Buffer to receive (state) */
unsigned RequestedBytes; /**< Number of bytes to transfer (state) */
unsigned RemainingBytes; /**< Number of bytes left to transfer(state) */
u32 IsBusy; /**< A transfer is in progress (state) */
u32 SlaveSelect; /**< The slave select value when
XSPIPS_FORCE_SSELECT_OPTION is set */
XSpiPs_StatusHandler StatusHandler;
void *StatusRef; /**< Callback reference for status handler */
} XSpiPs;
XSpiPs_Config XSpiPs_ConfigTable[] =
{
{
0,
0xE0006000,
166666672
}
};
XSpiPs_Config *g_SpiConfig;
void Spi_SetOptions(XSpiPs *InstancePtr, u32 Options)
{
u32 ConfigReg;
unsigned int Index;
u32 CurrentConfigReg;
/*
* Do not allow the slave select to change while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return;
}
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
CurrentConfigReg = ConfigReg;
/*
* Loop through the options table, turning the option on or off
* depending on whether the bit is set in the incoming options flag.
*/
for (Index = 0; Index < XSPIPS_NUM_OPTIONS; Index++) {
if (Options & OptionsTable[Index].Option) {
/* Turn it on */
ConfigReg |= OptionsTable[Index].Mask;
}
else {
/* Turn it off */
ConfigReg &= ~(OptionsTable[Index].Mask);
}
}
/*
* If CPOL-CPHA bits are toggled from previous state,
* disable before writing the configuration register and then enable.
*/
if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) !=
(ConfigReg & XSPIPS_CR_CPOL_MASK)) ||
((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) !=
(ConfigReg & XSPIPS_CR_CPHA_MASK)) ) {
XSpiPs_WriteReg((InstancePtr->Config.BaseAddress), XSPIPS_ER_OFFSET, 0);
}
/*
* Now write the Config register. Leave it to the upper layers
* to restart the device.
*/
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET, ConfigReg);
/*
* Enable
*/
if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) !=
(ConfigReg & XSPIPS_CR_CPOL_MASK)) ||
((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) !=
(ConfigReg & XSPIPS_CR_CPHA_MASK)) ) {
XSpiPs_WriteReg((InstancePtr->Config.BaseAddress), XSPIPS_ER_OFFSET, 1);
}
}
u32 Spi_GetOptions(XSpiPs *InstancePtr)
{
u32 OptionsFlag = 0;
u32 ConfigReg;
unsigned int Index;
/*
* Get the current options
*/
ConfigReg =
XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
/*
* Loop through the options table to grab options
*/
for (Index = 0; Index < XSPIPS_NUM_OPTIONS; Index++) {
if (ConfigReg & OptionsTable[Index].Mask) {
OptionsFlag |= OptionsTable[Index].Option;
}
}
return OptionsFlag;
}
#define XSpiPs_IsMaster(InstancePtr) \
((Spi_GetOptions(InstancePtr) & \
XSPIPS_MASTER_OPTION) ? 1 : 0)
#define XSpiPs_IsDecodeSSelect(InstancePtr) \
((Spi_GetOptions(InstancePtr) & \
XSPIPS_DECODE_SSELECT_OPTION) ? 1 : 0)
#define XSpiPs_IsManualStart(InstancePtr) \
((Spi_GetOptions(InstancePtr) & \
XSPIPS_MANUAL_START_OPTION) ? 1 : 0)
#define XSpiPs_IsManualChipSelect(InstancePtr) \
((Spi_GetOptions(InstancePtr) & \
XSPIPS_FORCE_SSELECT_OPTION) ? 1 : 0)
#define XSpiPs_SendByte(BaseAddress, Data) \
*(volatile u32 *)((BaseAddress) + XSPIPS_TXD_OFFSET) = Data;
#define XSpiPs_RecvByte(BaseAddress) \
(u8)(*(volatile u32 * )((BaseAddress) + XSPIPS_RXD_OFFSET))
#define REG_8 8
#define REG_16 16
#define REG_32 32
void XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SlaveSel)
{
u32 ConfigReg;
/*
* Do not allow the slave select to change while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return;
}
/*
* If decode slave select option is set,
* then set slave select value directly.
* Update the Instance structure member.
*/
if ( XSpiPs_IsDecodeSSelect( InstancePtr ) ) {
InstancePtr->SlaveSelect = SlaveSel << XSPIPS_CR_SSCTRL_SHIFT;
}
else {
/*
* Set the bit position to low using SlaveSel. Update the Instance
* structure member.
*/
InstancePtr->SlaveSelect = ((~(1 << SlaveSel)) & \
XSPIPS_CR_SSCTRL_MAXIMUM) << XSPIPS_CR_SSCTRL_SHIFT;
}
/*
* Read the config register, update the slave select value and write
* back to config register.
*/
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
ConfigReg &= (~XSPIPS_CR_SSCTRL_MASK);
ConfigReg |= InstancePtr->SlaveSelect;
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_CR_OFFSET,
ConfigReg);
}
void XSpiPs_SetClkPrescaler(XSpiPs *InstancePtr, u8 Prescaler)
{
u32 ConfigReg;
/*
* Do not allow the prescaler to be changed while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return;
}
/*
* Read the Config register, mask out the interesting bits, and set
* them with the shifted value passed into the function. Write the
* results back to the Config register.
*/
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
ConfigReg &= ~XSPIPS_CR_PRESC_MASK;
ConfigReg |= (u32) (Prescaler & XSPIPS_CR_PRESC_MAXIMUM) <<
XSPIPS_CR_PRESC_SHIFT;
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET,
ConfigReg);
}
int XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr,
u8 *RecvBufPtr, u32 ByteCount)
{
u32 StatusReg;
u32 ConfigReg;
u32 TransCount;
/*
* Check whether there is another transfer in progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return 1;
}
/*
* Set the busy flag, which will be cleared when the transfer is
* entirely done.
*/
InstancePtr->IsBusy = 1;
/*
* Set up buffer pointers.
*/
InstancePtr->SendBufferPtr = SendBufPtr;
InstancePtr->RecvBufferPtr = RecvBufPtr;
InstancePtr->RequestedBytes = ByteCount;
InstancePtr->RemainingBytes = ByteCount;
/*
* If manual chip select mode, initialize the slave select value.
*/
if (XSpiPs_IsManualChipSelect(InstancePtr)) {
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
/*
* Set the slave select value.
*/
ConfigReg &= ~XSPIPS_CR_SSCTRL_MASK;
ConfigReg |= InstancePtr->SlaveSelect;
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET, ConfigReg);
}
/*
* Enable the device.
*/
XSpiPs_Enable(InstancePtr);
while((InstancePtr->RemainingBytes > 0) ||
(InstancePtr->RequestedBytes > 0)) {
TransCount = 0;
/*
* Fill the TXFIFO with as many bytes as it will take (or as
* many as we have to send).
*/
while ((InstancePtr->RemainingBytes > 0) &&
(TransCount < XSPIPS_FIFO_DEPTH)) {
XSpiPs_SendByte(InstancePtr->Config.BaseAddress,
*InstancePtr->SendBufferPtr);
InstancePtr->SendBufferPtr++;
InstancePtr->RemainingBytes--;
++TransCount;
}
/*
* If master mode and manual start mode, issue manual start
* command to start the transfer.
*/
if (XSpiPs_IsManualStart(InstancePtr)
&& XSpiPs_IsMaster(InstancePtr)) {
ConfigReg = XSpiPs_ReadReg(
InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
ConfigReg |= XSPIPS_CR_MANSTRT_MASK;
//printf("reg:0x%x data = 0x%x.\n",XSPIPS_CR_OFFSET,ConfigReg);
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET, ConfigReg);
}
/*
* Wait for the transfer to finish by polling Tx fifo status.
*/
do {
StatusReg = XSpiPs_ReadReg(
InstancePtr->Config.BaseAddress,
XSPIPS_SR_OFFSET);
if ( StatusReg & XSPIPS_IXR_MODF_MASK )
{
/*
* Clear the mode fail bit
*/
XSpiPs_WriteReg(
InstancePtr->Config.BaseAddress,
XSPIPS_SR_OFFSET,
XSPIPS_IXR_MODF_MASK);
return 1;
}
} while ((StatusReg & XSPIPS_IXR_TXOW_MASK) == 0);
/*
* A transmit has just completed. Process received data and
* check for more data to transmit.
* First get the data received as a result of the transmit
* that just completed. Receive data based on the
* count obtained while filling tx fifo. Always get the
* received data, but only fill the receive buffer if it
* points to something (the upper layer software may not
* care to receive data).
*/
while (TransCount) {
u8 TempData;
TempData = XSpiPs_RecvByte(
InstancePtr->Config.BaseAddress);
if (InstancePtr->RecvBufferPtr != NULL) {
*InstancePtr->RecvBufferPtr++ = (u8) TempData;
}
InstancePtr->RequestedBytes--;
--TransCount;
}
}
/*
* Clear the slave selects now, before terminating the transfer.
*/
if (XSpiPs_IsManualChipSelect(InstancePtr)) {
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
ConfigReg |= XSPIPS_CR_SSCTRL_MASK;
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET, ConfigReg);
}
/*
* Clear the busy flag.
*/
InstancePtr->IsBusy = 0;
/*
* Disable the device.
*/
XSpiPs_Disable(InstancePtr);
return 0;
}
void delay_SL( u32 delayCount )
{
do{
__asm__("nop");
delayCount--;
}while(delayCount>0);
}
int writeBCM5396( XSpiPs *Spi_ptr,u8 page, u8 offset, u8 *pBuffer )
{
u8 data[20];
u32 retVal;
u32 u32SendNum, u32ReqRetNum;
int i;
for(i=0;i<20;i++)
data[i]=i;
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum);//pBuffer
if( retVal != 0 )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
// Read STS
READ_STS_1:
data[0] = NREAD;
data[1] = STS;
u32SendNum = 2;
u32ReqRetNum = 1;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum+u32ReqRetNum);
/*
xil_printf("STS 1 [%d]\n\r", retVal );
for( u8Idx=0; u8Idx<u32ReqRetNum; u8Idx++ )
xil_printf("%02x ", workBuf[u8Idx] );
xil_printf("\n\r");
*/
if( retVal == 0 )
{
if((pBuffer[2] & SPIF)==0)//( workBuf[2] & SPIF )
{
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum+u32ReqRetNum);
if( retVal != 0 )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
// Write Data
data[0] = NWRITE;
data[1] = offset;
data[2] = pBuffer[0];
data[3] = pBuffer[1];
u32SendNum = 4;
u32ReqRetNum = 0;//1;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum+u32ReqRetNum);
if( retVal != 0 )
{
printf("Call XSpiPs_PT_SL 2 Failed\n\r");
}
}
else
{
retVal = 1;
printf( "writeBCM5396 Timeout 1 Occured!\n" );
delay_SL(0x100000);
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
if( retVal != 0 )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
goto READ_STS_1;
}
}
else
printf("Call XSpiPs_PT_SL 4 Failed\n");
return retVal;
}
int writeBCM5396Reg( XSpiPs *Spi_ptr,u8 page, u8 offset, u8 *pBuffer ,u8 regType)
{
u8 data[20],recvBuf[10];
s32 retVal;
u32 u32SendNum, u32ReqRetNum;
int i;
memset(recvBuf,0,10);
for(i=0;i<20;i++)
data[i]=i;
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum);//pBuffer
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
// Read STS
READ_STS_1:
data[0] = NREAD;
data[1] = STS;
u32SendNum = 2;
u32ReqRetNum = 1;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,recvBuf,u32SendNum+u32ReqRetNum);
/*
xil_printf("STS 1 [%d]\n\r", retVal );
for( u8Idx=0; u8Idx<u32ReqRetNum; u8Idx++ )
xil_printf("%02x ", workBuf[u8Idx] );
xil_printf("\n\r");
*/
//
if( retVal == XST_SUCCESS )
{
if((recvBuf[2] & SPIF)==0)//( workBuf[2] & SPIF )
{
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
// Write Data
data[0] = NWRITE;
data[1] = offset;
for(i=0;i<regType/8;i++)
{
data[2+i] = pBuffer[i];
}
u32SendNum = 2+(regType/8);
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,NULL,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 2 Failed\n\r");
}
}
else
{
//TIMEOUT_HANDLER;
printf( "Timeout 1 Occured!\n\r" );
delay_SL(0x100000);
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
//retVal = XSpiPs_PT_SL(Spi_ptr , data, pBuffer, u32SendNum, &u32ReqRetNum );
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
goto READ_STS_1;
}
}
else
printf("Call XSpiPs_PT_SL 4 Failed\n\r");
return retVal;
}
int readBCM5396(XSpiPs *Spi_ptr, u8 page, u8 offset, u8 *pBuffer )
{
u8 data[8];
u32 retVal;
u32 u32SendNum, u32ReqRetNum;
// Set Page
/*
bcmCmd.cmd = NWRITE;
bcmCmd.regAdrs = SPG;
data[0] = page;
*/
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
// Read STS
READ_STS_1:
/*
bcmCmd.cmd = NREAD;
bcmCmd.regAdrs = STS;
*/
data[0] = NREAD;
data[1] = STS;
u32SendNum = 2;
u32ReqRetNum = 1;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
/*
printf("STS 1 [%d]\n\r", retVal );
for( i=0; i<u32ReqRetNum; i++ )
printf("%02x ", pBuffer[i] );
printf("\n\r");
*/
//
if( retVal == XST_SUCCESS )
{
if( (pBuffer[2] & SPIF)==0 )
{
// Set Page
/*
bcmCmd.cmd = NWRITE;
bcmCmd.regAdrs = SPG;
data[0] = page;
*/
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n\r");
}
// Set Offset in Page, "Null" operation :)
/*
bcmCmd.cmd = NREAD;
bcmCmd.regAdrs = offset;
*/
data[0] = NREAD;
data[1] = offset;
u32SendNum = 2;
u32ReqRetNum = 1;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 2 Failed\n\r");
}
// Read STS
READ_STS_2:
/*
bcmCmd.cmd = NREAD;
bcmCmd.regAdrs = STS;
*/
data[0] = NREAD;
data[1] = STS;
u32SendNum = 2;
u32ReqRetNum = 1;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
/*
for( u8Idx=0; u8Idx<u32ReqRetNum; u8Idx++ )
xil_printf("%02x ", pBuffer[u8Idx] );
xil_printf("\n\r");
*/
if( retVal == XST_SUCCESS )
{
if( pBuffer[2] & RACK )
{
data[0] = NREAD;
data[1] = SIO;
u32SendNum = 2;
u32ReqRetNum = 4;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
/*
xil_printf("DATA [%d]\n\r", retVal );
for( u8Idx=0; u8Idx<u32ReqRetNum; u8Idx++ )
xil_printf("%02x ", pBuffer[u8Idx] );
xil_printf("\n\r");
*/
}
else
{
retVal = XST_FAILURE;
printf( "Timeout 2 Occured!\n\r" );
delay_SL(0x100000);
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
//retVal = XSpiPs_PT_SL(Spi_ptr, data, pBuffer, u32SendNum, &u32ReqRetNum );
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n");
}
goto READ_STS_2;
}
}
else
printf("Call XSpiPs_PT_SL 3 Failed\n\r");
}
else
{
retVal = XST_FAILURE;
printf( "Timeout 1 Occured!\n" );
delay_SL(0x100000);
// Set Page
data[0] = NWRITE;
data[1] = SPG;
data[2] = page;
u32SendNum = 3;
u32ReqRetNum = 0;
retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
if( retVal != XST_SUCCESS )
{
printf("Call XSpiPs_PT_SL 1 Failed\n");
}
goto READ_STS_1;
}
}
else
printf("Call XSpiPs_PT_SL 4 Failed\n");
return retVal;
}
void myspi_init()
{
XSpiPs Spi;
int i32Option,status;
int i;
unsigned char workBuf[10];
workBuf[0]=0xf0;
workBuf[1]=0x1;
g_SpiConfig = &XSpiPs_ConfigTable[0];
//Initialize the SPI device.
Spi.IsBusy = 0;
Spi.Config.BaseAddress = g_SpiConfig->BaseAddress;
//Spi.StatusHandler = StubStatusHandler;
Spi.SendBufferPtr = NULL;
Spi.RecvBufferPtr = NULL;
Spi.RequestedBytes = 0;
Spi.RemainingBytes = 0;
Spi.IsReady = 0x11111111;
XSpiPs_WriteReg(Spi.Config.BaseAddress,0,0x00020000);
//Initialize the SPI device. end
i32Option = 0x1 | 0x2 | 0x4 | 0x10;
Spi_SetOptions(&Spi, i32Option);
XSpiPs_SetSlaveSelect(&Spi,1 );
XSpiPs_SetClkPrescaler(&Spi, 6 );
workBuf[0]=0xf0;
workBuf[1]=0x1;
workBuf[2]=0;
for(i=0x10;i<=0x1f;i++)
{
status = writeBCM5396(&Spi, i, 0x20, workBuf );
}
printf("*****************Read SPI Reg of 5396******************\r\n");
printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n");
for(i=0x10;i<=0x1f;i++)
{
status = readBCM5396(&Spi, i, 0x28, workBuf );
printf("port=%d,offset=0x28,data=0x%x\n",(i-0x10),workBuf[2]);
printf("port=%d,offset=0x29,data=0x%x\n",(i-0x10),workBuf[3]);
}
printf("---BMC Status Registers(PAGE 0x10-0x1F)---\n\r");
for(i=0x10;i<=0x1f;i++)
{
status = readBCM5396(&Spi, i, 0x20, workBuf );
printf("port=%d,offset=0x20,data=0x%x\n\r",(i-0x10),workBuf[2]);
printf("port=%d,offset=0x21,data=0x%x\n\r",(i-0x10),workBuf[3]);
}
//break loop
u8 buf[10];
printf("-----Break Loop Operation-----\r\n");
buf[0]=0x00;
buf[1]=0x03;
buf[2]=0x00;
//writeBCM5396Reg(&Spi, 0x31, 0x00, buf,REG_32);//Port 0 - Slot 10
//writeBCM5396Reg(&Spi, 0x31, 0x04, buf,REG_32);//Port 1 - Slot 9
//writeBCM5396Reg(&Spi, 0x31, 0x08, buf,REG_32);//Port 2 - Slot 8
writeBCM5396Reg(&Spi, 0x31, 0x0c, buf,REG_32);//Port 3 - Slot 7
writeBCM5396Reg(&Spi, 0x31, 0x10, buf,REG_32);//Port 4 - Slot 6
writeBCM5396Reg(&Spi, 0x31, 0x14, buf,REG_32);//Port 5 - Slot 5
writeBCM5396Reg(&Spi, 0x31, 0x18, buf,REG_32);//Port 6 - Slot 2
writeBCM5396Reg(&Spi, 0x31, 0x1c, buf,REG_32);//Port 7 - Slot 1
//writeBCM5396Reg(&Spi, 0x31, 0x38, buf,REG_32);//Port 14 - Slot 12
//writeBCM5396Reg(&Spi, 0x31, 0x3c, buf,REG_32);//Port 15 - Slot 11
buf[0]=0xff;
buf[1]=0xff;
buf[2]=0x01;
writeBCM5396Reg(&Spi, 0x31, 0x20, buf,REG_32);//Port 8
writeBCM5396Reg(&Spi, 0x31, 0x24, buf,REG_32);//Port 9
}
更多推荐
所有评论(0)