cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Adventurer
Adventurer
583 Views
Registered: ‎02-09-2017

how to use spi controller to control bcm5396 in linux

My hardware design is as follows.

20170407221123026.png

 

I use zynq spi controller to config broadcom 5396 network switch chip.

In standalone mode, I can use the following code.

int readBCM5396(XSpiPs *Spi_ptr, u8 page, u8 offset, u8 *pBuffer )
{
	u8 data[8];//
	s32 retVal;
	u32 u32SendNum, u32ReqRetNum;

	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 )
	{
		xil_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,pBuffer,u32SendNum+u32ReqRetNum);


	if( retVal == XST_SUCCESS )
	{
		if( (pBuffer[2] & SPIF)==0)
		{
			// 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 )
			{
				xil_printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			// Set Offset in Page, "Null" operation :)
			data[0] = NREAD;
			data[1] = offset;
			u32SendNum = 2;
			u32ReqRetNum = 1;
			retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
			if( retVal != XST_SUCCESS )
			{
				xil_printf("Call XSpiPs_PT_SL 2 Failed\n\r");
			}


			// Read STS
READ_STS_2:
            data[0] = NREAD;
	        data[1] = STS;
			u32SendNum = 2;
			u32ReqRetNum = 1;
			retVal = XSpiPs_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
			
			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);

				}
				else
				{
					TIMEOUT_HANDLER;
					xil_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_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
					if( retVal != XST_SUCCESS )
					{
						xil_printf("Call XSpiPs_PT_SL 1 Failed\n\r");
					}

					goto READ_STS_2;
				}

			}
			else
				xil_printf("Call XSpiPs_PT_SL 3 Failed\n\r");
		}
		else
		{
			TIMEOUT_HANDLER;
			xil_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_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
			if( retVal != XST_SUCCESS )
			{
				xil_printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			goto READ_STS_1;
		}
	}
	else
		xil_printf("Call XSpiPs_PT_SL 4 Failed\n\r");

	return retVal;
}


int writeBCM5396( XSpiPs *Spi_ptr,u8 page, u8 offset, u8 *pBuffer )
{
	u8 data[20];
	s32 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 != XST_SUCCESS )
	{
		xil_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);
	//
	if( retVal == XST_SUCCESS )
	{
		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 != XST_SUCCESS )
			{
				xil_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 != XST_SUCCESS )
			{
				xil_printf("Call XSpiPs_PT_SL 2 Failed\n\r");
			}

		}
		else
		{
			TIMEOUT_HANDLER;
			xil_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_PolledTransfer(Spi_ptr,data,pBuffer,u32SendNum+u32ReqRetNum);
			if( retVal != XST_SUCCESS )
			{
				xil_printf("Call XSpiPs_PT_SL 1 Failed\n\r");
			}

			goto READ_STS_1;
		}
	}
	else
		xil_printf("Call XSpiPs_PT_SL 4 Failed\n\r");

	return retVal;
}

I have found the related function ( XSpiPs_PolledTransfer) in the  xspips.c.

s32 XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr,
				u8 *RecvBufPtr, u32 ByteCount)
{
	u32 StatusReg;
	u32 ConfigReg;
	u32 TransCount;
	u32 CheckTransfer;
	s32 Status_Polled;
	u8 TempData;

	/*
	 * The RecvBufPtr argument can be NULL.
	 */
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(SendBufPtr != NULL);
	Xil_AssertNonvoid(ByteCount > 0U);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/*
	 * Check whether there is another transfer in progress. Not thread-safe.
	 */
	if (InstancePtr->IsBusy == TRUE) {
		Status_Polled = (s32)XST_DEVICE_BUSY;
	} else {

		/*
		 * Set the busy flag, which will be cleared when the transfer is
		 * entirely done.
		 */
		InstancePtr->IsBusy = TRUE;

		/*
		 * 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) == TRUE) {
			ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
						 XSPIPS_CR_OFFSET);
			/*
			 * Set the slave select value.
			 */
			ConfigReg &= (u32)(~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 > (u32)0U) ||
			(InstancePtr->RequestedBytes > (u32)0U)) {
			TransCount = 0U;
			/*
			 * Fill the TXFIFO with as many bytes as it will take (or as
			 * many as we have to send).
			 */
			while ((InstancePtr->RemainingBytes > (u32)0U) &&
				((u32)TransCount < (u32)XSPIPS_FIFO_DEPTH)) {
				XSpiPs_SendByte(InstancePtr->Config.BaseAddress,
						*InstancePtr->SendBufferPtr);
				InstancePtr->SendBufferPtr += 1;
				InstancePtr->RemainingBytes--;
				++TransCount;
			}

			/*
			 * If master mode and manual start mode, issue manual start
			 * command to start the transfer.
			 */
			if ((XSpiPs_IsManualStart(InstancePtr) == TRUE)
				&& (XSpiPs_IsMaster(InstancePtr) == TRUE)) {
				ConfigReg = XSpiPs_ReadReg(
						InstancePtr->Config.BaseAddress,
						 XSPIPS_CR_OFFSET);
				ConfigReg |= XSPIPS_CR_MANSTRT_MASK;
				XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
						 XSPIPS_CR_OFFSET, ConfigReg);
			}

			/*
			 * Wait for the transfer to finish by polling Tx fifo status.
			 */
	        CheckTransfer = (u32)0U;
	        while (CheckTransfer == 0U){
			StatusReg = XSpiPs_ReadReg(
					        InstancePtr->Config.BaseAddress,
						        XSPIPS_SR_OFFSET);
				if ( (StatusReg & XSPIPS_IXR_MODF_MASK) != 0U) {
					/*
					 * Clear the mode fail bit
					 */
					XSpiPs_WriteReg(
						InstancePtr->Config.BaseAddress,
						XSPIPS_SR_OFFSET,
						XSPIPS_IXR_MODF_MASK);
					return (s32)XST_SEND_ERROR;
				}
		        CheckTransfer = (StatusReg &
							XSPIPS_IXR_TXOW_MASK);
		    }

			/*
			 * 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 != (u32)0U) {
				TempData = (u8)XSpiPs_RecvByte(
					InstancePtr->Config.BaseAddress);
				if (InstancePtr->RecvBufferPtr != NULL) {
					*(InstancePtr->RecvBufferPtr) = TempData;
					InstancePtr->RecvBufferPtr += 1;
				}
				InstancePtr->RequestedBytes--;
				--TransCount;
			}
		}

		/*
		 * Clear the slave selects now, before terminating the transfer.
		 */
		if (XSpiPs_IsManualChipSelect(InstancePtr) == TRUE) {
			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 = FALSE;

		/*
		 * Disable the device.
		 */
		XSpiPs_Disable(InstancePtr);
		Status_Polled = (s32)XST_SUCCESS;
	}
	return Status_Polled;
}

If I want to config bcm5396 in linux mode, How to use the spi controller driver?

 

Thanks very much.

 

The attachment is the two code files.

 

0 Kudos
0 Replies