diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2010-07-22 18:40:41 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-07-23 20:26:18 -0700 |
commit | 02c0a803376731f8ad3a1330db61c44c3177e5a9 (patch) | |
tree | ca4a4c52c07ae8295ab00cd7b840f340d0497694 /arch/arm/mach-tegra/nvrm | |
parent | f658aa740ee09861856fadfd8094e48641c27a14 (diff) |
[arm/tegra] spi: Use native dma for data transfer
The rm spi driver is using the nvrm dma driver which is wrapper
over the native dma. Using directly the native dma driver to
get rid of one more level of wrapper call from spi driver.
Making sure that prev dma operation is completed before starting
new transfer.
Removed the code which was specific to OAL as this is not
required any more.
Calling the write buffer barriers after writing into the write
dma buffer and before starting the transmit dma to make sure
that all written data is available in physical memory before
dma start.
Change-Id: Iabcd86f0d63b2decffda0ad6da6f1b22161e9d3b
Reviewed-on: http://git-master/r/2670
Reviewed-by: Michael Hsu <mhsu@nvidia.com>
Tested-by: Michael Hsu <mhsu@nvidia.com>
Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra/nvrm')
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap15/rm_spi_slink.c | 575 |
1 files changed, 330 insertions, 245 deletions
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 59cd15dae155..2e191e863428 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 @@ -32,11 +32,9 @@ /** * @file - * @brief <b>NVIDIA Driver Development Kit: - * Spi Driver implementation</b> + * @brief <b>NVIDIA Driver Development Kit: Spi Driver implementation</b> * - * @b Description: Implementation of the NvRm SPI API of the OAL and non-OAL - * version. + * @b Description: Implementation of the NvRm SPI API for linux. * */ @@ -44,7 +42,6 @@ #include "nvrm_power.h" #include "nvrm_interrupt.h" #include "nvrm_memmgr.h" -#include "nvrm_dma.h" #include "nvodm_query.h" #include "nvodm_query_discovery.h" #include "rm_spi_slink_hw_private.h" @@ -58,6 +55,9 @@ #include "nvrm_priv_ap_general.h" #include "ap15/ap15rm_private.h" +#include "linux/module.h" +#include "mach/dma.h" + // Combined maximum spi/slink controllers #define MAX_SPI_SLINK_INSTANCE (MAX_SLINK_CONTROLLERS + MAX_SPI_CONTROLLERS) @@ -69,15 +69,7 @@ // The maximum slave size request in words. Maximum 64KB/64K packet #define MAXIMUM_SLAVE_TRANSFER_WORD (1 << (16-2)) -// Maximum number which is return by the NvOsGetTimeMS(). -// For NV_OAL, NvOsGetTimeMS() returns the MicroSecond Timer count divided by 1000. -// and microsecond timer have the maximum count of 0xFFFFFFFF. -// For Non-NV_OAL, it returned maximum of 0xFFFFFFFF -#if NV_OAL -#define MAX_TIME_IN_MS (0xFFFFFFFF/1000) -#else #define MAX_TIME_IN_MS 0xFFFFFFFF -#endif // The maximum request size for one transaction using the dma enum {DEFAULT_DMA_BUFFER_SIZE = (0x4000)}; // 16KB @@ -96,6 +88,10 @@ enum {SLINK_POLLING_HIGH_THRESOLD = 64}; // The dma buffer alignment requirement. enum {DMA_BUFFER_ALIGNMENT = 0x10}; +// Slink isr comes first then dma isr and so dma complete can be call later +// Wait for dma complete call back to process the transferred data +#define LATENCY_BETWEEN_SLINK_ISR_DMA_COMPLETE_MS 1000 + // Combined the Details of the current transfer information. typedef struct { @@ -153,19 +149,20 @@ typedef struct NvRmSpiRec // completion. NvOsSemaphoreHandle hSynchSema; - // Mutex to access this channel to provide the mutual exclusion. - NvOsMutexHandle hChannelAccessMutex; + // Synchronous sempahore Id which need to be signalled on Tx transfer + // completion. + NvOsSemaphoreHandle hSynchTxDmaSema; - // Tells whether the dma mode is supported or not. - NvBool IsApbDmaAllocated; + // Synchronous sempahore Id which need to be signalled on Rx transfer + // completion. + NvOsSemaphoreHandle hSynchRxDmaSema; - NvU32 TransCountFromLastDmaUsage; - // Read dma handle. - NvRmDmaHandle hRmRxDma; + // Mutex to access this channel to provide the mutual exclusion. + NvOsMutexHandle hChannelAccessMutex; - // Write dma handle. - NvRmDmaHandle hRmTxDma; + // Number of transfer count from last dma usage. + NvU32 TransCountFromLastDmaUsage; // Memory handle to create the uncached memory. NvRmMemHandle hRmMemory; @@ -185,15 +182,24 @@ typedef struct NvRmSpiRec // Current Dma transfer size for the Rx and tx NvU32 DmaBufferSize; - // Dma request for Tx - NvRmDmaClientBuffer TxDmaReq; - - // Dma request for rx - NvRmDmaClientBuffer RxDmaReq; + // Tells whether the dma mode is supported or not. + NvBool IsApbDmaAllocated; // Tell whether it is using the apb dma for the transfer or not. NvBool IsUsingApbDma; + // Dma request for Tx + struct tegra_dma_req TxDmaReq; + + // Tx dma channel handle. + struct tegra_dma_channel *hTxDma; + + // Dma request for Rx + struct tegra_dma_req RxDmaReq; + + // Rx dma channel handle + struct tegra_dma_channel *hRxDma; + // Buffer which will be used when cpu does the data receving. NvU32 *pRxCpuBuffer; @@ -248,6 +254,8 @@ typedef struct NvRmSpiRec // Tells whether frequency is boosted or not. NvBool IsFreqBoosted; + + NvBool IsIntDoneDue; } NvRmSpi; /** @@ -275,6 +283,21 @@ static NvRmPrivSpiSlinkInfo s_SpiSlinkInfo; static HwInterface s_SpiHwInterface; static HwInterface s_SlinkHwInterface; +static const NvU32 s_Slink_Trigger[] = { + TEGRA_DMA_REQ_SEL_SL2B1, + TEGRA_DMA_REQ_SEL_SL2B2, + TEGRA_DMA_REQ_SEL_SL2B3, + TEGRA_DMA_REQ_SEL_SL2B4, +}; + +static const NvU32 s_Spi_Trigger[] = { + TEGRA_DMA_REQ_SEL_SPI, +}; + +// Way to reset the semaphore count. +#define ResetSemaphoreCount(hSema) \ + while(NvOsSemaphoreWaitTimeout(hSema, 0) != NvError_Timeout) + /** * Get the interfacing property for the device connected to given chip select Id. * Returns whether this is supported or not. @@ -346,7 +369,6 @@ SpiSlinkIsPmuInterface( return NV_FALSE; } - /** * Create the dma buffer memory handle. */ @@ -368,8 +390,7 @@ CreateDmaBufferMemoryHandle( // Allocates the memory from the sdram if (!Error) - Error = NvRmMemAlloc(hNewMemHandle, NULL, - 0, DMA_BUFFER_ALIGNMENT, + Error = NvRmMemAlloc(hNewMemHandle, NULL, 0, DMA_BUFFER_ALIGNMENT, NvOsMemAttribute_Uncached); // Pin the memory allocation so that it should not move by memory manager. @@ -434,7 +455,7 @@ CreateDmaTransferBuffer( // Create the dma buffer memory for receive and transmit. // It will be double of the OneBufferSize Error = CreateDmaBufferMemoryHandle(hRmDevice, &hRmMemory, &BuffPhysAddr, - (OneBufferSize <<1)); + (OneBufferSize <<1)); if (!Error) { // 0 to OneBufferSize-1 is buffer 1 and OneBufferSize to 2*OneBufferSize @@ -484,6 +505,70 @@ DestroyDmaTransferBuffer( DestroyDmaBufferMemoryHandle(hRmMemory); } } +static NvError AllocateDmas(NvRmSpiHandle hRmSpiSlink) +{ + hRmSpiSlink->TransCountFromLastDmaUsage = 0; + hRmSpiSlink->IsApbDmaAllocated = NV_FALSE; + hRmSpiSlink->hRxDma = NULL; + hRmSpiSlink->hTxDma = NULL; + + hRmSpiSlink->hRxDma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); + if (hRmSpiSlink->hRxDma) + { + hRmSpiSlink->hTxDma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT); + if (!hRmSpiSlink->hTxDma) + { + tegra_dma_free_channel(hRmSpiSlink->hRxDma); + hRmSpiSlink->hRxDma = NULL; + return NvError_DmaChannelNotAvailable; + } + hRmSpiSlink->IsApbDmaAllocated = NV_TRUE; + } + return NvSuccess; +} + +static void FreeDmas(NvRmSpiHandle hRmSpiSlink) +{ + if (hRmSpiSlink->hRxDma) + tegra_dma_free_channel(hRmSpiSlink->hRxDma); + + if (hRmSpiSlink->hTxDma) + tegra_dma_free_channel(hRmSpiSlink->hTxDma); + + hRmSpiSlink->TransCountFromLastDmaUsage = 0; + hRmSpiSlink->IsApbDmaAllocated = NV_FALSE; + hRmSpiSlink->hRxDma = NULL; + hRmSpiSlink->hTxDma = NULL; +} +static NvError StartDma(struct tegra_dma_channel *ch, struct tegra_dma_req *req) +{ + if (tegra_dma_enqueue_req(ch, req)) + { + pr_debug("Could not enqueue Rx DMA req\n"); + return NvError_BadParameter; + } + return NvSuccess; +} +static void AbortDma(struct tegra_dma_channel *ch) +{ + tegra_dma_dequeue(ch); +} + +static void SpiTxDmaCompleteCallback(struct tegra_dma_req *req) +{ + NvRmSpiHandle hRmSpiSlink = req->dev; + if (req->status == -TEGRA_DMA_REQ_ERROR_ABORTED) + return; + NvOsSemaphoreSignal(hRmSpiSlink->hSynchTxDmaSema); +} + +static void SpiRxDmaCompleteCallback(struct tegra_dma_req *req) +{ + NvRmSpiHandle hRmSpiSlink = req->dev; + if (req->status == -TEGRA_DMA_REQ_ERROR_ABORTED) + return; + NvOsSemaphoreSignal(hRmSpiSlink->hSynchRxDmaSema); +} static NvBool HandleTransferCompletion(NvRmSpiHandle hRmSpiSlink) { @@ -578,9 +663,19 @@ static void SpiSlinkIsr(void *args) NvRmSpiHandle hRmSpiSlink = args; NvBool IsTransferCompleted; + /* If apb dma is used then postpone the handling in caller context */ + if (hRmSpiSlink->IsUsingApbDma) + { + NvOsSemaphoreSignal(hRmSpiSlink->hSynchSema); + hRmSpiSlink->IsIntDoneDue = NV_TRUE; + return; + } + + /* Handle the transfer completion here only for non dma transfer */ IsTransferCompleted = HandleTransferCompletion(hRmSpiSlink); if (IsTransferCompleted) NvOsSemaphoreSignal(hRmSpiSlink->hSynchSema); + hRmSpiSlink->IsIntDoneDue = NV_FALSE; NvRmInterruptDone(hRmSpiSlink->SpiInterruptHandle); } @@ -605,17 +700,14 @@ WaitForTransferCompletion( NvU32 WordsAvailbleInFifo; NvU32 WordsRead; NvU32 *pUpdatedRxBuffer = NULL; -#if NV_OAL - // For oal version, we only use the polling method. - IsPoll = NV_TRUE; -#endif + HwInterfaceHandle hHwInt = hRmSpiSlink->hHwInterface; if (IsPoll) { StartTime = NvOsGetTimeMS(); while (IsWait) { - IsReady = hRmSpiSlink->hHwInterface->HwIsTransferCompletedFxn(&hRmSpiSlink->HwRegs); + IsReady = hHwInt->HwIsTransferCompletedFxn(&hRmSpiSlink->HwRegs); if (IsReady) { IsTransferComplete = HandleTransferCompletion(hRmSpiSlink); @@ -632,17 +724,6 @@ WaitForTransferCompletion( } Error = (IsTransferComplete)? NvError_Success: NvError_Timeout; -#if NV_OAL - // If no error and apb dma based transfer then stop the dma transfer to - // make the state dma state machine as non busy. - if ((!Error) && (hRmSpiSlink->IsUsingApbDma)) - { - if (hRmSpiSlink->CurrentDirection & SerialHwDataFlow_Rx) - NvRmDmaAbort(hRmSpiSlink->hRmRxDma); - if (hRmSpiSlink->CurrentDirection & SerialHwDataFlow_Tx) - NvRmDmaAbort(hRmSpiSlink->hRmTxDma); - } -#endif } else { @@ -653,7 +734,7 @@ WaitForTransferCompletion( if (Error == NvError_Timeout) { // Disable the data flow first. - hRmSpiSlink->hHwInterface->HwSetDataFlowFxn(&hRmSpiSlink->HwRegs, + hHwInt->HwSetDataFlowFxn(&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrentDirection, NV_FALSE); // Get the transfer count now. @@ -661,21 +742,20 @@ WaitForTransferCompletion( { if (hRmSpiSlink->CurrentDirection & SerialHwDataFlow_Rx) { - NvError DmaError; - // Get the Rx transfer count transferred by Dma. - DmaError = NvRmDmaGetTransferredCount(hRmSpiSlink->hRmRxDma, - &DmaRxTransferCountBytes, NV_TRUE); - NV_ASSERT(DmaError == NvSuccess); - if (DmaError != NvSuccess) - DmaRxTransferCountBytes = 0; + AbortDma(hRmSpiSlink->hRxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchRxDmaSema); + DmaRxTransferCountBytes = hRmSpiSlink->RxDmaReq.bytes_transferred; PacketTransferedFromFifoYet = (DmaRxTransferCountBytes >> 2) * hRmSpiSlink->CurrTransInfo.PacketsPerWord; - pUpdatedRxBuffer = hRmSpiSlink->pRxDmaBuffer + (DmaRxTransferCountBytes >> 2); - NvRmDmaAbort(hRmSpiSlink->hRmRxDma); + pUpdatedRxBuffer = hRmSpiSlink->pRxDmaBuffer + + (DmaRxTransferCountBytes >> 2); } if (hRmSpiSlink->CurrentDirection & SerialHwDataFlow_Tx) - NvRmDmaAbort(hRmSpiSlink->hRmTxDma); + { + AbortDma(hRmSpiSlink->hTxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + } } else { @@ -687,7 +767,7 @@ WaitForTransferCompletion( // It may be possible that transfer is completed when we reach here. // If transfer is completed then we may read 0 from the status // register - IsReady = hRmSpiSlink->hHwInterface->HwIsTransferCompletedFxn(&hRmSpiSlink->HwRegs); + IsReady = hHwInt->HwIsTransferCompletedFxn(&hRmSpiSlink->HwRegs); if (IsReady) { // All requested transfer has been done. @@ -698,7 +778,7 @@ WaitForTransferCompletion( { // Get the transfer count from status register. CurrentSlinkPacketTransfer = - hRmSpiSlink->hHwInterface->HwGetTransferdCountFxn(&hRmSpiSlink->HwRegs); + hHwInt->HwGetTransferdCountFxn(&hRmSpiSlink->HwRegs); // If it is in packed mode and number of received packet is non word // aligned then ignore the packet which does not able to make the word. @@ -717,7 +797,7 @@ WaitForTransferCompletion( // Disable the interrupt. if (!IsPoll) - hRmSpiSlink->hHwInterface->HwSetInterruptSourceFxn(&hRmSpiSlink->HwRegs, + hHwInt->HwSetInterruptSourceFxn(&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrentDirection, NV_FALSE); // For Rx: Dma will always transfer equal to or less than slink has @@ -738,7 +818,7 @@ WaitForTransferCompletion( WordsAvailbleInFifo = (PacketsInRxFifo + hRmSpiSlink->CurrTransInfo.PacketsPerWord -1)/ hRmSpiSlink->CurrTransInfo.PacketsPerWord; - WordsRead = hRmSpiSlink->hHwInterface->HwReadFromReceiveFifoFxn( + WordsRead = hHwInt->HwReadFromReceiveFifoFxn( &hRmSpiSlink->HwRegs, pUpdatedRxBuffer, WordsAvailbleInFifo); // Expecting the WordsRead should be equal to WordsAvailbleInFifo @@ -749,34 +829,89 @@ WaitForTransferCompletion( } } - // The busy bit will still show the busy status so need to reset the // controller. .. Hw Bug NvRmModuleReset(hRmSpiSlink->hDevice, NVRM_MODULE_ID(hRmSpiSlink->RmModuleId, hRmSpiSlink->InstanceId)); hRmSpiSlink->CurrentDirection = SerialHwDataFlow_None; + if ((!IsPoll) && (hRmSpiSlink->IsIntDoneDue)) + NvRmInterruptDone(hRmSpiSlink->SpiInterruptHandle); + + return Error; } - return Error; -} -#if NV_OAL -static void OalMasterSpiSlinkPoll(NvRmSpiHandle hRmSpiSlink) -{ - NvBool IsReady; - NvBool TransferComplete = NV_FALSE; - //Check for the transfer complete in infinite loop - while (1) + /* If non dma based transfer then return as the slink status has already + * been handled. + */ + if (!hRmSpiSlink->IsUsingApbDma) + return Error; + + hRmSpiSlink->RxTransferStatus = NvSuccess; + hRmSpiSlink->TxTransferStatus = NvSuccess; + Error = NvSuccess; + if (hRmSpiSlink->CurrentDirection & SerialHwDataFlow_Rx) { - IsReady = hRmSpiSlink->hHwInterface->HwIsTransferCompletedFxn(&hRmSpiSlink->HwRegs); - if (IsReady) + hRmSpiSlink->RxTransferStatus = + hHwInt->HwGetTransferStatusFxn(&hRmSpiSlink->HwRegs, SerialHwDataFlow_Rx); + if (hRmSpiSlink->RxTransferStatus) { - TransferComplete = HandleTransferCompletion(hRmSpiSlink); - if(TransferComplete) - break; + pr_err("Spi: RxTransfer Error\n"); + AbortDma(hRmSpiSlink->hRxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchRxDmaSema); + } + else + { + if (NvOsSemaphoreWaitTimeout(hRmSpiSlink->hSynchRxDmaSema, + LATENCY_BETWEEN_SLINK_ISR_DMA_COMPLETE_MS)) + { + pr_err("Spi: RxDmaSync Error \n"); + AbortDma(hRmSpiSlink->hRxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchRxDmaSema); + hRmSpiSlink->RxTransferStatus = NvError_SpiReceiveError; + } + } + } + + if (hRmSpiSlink->CurrentDirection & SerialHwDataFlow_Tx) + { + hRmSpiSlink->TxTransferStatus = + hHwInt->HwGetTransferStatusFxn(&hRmSpiSlink->HwRegs, SerialHwDataFlow_Tx); + + if (hRmSpiSlink->TxTransferStatus) + { + pr_err("Spi: TxTransfer Error\n"); + AbortDma(hRmSpiSlink->hTxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + } + else + { + if (NvOsSemaphoreWaitTimeout(hRmSpiSlink->hSynchTxDmaSema, + LATENCY_BETWEEN_SLINK_ISR_DMA_COMPLETE_MS)) + { + pr_err("Spi: TxDmaSync Error \n"); + AbortDma(hRmSpiSlink->hTxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + hRmSpiSlink->TxTransferStatus = NvError_SpiTransmitError; + } } } + + hHwInt->HwClearTransferStatusFxn(&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrentDirection); + + if (hRmSpiSlink->RxTransferStatus || hRmSpiSlink->TxTransferStatus) + { + hHwInt->HwSetDataFlowFxn(&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrentDirection, NV_FALSE); + hHwInt->HwResetFifoFxn(&hRmSpiSlink->HwRegs, SerialHwFifo_Both); + hRmSpiSlink->CurrTransInfo.PacketTransferred += + hHwInt->HwGetTransferdCountFxn(&hRmSpiSlink->HwRegs); + hRmSpiSlink->CurrentDirection = SerialHwDataFlow_None; + Error = (hRmSpiSlink->RxTransferStatus)? hRmSpiSlink->RxTransferStatus: + hRmSpiSlink->TxTransferStatus; + } + if ((!IsPoll) && (hRmSpiSlink->IsIntDoneDue)) + NvRmInterruptDone(hRmSpiSlink->SpiInterruptHandle); + return Error; } -#endif /** * Register the spi interrupt. @@ -889,28 +1024,15 @@ static NvError SetPowerControl(NvRmSpiHandle hRmSpiSlink, NvBool IsEnable) static void DestroySpiSlinkChannelHandle(NvRmSpiHandle hRmSpiSlink) { NvU32 HandleStartIndex; -#if !NV_OAL + NvRmInterruptUnregister(hRmSpiSlink->hDevice, hRmSpiSlink->SpiInterruptHandle); hRmSpiSlink->SpiInterruptHandle = NULL; -#endif - // Unmap the virtual mapping of the spi hw register. NvRmPhysicalMemUnmap(hRmSpiSlink->HwRegs.pRegsBaseAdd, hRmSpiSlink->HwRegs.RegBankSize); - // the clocks should already be disabled for Non-oal. don't disable it here for non-oal - // For oal disable here. -#if NV_OAL - - // Resetting the Emc/Ahb/Apb/Cpu frequency - BoostFrequency(hRmSpiSlink, NV_FALSE, 0, 0); - (void)SetPowerControl(hRmSpiSlink, NV_FALSE); -#endif - -#if !NV_OAL // Unregister for the power manager. NvRmPowerUnRegister(hRmSpiSlink->hDevice, hRmSpiSlink->RmPowerClientId); -#endif // Tri-State the pin-mux pins NV_ASSERT_SUCCESS(NvRmSetModuleTristate(hRmSpiSlink->hDevice, @@ -919,28 +1041,28 @@ static void DestroySpiSlinkChannelHandle(NvRmSpiHandle hRmSpiSlink) NvOsFree(hRmSpiSlink->pTxCpuBuffer); NvOsFree(hRmSpiSlink->pRxCpuBuffer); - if (hRmSpiSlink->hRmRxDma) - { - NvRmDmaAbort(hRmSpiSlink->hRmRxDma); - NvRmDmaFree(hRmSpiSlink->hRmRxDma); - } + if (hRmSpiSlink->hRxDma) + AbortDma(hRmSpiSlink->hRxDma); - if (hRmSpiSlink->hRmTxDma) - { - NvRmDmaAbort(hRmSpiSlink->hRmTxDma); - NvRmDmaFree(hRmSpiSlink->hRmTxDma); - } + if (hRmSpiSlink->hTxDma) + AbortDma(hRmSpiSlink->hTxDma); + + FreeDmas(hRmSpiSlink); DestroyDmaTransferBuffer(hRmSpiSlink->hRmMemory, hRmSpiSlink->pRxDmaBuffer, hRmSpiSlink->pTxDmaBuffer, hRmSpiSlink->DmaBufferSize); -#if !NV_OAL // Destroy the mutex allocated for the channel accss. NvOsMutexDestroy(hRmSpiSlink->hChannelAccessMutex); // Destroy the sync sempahores. NvOsSemaphoreDestroy(hRmSpiSlink->hSynchSema); -#endif + + // Destroy the sync sempahores. + NvOsSemaphoreDestroy(hRmSpiSlink->hSynchTxDmaSema); + + // Destroy the sync sempahores. + NvOsSemaphoreDestroy(hRmSpiSlink->hSynchRxDmaSema); HandleStartIndex = (hRmSpiSlink->IsSpiChannel)? 0: MAX_SPI_CONTROLLERS; s_SpiSlinkInfo.hSpiSlinkChannelList[HandleStartIndex + hRmSpiSlink->InstanceId] = NULL; @@ -969,8 +1091,8 @@ static NvError CreateSpiSlinkChannelHandle( const NvU32 *pOdmConfigs; NvU32 NumOdmConfigs; NvU32 CpuBufferSize; - NvRmDmaModuleID DmaModuleId; const NvOdmQuerySpiIdleSignalState *pSignalState = NULL; + int DmaReq; *phSpiSlinkChannel = NULL; @@ -991,9 +1113,9 @@ static NvError CreateSpiSlinkChannelHandle( hRmSpiSlink->OpenCount = 1; hRmSpiSlink->IsApbDmaAllocated = NV_FALSE; hRmSpiSlink->TransCountFromLastDmaUsage = 0; - hRmSpiSlink->hRmRxDma = NULL; + hRmSpiSlink->hRxDma = NULL; hRmSpiSlink->hRmMemory = NULL; - hRmSpiSlink->hRmTxDma = NULL; + hRmSpiSlink->hTxDma = NULL; hRmSpiSlink->DmaRxBuffPhysAdd = 0; hRmSpiSlink->DmaTxBuffPhysAdd = 0; hRmSpiSlink->pRxDmaBuffer = NULL; @@ -1008,6 +1130,10 @@ static NvError CreateSpiSlinkChannelHandle( hRmSpiSlink->IsChipSelConfigured = NV_FALSE; hRmSpiSlink->IsCurrentlySwBasedChipSel = NV_TRUE; + hRmSpiSlink->hSynchSema = NULL; + hRmSpiSlink->hSynchTxDmaSema = NULL; + hRmSpiSlink->hSynchRxDmaSema = NULL; + // Initialize the frequncy requirements array hRmSpiSlink->BusyHints[0].ClockId = NvRmDfsClockId_Emc; hRmSpiSlink->BusyHints[0].BoostDurationMs = NV_WAIT_INFINITE; @@ -1078,7 +1204,6 @@ static NvError CreateSpiSlinkChannelHandle( hRmSpiSlink->hHwInterface->HwRegisterInitializeFxn(InstanceId, &hRmSpiSlink->HwRegs); -#if !NV_OAL // Create the mutex for channel access. if (!Error) Error = NvOsMutexCreate(&hRmSpiSlink->hChannelAccessMutex); @@ -1086,7 +1211,14 @@ static NvError CreateSpiSlinkChannelHandle( // Create the synchronous semaphores. if (!Error) Error = NvOsSemaphoreCreate(&hRmSpiSlink->hSynchSema, 0); -#endif + + // Create the synchronous semaphores. + if (!Error) + Error = NvOsSemaphoreCreate(&hRmSpiSlink->hSynchTxDmaSema, 0); + + // Create the synchronous semaphores. + if (!Error) + Error = NvOsSemaphoreCreate(&hRmSpiSlink->hSynchRxDmaSema, 0); // Get the spi hw physical base address and map in virtual memory space. if (!Error) @@ -1106,50 +1238,21 @@ static NvError CreateSpiSlinkChannelHandle( // Allocate the dma buffer and the dma channel if (!Error) { - hRmSpiSlink->IsApbDmaAllocated = NV_TRUE; - - // Don't go to the dma allocation if the oal and master mode. - // It creates the download issue using the spi kitl if dma mode is used. -#if NV_OAL - if (IsMasterMode) - { - Error = NvError_NotSupported; - } - else - { - Error = CreateDmaTransferBuffer(hRmSpiSlink->hDevice, &hRmSpiSlink->hRmMemory, - &hRmSpiSlink->DmaRxBuffPhysAdd, (void **)&hRmSpiSlink->pRxDmaBuffer, - &hRmSpiSlink->DmaTxBuffPhysAdd, (void **)&hRmSpiSlink->pTxDmaBuffer, - DEFAULT_DMA_BUFFER_SIZE); - } -#else Error = CreateDmaTransferBuffer(hRmSpiSlink->hDevice, &hRmSpiSlink->hRmMemory, &hRmSpiSlink->DmaRxBuffPhysAdd, (void **)&hRmSpiSlink->pRxDmaBuffer, &hRmSpiSlink->DmaTxBuffPhysAdd, (void **)&hRmSpiSlink->pTxDmaBuffer, DEFAULT_DMA_BUFFER_SIZE); -#endif if (!Error) { hRmSpiSlink->DmaBufferSize = DEFAULT_DMA_BUFFER_SIZE; - DmaModuleId = (IsSpiChannel)?NvRmDmaModuleID_Spi: NvRmDmaModuleID_Slink; // Allocate the dma (for Rx and for Tx) with high priority // Allocate dma now only for the slave mode handle. - // For master mode, it will be allaocated based on the transaction size + // For master mode, it will be allocated based on the transaction size // to make it adaptive. if (!IsMasterMode) { - Error = NvRmDmaAllocate(hRmSpiSlink->hDevice, &hRmSpiSlink->hRmRxDma, - NV_FALSE, NvRmDmaPriority_High, DmaModuleId, - hRmSpiSlink->InstanceId); - if (!Error) - { - Error = NvRmDmaAllocate(hRmSpiSlink->hDevice, &hRmSpiSlink->hRmTxDma, - NV_FALSE, NvRmDmaPriority_High, DmaModuleId, - hRmSpiSlink->InstanceId); - if (Error) - NvRmDmaFree(hRmSpiSlink->hRmRxDma); - } + Error = AllocateDmas(hRmSpiSlink); if (Error) { DestroyDmaTransferBuffer(hRmSpiSlink->hRmMemory, @@ -1160,33 +1263,55 @@ static NvError CreateSpiSlinkChannelHandle( else { hRmSpiSlink->IsApbDmaAllocated = NV_FALSE; - hRmSpiSlink->hRmRxDma = NULL; - hRmSpiSlink->hRmTxDma = NULL; + hRmSpiSlink->hRxDma = NULL; + hRmSpiSlink->hTxDma = NULL; } } if (Error) { hRmSpiSlink->IsApbDmaAllocated = NV_FALSE; - hRmSpiSlink->hRmRxDma = NULL; + hRmSpiSlink->hRxDma = NULL; hRmSpiSlink->hRmMemory = NULL; - hRmSpiSlink->hRmTxDma = NULL; + hRmSpiSlink->hTxDma = NULL; hRmSpiSlink->DmaRxBuffPhysAdd = 0; hRmSpiSlink->DmaTxBuffPhysAdd = 0; hRmSpiSlink->pRxDmaBuffer = NULL; hRmSpiSlink->pTxDmaBuffer = NULL; + hRmSpiSlink->DmaBufferSize = 0; Error = NvSuccess; } else { - hRmSpiSlink->RxDmaReq.SourceBufferPhyAddress= hRmSpiSlink->HwRegs.HwRxFifoAdd; - hRmSpiSlink->RxDmaReq.DestinationBufferPhyAddress = hRmSpiSlink->DmaRxBuffPhysAdd; - hRmSpiSlink->RxDmaReq.SourceAddressWrapSize = 4; - hRmSpiSlink->RxDmaReq.DestinationAddressWrapSize = 0; - - hRmSpiSlink->TxDmaReq.SourceBufferPhyAddress= hRmSpiSlink->DmaTxBuffPhysAdd; - hRmSpiSlink->TxDmaReq.DestinationBufferPhyAddress = hRmSpiSlink->HwRegs.HwTxFifoAdd; - hRmSpiSlink->TxDmaReq.SourceAddressWrapSize = 0; - hRmSpiSlink->TxDmaReq.DestinationAddressWrapSize = 4; + DmaReq = (IsSpiChannel)?s_Spi_Trigger[InstanceId]: + s_Slink_Trigger[InstanceId]; + + NvOsMemset(&hRmSpiSlink->RxDmaReq, 0, sizeof(hRmSpiSlink->RxDmaReq)); + hRmSpiSlink->RxDmaReq.source_addr = (unsigned long)hRmSpiSlink->HwRegs.HwRxFifoAdd; + hRmSpiSlink->RxDmaReq.source_wrap = 4; + hRmSpiSlink->RxDmaReq.dest_addr = (unsigned long)hRmSpiSlink->DmaRxBuffPhysAdd; + hRmSpiSlink->RxDmaReq.dest_wrap = 0; + hRmSpiSlink->RxDmaReq.virt_addr = hRmSpiSlink->pRxDmaBuffer; + hRmSpiSlink->RxDmaReq.to_memory = 1; + hRmSpiSlink->RxDmaReq.source_bus_width = 32; + hRmSpiSlink->RxDmaReq.dest_bus_width = 32; + hRmSpiSlink->RxDmaReq.req_sel = DmaReq; + hRmSpiSlink->RxDmaReq.complete = SpiRxDmaCompleteCallback; + hRmSpiSlink->RxDmaReq.threshold = NULL; + hRmSpiSlink->RxDmaReq.dev = hRmSpiSlink; + + NvOsMemset(&hRmSpiSlink->TxDmaReq, 0, sizeof(hRmSpiSlink->TxDmaReq)); + hRmSpiSlink->TxDmaReq.source_addr = (unsigned long)hRmSpiSlink->DmaTxBuffPhysAdd; + hRmSpiSlink->TxDmaReq.source_wrap = 0; + hRmSpiSlink->TxDmaReq.dest_addr = (unsigned long)hRmSpiSlink->HwRegs.HwTxFifoAdd; + hRmSpiSlink->TxDmaReq.dest_wrap = 4; + hRmSpiSlink->TxDmaReq.virt_addr = hRmSpiSlink->pTxDmaBuffer; + hRmSpiSlink->TxDmaReq.to_memory = 0; + hRmSpiSlink->TxDmaReq.source_bus_width = 32; + hRmSpiSlink->TxDmaReq.dest_bus_width = 32; + hRmSpiSlink->TxDmaReq.req_sel = DmaReq; + hRmSpiSlink->TxDmaReq.complete = SpiTxDmaCompleteCallback; + hRmSpiSlink->TxDmaReq.threshold = NULL; + hRmSpiSlink->TxDmaReq.dev = hRmSpiSlink; } } @@ -1211,14 +1336,12 @@ static NvError CreateSpiSlinkChannelHandle( hRmSpiSlink->CpuBufferSizeInWords = CpuBufferSize >> 2; } -#if !NV_OAL // Register slink/spi for Rm power client if (!Error) { hRmSpiSlink->RmPowerClientId = NVRM_POWER_CLIENT_TAG('S','P','I',' '); Error = NvRmPowerRegister(hRmSpiSlink->hDevice, NULL, &hRmSpiSlink->RmPowerClientId); } -#endif // Enable Power/Clock. if (!Error) @@ -1228,11 +1351,9 @@ static NvError CreateSpiSlinkChannelHandle( if (!Error) NvRmModuleReset(hDevice, ModuleId); -#if !NV_OAL // Register the interrupt. if (!Error) Error = RegisterSpiSlinkInterrupt(hDevice, hRmSpiSlink, InstanceId); -#endif // Initialize the controller register. if (!Error) @@ -1256,10 +1377,8 @@ static NvError CreateSpiSlinkChannelHandle( } // Let chipselect to be stable for 1 ms before doing any transaction. NvOsWaitUS(1000); -#if !NV_OAL // switch off clock and power to the slink module by default. Error = SetPowerControl(hRmSpiSlink, NV_FALSE); -#endif } // If error then destroy all the allocation done here. @@ -1805,11 +1924,9 @@ MasterModeReadWriteCpu( hRmSpiSlink->hHwInterface->HwSetDmaTransferSizeFxn(&hRmSpiSlink->HwRegs, hRmSpiSlink->CurrTransInfo.CurrPacketCount); hRmSpiSlink->hHwInterface->HwStartTransferFxn(&hRmSpiSlink->HwRegs, NV_TRUE); -#if NV_OAL - OalMasterSpiSlinkPoll(hRmSpiSlink); -#else + WaitForTransferCompletion(hRmSpiSlink, NV_WAIT_INFINITE, IsPolling); -#endif + Error = (hRmSpiSlink->RxTransferStatus)? hRmSpiSlink->RxTransferStatus: hRmSpiSlink->TxTransferStatus; if (Error) @@ -1866,6 +1983,9 @@ static NvError MasterModeReadWriteDma( PacketsRemaining = PacketsRequested; while (PacketsRemaining) { + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + ResetSemaphoreCount(hRmSpiSlink->hSynchRxDmaSema); + MaxPacketTransPossible = NV_MIN(PacketsRemaining, MaxPacketPerTrans); // If hw does not support the nonword alined packed mode then @@ -1936,14 +2056,16 @@ static NvError MasterModeReadWriteDma( hRmSpiSlink->pTxDmaBuffer, CurrentTransPacket*BytesPerPacket, PacketBitLength, IsPackedMode); hRmSpiSlink->CurrTransInfo.pTxBuff = hRmSpiSlink->pTxDmaBuffer; - hRmSpiSlink->TxDmaReq.TransferSize = CurrentTransWord *4; + hRmSpiSlink->TxDmaReq.size = CurrentTransWord *4; // If transfer word is more than fifo size the use the dma // otherwise direct write into the fifo. if (CurrentTransWord >= hRmSpiSlink->HwRegs.MaxWordTransfer) { - Error = NvRmDmaStartDmaTransfer(hRmSpiSlink->hRmTxDma, - &hRmSpiSlink->TxDmaReq, NvRmDmaDirection_Forward, 0, NULL); + wmb(); + dsb(); + outer_sync(); + Error = StartDma(hRmSpiSlink->hTxDma, &hRmSpiSlink->TxDmaReq); // Wait till fifo full if the transfer size is more than fifo size if (!Error) { @@ -1970,11 +2092,13 @@ static NvError MasterModeReadWriteDma( if ((!Error) && (pClientRxBuffer)) { - hRmSpiSlink->RxDmaReq.TransferSize = CurrentTransWord *4; - Error = NvRmDmaStartDmaTransfer(hRmSpiSlink->hRmRxDma, &hRmSpiSlink->RxDmaReq, - NvRmDmaDirection_Forward, 0, NULL); + hRmSpiSlink->RxDmaReq.size = CurrentTransWord *4; + Error = StartDma(hRmSpiSlink->hRxDma, &hRmSpiSlink->RxDmaReq); if ((Error) && (pClientTxBuffer)) - NvRmDmaAbort(hRmSpiSlink->hRmTxDma); + { + AbortDma(hRmSpiSlink->hTxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + } } if (!Error) @@ -1986,15 +2110,13 @@ static NvError MasterModeReadWriteDma( Error = (hRmSpiSlink->RxTransferStatus)? hRmSpiSlink->RxTransferStatus: hRmSpiSlink->TxTransferStatus; if (Error) - { - if (pClientRxBuffer) - NvRmDmaAbort(hRmSpiSlink->hRmRxDma); - if (pClientTxBuffer) - NvRmDmaAbort(hRmSpiSlink->hRmTxDma); break; - } + if (pClientRxBuffer) { + rmb(); + dsb(); + outer_sync(); MakeMasterClientBufferFromSpiBuffer(pClientRxBuffer + BufferOffset, hRmSpiSlink->pRxDmaBuffer, CurrentTransPacket*BytesPerPacket, PacketBitLength, IsPackedMode); @@ -2109,6 +2231,8 @@ static NvError SlaveModeSpiStartReadWriteDma( TotalWordsRequested = (PacketsRequested + PacketsPerWord -1)/PacketsPerWord; hRmSpiSlink->IsUsingApbDma = NV_TRUE; + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + ResetSemaphoreCount(hRmSpiSlink->hSynchRxDmaSema); // Create the buffer if the required size of the buffer is not available. if (hRmSpiSlink->DmaBufferSize < (TotalWordsRequested*4)) @@ -2119,6 +2243,7 @@ static NvError SlaveModeSpiStartReadWriteDma( hRmSpiSlink->hRmMemory = NULL; hRmSpiSlink->pRxDmaBuffer = NULL; hRmSpiSlink->DmaRxBuffPhysAdd = 0; + hRmSpiSlink->DmaTxBuffPhysAdd = 0; // Better to findout the neearest 2powern NewBufferSize = NV_MAX(hRmSpiSlink->DmaBufferSize, (TotalWordsRequested*4)); @@ -2132,9 +2257,12 @@ static NvError SlaveModeSpiStartReadWriteDma( hRmSpiSlink->DmaBufferSize = 0; return Error; } - hRmSpiSlink->RxDmaReq.DestinationBufferPhyAddress = hRmSpiSlink->DmaRxBuffPhysAdd; - hRmSpiSlink->TxDmaReq.SourceBufferPhyAddress = hRmSpiSlink->DmaTxBuffPhysAdd; + hRmSpiSlink->RxDmaReq.dest_addr = (unsigned long)hRmSpiSlink->DmaRxBuffPhysAdd; + hRmSpiSlink->TxDmaReq.source_addr = (unsigned long)hRmSpiSlink->DmaTxBuffPhysAdd; + hRmSpiSlink->RxDmaReq.virt_addr = hRmSpiSlink->pRxDmaBuffer; + hRmSpiSlink->TxDmaReq.virt_addr = hRmSpiSlink->pTxDmaBuffer; hRmSpiSlink->DmaBufferSize = NewBufferSize; + pr_err("allocated new buffers of size %d\n",NewBufferSize); } hRmSpiSlink->CurrTransInfo.PacketsPerWord = PacketsPerWord; @@ -2168,9 +2296,11 @@ static NvError SlaveModeSpiStartReadWriteDma( CurrentTransPacket*BytesPerPacket, PacketBitLength, IsPackedMode); hRmSpiSlink->CurrTransInfo.pTxBuff = hRmSpiSlink->pTxDmaBuffer; - hRmSpiSlink->TxDmaReq.TransferSize = CurrentTransWord *4; - Error = NvRmDmaStartDmaTransfer(hRmSpiSlink->hRmTxDma, &hRmSpiSlink->TxDmaReq, - NvRmDmaDirection_Forward, 0, NULL); + hRmSpiSlink->TxDmaReq.size = CurrentTransWord *4; + wmb(); + dsb(); + outer_sync(); + Error = StartDma(hRmSpiSlink->hTxDma, &hRmSpiSlink->TxDmaReq); do { if (hRmSpiSlink->hHwInterface->HwIsTransmitFifoFull(&hRmSpiSlink->HwRegs)) @@ -2180,14 +2310,16 @@ static NvError SlaveModeSpiStartReadWriteDma( if ((!Error) && (IsReadTransfer)) { - hRmSpiSlink->RxDmaReq.TransferSize = CurrentTransWord *4; + hRmSpiSlink->RxDmaReq.size = CurrentTransWord *4; hRmSpiSlink->CurrTransInfo.RxPacketsRemaining = CurrentTransPacket; hRmSpiSlink->CurrTransInfo.pRxBuff = hRmSpiSlink->pRxDmaBuffer; - Error = NvRmDmaStartDmaTransfer(hRmSpiSlink->hRmRxDma, &hRmSpiSlink->RxDmaReq, - NvRmDmaDirection_Forward, 0, NULL); + Error = StartDma(hRmSpiSlink->hRxDma, &hRmSpiSlink->RxDmaReq); if ((Error) && (pClientTxBuffer)) - NvRmDmaAbort(hRmSpiSlink->hRmTxDma); + { + AbortDma(hRmSpiSlink->hTxDma); + ResetSemaphoreCount(hRmSpiSlink->hSynchTxDmaSema); + } } if (!Error) @@ -2227,6 +2359,9 @@ static NvError SlaveModeSpiCompleteReadWrite( { pRxBuffer = (hRmSpiSlink->IsUsingApbDma)?hRmSpiSlink->pRxDmaBuffer: hRmSpiSlink->pRxCpuBuffer; + rmb(); + dsb(); + outer_sync(); MakeSlaveClientBufferFromSpiBuffer(pClientRxBuffer, pRxBuffer, ReqSizeInBytes, hRmSpiSlink->CurrTransInfo.PacketBitLength, @@ -2350,6 +2485,7 @@ NvRmSpiOpen( *phRmSpi = NULL; + pr_err("NvRmSpiOpen() Opening channel Inst %d and IsMaster %d\n",InstanceId, IsMasterMode); IsSpiChannel = (IoModule == NvOdmIoModule_Sflash)? NV_TRUE: NV_FALSE; // SPI controller does not support the slave mode @@ -2389,6 +2525,7 @@ NvRmSpiOpen( } else { + pr_err("The channel is already allocated\n"); Error = NvError_AlreadyAllocated; goto FuncExit; } @@ -2433,7 +2570,6 @@ void NvRmSpiMultipleTransactions( NvU32 TotalPacketsRequsted; NvU32 TotalWordsRequested; NvU32 i; - NvRmDmaModuleID DmaModuleId; NvRmSpiTransactionInfo *pTrans = t; NvU32 TotalTransByte = 0; NvBool IsOnlySwCs = NV_TRUE; @@ -2520,28 +2656,12 @@ void NvRmSpiMultipleTransactions( // Allocate the dma here if transaction size is more than cpu based // transaction thresold. if ((TotalWordsRequested > hRmSpi->HwRegs.MaxWordTransfer) && - (hRmSpi->DmaBufferSize) && - (!hRmSpi->IsApbDmaAllocated)) + (hRmSpi->DmaBufferSize) && (!hRmSpi->IsApbDmaAllocated)) { - hRmSpi->TransCountFromLastDmaUsage = 0; - hRmSpi->IsApbDmaAllocated = NV_TRUE; - DmaModuleId = (hRmSpi->IsSpiChannel)?NvRmDmaModuleID_Spi: NvRmDmaModuleID_Slink; - Error = NvRmDmaAllocate(hRmSpi->hDevice, &hRmSpi->hRmRxDma, - NV_FALSE, NvRmDmaPriority_High, DmaModuleId, - hRmSpi->InstanceId); - if (!Error) - { - Error = NvRmDmaAllocate(hRmSpi->hDevice, &hRmSpi->hRmTxDma, - NV_FALSE, NvRmDmaPriority_High, DmaModuleId, - hRmSpi->InstanceId); - if (Error) - NvRmDmaFree(hRmSpi->hRmRxDma); - } + Error = AllocateDmas(hRmSpi); if (Error) { - hRmSpi->hRmRxDma = NULL; - hRmSpi->hRmTxDma = NULL; - hRmSpi->IsApbDmaAllocated = NV_FALSE; + pr_debug("Dma not allocated\n"); Error = NvSuccess; } } @@ -2595,13 +2715,7 @@ cleanup: } if ((hRmSpi->IsApbDmaAllocated) && (hRmSpi->TransCountFromLastDmaUsage > MAX_DMA_HOLD_TIME)) - { - NvRmDmaFree(hRmSpi->hRmRxDma); - NvRmDmaFree(hRmSpi->hRmTxDma); - hRmSpi->hRmRxDma = NULL; - hRmSpi->hRmTxDma = NULL; - hRmSpi->IsApbDmaAllocated = NV_FALSE; - } + FreeDmas(hRmSpi); SetPowerControl(hRmSpi, NV_FALSE); NvOsMutexUnlock(hRmSpi->hChannelAccessMutex); @@ -2628,7 +2742,6 @@ void NvRmSpiTransaction( NvU32 PacketsPerWord; NvU32 TotalPacketsRequsted; NvU32 TotalWordsRequested; - NvRmDmaModuleID DmaModuleId; NV_ASSERT(hRmSpi); NV_ASSERT(pReadBuffer || pWriteBuffer); @@ -2656,7 +2769,6 @@ void NvRmSpiTransaction( PacketsPerWord = (IsPackedMode)? 4/BytesPerPackets: 1; TotalWordsRequested = (TotalPacketsRequsted + PacketsPerWord -1)/PacketsPerWord; -#if !NV_OAL // Lock the channel access by other client till this client finishes the ops NvOsMutexLock(hRmSpi->hChannelAccessMutex); @@ -2667,9 +2779,6 @@ void NvRmSpiTransaction( goto cleanup; BoostFrequency(hRmSpi, NV_TRUE, BytesRequested, ClockSpeedInKHz); -#else - hRmSpi->CurrTransferChipSelId = ChipSelectId; -#endif hRmSpi->CurrTransInfo.PacketsPerWord = PacketsPerWord; // Enable the transmit if the Tx buffer is supplied. @@ -2705,28 +2814,12 @@ void NvRmSpiTransaction( // Allocate the dma here if transaction size is more than cpu based // transaction thresold. if ((TotalWordsRequested > hRmSpi->HwRegs.MaxWordTransfer) && - (hRmSpi->DmaBufferSize) && - (!hRmSpi->IsApbDmaAllocated)) + (hRmSpi->DmaBufferSize) && (!hRmSpi->IsApbDmaAllocated)) { - hRmSpi->TransCountFromLastDmaUsage = 0; - hRmSpi->IsApbDmaAllocated = NV_TRUE; - DmaModuleId = (hRmSpi->IsSpiChannel)?NvRmDmaModuleID_Spi: NvRmDmaModuleID_Slink; - Error = NvRmDmaAllocate(hRmSpi->hDevice, &hRmSpi->hRmRxDma, - NV_FALSE, NvRmDmaPriority_High, DmaModuleId, - hRmSpi->InstanceId); - if (!Error) - { - Error = NvRmDmaAllocate(hRmSpi->hDevice, &hRmSpi->hRmTxDma, - NV_FALSE, NvRmDmaPriority_High, DmaModuleId, - hRmSpi->InstanceId); - if (Error) - NvRmDmaFree(hRmSpi->hRmRxDma); - } + Error = AllocateDmas(hRmSpi); if (Error) { - hRmSpi->hRmRxDma = NULL; - hRmSpi->hRmTxDma = NULL; - hRmSpi->IsApbDmaAllocated = NV_FALSE; + pr_debug("Dma Allocation failed\n"); Error = NvSuccess; } } @@ -2784,18 +2877,10 @@ cleanup: if ((hRmSpi->IsApbDmaAllocated) && (hRmSpi->TransCountFromLastDmaUsage > MAX_DMA_HOLD_TIME)) - { - NvRmDmaFree(hRmSpi->hRmRxDma); - NvRmDmaFree(hRmSpi->hRmTxDma); - hRmSpi->hRmRxDma = NULL; - hRmSpi->hRmTxDma = NULL; - hRmSpi->IsApbDmaAllocated = NV_FALSE; - } + FreeDmas(hRmSpi); -#if !NV_OAL SetPowerControl(hRmSpi, NV_FALSE); NvOsMutexUnlock(hRmSpi->hChannelAccessMutex); -#endif NV_ASSERT(Error == NvSuccess); |