diff options
author | Gerrit Code Review <gerrit2@git-master.nvidia.com> | 2010-01-08 01:25:56 +0200 |
---|---|---|
committer | Gerrit Code Review <gerrit2@git-master.nvidia.com> | 2010-01-08 01:25:56 +0200 |
commit | 993d229c19beb3a3d093d6063e3c72959496d316 (patch) | |
tree | 49991707a1b18b9039fd9bb1e8d6afa846d9200b | |
parent | 97753a87e41d7dae06ae53c5fccb55ad810bc98a (diff) | |
parent | f09edd005d75f8a8579bb0d723d0e592c905bf52 (diff) |
Merge change Ic5260c24 into android-tegra-2.6.29
* changes:
tegra: Handling the arbitration lost error in i2c.
-rw-r--r-- | arch/arm/mach-tegra/include/nverrval.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-tegra/include/nvodm_services.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvodm/nvodm_services.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c | 103 |
4 files changed, 81 insertions, 31 deletions
diff --git a/arch/arm/mach-tegra/include/nverrval.h b/arch/arm/mach-tegra/include/nverrval.h index 797e65b388f8..87b2f4e6bc62 100644 --- a/arch/arm/mach-tegra/include/nverrval.h +++ b/arch/arm/mach-tegra/include/nverrval.h @@ -139,6 +139,8 @@ NVERROR(UartBreakReceived, 0x00044004, "received break signal") NVERROR(I2cReadFailed, 0x00045000, "Failed to read data through I2C") NVERROR(I2cWriteFailed, 0x00045001, "Failed to write data through I2C") NVERROR(I2cDeviceNotFound, 0x00045003, "Slave Device Not Found") +NVERROR(I2cInternalError, 0x00045004, "The controller reports the error during transaction like fifo overrun, underrun") +NVERROR(I2cArbitrationFailed, 0x00045005, "Master does not able to get the control of bus") NVERROR(IdeHwError, 0x00046000, "Ide HW error") NVERROR(IdeReadError, 0x00046001, "Ide read error") NVERROR(IdeWriteError, 0x00046002, "Ide write error") diff --git a/arch/arm/mach-tegra/include/nvodm_services.h b/arch/arm/mach-tegra/include/nvodm_services.h index 97fcf27e1c82..904821ca8049 100644 --- a/arch/arm/mach-tegra/include/nvodm_services.h +++ b/arch/arm/mach-tegra/include/nvodm_services.h @@ -943,6 +943,7 @@ typedef enum NvOdmI2cStatus_ReadFailed, NvOdmI2cStatus_WriteFailed, NvOdmI2cStatus_InternalError, + NvOdmI2cStatus_ArbitrationFailed, NvOdmI2cStatus_Force32 = 0x7FFFFFFF } NvOdmI2cStatus; diff --git a/arch/arm/mach-tegra/nvodm/nvodm_services.c b/arch/arm/mach-tegra/nvodm/nvodm_services.c index 571da69f4bfd..76f1bb344760 100644 --- a/arch/arm/mach-tegra/nvodm/nvodm_services.c +++ b/arch/arm/mach-tegra/nvodm/nvodm_services.c @@ -525,6 +525,12 @@ NvOdmI2cTransaction( case NvError_I2cWriteFailed: status = NvOdmI2cStatus_WriteFailed; break; + case NvError_I2cArbitrationFailed: + status = NvOdmI2cStatus_ArbitrationFailed; + break; + case NvError_I2cInternalError: + status = NvOdmI2cStatus_InternalError; + break; case NvError_Timeout: default: status = NvOdmI2cStatus_Timeout; diff --git a/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c b/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c index 52c66879a16e..c9d40286704b 100644 --- a/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c +++ b/arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c @@ -62,7 +62,7 @@ NV_REGW((c)->hRmDevice, (c)->ModuleId, (c)->Instance, \ ((c)->I2cRegisterOffset + (((c)->ModuleId == NvRmModuleID_Dvc) ? DVC_##reg##_0 : \ I2C_##reg##_0)), (val)); \ - } while(0) + } while(0) #define DVC_REGR(c, reg) NV_REGR((c)->hRmDevice, NvRmModuleID_Dvc, (c)->Instance, \ DVC_##reg##_0) @@ -70,7 +70,7 @@ do { \ NV_REGW((c)->hRmDevice, NvRmModuleID_Dvc, (c)->Instance, \ DVC_##reg##_0, val); \ - } while(0) + } while(0) /* Register access Macros */ @@ -81,7 +81,7 @@ do { \ NV_REGW((c)->hRmDevice, (c)->ModuleId, (c)->Instance, \ ((c)->I2cRegisterOffset + I2C_##reg##_0), (val) ); \ - }while(0); + } while(0); #define DEBUG_SEND_PROCESS 0 @@ -118,7 +118,7 @@ if (Expr) \ { \ NvOsDebugPrintf Format; \ - } \ + } \ } while(0) #else #define DEBUG_I2C_TRACE(Expr, Format) @@ -135,7 +135,7 @@ enum {DEFAULT_I2C_DMA_BUFFER_SIZE = (MAX_I2C_ONE_TRANSACTION_SIZE + 0x40)}; // 4 enum {DEFAULT_I2C_CPU_BUFFER_SIZE = MAX_I2C_ONE_TRANSACTION_SIZE}; // Wait time to poll the status for completion. -enum { I2C_POLLING_TIMEOUT_STEP_USEC = 50}; +enum { I2C_POLLING_TIMEOUT_STEP_USEC = 1000}; // I2C fifo depth. enum { I2C_FIFO_DEPTH = 8}; @@ -145,10 +145,26 @@ enum { I2C_MAX_WORD_TO_USE_CPU = 16}; // Holding the apb dma for the continuous non dma transaction count enum {HOLDING_DMA_TRANSACTION_COUNT = 15}; -#define I2C_FIFO_ERROR_INTERRUPTS (NV_DRF_DEF(I2C, INTERRUPT_STATUS_REGISTER, TFIFO_OVF, SET) | \ - NV_DRF_DEF(I2C, INTERRUPT_STATUS_REGISTER, RFIFO_UNF, SET)) +#define I2C_TRANSACTION_STATUS_ERRORS \ + (NV_DRF_DEF(I2C, INTERRUPT_STATUS_REGISTER, TFIFO_OVF, SET) | \ + NV_DRF_DEF(I2C, INTERRUPT_STATUS_REGISTER, RFIFO_UNF, SET) | \ + NV_DRF_DEF(I2C, INTERRUPT_STATUS_REGISTER, ARB_LOST, SET)) + +#define I2C_ARBITRATION_LOST_ERRORS \ + (NV_DRF_DEF(I2C, INTERRUPT_STATUS_REGISTER, ARB_LOST, SET)) + +#define I2C_ERRORS_INTERRUPT_MASK \ + (NV_DRF_DEF(I2C, INTERRUPT_MASK_REGISTER, TFIFO_OVF_INT_EN, ENABLE) | \ + NV_DRF_DEF(I2C, INTERRUPT_MASK_REGISTER, RFIFO_UNF_INT_EN, ENABLE) | \ + NV_DRF_DEF(I2C, INTERRUPT_MASK_REGISTER, ARB_LOST_INT_EN, ENABLE)) #if NV_OAL +#define USE_POLLING_METHOD 1 +#else +#define USE_POLLING_METHOD 0 +#endif + +#if USE_POLLING_METHOD #define RESET_SEMA_COUNT(hSema) #else #define RESET_SEMA_COUNT(hSema) \ @@ -450,7 +466,7 @@ DoTxFifoEmpty( static void WriteIntMaksReg(NvRmI2cControllerHandle hRmI2cCont) { -#if !NV_OAL +#if !USE_POLLING_METHOD I2C_REGW (hRmI2cCont, INTERRUPT_MASK_REGISTER, hRmI2cCont->IntMaskReg); #endif } @@ -477,6 +493,15 @@ static void I2cIsr(void* args) if (hRmI2cCont->ControllerStatus & hRmI2cCont->FinalInterrupt) IsFinalIntGot = NV_TRUE; + // If any error then stop transfer. + if (hRmI2cCont->ControllerStatus & I2C_TRANSACTION_STATUS_ERRORS) + { + NvOsDebugPrintf("Err in I2c transfer: Controller Status 0x%08x \n", + hRmI2cCont->ControllerStatus); + IsFinalIntGot = NV_TRUE; + goto FinalIntDone; + } + if (hRmI2cCont->IsCurrentTransferRead) { // If there is remianing word to read then read here from fifo. @@ -604,13 +629,16 @@ Done: NvRmInterruptDone(hRmI2cCont->I2CInterruptHandle); } -#if NV_OAL +#if USE_POLLING_METHOD static NvError WaitForTransactionCompletesPolling( NvRmI2cControllerHandle hRmI2cCont, NvU32 Timeout) { - NvU32 RemainingTime = Timeout; + NvU32 RemainingTime; + RemainingTime = (Timeout == NV_WAIT_INFINITE)?Timeout:Timeout*1000; do { + NvOsWaitUS(I2C_POLLING_TIMEOUT_STEP_USEC); + // Read the Interrupt status register & PKT_STATUS hRmI2cCont->ControllerStatus = I2C_REGR(hRmI2cCont, INTERRUPT_STATUS_REGISTER); if (hRmI2cCont->ControllerStatus & hRmI2cCont->IntMaskReg) @@ -619,14 +647,11 @@ static NvError WaitForTransactionCompletesPolling( if (hRmI2cCont->IsTransferCompleted) break; } - - NvOsWaitUS(I2C_POLLING_TIMEOUT_STEP_USEC); - RemainingTime = (RemainingTime > I2C_POLLING_TIMEOUT_STEP_USEC)? - (RemainingTime - I2C_POLLING_TIMEOUT_STEP_USEC): 0; - } while(RemainingTime); - if (RemainingTime && (hRmI2cCont->ModuleId == NvRmModuleID_Dvc)) - DVC_REGW(hRmI2cCont, STATUS_REG, NV_DRF_NUM(DVC, STATUS_REG, I2C_DONE_INTR, 1)); + if (Timeout != NV_WAIT_INFINITE) + RemainingTime = (RemainingTime > I2C_POLLING_TIMEOUT_STEP_USEC)? + (RemainingTime - I2C_POLLING_TIMEOUT_STEP_USEC): 0; + } while(RemainingTime); if (!RemainingTime) return NvError_Timeout; @@ -640,14 +665,13 @@ static NvError WaitForTransactionCompletes( NvU32 Timeout) { NvError Error; - - hRmI2cCont->IsTransferCompleted = NV_FALSE; -#if NV_OAL +#if USE_POLLING_METHOD + hRmI2cCont->IsTransferCompleted = NV_FALSE; Error = WaitForTransactionCompletesPolling(hRmI2cCont, hRmI2cCont->timeout); #else // Wait for the Transfer completes - Error = NvOsSemaphoreWaitTimeout(hRmI2cCont->I2cSyncSemaphore, hRmI2cCont->timeout); + Error = NvOsSemaphoreWaitTimeout(hRmI2cCont->I2cSyncSemaphore, Timeout); #endif return Error; } @@ -681,8 +705,9 @@ DoOneReceiveTransaction( DoTxFifoEmpty(hRmI2cCont, &TFifoEmptyCount); - - IntMaskReg = 0; + // Enable all possible i2c controller error. + IntMaskReg = I2C_ERRORS_INTERRUPT_MASK; + if (!hRmI2cCont->IsCurrentTransferNoAck) IntMaskReg = NV_FLD_SET_DRF_DEF(I2C, INTERRUPT_MASK_REGISTER, NOACK_INT_EN, ENABLE, IntMaskReg); @@ -694,6 +719,8 @@ DoOneReceiveTransaction( hRmI2cCont->WordTransferred = 0; hRmI2cCont->WordRemaining = WordsToRead; + hRmI2cCont->IsTransferCompleted = NV_FALSE; + // If requested size is more than cpu transaction thresold then use dma. if ((hRmI2cCont->DmaBufferSize) && (hRmI2cCont->WordRemaining > I2C_MAX_WORD_TO_USE_CPU)) @@ -719,7 +746,7 @@ DoOneReceiveTransaction( SetRxFifoTriggerLevel(hRmI2cCont, 1); if (hRmI2cCont->IsCurrentTransferNoStop) { -#if NV_OAL +#if USE_POLLING_METHOD goto CpuBasedReading; #else Error = NvRmDmaStartDmaTransfer(hRmI2cCont->hRmDma, &hRmI2cCont->RxDmaReq, @@ -751,7 +778,6 @@ DoOneReceiveTransaction( goto WaitForCompletion; } Error = NvSuccess; -// NvOsDebugPrintf("Read Using Dma\n"); } CpuBasedReading: @@ -789,9 +815,13 @@ WaitForCompletion: if (Error == NvSuccess) { hRmI2cCont->I2cTransferStatus = NvError_I2cReadFailed; - if (hRmI2cCont->ControllerStatus & I2C_FIFO_ERROR_INTERRUPTS) + if (hRmI2cCont->ControllerStatus & I2C_TRANSACTION_STATUS_ERRORS) { - hRmI2cCont->I2cTransferStatus = NvError_I2cReadFailed; + if (hRmI2cCont->ControllerStatus & I2C_ARBITRATION_LOST_ERRORS) + hRmI2cCont->I2cTransferStatus = NvError_I2cArbitrationFailed; + else + hRmI2cCont->I2cTransferStatus = NvError_I2cInternalError; + goto ReadExitWithReset; } else @@ -893,7 +923,9 @@ DoOneSendTransaction( &PacketHeader2, &PacketHeader3); DoTxFifoEmpty(hRmI2cCont, &TFifoEmptyCount); - IntMaskReg = 0; + // Enable all possible i2c controller error. + IntMaskReg = I2C_ERRORS_INTERRUPT_MASK; + if (!hRmI2cCont->IsCurrentTransferNoAck) IntMaskReg = NV_FLD_SET_DRF_DEF(I2C, INTERRUPT_MASK_REGISTER, NOACK_INT_EN, ENABLE, IntMaskReg); @@ -904,6 +936,7 @@ DoOneSendTransaction( WordsToSend = BYTES_TO_WORD(pTransaction->NumBytes); hRmI2cCont->WordTransferred = 0; hRmI2cCont->WordRemaining = WordsToSend; + hRmI2cCont->IsTransferCompleted = NV_FALSE; if ((hRmI2cCont->DmaBufferSize) && (hRmI2cCont->WordRemaining > I2C_MAX_WORD_TO_USE_CPU)) @@ -1012,9 +1045,12 @@ WaitForCompletion: if (Error == NvSuccess) { hRmI2cCont->I2cTransferStatus = NvError_I2cWriteFailed; - if (hRmI2cCont->ControllerStatus & I2C_FIFO_ERROR_INTERRUPTS) + if (hRmI2cCont->ControllerStatus & I2C_TRANSACTION_STATUS_ERRORS) { - hRmI2cCont->I2cTransferStatus = NvError_I2cWriteFailed; + if (hRmI2cCont->ControllerStatus & I2C_ARBITRATION_LOST_ERRORS) + hRmI2cCont->I2cTransferStatus = NvError_I2cArbitrationFailed; + else + hRmI2cCont->I2cTransferStatus = NvError_I2cInternalError; goto WriteExitWithReset; } else @@ -1362,7 +1398,9 @@ static void AP20RmI2cClose(NvRmI2cControllerHandle hRmI2cCont) if (hRmI2cCont->I2cSyncSemaphore) { +#if !USE_POLLING_METHOD NvRmInterruptUnregister(hRmI2cCont->hRmDevice, hRmI2cCont->I2CInterruptHandle); +#endif NvOsSemaphoreDestroy(hRmI2cCont->I2cSyncSemaphore); hRmI2cCont->I2cSyncSemaphore = NULL; hRmI2cCont->I2CInterruptHandle = NULL; @@ -1399,8 +1437,10 @@ static void AP20RmI2cClose(NvRmI2cControllerHandle hRmI2cCont) NvError AP20RmI2cOpen(NvRmI2cControllerHandle hRmI2cCont) { NvError Error = NvSuccess; +#if !USE_POLLING_METHOD NvU32 IrqList; NvOsInterruptHandler IntHandlers = I2cIsr; +#endif NvU32 RxFifoPhyAddress; NvU32 TxFifoPhyAddress; @@ -1482,6 +1522,7 @@ NvError AP20RmI2cOpen(NvRmI2cControllerHandle hRmI2cCont) if (!Error) Error = NvOsSemaphoreCreate( &hRmI2cCont->I2cSyncSemaphore, 0); +#if !USE_POLLING_METHOD if (!Error) { IrqList = NvRmGetIrqForLogicalInterrupt( @@ -1490,7 +1531,7 @@ NvError AP20RmI2cOpen(NvRmI2cControllerHandle hRmI2cCont) Error = NvRmInterruptRegister(hRmI2cCont->hRmDevice, 1, &IrqList, &IntHandlers, hRmI2cCont, &hRmI2cCont->I2CInterruptHandle, NV_TRUE); } - +#endif // Packet mode initialization hRmI2cCont->RsTransfer = NV_FALSE; |