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

}

 

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐