summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2010-07-21 22:57:44 +0530
committerGary King <gking@nvidia.com>2010-07-26 15:22:39 -0700
commit51b2a84496a6426cec1f8aa56a60ea3a05e7d1f5 (patch)
treefc303d6a5a4ec2a6dfca3ac856d945def1d971bf
parentdf8cf1f41f62864ba2131cc6920d917933b908c5 (diff)
[arm/tegra]spi: Fifo should be empty before starting transfer.
It is recommended by ASIC to make sure that fifos are empty before starting any new transfer specially dma based transfer. Adding support code for this. Change-Id: Ic6b5db650b50e664b5cdd601eed9e0c3286a764b Reviewed-on: http://git-master/r/4211 Reviewed-by: Michael Hsu <mhsu@nvidia.com> Tested-by: Michael Hsu <mhsu@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_slink_hw_private.c9
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/rm_common_slink_hw_private.c9
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_hw_private.c9
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c15
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink_hw_private.h10
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_slink_hw_private.c29
6 files changed, 79 insertions, 2 deletions
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_slink_hw_private.c b/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_slink_hw_private.c
index eb26e852c892..51a2b0ac6db1 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_slink_hw_private.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_slink_hw_private.c
@@ -306,6 +306,14 @@ SlinkHwReadFromReceiveFifo(
return WordRequested;
}
+static NvBool
+SlinkHwClearFifosForNewTransfer(
+ SerialHwRegisters *pSlinkHwRegs,
+ SerialHwDataFlow DataDirection)
+{
+ return NV_FALSE;
+}
+
/**
* Initialize the slink intterface for the hw access.
*/
@@ -319,4 +327,5 @@ void NvRmPrivSpiSlinkInitSlinkInterface_v1_0(HwInterface *pSlinkInterface)
pSlinkInterface->HwSetCsSetupHoldTime = SlinkHwSetCsSetupHoldTime;
pSlinkInterface->HwWriteInTransmitFifoFxn = SlinkHwWriteInTransmitFifo;
pSlinkInterface->HwReadFromReceiveFifoFxn = SlinkHwReadFromReceiveFifo;
+ pSlinkInterface->HwClearFifosForNewTransferFxn = SlinkHwClearFifosForNewTransfer;
}
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/rm_common_slink_hw_private.c b/arch/arm/mach-tegra/nvrm/io/ap15/rm_common_slink_hw_private.c
index 3065c312323c..4351c859742e 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/rm_common_slink_hw_private.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/rm_common_slink_hw_private.c
@@ -46,6 +46,7 @@
#include "nvrm_hardware_access.h"
#include "nvassert.h"
#include "nvos.h"
+#include "linux/kernel.h"
#define SLINK_REG_READ32(pSlinkHwRegsVirtBaseAdd, reg) \
NV_READ32((pSlinkHwRegsVirtBaseAdd) + ((SLINK_##reg##_0)/4))
@@ -395,15 +396,19 @@ static NvError SlinkHwGetTransferStatus(SerialHwRegisters *pSlinkHwRegs,
// Check for the receive error
if (DataFlow & SerialHwDataFlow_Rx)
{
- if (StatusReg & RX_ERROR_STATUS)
+ if (StatusReg & RX_ERROR_STATUS) {
+ pr_err("SPI RX ERROR Status 0x%x\n",StatusReg);
return NvError_SpiReceiveError;
+ }
}
// Check for the transmit error
if (DataFlow & SerialHwDataFlow_Tx)
{
- if (StatusReg & TX_ERROR_STATUS)
+ if (StatusReg & TX_ERROR_STATUS) {
+ pr_err("SPI TX ERROR Status 0x%x\n",StatusReg);
return NvError_SpiTransmitError;
+ }
}
return NvSuccess;
}
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_hw_private.c b/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_hw_private.c
index 652b25aa3f08..2768cec033bc 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_hw_private.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_hw_private.c
@@ -614,6 +614,14 @@ static NvBool SpiHwIsTransferCompleted(SerialHwRegisters *pSpiHwRegs)
return NV_TRUE;
}
+static NvBool
+SpiHwClearFifosForNewTransfer(
+ SerialHwRegisters *pSpiHwRegs,
+ SerialHwDataFlow DataDirection)
+{
+ return NV_FALSE;
+}
+
/**
* Initialize the spi intterface for the hw access.
*/
@@ -642,4 +650,5 @@ void NvRmPrivSpiSlinkInitSpiInterface(HwInterface *pSpiInterface)
pSpiInterface->HwClearTransferStatusFxn = SpiHwClearTransferStatus;
pSpiInterface->HwGetTransferStatusFxn = SpiHwGetTransferStatus;
pSpiInterface->HwIsTransferCompletedFxn = SpiHwIsTransferCompleted;
+ pSpiInterface->HwClearFifosForNewTransferFxn = SpiHwClearFifosForNewTransfer;
}
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c b/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c
index 2e191e863428..691e3c61fcb6 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c
@@ -1971,6 +1971,7 @@ static NvError MasterModeReadWriteDma(
NvU8 *pWriteReqCpuBuffer = NULL;
NvU32 WrittenWord;
NvBool IsOnlyUseSWCS;
+ NvBool IsFlushRequired;
hRmSpiSlink->IsUsingApbDma = NV_TRUE;
hRmSpiSlink->hHwInterface->HwSetInterruptSourceFxn(&hRmSpiSlink->HwRegs,
@@ -2043,6 +2044,12 @@ static NvError MasterModeReadWriteDma(
hRmSpiSlink->IsChipSelConfigured = NV_TRUE;
}
+ IsFlushRequired = hRmSpiSlink->hHwInterface->HwClearFifosForNewTransferFxn(
+ &hRmSpiSlink->HwRegs, hRmSpiSlink->CurrentDirection);
+ if (IsFlushRequired)
+ {
+ WARN_ON(1);
+ }
hRmSpiSlink->hHwInterface->HwSetDmaTransferSizeFxn(&hRmSpiSlink->HwRegs,
CurrentTransPacket);
@@ -2225,6 +2232,7 @@ static NvError SlaveModeSpiStartReadWriteDma(
NvU32 TriggerLevel;
NvU32 TotalWordsRequested;
NvU32 NewBufferSize;
+ NvBool IsFlushRequired;
BytesPerPacket = (PacketBitLength + 7)/8;
PacketsPerWord = (IsPackedMode)? 4/BytesPerPacket: 1;
@@ -2284,6 +2292,13 @@ static NvError SlaveModeSpiStartReadWriteDma(
CurrentTransWord = (CurrentTransPacket + PacketsPerWord -1)/PacketsPerWord;
+ IsFlushRequired = hRmSpiSlink->hHwInterface->HwClearFifosForNewTransferFxn(
+ &hRmSpiSlink->HwRegs, hRmSpiSlink->CurrentDirection);
+ if (IsFlushRequired)
+ {
+ WARN_ON(1);
+ }
+
TriggerLevel = (CurrentTransWord & 0x3)? 4: 16;
hRmSpiSlink->hHwInterface->HwSetTriggerLevelFxn(&hRmSpiSlink->HwRegs,
SerialHwFifo_Both , TriggerLevel);
diff --git a/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink_hw_private.h b/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink_hw_private.h
index 741ebf3dda37..6cd3015de09f 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink_hw_private.h
+++ b/arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink_hw_private.h
@@ -371,6 +371,16 @@ typedef struct
SerialHwRegisters *pHwRegs,
SerialHwDataFlow DataDirection);
+
+ /**
+ * Clear the fifos before starting new transfer to make sure there is no
+ * residuals from past.
+ */
+ NvBool
+ (* HwClearFifosForNewTransferFxn)(
+ SerialHwRegisters *pHwRegs,
+ SerialHwDataFlow DataDirection);
+
/**
* Check whether transfer is completed or not.
*/
diff --git a/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_slink_hw_private.c b/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_slink_hw_private.c
index ce87dda381ba..0b16c22605fe 100644
--- a/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_slink_hw_private.c
+++ b/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_slink_hw_private.c
@@ -422,6 +422,34 @@ SlinkHwReadFromReceiveFifo(
return WordsRead;
}
+static NvBool
+SlinkHwClearFifosForNewTransfer(
+ SerialHwRegisters *pSlinkHwRegs,
+ SerialHwDataFlow DataDirection)
+{
+ NvU32 ResetBits = 0;
+ NvU32 StatusReg = SLINK_REG_READ32(pSlinkHwRegs->pRegsBaseAdd, STATUS);
+
+ if (!(StatusReg & NV_DRF_DEF(SLINK, STATUS, TX_EMPTY, EMPTY)))
+ ResetBits |= NV_DRF_NUM(SLINK, STATUS, TX_FLUSH, 1);
+
+ if (!(StatusReg & NV_DRF_DEF(SLINK, STATUS, RX_EMPTY, EMPTY)))
+ ResetBits |= NV_DRF_NUM(SLINK, STATUS, RX_FLUSH, 1);
+
+ if (!ResetBits)
+ return NV_FALSE;
+
+ StatusReg |= ResetBits;
+ SLINK_REG_WRITE32(pSlinkHwRegs->pRegsBaseAdd, STATUS, StatusReg);
+
+ // Now wait till the flush bits become 0
+ do
+ {
+ StatusReg = SLINK_REG_READ32(pSlinkHwRegs->pRegsBaseAdd, STATUS);
+ } while (StatusReg & ResetBits);
+ return NV_TRUE;
+}
+
/**
* Initialize the slink intterface for the hw access.
*/
@@ -435,4 +463,5 @@ void NvRmPrivSpiSlinkInitSlinkInterface_v1_1(HwInterface *pSlinkInterface)
pSlinkInterface->HwSetCsSetupHoldTime = SlinkHwSetCsSetupHoldTime;
pSlinkInterface->HwWriteInTransmitFifoFxn = SlinkHwWriteInTransmitFifo;
pSlinkInterface->HwReadFromReceiveFifoFxn = SlinkHwReadFromReceiveFifo;
+ pSlinkInterface->HwClearFifosForNewTransferFxn = SlinkHwClearFifosForNewTransfer;
}