blob: c8e7f9e0e66805c9e1166cc0a7a2f24ef7c1f471 [file] [log] [blame]
/*********************************************************************
*
* (C) Copyright IBM Corp. 2007,2010
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 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 GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses>.
*
********************************************************************/
#ifndef _DMA_FIFO_H_ /* Prevent multiple inclusion */
#define _DMA_FIFO_H_
/*!
* \file spi/DMA_Fifo.h
*
* \brief DMA SPI Fifo Definitions and Inline Functions Common to Injection
* and Reception Fifos
*
* This include file contains data structures and inline functions that are
* common among injection and reception fifos. The inlines are used to
* interface with the fifos at the lowest level.
*
* There are two levels of access: hardware and software. For direct
* hardware access, the DMA_FifoHW_t structure describes fields that reside
* in the "hardware fifo" in DMA SRAM. For normal software access, the
* DMA_Fifo_t structure contains a pointer to the hardware structure,
* shadows (snapshot copies) of the fields in the hardware structure, and
* size information calculated from the shadows.
*
* \verbatim Picture of fifo structures
========DDR MEMORY===================|==========DMA SRAM MEMORY==========
------------------------------ |
| DMA_Fifo_t | |
| | |
| Software Fifo | |
| | |
| | | -----------------------------
| fifo_hw_ptr--------------|-------|---->| DMA_FifoHW_t |
| | | | |
| | | | Hardware Fifo |
| Shadow Pointers | | -----------------------------
| . | |
------------------------------ |
\endverbatim
*
* For normal messaging software, one should access the DMA using the
* DMA_Fifo_t, DMA_InjFifo_t, or DMA_RecFifo_t structures since
* they maintain shadows. This include file contains inline functions that
* operate on the DMA_Fifo_t for this purpose. Functions include:
* - get va_start, va_head, va_tail, va_end, fifo size, fifo free_space
* - set va_head, va_tail
* - update fifo free-space based upon current shadows
*
* However, for bringup or diagnostic software, there is a need for direct
* access to the hardware fifos. This include file contains functions that
* operate on the DMA_FifoHW_t for this purpose. Functions include:
* - get pa_start, pa_head, pa_tail, pa_end
* - set pa_start, pa_head, pa_tail, pa_end
* While it probably doesn't make sense to have a stand-alone
* DMA_FifoSetStartPa() or DMA_FifoSetEndPa() since this dynamically
* messes up the fifo, causing unpredictable results. But bringup or
* diagnostic software will need this (with dma disabled, or the fifo
* disabled). Therefore we provide direct interfaces using physical
* addresses and no shadows (for speed).
*
* Definitions:
* - A fifo represents a contiguous block of DDR memory
* - A fifo has a starting address and an ending address (defines the memory
* block)
* - An injection fifo is a series of 32-byte descriptors.
* - Injection consists of copying a 32-byte descriptor into the next available
* slot (pointed to by the tail) and incrementing the tail pointer.
* - The DMA engine asynchronously processes descriptors, beginning with the
* descriptor pointed to by head, and ending with the descriptor just prior
* to tail.
* - There are injection (DMA InjFifo) and reception (DMA RecFifo) fifos
* (separate interfaces)
* - There are DMA_NUM_INJ_FIFO_GROUPS injection fifo groups
* - There are DMA_NUM_INJ_FIFOS_PER_GROUP injection fifos per group
* - Thus, there are DMA_NUM_INJ_FIFOS injection fifos per node
* - There are DMA_NUM_REC_FIFO_GROUPS reception fifo groups
* - There are DMA_NUM_REC_FIFOS_PER_GROUP reception fifos per group
* - Thus, there are DMA_NUM_REC_FIFOS reception fifos per node
* - A "shadow" refers to a copy of the elements of the fifo (start, end, head,
* tail) that is maintained by these inline functions. The shadows may be
* used to calculate other values such as free space. The shadows are updated
* by these inlines whenever the hardware fifo is read or written.
*
* \note Memory consistency/coherency inside these inlines is achieved using
* mbar and msync.
*
* MBAR is used to make sure that all writes to memory issued by the
* calling core have been accepted by the memory system before
* continuing. This guarantees that writes and reads to/from different
* addresses to go in defined order.
*
* MBAR EXAMPLE 1: When a store is done to DMA SRAM, it may not complete
* for a period of time. If a counter value is set, and then an injection
* fifo tail pointer is set, DMA may see the tail pointer update and begin
* the operation before the counter value has been set. Inserting an mbar
* between the setting of the counter and the setting of the tail pointer
* guarantees that the counter will be set before the tail pointer is
* updated.
*
* MBAR EXAMPLE 2: A counter hits zero. We process the hit-zero and write
* a "clear hit zero" to DMA SRAM, and then go read that counter's hit-zero
* status (different address). The hit-zero status will still indicate
* that it hit zero, even though we have already processed it, unless an
* mbar is inserted between clearing the hit-zero and reading the hit-zero
* status.
*
* MBAR PHILOSOPHY: After DMA SRAM is updated in the DMA inline functions,
* they always do at least an mbar (possibly an msync instead...see below).
*
* MSYNC does what mbar does, plus ensures consistency across cores. That
* is, it waits for snoops (invalidations of L1 cache) on the other cores
* to complete before continuing. This guarantees that all of the cores
* will see a consistent view of memory after the msync.
*
* MSYNC EXAMPLE: When a reception counter has hit zero, we assume the
* DMA'd data is available to be read by any core. However, old copies of
* that data may still be in the L1 caches. Inserting an msync after
* detecting that a counter has hit zero guarantees that the old data has
* been removed from the L1 caches.
*
* MSYNC PHILOSOPHY: After the inline functions detect that a counter has
* hit zero, they always do an msync.
*
* SPECULATIVE EXECUTION OF MSYNC: There are cases where msync is done
* conditionally. The CPU will begin execution of both sides of the
* condition before the result of the condition has been determined.
* Then, it will cancel the execution of one side once the result of the
* condition has been determined. This speculation is unwanted when
* the first instruction on one side of the condition is msync because
* cancelling an msync is similar to executing the complete msync.
* To avoid this speculative execution of msync, we call
* _bgp_msync_nonspeculative(). This will trick the CPU so it won't begin
* the msync until the result of the condition is known.
*
* CALLER ADVICE: Users of these functions should not need to do
* mbar/msync themselves, unless they are doing something like the
* following: Read a counter and operate on the result when the counter
* hasn't reached zero. The caller will need to perform an msync after
* reading the counter in order to ensure that snoops have completed
* on all CPUs before operating on the DMA'd data.
*/
#include <common/namespace.h>
__BEGIN_DECLS
/*!
* \brief __INLINE__ definition
*
* Option 1:
* Make all functions be "static inline":
* - They are inlined if the compiler can do it
* - If the compiler does not inline it, a single copy of the function is
* placed in the translation unit (eg. xxx.c)for use within that unit.
* The function is not externalized for use by another unit...we want this
* so we don't end up with multiple units exporting the same function,
* which would result in linker errors.
*
* Option 2:
* A GNU C model: Use "extern inline" in a common header (this one) and provide
* a definition in a .c file somewhere, perhaps using macros to ensure that the
* same code is used in each case. For instance, in the header file:
*
\verbatim
#ifndef INLINE
# define INLINE extern inline
#endif
INLINE int max(int a, int b) {
return a > b ? a : b;
}
\endverbatim
*
* ...and in exactly one source file (in runtime/SPI), that is included in a
* library...
*
\verbatim
#define INLINE
#include "header.h"
\endverbatim
*
* This allows inlining, where possible, but when not possible, only one
* instance of the function is in storage (in the library).
*/
#ifndef __INLINE__
#define __INLINE__ extern inline
#endif
#include <spi/DMA_Assert.h>
#include <spi/kernel_interface.h>
/*!
* \brief Number of fifo groups
*/
#define DMA_NUM_FIFO_GROUPS 4
/*!
* \brief Hardware DMA Fifo
*
* This maps the hardware fifo (the DMA SRAM) for a fifo. These fields are
* common for injection and reception fifos.
*
* The fifo represents a physically contiguous block of memory.
*
*/
typedef struct DMA_FifoHW_t
{
volatile unsigned pa_start; /*!< RW fifo start address.
16B-aligned 4-bit shifted address. */
volatile unsigned pa_end; /*!< RW fifo end address.
16B-aligned 4-bit shifted address. */
volatile unsigned pa_head; /*!< RW fifo head pointer.
16B-aligned 4-bit shifted address.
Injection fifo head moved by DMA.
Reception fifo head moved by cores.
Remote get injection fifo head moved
by DMA. */
volatile unsigned pa_tail; /*!< RW fifo tail pointer.
16B-aligned 4-bit shifted address.
Injection fifo tail moved by cores.
Reception fifo tail moved by DMA.
Remote get injection fifo tail moved
by DMA. */
}
DMA_FifoHW_t;
/*!
* \brief Software DMA Fifo structure
*
* This structure contains a pointer to the hardware fifo, and other fields that
* describe software's view of the fifo. These fields are common for injection
* and reception fifos.
*
* \todo Some more careful thought should be given how to group these so as to
* get best memory system performance.
* eg. Probably want to ALIGN_L3_CACHE the fifo_hw_ptr.
* Might want to have an assert to check that sizeof( DMA_Fifo_t)
* is 32.
* COMMENT: I think below definition puts the entire structure in one
* L1 line.
*/
typedef struct DMA_Fifo_t
{
DMA_FifoHW_t *fifo_hw_ptr; /*!< Pointer to hardware fifo. */
unsigned int free_space; /*!< Shadow of how much free space is in the
fifo, in units of 16B quads. */
unsigned int fifo_size; /*!< Shadow of how much total space is in the
fifo, in units of 16B quads. */
unsigned int pa_start; /*!< Physical address of the start. (shadow)
16B-aligned 4-bit shifted address.
Enables simple calculation of va_head,
va_tail, and va_end. */
/*!
* \note The following 4 fields are shadows of the hardware fifo.
* They should be in the same L1 cache line for performance.
* They are updated by the inline functions in this file upon each
* read or write to the fifo.
*/
void *va_start; /*!< Shadow of the virtual address start of
the fifo. Must be 32B aligned. */
void *va_head; /*!< Shadow of the virtual address head of
the fifo. */
void *va_tail; /*!< Shadow of the virtual address tail of
the fifo. */
void *va_end; /*!< Shadow of the virtual address end of
the fifo. Must be 32B aligned. */
}
/*!
* With above, there should be 8 fields x 4 bytes/field = 32 bytes in the
* structure. Below ensures these 32 bytes are in the same cache line.
*/
ALIGN_L1D_CACHE DMA_Fifo_t;
/*
*------------------------------------------------------------------------------
* The following functions operate on fields in the hardware and software fifo
* structures.
*------------------------------------------------------------------------------
*/
/*!
* \brief Update DMA Fifo Free Space from the Shadow
*
* Force a recalculation of a DMA fifo's amount of free space, given a software
* fifo structure.
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \return None
*
* \note WARNING: The calculation is based on the current shadow values of the
* head and tail, not the actual hardware values.
*
*/
__INLINE__ void DMA_FifoUpdateFreeSpaceFromShadow(
DMA_Fifo_t *f_ptr
)
{
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
/*
* Recompute the amount of free space in the fifo, given the current shadows.
*/
if ( f_ptr->va_tail >= f_ptr->va_head)
{
f_ptr->free_space = f_ptr->fifo_size -
( ( (unsigned)(f_ptr->va_tail) -
(unsigned)(f_ptr->va_head) ) >> 4 );
}
else
{
f_ptr->free_space = ( (unsigned)(f_ptr->va_head) -
(unsigned)(f_ptr->va_tail) ) >> 4;
}
}
/*!
* \brief Get DMA Fifo Start Virtual Address from the Shadow
*
* Get a DMA fifo's "start" virtual address, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_start The virtual address of the start of the fifo
*
* \note WARNING: This function does not read the DMA SRAM, but instead returns
* the current shadow va_start. To actually issue a read to the
* DMA, use DMA_FifoGetStartPa().
*/
__INLINE__ void * DMA_FifoGetStartFromShadow(
DMA_Fifo_t *f_ptr
)
{
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
return f_ptr->va_start;
}
/*!
* \brief Get DMA Fifo Head Virtual Address
*
* Get a DMA fifo's "head" virtual address, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_head The virtual address of the head of the fifo
*
* \post va_head is recalculated from the current hardware head, updated in
* the software fifo structure, and returned. Additionally, the free
* space in the software fifo structure is updated.
*
*/
__INLINE__ void * DMA_FifoGetHead(
DMA_Fifo_t *f_ptr
)
{
unsigned int val;
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
/* Read the DMA to get the head.
* Recompute va_head based upon the va_start and the current hardware head.
* Update free_space.
*/
val = f_ptr->fifo_hw_ptr->pa_head;
f_ptr->va_head = (char*)( (unsigned)f_ptr->va_start +
( ( val - f_ptr->pa_start ) << 4 ) );
DMA_FifoUpdateFreeSpaceFromShadow( f_ptr );
return f_ptr->va_head;
}
/*!
* \brief Get DMA Fifo Head Virtual Address Without Updating Free Space
*
* Get a DMA fifo's "head" virtual address, given a software fifo structure,
* without updating the fifo's free space. It is up to the caller to ensure
* this update occurs later, if necessary.
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_head The virtual address of the head of the fifo
*
* \post va_head is recalculated from the current hardware head, updated in
* the software fifo structure, and returned.
*
*/
__INLINE__ void * DMA_FifoGetHeadNoFreeSpaceUpdate(
DMA_Fifo_t *f_ptr
)
{
unsigned int val;
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
/* Read the DMA to get the head.
* Recompute va_head based upon the va_start and the current hardware head.
*/
val = f_ptr->fifo_hw_ptr->pa_head;
f_ptr->va_head = (char*)( (unsigned)f_ptr->va_start +
( ( val - f_ptr->pa_start ) << 4 ) );
return f_ptr->va_head;
}
/*!
* \brief Get DMA Fifo Tail Virtual Address
*
* Get a DMA fifo's "tail" virtual address, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_tail The virtual address of the tail of the fifo
*
* \post va_tail is recalculated from the current hardware tail, updated in
* the software fifo structure, and returned. Additionally, the free
* space in the software fifo structure is updated.
*
*/
__INLINE__ void * DMA_FifoGetTail(
DMA_Fifo_t *f_ptr
)
{
unsigned int val;
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
/* Read the DMA to get the tail.
* Recompute va_tail based upon the va_start and the current hardware tail.
* Update free_space.
*/
val = f_ptr->fifo_hw_ptr->pa_tail;
f_ptr->va_tail = (char*)( (unsigned)f_ptr->va_start +
( ( val - f_ptr->pa_start ) << 4 ) );
DMA_FifoUpdateFreeSpaceFromShadow( f_ptr );
return f_ptr->va_tail;
}
/*!
* \brief Get DMA Fifo Tail Virtual Address Without Updating Free Space
*
* Get a DMA fifo's "tail" virtual address, given a software fifo structure,
* without updating the fifo's free space. It is up to the caller to
* invoke DMA_FifoUpdateFreeSpaceFromShadow() at a later time.
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_tail The virtual address of the tail of the fifo
*
* \post va_tail is recalculated from the current hardware tail, updated in
* the software fifo structure, and returned.
*
*/
__INLINE__ void * DMA_FifoGetTailNoFreeSpaceUpdate(
DMA_Fifo_t *f_ptr
)
{
unsigned int val;
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
/* Read the DMA to get the tail.
* Recompute va_tail based upon the va_start and the current hardware tail.
*/
val = f_ptr->fifo_hw_ptr->pa_tail;
f_ptr->va_tail = (char*)( (unsigned)f_ptr->va_start +
( ( val - f_ptr->pa_start ) << 4 ) );
return f_ptr->va_tail;
}
/*!
* \brief Get DMA Fifo Tail Virtual Address from Shadow
*
* Get a DMA fifo's "tail" virtual address, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_tail The virtual address of the tail of the fifo
*
* \post va_tail is obtained from the shadow, NOT recalculated from the
* current hardware tail. The free space in the software fifo
* structure is NOT updated.
*
*/
__INLINE__ void * DMA_FifoGetTailFromShadow(
DMA_Fifo_t *f_ptr
)
{
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
return f_ptr->va_tail;
}
/*!
* \brief Get DMA Fifo End Virtual Address from the Shadow
*
* Get a DMA fifo's "end" virtual address, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval va_end The virtual address of the end of the fifo
*
* \note WARNING: This function does not read the DMA SRAM, but instead returns
* the current shadow va_end. To actually issue a read to the
* DMA, use DMA_FifoGetEndPa().
*/
__INLINE__ void * DMA_FifoGetEndFromShadow(
DMA_Fifo_t *f_ptr
)
{
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
return f_ptr->va_end;
}
/*!
* \brief Get DMA Fifo Size
*
* Get a DMA fifo's size, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval size The size of the DMA fifo, in units of 16B quads.
*
* \note WARNING: This function does not calculate the size based on the DMA
* SRAM's current start and end values, but instead returns the
* size that was calculated when the fifo was initialized.
*/
__INLINE__ unsigned int DMA_FifoGetSize(
DMA_Fifo_t *f_ptr
)
{
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
return f_ptr->fifo_size;
}
/*!
* \brief Get DMA Fifo Free Space With No Update Calculation
*
* Get a DMA fifo's amount of free space, given a software fifo structure.
* Do not perform update calculations.
*
* \param[in] f_ptr Pointer to the software fifo structure
*
* \retval freeSpace The amount of free space in the fifo, in units of
* 16B quads.
*/
__INLINE__ unsigned int DMA_FifoGetFreeSpaceNoUpdateCalculation(
DMA_Fifo_t *f_ptr
)
{
SPI_assert( f_ptr != NULL );
return f_ptr->free_space;
}
/*!
* \brief Get DMA Fifo Free Space
*
* Get a DMA fifo's amount of free space, given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
* \param[in] read_head Indicates whether to read the head from the hardware
* fifo before calculating the free space.
* - 1 means to read the hardware head
* - 0 means to use the current head shadow
* \param[in] read_tail Indicates whether to read the tail from the hardware
* fifo before calculating the free space.
* - 1 means to read the hardware tail
* - 0 means to use the current tail shadow
*
* \retval freeSpace The amount of free space in the fifo, in units of
* 16B quads.
*
* \note If both read_head and read_tail are false, the amount of free space is
* calculated based on the current shadow values of head and tail.
*/
__INLINE__ unsigned int DMA_FifoGetFreeSpace(
DMA_Fifo_t *f_ptr,
unsigned int read_head,
unsigned int read_tail
)
{
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
SPI_assert( read_head == 1 || read_head == 0 );
SPI_assert( read_tail == 1 || read_tail == 0 );
/*
* If both read_head and read_tail are 0, return the current shadow.
* If read_head != 0, read the head of the fifo first and recompute free space.
* If read_tail != 0, read the tail of the fifo first and recompute free space.
*/
if ( (read_head == 0) && ( read_tail == 0) )
DMA_FifoUpdateFreeSpaceFromShadow( f_ptr);
else
{
if ( read_head == 1) DMA_FifoGetHead(f_ptr); /* This does an update */
/* of the free space. */
if ( read_tail == 1) DMA_FifoGetTail(f_ptr); /* This does an update */
/* of the free space. */
}
return f_ptr->free_space;
}
/*!
* \brief Set DMA Fifo Head
*
* Set a DMA fifo's "head", given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
* \param[in] va_head Virtual address of the head to be set
*
* \return None
*
* \post va_head is set in both the hardware and software fifo structures,
* and the fifo free space is recalculated.
*
* \note Normally, for an injection fifo, the dma manipulates the head, but in
* optimized persistant communications the core can do it if it is sure
* the fifo is empty at the time this is called.
*/
__INLINE__ void DMA_FifoSetHead(
DMA_Fifo_t *f_ptr,
void *va_head
)
{
unsigned int pa_head;
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
SPI_assert( va_head >= f_ptr->va_start &&
va_head < f_ptr->va_end );
/*
* Calculate new pa_head based on the shadow pa_start and va_start.
*/
pa_head = f_ptr->pa_start + ( ( (unsigned)va_head -
(unsigned)f_ptr->va_start ) >> 4 );
/*
* Set the hardware head
*/
f_ptr->fifo_hw_ptr->pa_head = pa_head;
_bgp_mbar();
/*
* Update the software fifo structure's head and free space.
*/
f_ptr->va_head = va_head;
DMA_FifoUpdateFreeSpaceFromShadow( f_ptr );
}
/*!
* \brief Set DMA Fifo Tail
*
* Set a DMA fifo's "tail", given a software fifo structure
*
* \param[in] f_ptr Pointer to the software fifo structure
* \param[in] va_tail Virtual address of the tail to be set
*
* \return None
*
* \post va_tail is set in both the hardware and software fifo structures,
* and the fifo free space is recalculated.
*
*/
__INLINE__ void DMA_FifoSetTail(
DMA_Fifo_t *f_ptr,
void *va_tail
)
{
unsigned int pa_tail;
SPI_assert( f_ptr != NULL );
SPI_assert( f_ptr->fifo_hw_ptr != NULL );
SPI_assert( va_tail >= f_ptr->va_start &&
va_tail < f_ptr->va_end );
/*
* Calculate new pa_tail based on the shadow pa_start and va_start.
*/
pa_tail = f_ptr->pa_start + ( ( (unsigned)va_tail -
(unsigned)f_ptr->va_start ) >> 4 );
/*
* Set the hardware tail
*/
f_ptr->fifo_hw_ptr->pa_tail = pa_tail;
_bgp_mbar();
/*
* Update the software fifo structure's tail and free space.
*/
f_ptr->va_tail = va_tail;
DMA_FifoUpdateFreeSpaceFromShadow( f_ptr );
}
/*
*------------------------------------------------------------------------------
* The following functions operate directly on the hardware fifo. Normally,
* users should use the software fifo routines (previously defined), but for
* bringup or diagnostics, it may be desirable to use these.
*------------------------------------------------------------------------------
*/
/*!
* \brief Set DMA Hardware Fifo Start
*
* Set a DMA fifo's "start", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
* \param[in] pa_start Physical address of the start to be set.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
* \note This function does an MBAR after setting the fifo to ensure the
* writes have been accepted by the memory system before allowing other
* memory accesses to to occur.
*/
__INLINE__ void DMA_FifoSetStartPa(
DMA_FifoHW_t *fifo_hw_ptr,
unsigned int pa_start
)
{
SPI_assert( fifo_hw_ptr != NULL );
fifo_hw_ptr->pa_start = pa_start;
_bgp_mbar();
}
/*!
* \brief Set DMA Hardware Fifo Head
*
* Set a DMA fifo's "head", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
* \param[in] pa_head Physical address of the head to be set.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
* \note This function does an MBAR after setting the fifo to ensure the
* writes have been accepted by the memory system before allowing other
* memory accesses to to occur.
*/
__INLINE__ void DMA_FifoSetHeadPa(
DMA_FifoHW_t *fifo_hw_ptr,
unsigned int pa_head
)
{
SPI_assert( fifo_hw_ptr != NULL );
fifo_hw_ptr->pa_head = pa_head;
_bgp_mbar();
}
/*!
* \brief Set DMA Hardware Fifo Tail
*
* Set a DMA fifo's "tail", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
* \param[in] pa_tail Physical address of the tail to be set.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
* \note This function does an MBAR after setting the fifo to ensure the
* writes have been accepted by the memory system before allowing other
* memory accesses to to occur.
*/
__INLINE__ void DMA_FifoSetTailPa(
DMA_FifoHW_t *fifo_hw_ptr,
unsigned int pa_tail
)
{
SPI_assert( fifo_hw_ptr != NULL );
fifo_hw_ptr->pa_tail = pa_tail;
_bgp_mbar();
}
/*!
* \brief Set DMA Hardware Fifo End
*
* Set a DMA fifo's "end", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
* \param[in] pa_end Physical address of the end to be set.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
* \note This function does an MBAR after setting the fifo to ensure the
* writes have been accepted by the memory system before allowing other
* memory accesses to to occur.
*/
__INLINE__ void DMA_FifoSetEndPa(
DMA_FifoHW_t *fifo_hw_ptr,
unsigned int pa_end
)
{
SPI_assert( fifo_hw_ptr != NULL );
fifo_hw_ptr->pa_end = pa_end;
_bgp_mbar();
}
/*!
* \brief Get DMA Hardware Fifo Start
*
* Get a DMA fifo's "start", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
*
* \retval pa_start Physical address of the fifo start.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
*/
__INLINE__ unsigned int DMA_FifoGetStartPa(
DMA_FifoHW_t *fifo_hw_ptr
)
{
SPI_assert( fifo_hw_ptr != NULL );
return fifo_hw_ptr->pa_start;
}
/*!
* \brief Get DMA Hardware Fifo Head
*
* Get a DMA fifo's "head", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
*
* \retval pa_head Physical address of the fifo head.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
*/
__INLINE__ unsigned int DMA_FifoGetHeadPa(
DMA_FifoHW_t *fifo_hw_ptr
)
{
SPI_assert( fifo_hw_ptr != NULL );
return fifo_hw_ptr->pa_head;
}
/*!
* \brief Get DMA Hardware Fifo Tail
*
* Get a DMA fifo's "tail", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
*
* \retval pa_tail Physical address of the fifo tail.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
*/
__INLINE__ unsigned int DMA_FifoGetTailPa(
DMA_FifoHW_t *fifo_hw_ptr
)
{
SPI_assert( fifo_hw_ptr != NULL );
return fifo_hw_ptr->pa_tail;
}
/*!
* \brief Get DMA Hardware Fifo End
*
* Get a DMA fifo's "end", given a hardware fifo structure
*
* \param[in] fifo_hw_ptr Pointer to the hardware fifo structure
*
* \retval pa_end Physical address of the fifo end.
* 16B-aligned 4-bit shifted physical address.
*
* \return None
*
*/
__INLINE__ unsigned int DMA_FifoGetEndPa(
DMA_FifoHW_t *fifo_hw_ptr
)
{
SPI_assert( fifo_hw_ptr != NULL );
return fifo_hw_ptr->pa_end;
}
__END_DECLS
#endif