summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r--arch/arm/mach-tegra/include/nvodm_query.h17
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/ap15rm_slink_hw_private.c10
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_hw_private.c10
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c29
-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.c22
6 files changed, 92 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/include/nvodm_query.h b/arch/arm/mach-tegra/include/nvodm_query.h
index 9bc66d4f44a9..68e38607d44d 100644
--- a/arch/arm/mach-tegra/include/nvodm_query.h
+++ b/arch/arm/mach-tegra/include/nvodm_query.h
@@ -219,6 +219,23 @@ typedef struct
/// If this is NV_TRUE, then this device is an SPI slave.
NvBool IsSlave;
+
+ /// Specifies whether it can use the hw based cs or not.
+ NvBool CanUseHwBasedCs;
+
+ /// Specifies the Chipselect setup time i.e. Time between the CS active
+ /// state transition to to first clock in the transaction.
+ /// This parameter is used when using the hw based CS.
+ /// The value is in terms of the clock tick where the clock freq is
+ /// the interface frequency.
+ NvU32 CsSetupTimeInClock;
+
+ /// Specifies the Chipselect Hold time i.e. Time between the last clock and
+ /// CS state transition from active to inactive.
+ /// This parameter is used when using the hw based CS.
+ /// The value is in terms of the clock tick where the clock freq is
+ /// the interface frequency.
+ NvU32 CsHoldTimeInClock;
} NvOdmQuerySpiDeviceInfo;
/**
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 41c17684a6bc..c57d9cbe6666 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
@@ -254,6 +254,15 @@ SlinkHwSetChipSelectLevelBasedOnPacket(
return NV_TRUE;
}
+static void
+SlinkHwSetCsSetupHoldTime(
+ SerialHwRegisters *pSlinkHwRegs,
+ NvU32 CsSetupTimeInClocks,
+ NvU32 CsHoldTimeInClocks)
+{
+ NV_ASSERT(0);
+}
+
/**
* Write into the transmit fifo register.
* returns the number of words written.
@@ -307,6 +316,7 @@ void NvRmPrivSpiSlinkInitSlinkInterface_v1_0(HwInterface *pSlinkInterface)
pSlinkInterface->HwSetChipSelectDefaultLevelFxn = SlinkHwSetChipSelectDefaultLevelFxn;
pSlinkInterface->HwSetChipSelectLevelFxn = SlinkHwSetChipSelectLevel;
pSlinkInterface->HwSetChipSelectLevelBasedOnPacketFxn = SlinkHwSetChipSelectLevelBasedOnPacket;
+ pSlinkInterface->HwSetCsSetupHoldTime = SlinkHwSetCsSetupHoldTime;
pSlinkInterface->HwWriteInTransmitFifoFxn = SlinkHwWriteInTransmitFifo;
pSlinkInterface->HwReadFromReceiveFifoFxn = SlinkHwReadFromReceiveFifo;
}
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 cb7293e1896a..652b25aa3f08 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
@@ -363,6 +363,15 @@ SpiHwSetChipSelectLevelBasedOnPacket(
return NV_TRUE;
}
+static void
+SlinkHwSetCsSetupHoldTime(
+ SerialHwRegisters *pSlinkHwRegs,
+ NvU32 CsSetupTimeInClocks,
+ NvU32 CsHoldTimeInClocks)
+{
+ NV_ASSERT(0);
+}
+
/**
* Set the packet length and packed mode.
*/
@@ -622,6 +631,7 @@ void NvRmPrivSpiSlinkInitSpiInterface(HwInterface *pSpiInterface)
pSpiInterface->HwSetChipSelectDefaultLevelFxn = SpiHwSetChipSelectDefaultLevelFxn;
pSpiInterface->HwSetChipSelectLevelFxn = SpiHwSetChipSelectLevel;
pSpiInterface->HwSetChipSelectLevelBasedOnPacketFxn = SpiHwSetChipSelectLevelBasedOnPacket;
+ pSpiInterface->HwSetCsSetupHoldTime = SlinkHwSetCsSetupHoldTime;
pSpiInterface->HwSetPacketLengthFxn = SpiHwSetPacketLength;
pSpiInterface->HwSetDmaTransferSizeFxn = SpiHwSetDmaTransferSize;
pSpiInterface->HwGetTransferdCountFxn = SpiHwGetTransferdCount;
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 26fd65121355..147d6ce7ef1e 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
@@ -296,10 +296,16 @@ SpiSlinkGetDeviceInfo(
// No device info in odm, so set it on default state.
pDeviceInfo->SignalMode = NvOdmQuerySpiSignalMode_0;
pDeviceInfo->ChipSelectActiveLow = NV_TRUE;
+ pDeviceInfo->CanUseHwBasedCs = NV_FALSE;
+ pDeviceInfo->CsHoldTimeInClock = 0;
+ pDeviceInfo->CsSetupTimeInClock = 0;
return NV_FALSE;
}
pDeviceInfo->SignalMode = pSpiDevInfo->SignalMode;
pDeviceInfo->ChipSelectActiveLow = pSpiDevInfo->ChipSelectActiveLow;
+ pDeviceInfo->CanUseHwBasedCs = pSpiDevInfo->CanUseHwBasedCs;
+ pDeviceInfo->CsHoldTimeInClock = pSpiDevInfo->CsHoldTimeInClock;
+ pDeviceInfo->CsSetupTimeInClock = pSpiDevInfo->CsSetupTimeInClock;
return NV_TRUE;
}
@@ -1302,7 +1308,8 @@ SetChipSelectSignalLevel(
if (hRmSpiSlink->IsMasterMode != hRmSpiSlink->HwRegs.IsMasterMode)
hHwIntf->HwSetFunctionalModeFxn(&hRmSpiSlink->HwRegs, hRmSpiSlink->IsMasterMode);
- if (IsOnlyUseSWCS || (!hRmSpiSlink->HwRegs.IsHwChipSelectSupported))
+ if (IsOnlyUseSWCS || (!hRmSpiSlink->HwRegs.IsHwChipSelectSupported) ||
+ (!pDevInfo->CanUseHwBasedCs))
{
IsHigh = (pDevInfo->ChipSelectActiveLow)? NV_FALSE: NV_TRUE;
hHwIntf->HwSetChipSelectLevelFxn(&hRmSpiSlink->HwRegs, ChipSelectId, IsHigh);
@@ -1777,6 +1784,12 @@ MasterModeReadWriteCpu(
&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrTransferChipSelId,
!hRmSpiSlink->DeviceInfo[hRmSpiSlink->CurrTransferChipSelId].ChipSelectActiveLow,
PacketsRequested, PacketsPerWord, NV_FALSE, NV_FALSE);
+
+ if (!hRmSpiSlink->IsCurrentlySwBasedChipSel)
+ hRmSpiSlink->hHwInterface->HwSetCsSetupHoldTime(&hRmSpiSlink->HwRegs,
+ hRmSpiSlink->DeviceInfo[hRmSpiSlink->CurrTransferChipSelId].CsSetupTimeInClock,
+ hRmSpiSlink->DeviceInfo[hRmSpiSlink->CurrTransferChipSelId].CsHoldTimeInClock);
+
hRmSpiSlink->IsChipSelConfigured = NV_TRUE;
}
@@ -1892,6 +1905,12 @@ static NvError MasterModeReadWriteDma(
&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrTransferChipSelId,
!hRmSpiSlink->DeviceInfo[hRmSpiSlink->CurrTransferChipSelId].ChipSelectActiveLow,
PacketsRequested, PacketsPerWord, NV_TRUE, IsOnlyUseSWCS);
+
+ if (!hRmSpiSlink->IsCurrentlySwBasedChipSel)
+ hRmSpiSlink->hHwInterface->HwSetCsSetupHoldTime(&hRmSpiSlink->HwRegs,
+ hRmSpiSlink->DeviceInfo[hRmSpiSlink->CurrTransferChipSelId].CsSetupTimeInClock,
+ hRmSpiSlink->DeviceInfo[hRmSpiSlink->CurrTransferChipSelId].CsHoldTimeInClock);
+
hRmSpiSlink->IsChipSelConfigured = NV_TRUE;
}
@@ -2408,6 +2427,7 @@ void NvRmSpiMultipleTransactions(
NvRmDmaModuleID DmaModuleId;
NvRmSpiTransactionInfo *pTrans = t;
NvU32 TotalTransByte = 0;
+ NvBool IsOnlySwCs = NV_TRUE;
NV_ASSERT(hRmSpi);
NV_ASSERT((PacketSizeInBits > 0) && (PacketSizeInBits <= 32));
@@ -2461,8 +2481,11 @@ void NvRmSpiMultipleTransactions(
}
if (!Error)
+ {
+ IsOnlySwCs = (NumOfTransactions == 1)? NV_FALSE: NV_TRUE;
Error = SetChipSelectSignalLevel(hRmSpi, ChipSelectId, ClockSpeedInKHz,
- NV_TRUE, NV_TRUE);
+ NV_TRUE, IsOnlySwCs);
+ }
if (Error)
goto cleanup;
@@ -2542,7 +2565,7 @@ void NvRmSpiMultipleTransactions(
}
hRmSpi->CurrentDirection = SerialHwDataFlow_None;
(void)SetChipSelectSignalLevel(hRmSpi, ChipSelectId, ClockSpeedInKHz,
- NV_FALSE, NV_TRUE);
+ NV_FALSE, IsOnlySwCs);
cleanup:
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 3e1d83fdc229..741ebf3dda37 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
@@ -285,8 +285,16 @@ typedef struct
NvBool IsApbDmaBasedTransfer,
NvBool IsOnlyUseSWCS);
+ /**
+ * Set the CS setup and hold time.
+ */
+ void
+ (* HwSetCsSetupHoldTime)(
+ SerialHwRegisters *pHwRegs,
+ NvU32 CsSetupTimeInClocks,
+ NvU32 CsHoldTimeInClocks);
- /**
+ /**
* Set the packet length.
*/
void
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 dfee4becc53b..ce87dda381ba 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
@@ -47,8 +47,7 @@
#include "nvos.h"
// Enable the hw based chipselect
-#define ENABLE_HW_BASED_CS 0
-
+#define ENABLE_HW_BASED_CS 1
#define SLINK_REG_READ32(pSlinkHwRegsVirtBaseAdd, reg) \
NV_READ32((pSlinkHwRegsVirtBaseAdd) + ((SLINK_##reg##_0)/4))
#define SLINK_REG_WRITE32(pSlinkHwRegsVirtBaseAdd, reg, val) \
@@ -354,6 +353,24 @@ SlinkHwSetChipSelectLevelBasedOnPacket(
return NV_FALSE;
}
+static void
+SlinkHwSetCsSetupHoldTime(
+ SerialHwRegisters *pSlinkHwRegs,
+ NvU32 CsSetupTimeInClocks,
+ NvU32 CsHoldTimeInClocks)
+{
+ NvU32 CommandReg2 = pSlinkHwRegs->HwRegs.SlinkRegs.Command2;
+ NvU32 SetupTime;
+
+ SetupTime = (CsSetupTimeInClocks +1)/2;
+ SetupTime = (SetupTime > 3)?3: SetupTime;
+ CommandReg2 = NV_FLD_SET_DRF_NUM(SLINK, COMMAND2, SS_SETUP,
+ SetupTime, CommandReg2);
+ pSlinkHwRegs->HwRegs.SlinkRegs.Command2 = CommandReg2;
+ SLINK_REG_WRITE32(pSlinkHwRegs->pRegsBaseAdd, COMMAND2,
+ pSlinkHwRegs->HwRegs.SlinkRegs.Command2);
+}
+
/**
* Write into the transmit fifo register.
* returns the number of words written.
@@ -415,6 +432,7 @@ void NvRmPrivSpiSlinkInitSlinkInterface_v1_1(HwInterface *pSlinkInterface)
pSlinkInterface->HwSetChipSelectDefaultLevelFxn = SlinkHwSetChipSelectDefaultLevel;
pSlinkInterface->HwSetChipSelectLevelFxn = SlinkHwSetChipSelectLevel;
pSlinkInterface->HwSetChipSelectLevelBasedOnPacketFxn = SlinkHwSetChipSelectLevelBasedOnPacket;
+ pSlinkInterface->HwSetCsSetupHoldTime = SlinkHwSetCsSetupHoldTime;
pSlinkInterface->HwWriteInTransmitFifoFxn = SlinkHwWriteInTransmitFifo;
pSlinkInterface->HwReadFromReceiveFifoFxn = SlinkHwReadFromReceiveFifo;
}