574 lines
17 KiB
C
574 lines
17 KiB
C
|
/*******************************************************************************
|
||
|
Copyright (C) Marvell International Ltd. and its affiliates
|
||
|
|
||
|
This software file (the "File") is owned and distributed by Marvell
|
||
|
International Ltd. and/or its affiliates ("Marvell") under the following
|
||
|
alternative licensing terms. Once you have made an election to distribute the
|
||
|
File under one of the following license alternatives, please (i) delete this
|
||
|
introductory statement regarding license alternatives, (ii) delete the two
|
||
|
license alternatives that you have not elected to use and (iii) preserve the
|
||
|
Marvell copyright notice above.
|
||
|
|
||
|
********************************************************************************
|
||
|
Marvell Commercial License Option
|
||
|
|
||
|
If you received this File from Marvell and you have entered into a commercial
|
||
|
license agreement (a "Commercial License") with Marvell, the File is licensed
|
||
|
to you under the terms of the applicable Commercial License.
|
||
|
|
||
|
********************************************************************************
|
||
|
Marvell GPL License Option
|
||
|
|
||
|
If you received this File from Marvell, you may opt to use, redistribute and/or
|
||
|
modify this File in accordance with the terms and conditions of the General
|
||
|
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
|
||
|
available along with the File in the license.txt file or by writing to the Free
|
||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
|
||
|
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
|
||
|
|
||
|
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
|
||
|
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
|
||
|
DISCLAIMED. The GPL License provides additional details about this warranty
|
||
|
disclaimer.
|
||
|
********************************************************************************
|
||
|
Marvell BSD License Option
|
||
|
|
||
|
If you received this File from Marvell, you may opt to use, redistribute and/or
|
||
|
modify this File under the following licensing terms.
|
||
|
Redistribution and use in source and binary forms, with or without modification,
|
||
|
are permitted provided that the following conditions are met:
|
||
|
|
||
|
* Redistributions of source code must retain the above copyright notice,
|
||
|
this list of conditions and the following disclaimer.
|
||
|
|
||
|
* Redistributions in binary form must reproduce the above copyright
|
||
|
notice, this list of conditions and the following disclaimer in the
|
||
|
documentation and/or other materials provided with the distribution.
|
||
|
|
||
|
* Neither the name of Marvell nor the names of its contributors may be
|
||
|
used to endorse or promote products derived from this software without
|
||
|
specific prior written permission.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "spi/mvSpi.h"
|
||
|
#include "spi/mvSpiSpec.h"
|
||
|
|
||
|
#include "ctrlEnv/mvCtrlEnvLib.h"
|
||
|
|
||
|
/* #define MV_DEBUG */
|
||
|
#ifdef MV_DEBUG
|
||
|
#define DB(x) x
|
||
|
#define mvOsPrintf printf
|
||
|
#else
|
||
|
#define DB(x)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpi16bitDataTxRx - Transmt and receive data
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Tx data and block waiting for data to be transmitted
|
||
|
*
|
||
|
********************************************************************************/
|
||
|
static MV_STATUS mvSpi16bitDataTxRx (MV_U16 txData, MV_U16 * pRxData)
|
||
|
{
|
||
|
MV_U32 i;
|
||
|
MV_BOOL ready = MV_FALSE;
|
||
|
|
||
|
/* First clear the bit in the interrupt cause register */
|
||
|
MV_REG_WRITE(MV_SPI_INT_CAUSE_REG, 0x0);
|
||
|
|
||
|
/* Transmit data */
|
||
|
MV_REG_WRITE(MV_SPI_DATA_OUT_REG, MV_16BIT_LE(txData));
|
||
|
|
||
|
/* wait with timeout for memory ready */
|
||
|
for (i=0; i<MV_SPI_WAIT_RDY_MAX_LOOP; i++)
|
||
|
{
|
||
|
if (MV_REG_READ(MV_SPI_INT_CAUSE_REG))
|
||
|
{
|
||
|
ready = MV_TRUE;
|
||
|
break;
|
||
|
}
|
||
|
#ifdef MV_SPI_SLEEP_ON_WAIT
|
||
|
mvOsSleep(1);
|
||
|
#endif /* MV_SPI_SLEEP_ON_WAIT */
|
||
|
}
|
||
|
|
||
|
if (!ready)
|
||
|
return MV_TIMEOUT;
|
||
|
|
||
|
/* check that the RX data is needed */
|
||
|
if (pRxData)
|
||
|
{
|
||
|
if ((MV_U32)pRxData & 0x1) /* check if address is not alligned to 16bit */
|
||
|
{
|
||
|
#if defined(MV_CPU_LE)
|
||
|
/* perform the data write to the buffer in two stages with 8bit each */
|
||
|
MV_U8 * bptr = (MV_U8*)pRxData;
|
||
|
MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG));
|
||
|
*bptr = (data & 0xFF);
|
||
|
++bptr;
|
||
|
*bptr = ((data >> 8) & 0xFF);
|
||
|
|
||
|
#elif defined(MV_CPU_BE)
|
||
|
|
||
|
/* perform the data write to the buffer in two stages with 8bit each */
|
||
|
MV_U8 * bptr = (MV_U8 *)pRxData;
|
||
|
MV_U16 data = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG));
|
||
|
*bptr = ((data >> 8) & 0xFF);
|
||
|
++bptr;
|
||
|
*bptr = (data & 0xFF);
|
||
|
|
||
|
#else
|
||
|
#error "CPU endianess isn't defined!\n"
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
else
|
||
|
*pRxData = MV_16BIT_LE(MV_REG_READ(MV_SPI_DATA_IN_REG));
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpi8bitDataTxRx - Transmt and receive data (8bits)
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Tx data and block waiting for data to be transmitted
|
||
|
*
|
||
|
********************************************************************************/
|
||
|
static MV_STATUS mvSpi8bitDataTxRx (MV_U8 txData, MV_U8 * pRxData)
|
||
|
{
|
||
|
MV_U32 i;
|
||
|
MV_BOOL ready = MV_FALSE;
|
||
|
|
||
|
/* First clear the bit in the interrupt cause register */
|
||
|
MV_REG_WRITE(MV_SPI_INT_CAUSE_REG, 0x0);
|
||
|
|
||
|
/* Transmit data */
|
||
|
MV_REG_WRITE(MV_SPI_DATA_OUT_REG, txData);
|
||
|
|
||
|
/* wait with timeout for memory ready */
|
||
|
for (i=0; i<MV_SPI_WAIT_RDY_MAX_LOOP; i++)
|
||
|
{
|
||
|
if (MV_REG_READ(MV_SPI_INT_CAUSE_REG))
|
||
|
{
|
||
|
ready = MV_TRUE;
|
||
|
break;
|
||
|
}
|
||
|
#ifdef MV_SPI_SLEEP_ON_WAIT
|
||
|
mvOsSleep(1);
|
||
|
#endif /* MV_SPI_SLEEP_ON_WAIT */
|
||
|
}
|
||
|
|
||
|
if (!ready)
|
||
|
return MV_TIMEOUT;
|
||
|
|
||
|
/* check that the RX data is needed */
|
||
|
if (pRxData)
|
||
|
*pRxData = MV_REG_READ(MV_SPI_DATA_IN_REG);
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
#####################################################################################
|
||
|
#####################################################################################
|
||
|
*/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiInit - Initialize the SPI controller
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Perform the neccessary initialization in order to be able to send an
|
||
|
* receive over the SPI interface.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* serialBaudRate: Baud rate (SPI clock frequency)
|
||
|
* use16BitMode: Whether to use 2bytes (MV_TRUE) or 1bytes (MV_FALSE)
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_STATUS mvSpiInit (MV_U32 serialBaudRate)
|
||
|
{
|
||
|
MV_STATUS ret;
|
||
|
|
||
|
/* Set the serial clock */
|
||
|
if ((ret = mvSpiBaudRateSet(serialBaudRate)) != MV_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* For devices in which the SPI is muxed on the MPP with other interfaces*/
|
||
|
mvMPPConfigToSPI();
|
||
|
|
||
|
/* Configure the default SPI mode to be 16bit */
|
||
|
MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* Fix ac timing on SPI in 6183 and 6183L only */
|
||
|
if ((mvCtrlModelGet() == MV_6183_DEV_ID) ||
|
||
|
(mvCtrlModelGet() == MV_6183L_DEV_ID))
|
||
|
MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, BIT14);
|
||
|
|
||
|
/* Verify that the CS is deasserted */
|
||
|
mvSpiCsDeassert();
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiBaudRateSet - Set the Frequency of the SPI clock
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Set the Prescale bits to adapt to the requested baud rate (the clock
|
||
|
* used for thr SPI).
|
||
|
*
|
||
|
* INPUT:
|
||
|
* serialBaudRate: Baud rate (SPI clock frequency)
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_STATUS mvSpiBaudRateSet (MV_U32 serialBaudRate)
|
||
|
{
|
||
|
MV_U8 i;
|
||
|
/* MV_U8 preScale[32] = {1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||
|
2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
|
||
|
*/
|
||
|
MV_U8 preScale[14] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
|
||
|
MV_U8 bestPrescaleIndx = 100;
|
||
|
MV_U32 minBaudOffset = 0xFFFFFFFF;
|
||
|
MV_U32 cpuClk = mvBoardTclkGet(); /*mvCpuPclkGet();*/
|
||
|
MV_U32 tempReg;
|
||
|
|
||
|
/* Find the best prescale configuration - less or equal */
|
||
|
for (i=0; i<14; i++)
|
||
|
{
|
||
|
/* check for higher - irrelevent */
|
||
|
if ((cpuClk / preScale[i]) > serialBaudRate)
|
||
|
continue;
|
||
|
|
||
|
/* check for exact fit */
|
||
|
if ((cpuClk / preScale[i]) == serialBaudRate)
|
||
|
{
|
||
|
bestPrescaleIndx = i;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* check if this is better than the previous one */
|
||
|
if ((serialBaudRate - (cpuClk / preScale[i])) < minBaudOffset)
|
||
|
{
|
||
|
minBaudOffset = (serialBaudRate - (cpuClk / preScale[i]));
|
||
|
bestPrescaleIndx = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bestPrescaleIndx > 14)
|
||
|
{
|
||
|
mvOsPrintf("%s ERROR: SPI baud rate prescale error!\n", __FUNCTION__);
|
||
|
return MV_OUT_OF_RANGE;
|
||
|
}
|
||
|
|
||
|
/* configure the Prescale */
|
||
|
tempReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG);
|
||
|
tempReg = ((tempReg & ~MV_SPI_CLK_PRESCALE_MASK) | (bestPrescaleIndx + 0x12));
|
||
|
MV_REG_WRITE(MV_SPI_IF_CONFIG_REG, tempReg);
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiCsAssert - Assert the Chip Select pin indicating a new transfer
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Assert The chip select - used to select an external SPI device
|
||
|
*
|
||
|
* INPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
********************************************************************************/
|
||
|
MV_VOID mvSpiCsAssert(MV_VOID)
|
||
|
{
|
||
|
/* For devices in which the SPI is muxed on the MPP with other interfaces*/
|
||
|
mvMPPConfigToSPI();
|
||
|
|
||
|
MV_REG_BIT_SET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiCsDeassert - DeAssert the Chip Select pin indicating the end of a
|
||
|
* SPI transfer sequence
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* DeAssert the chip select pin
|
||
|
*
|
||
|
* INPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
********************************************************************************/
|
||
|
MV_VOID mvSpiCsDeassert(MV_VOID)
|
||
|
{
|
||
|
MV_REG_BIT_RESET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK);
|
||
|
|
||
|
/* For devices in which the SPI is muxed on the MPP with other interfaces*/
|
||
|
mvMPPConfigToDefault();
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiRead - Read a buffer over the SPI interface
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Receive (read) a buffer over the SPI interface in 16bit chunks. If the
|
||
|
* buffer size is odd, then the last chunk will be 8bits. Chip select is not
|
||
|
* handled at this level.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* pRxBuff: Pointer to the buffer to hold the received data
|
||
|
* buffSize: length of the pRxBuff
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* pRxBuff: Pointer to the buffer with the received data
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_STATUS mvSpiRead (MV_U8* pRxBuff, MV_U32 buffSize)
|
||
|
{
|
||
|
MV_STATUS ret;
|
||
|
MV_U32 bytesLeft = buffSize;
|
||
|
MV_U16* rxPtr = (MV_U16*)pRxBuff;
|
||
|
|
||
|
/* check for null parameters */
|
||
|
if (pRxBuff == NULL)
|
||
|
{
|
||
|
mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
|
||
|
return MV_BAD_PARAM;
|
||
|
}
|
||
|
|
||
|
/* Check that the buffer pointer and the buffer size are 16bit aligned */
|
||
|
if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0))
|
||
|
{
|
||
|
/* Verify that the SPI mode is in 16bit mode */
|
||
|
MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* TX/RX as long we have complete 16bit chunks */
|
||
|
while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE)
|
||
|
{
|
||
|
/* Transmitted and wait for the transfer to be completed */
|
||
|
if ((ret = mvSpi16bitDataTxRx(MV_SPI_DUMMY_WRITE_16BITS, rxPtr)) != MV_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* increment the pointers */
|
||
|
rxPtr++;
|
||
|
bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Verify that the SPI mode is in 8bit mode */
|
||
|
MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* TX/RX in 8bit chanks */
|
||
|
while (bytesLeft > 0)
|
||
|
{
|
||
|
/* Transmitted and wait for the transfer to be completed */
|
||
|
if ((ret = mvSpi8bitDataTxRx(MV_SPI_DUMMY_WRITE_8BITS, pRxBuff)) != MV_OK)
|
||
|
return ret;
|
||
|
/* increment the pointers */
|
||
|
pRxBuff++;
|
||
|
bytesLeft--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiWrite - Transmit a buffer over the SPI interface
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Transmit a buffer over the SPI interface in 16bit chunks. If the
|
||
|
* buffer size is odd, then the last chunk will be 8bits. No chip select
|
||
|
* action is taken.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* pTxBuff: Pointer to the buffer holding the TX data
|
||
|
* buffSize: length of the pTxBuff
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* None.
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_STATUS mvSpiWrite(MV_U8* pTxBuff, MV_U32 buffSize)
|
||
|
{
|
||
|
MV_STATUS ret;
|
||
|
MV_U32 bytesLeft = buffSize;
|
||
|
MV_U16* txPtr = (MV_U16*)pTxBuff;
|
||
|
|
||
|
/* check for null parameters */
|
||
|
if (pTxBuff == NULL)
|
||
|
{
|
||
|
mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
|
||
|
return MV_BAD_PARAM;
|
||
|
}
|
||
|
|
||
|
/* Check that the buffer pointer and the buffer size are 16bit aligned */
|
||
|
if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pTxBuff & 1) == 0))
|
||
|
{
|
||
|
/* Verify that the SPI mode is in 16bit mode */
|
||
|
MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* TX/RX as long we have complete 16bit chunks */
|
||
|
while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE)
|
||
|
{
|
||
|
/* Transmitted and wait for the transfer to be completed */
|
||
|
if ((ret = mvSpi16bitDataTxRx(*txPtr, NULL)) != MV_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* increment the pointers */
|
||
|
txPtr++;
|
||
|
bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
/* Verify that the SPI mode is in 8bit mode */
|
||
|
MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* TX/RX in 8bit chanks */
|
||
|
while (bytesLeft > 0)
|
||
|
{
|
||
|
/* Transmitted and wait for the transfer to be completed */
|
||
|
if ((ret = mvSpi8bitDataTxRx(*pTxBuff, NULL)) != MV_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* increment the pointers */
|
||
|
pTxBuff++;
|
||
|
bytesLeft--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* mvSpiReadWrite - Read and Write a buffer simultanuosely
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Transmit and receive a buffer over the SPI in 16bit chunks. If the
|
||
|
* buffer size is odd, then the last chunk will be 8bits. The SPI chip
|
||
|
* select is not handled implicitely.
|
||
|
*
|
||
|
* INPUT:
|
||
|
* pRxBuff: Pointer to the buffer to write the RX info in
|
||
|
* pTxBuff: Pointer to the buffer holding the TX info
|
||
|
* buffSize: length of both the pTxBuff and pRxBuff
|
||
|
*
|
||
|
* OUTPUT:
|
||
|
* pRxBuff: Pointer of the buffer holding the RX data
|
||
|
*
|
||
|
* RETURN:
|
||
|
* Success or Error code.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
MV_STATUS mvSpiReadWrite(MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize)
|
||
|
{
|
||
|
MV_STATUS ret;
|
||
|
MV_U32 bytesLeft = buffSize;
|
||
|
MV_U16* txPtr = (MV_U16*)pTxBuff;
|
||
|
MV_U16* rxPtr = (MV_U16*)pRxBuff;
|
||
|
|
||
|
/* check for null parameters */
|
||
|
if ((pRxBuff == NULL) || (pTxBuff == NULL))
|
||
|
{
|
||
|
mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
|
||
|
return MV_BAD_PARAM;
|
||
|
}
|
||
|
|
||
|
/* Check that the buffer pointer and the buffer size are 16bit aligned */
|
||
|
if ((((MV_U32)buffSize & 1) == 0) && (((MV_U32)pTxBuff & 1) == 0) && (((MV_U32)pRxBuff & 1) == 0))
|
||
|
{
|
||
|
/* Verify that the SPI mode is in 16bit mode */
|
||
|
MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* TX/RX as long we have complete 16bit chunks */
|
||
|
while (bytesLeft >= MV_SPI_16_BIT_CHUNK_SIZE)
|
||
|
{
|
||
|
/* Transmitted and wait for the transfer to be completed */
|
||
|
if ((ret = mvSpi16bitDataTxRx(*txPtr, rxPtr)) != MV_OK)
|
||
|
return ret;
|
||
|
|
||
|
/* increment the pointers */
|
||
|
txPtr++;
|
||
|
rxPtr++;
|
||
|
bytesLeft -= MV_SPI_16_BIT_CHUNK_SIZE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Verify that the SPI mode is in 8bit mode */
|
||
|
MV_REG_BIT_RESET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
|
||
|
|
||
|
/* TX/RX in 8bit chanks */
|
||
|
while (bytesLeft > 0)
|
||
|
{
|
||
|
/* Transmitted and wait for the transfer to be completed */
|
||
|
if ( (ret = mvSpi8bitDataTxRx(*pTxBuff, pRxBuff) ) != MV_OK)
|
||
|
return ret;
|
||
|
pRxBuff++;
|
||
|
pTxBuff++;
|
||
|
bytesLeft--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
|