diff options
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 7912470fb470..4b31dabb7b9e 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..c9220113262f 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 ((hRmSpiSlink->IsMasterMode) && ((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; } |