summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerrit Code Review <gerrit2@git-master.nvidia.com>2010-01-08 01:25:56 +0200
committerGerrit Code Review <gerrit2@git-master.nvidia.com>2010-01-08 01:25:56 +0200
commit993d229c19beb3a3d093d6063e3c72959496d316 (patch)
tree49991707a1b18b9039fd9bb1e8d6afa846d9200b
parent97753a87e41d7dae06ae53c5fccb55ad810bc98a (diff)
parentf09edd005d75f8a8579bb0d723d0e592c905bf52 (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.h2
-rw-r--r--arch/arm/mach-tegra/include/nvodm_services.h1
-rw-r--r--arch/arm/mach-tegra/nvodm/nvodm_services.c6
-rw-r--r--arch/arm/mach-tegra/nvrm/io/ap20/ap20rm_i2c.c103
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;