
Added initial support Xilinx Embedded Software. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
489 lines
17 KiB
C
Executable file
489 lines
17 KiB
C
Executable file
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2005 - 2014 Xilinx, Inc. All rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* Use of the Software is limited solely to applications:
|
|
* (a) running on a Xilinx device, or
|
|
* (b) that interact with a Xilinx device through a bus or interconnect.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
|
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
* Except as contained in this notice, the name of the Xilinx shall not be used
|
|
* in advertising or otherwise to promote the sale, use or other dealings in
|
|
* this Software without prior written authorization from Xilinx.
|
|
*
|
|
******************************************************************************/
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* @file xllfifo.c
|
|
*
|
|
* The Xilinx local link FIFO driver component. This driver supports the
|
|
* Xilinx xps_ll_fifo core.
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- -------- -------------------------------------------------------
|
|
* 1.00a jvb 10/13/06 First release
|
|
* 1.00a xd 12/17/07 Added type casting to fix CR #456850
|
|
* 1.02a jz 12/04/09 Hal phase 1 support
|
|
* 2.00a hbm 01/20/10 Hal phase 1 support, bump up major release
|
|
* 2.01a asa 09/17/10 Added code for resetting Streaming interface
|
|
* for CR574868
|
|
* 3.00a adk 08/10/13 Added support for AXI4 Datainterface.Updated
|
|
* XLlFifo_RxGetWord, XLlFifo_TxPutword inorder to
|
|
* handle AXI4 Datainterface. Added Config
|
|
* initialization for the driver.
|
|
* </pre>
|
|
******************************************************************************/
|
|
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "xstatus.h"
|
|
#include "xllfifo.h"
|
|
#include "xil_assert.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
#define FIFO_WIDTH_BYTES 4
|
|
|
|
/*
|
|
* Implementation Notes:
|
|
*
|
|
* This Fifo driver makes use of a byte streamer driver (xstreamer.h). The code
|
|
* is structured like so:
|
|
*
|
|
* +--------------------+
|
|
* | llfifo |
|
|
* | +----------------+
|
|
* | | +--------------+
|
|
* | | | xstreamer |
|
|
* | | +--------------+
|
|
* | +----------------+
|
|
* | |
|
|
* +--------------------+
|
|
*
|
|
* Initialization
|
|
* At initialization time this driver (llfifo) sets up the streamer objects to
|
|
* use routines in this driver (llfifo) to perform the actual I/O to the H/W
|
|
* FIFO core.
|
|
*
|
|
* Operation
|
|
* Once the streamer objects are set up, the API routines in this driver, just
|
|
* call through to the streamer driver to perform the read/write operations.
|
|
* The streamer driver will eventually make calls back into the routines (which
|
|
* reside in this driver) given at initialization to peform the actual I/O.
|
|
*
|
|
* Interrupts
|
|
* Interrupts are handled in the OS/Application layer above this driver.
|
|
*/
|
|
|
|
xdbg_stmnt(u32 _xllfifo_rr_value;)
|
|
xdbg_stmnt(u32 _xllfifo_ipie_value;)
|
|
xdbg_stmnt(u32 _xllfifo_ipis_value;)
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_iRxOccupancy returns the number of 32-bit words available (occupancy)
|
|
* to be read from the receive channel of the FIFO, specified by
|
|
* <i>InstancePtr</i>.
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @return XLlFifo_iRxOccupancy returns the occupancy count in 32-bit words for
|
|
* the specified FIFO.
|
|
*
|
|
******************************************************************************/
|
|
u32 XLlFifo_iRxOccupancy(XLlFifo *InstancePtr)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr);
|
|
|
|
return XLlFifo_ReadReg(InstancePtr->BaseAddress,
|
|
XLLF_RDFO_OFFSET);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_iRxGetLen notifies the hardware that the program is ready to receive the
|
|
* next frame from the receive channel of the FIFO specified by <i>InstancePtr</i>.
|
|
*
|
|
* Note that the program must first call XLlFifo_iRxGetLen before pulling data
|
|
* out of the receive channel of the FIFO with XLlFifo_Read.
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @return XLlFifo_iRxGetLen returns the number of bytes available in the next
|
|
* frame.
|
|
*
|
|
******************************************************************************/
|
|
u32 XLlFifo_iRxGetLen(XLlFifo *InstancePtr)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr);
|
|
|
|
return XLlFifo_ReadReg(InstancePtr->BaseAddress,
|
|
XLLF_RLF_OFFSET);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_iRead_Aligned reads, <i>WordCount</i>, words from the FIFO referenced by
|
|
* <i>InstancePtr</i> to the block of memory, referenced by <i>BufPtr</i>.
|
|
*
|
|
* XLlFifo_iRead_Aligned assumes that <i>BufPtr</i> is already aligned according
|
|
* to the following hardware limitations:
|
|
* ppc - aligned on 32 bit boundaries to avoid performance penalties
|
|
* from unaligned exception handling.
|
|
* microblaze - aligned on 32 bit boundaries as microblaze does not handle
|
|
* unaligned transfers.
|
|
*
|
|
* Care must be taken to ensure that the number of words read with one or more
|
|
* calls to XLlFifo_Read() does not exceed the number of bytes (rounded up to
|
|
* the nearest whole 32 bit word) available given from the last call to
|
|
* XLlFifo_RxGetLen().
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @param BufPtr specifies the memory address to place the data read.
|
|
*
|
|
* @param WordCount specifies the number of 32 bit words to read.
|
|
*
|
|
* @return XLlFifo_iRead_Aligned always returns XST_SUCCESS. Error handling is
|
|
* otherwise handled through hardware exceptions and interrupts.
|
|
*
|
|
* @note
|
|
*
|
|
* C Signature: int XLlFifo_iRead_Aligned(XLlFifo *InstancePtr,
|
|
* void *BufPtr, unsigned WordCount);
|
|
*
|
|
******************************************************************************/
|
|
/* static */ int XLlFifo_iRead_Aligned(XLlFifo *InstancePtr, void *BufPtr,
|
|
unsigned WordCount)
|
|
{
|
|
unsigned WordsRemaining = WordCount;
|
|
u32 *BufPtrIdx = (u32 *)BufPtr;
|
|
|
|
xdbg_printf(XDBG_DEBUG_FIFO_RX, "XLlFifo_iRead_Aligned: start\n");
|
|
Xil_AssertNonvoid(InstancePtr);
|
|
Xil_AssertNonvoid(BufPtr);
|
|
/* assert bufer is 32 bit aligned */
|
|
Xil_AssertNonvoid(((unsigned)BufPtr & 0x3) == 0x0);
|
|
xdbg_printf(XDBG_DEBUG_FIFO_RX, "XLlFifo_iRead_Aligned: after asserts\n");
|
|
|
|
while (WordsRemaining) {
|
|
/* xdbg_printf(XDBG_DEBUG_FIFO_RX,
|
|
"XLlFifo_iRead_Aligned: WordsRemaining: %d\n",
|
|
WordsRemaining);
|
|
*/
|
|
*BufPtrIdx = XLlFifo_RxGetWord(InstancePtr);
|
|
BufPtrIdx++;
|
|
WordsRemaining--;
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_FIFO_RX,
|
|
"XLlFifo_iRead_Aligned: returning SUCCESS\n");
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_iTxVacancy returns the number of unused 32 bit words available
|
|
* (vacancy) in the send channel of the FIFO, specified by <i>InstancePtr</i>.
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @return XLlFifo_iTxVacancy returns the vacancy count in 32-bit words for
|
|
* the specified FIFO.
|
|
*
|
|
*****************************************************************************/
|
|
u32 XLlFifo_iTxVacancy(XLlFifo *InstancePtr)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr);
|
|
|
|
return XLlFifo_ReadReg(InstancePtr->BaseAddress,
|
|
XLLF_TDFV_OFFSET);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_iTxSetLen begins a hardware transfer of data out of the transmit
|
|
* channel of the FIFO, specified by <i>InstancePtr</i>. <i>Bytes</i> specifies the number
|
|
* of bytes in the frame to transmit.
|
|
*
|
|
* Note that <i>Bytes</i> (rounded up to the nearest whole 32 bit word) must be same
|
|
* number of words just written using one or more calls to
|
|
* XLlFifo_iWrite_Aligned()
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @param Bytes specifies the number of bytes to transmit.
|
|
*
|
|
* @return N/A
|
|
*
|
|
******************************************************************************/
|
|
void XLlFifo_iTxSetLen(XLlFifo *InstancePtr, u32 Bytes)
|
|
{
|
|
Xil_AssertVoid(InstancePtr);
|
|
|
|
XLlFifo_WriteReg(InstancePtr->BaseAddress, XLLF_TLF_OFFSET,
|
|
Bytes);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_iWrite_Aligned writes, <i>WordCount</i>, words to the FIFO referenced by
|
|
* <i>InstancePtr</i> from the block of memory, referenced by <i>BufPtr</i>.
|
|
*
|
|
* XLlFifo_iWrite_Aligned assumes that <i>BufPtr</i> is already aligned according
|
|
* to the following hardware limitations:
|
|
* ppc - aligned on 32 bit boundaries to avoid performance penalties
|
|
* from unaligned exception handling.
|
|
* microblaze - aligned on 32 bit boundaries as microblaze does not handle
|
|
* unaligned transfers.
|
|
*
|
|
* Care must be taken to ensure that the number of words written with one or
|
|
* more calls to XLlFifo_iWrite_Aligned() matches the number of bytes (rounded up
|
|
* to the nearest whole 32 bit word) given in the next call to
|
|
* XLlFifo_iTxSetLen().
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @param BufPtr specifies the memory address to place the data read.
|
|
*
|
|
* @param WordCount specifies the number of 32 bit words to read.
|
|
*
|
|
* @return XLlFifo_iWrite_Aligned always returns XST_SUCCESS. Error handling is
|
|
* otherwise handled through hardware exceptions and interrupts.
|
|
*
|
|
* @note
|
|
*
|
|
* C Signature: int XLlFifo_iWrite_Aligned(XLlFifo *InstancePtr,
|
|
* void *BufPtr, unsigned WordCount);
|
|
*
|
|
******************************************************************************/
|
|
/* static */ int XLlFifo_iWrite_Aligned(XLlFifo *InstancePtr, void *BufPtr,
|
|
unsigned WordCount)
|
|
{
|
|
unsigned WordsRemaining = WordCount;
|
|
u32 *BufPtrIdx = (u32 *)BufPtr;
|
|
|
|
xdbg_printf(XDBG_DEBUG_FIFO_TX,
|
|
"XLlFifo_iWrite_Aligned: Inst: %p; Buff: %p; Count: %d\n",
|
|
InstancePtr, BufPtr, WordCount);
|
|
Xil_AssertNonvoid(InstancePtr);
|
|
Xil_AssertNonvoid(BufPtr);
|
|
/* assert bufer is 32 bit aligned */
|
|
Xil_AssertNonvoid(((unsigned)BufPtr & 0x3) == 0x0);
|
|
|
|
xdbg_printf(XDBG_DEBUG_FIFO_TX,
|
|
"XLlFifo_iWrite_Aligned: WordsRemaining: %d\n",
|
|
WordsRemaining);
|
|
while (WordsRemaining) {
|
|
XLlFifo_TxPutWord(InstancePtr, *BufPtrIdx);
|
|
BufPtrIdx++;
|
|
WordsRemaining--;
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_FIFO_TX,
|
|
"XLlFifo_iWrite_Aligned: returning SUCCESS\n");
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* XLlFifo_CfgInitialize initializes an XPS_ll_Fifo device along with the
|
|
* <i>InstancePtr</i> that references it.
|
|
*
|
|
* @param InstancePtr is a pointer to the Axi Streaming FIFO instance
|
|
* to be worked on.
|
|
* @param CfgPtr references the structure holding the hardware
|
|
* configuration for the Axi Streaming FIFO core to initialize.
|
|
* @param EffectiveAddr is the device base address in the virtual memory
|
|
* address space. The caller is responsible for keeping the
|
|
* address mapping from EffectiveAddr to the device physical base
|
|
* address unchanged once this function is invoked. Unexpected
|
|
* errors may occur if the address mapping changes after this
|
|
* function is called. If address translation is not used,
|
|
* use Config->BaseAddress for this parameters, passing the
|
|
* physical address instead.
|
|
*
|
|
* @return N/A
|
|
*
|
|
******************************************************************************/
|
|
int XLlFifo_CfgInitialize(XLlFifo *InstancePtr,
|
|
XLlFifo_Config *Config, u32 EffectiveAddress)
|
|
{
|
|
Xil_AssertNonvoid(InstancePtr);
|
|
|
|
if(!Config) {
|
|
return XST_INVALID_PARAM;
|
|
}
|
|
|
|
|
|
/* Clear instance memory */
|
|
memset(InstancePtr, 0, sizeof(XLlFifo));
|
|
|
|
/*
|
|
* We don't care about the physical base address, just copy the
|
|
* processor address over it.
|
|
*/
|
|
InstancePtr->BaseAddress = EffectiveAddress;
|
|
|
|
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
|
|
|
|
InstancePtr->Datainterface = Config->Datainterface;
|
|
InstancePtr->Axi4BaseAddress = Config->Axi4BaseAddress;
|
|
if (InstancePtr->Datainterface == 0)
|
|
InstancePtr->Axi4BaseAddress = EffectiveAddress;
|
|
|
|
XLlFifo_TxReset(InstancePtr);
|
|
XLlFifo_RxReset(InstancePtr);
|
|
|
|
/*
|
|
* Reset the core and generate the external reset by writing to
|
|
* the Local Link/AXI Streaming Reset Register.
|
|
*/
|
|
XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_LLR_OFFSET,
|
|
XLLF_RDFR_RESET_MASK);
|
|
|
|
XStrm_RxInitialize(&(InstancePtr->RxStreamer), FIFO_WIDTH_BYTES,
|
|
(void *)InstancePtr,
|
|
(XStrm_XferFnType)XLlFifo_iRead_Aligned,
|
|
(XStrm_GetLenFnType)XLlFifo_iRxGetLen,
|
|
(XStrm_GetOccupancyFnType)XLlFifo_iRxOccupancy);
|
|
|
|
XStrm_TxInitialize(&(InstancePtr->TxStreamer), FIFO_WIDTH_BYTES,
|
|
(void *)InstancePtr,
|
|
(XStrm_XferFnType)XLlFifo_iWrite_Aligned,
|
|
(XStrm_SetLenFnType)XLlFifo_iTxSetLen,
|
|
(XStrm_GetVacancyFnType)XLlFifo_iTxVacancy);
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_RxGetWord reads one 32 bit word from the FIFO specified by
|
|
* <i>InstancePtr</i>.
|
|
*
|
|
* XLlFifo_RxGetLen or XLlFifo_iRxGetLen must be called before calling
|
|
* XLlFifo_RxGetWord. Otherwise, the hardware will raise an <i>Over Read
|
|
* Exception</i>.
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @return XLlFifo_RxGetWord returns the 32 bit word read from the FIFO.
|
|
*
|
|
* @note
|
|
* C-style signature:
|
|
* u32 XLlFifo_RxGetWord(XLlFifo *InstancePtr)
|
|
*
|
|
*****************************************************************************/
|
|
u32 XLlFifo_RxGetWord(XLlFifo *InstancePtr)
|
|
{
|
|
return XLlFifo_ReadReg((InstancePtr)->Axi4BaseAddress,
|
|
XLLF_RDFD_OFFSET);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
*
|
|
* XLlFifo_TxPutWord writes the 32 bit word, <i>Word</i> to the FIFO specified by
|
|
* <i>InstancePtr</i>.
|
|
*
|
|
* @param InstancePtr references the FIFO on which to operate.
|
|
*
|
|
* @return N/A
|
|
*
|
|
* @note
|
|
* C-style signature:
|
|
* void XLlFifo_TxPutWord(XLlFifo *InstancePtr, u32 Word)
|
|
*
|
|
*****************************************************************************/
|
|
void XLlFifo_TxPutWord(XLlFifo *InstancePtr, u32 Word)
|
|
{
|
|
|
|
XLlFifo_WriteReg((InstancePtr)->Axi4BaseAddress,
|
|
XLLF_TDFD_OFFSET, (Word));
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* XLlFifo_Initialize initializes an XPS_ll_Fifo device along with the
|
|
* <i>InstancePtr</i> that references it.
|
|
*
|
|
* @param InstancePtr references the memory instance to be associated with
|
|
* the FIFO device upon initialization.
|
|
*
|
|
* @param BaseAddress is the processor address used to access the
|
|
* base address of the Fifo device.
|
|
*
|
|
* @return N/A
|
|
*
|
|
******************************************************************************/
|
|
void XLlFifo_Initialize(XLlFifo *InstancePtr, u32 BaseAddress)
|
|
{
|
|
Xil_AssertVoid(InstancePtr);
|
|
Xil_AssertVoid(BaseAddress);
|
|
|
|
/* Clear instance memory */
|
|
memset(InstancePtr, 0, sizeof(XLlFifo));
|
|
|
|
/*
|
|
* We don't care about the physical base address, just copy the
|
|
* processor address over it.
|
|
*/
|
|
InstancePtr->BaseAddress = BaseAddress;
|
|
|
|
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
|
|
InstancePtr->Axi4BaseAddress = BaseAddress;
|
|
|
|
XLlFifo_TxReset(InstancePtr);
|
|
XLlFifo_RxReset(InstancePtr);
|
|
|
|
/*
|
|
* Reset the core and generate the external reset by writing to
|
|
* the Local Link/AXI Streaming Reset Register.
|
|
*/
|
|
XLlFifo_WriteReg((InstancePtr)->BaseAddress, XLLF_LLR_OFFSET,
|
|
XLLF_RDFR_RESET_MASK);
|
|
|
|
XStrm_RxInitialize(&(InstancePtr->RxStreamer), FIFO_WIDTH_BYTES,
|
|
(void *)InstancePtr,
|
|
(XStrm_XferFnType)XLlFifo_iRead_Aligned,
|
|
(XStrm_GetLenFnType)XLlFifo_iRxGetLen,
|
|
(XStrm_GetOccupancyFnType)XLlFifo_iRxOccupancy);
|
|
|
|
XStrm_TxInitialize(&(InstancePtr->TxStreamer), FIFO_WIDTH_BYTES,
|
|
(void *)InstancePtr,
|
|
(XStrm_XferFnType)XLlFifo_iWrite_Aligned,
|
|
(XStrm_SetLenFnType)XLlFifo_iTxSetLen,
|
|
(XStrm_GetVacancyFnType)XLlFifo_iTxVacancy);
|
|
}
|
|
|