#include #include #include #include #include #include //20100915 lwhite add this for porting driver to Kernel-2.6.35 (for drv_kmalloc & drv_vfree) #include "drv_i2c_main.h" I2C_DEV I2cDev; struct list_head CmdList; UINT32 M0BusyCounter = 0; UINT32 M1BusyCounter = 0; UINT8 bSuspend = 0; UINT16 g_ucHangNum = 0; UINT16 g_BusyLoop = 100; #define I2C_STATUS_SYSTEM_TIMEOUT 6 #define GPIO_I2C #if 1 //330 did ot supprt suspend/resume #else INT32 I2CResume(void); INT32 I2CSuspend(pm_message_t state); #endif INT32 DRV_I2C_QueueCmdFun(UINT8 Mx,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed, INT8 bRead); INT32 DRV_I2C_RunCmdFun(UINT8 Mx,UINT8 *pData); void RunQueueFun(struct work_struct *work); void MxI2CRestart(UINT8 Mx,UINT32 lag); void MxI2CStart(UINT8 Mx,UINT32 lag); void MxI2CStop(UINT8 Mx,UINT32 lag); void MxI2CWriteByte(UINT8 Mx,UINT8 Value,UINT32 lag); UINT32 SwI2CReadBasicFun(UINT8 Mx,UINT8 SlaveAddress,UINT8 BaseAddress,UINT8 Length,UINT8 Speed,UINT8 *pStatus); void SwI2CWriteBasicFun(UINT8 Mx,UINT8 SlaveAddress,UINT8 BaseAddress,UINT32 Data,UINT8 Length,UINT8 Speed,UINT8 *pStatus); void I2CRead(UINT8 MasterIndex,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed,UINT8 *pStatus); void I2CWrite(UINT8 MasterIndex,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed,UINT8 *pStatus); static INT32 QueueI2CFun(UINT8 Mx,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed) { unsigned long flags; PQUEUE_I2C pQueue; pQueue = drv_kmalloc(sizeof(QUEUE_I2C)+Length-1,GFP_ATOMIC, MODULEID_I2C); // Cannot sleep if(!pQueue) { DebugPrint("Cannot allocate QUEUE_I2C"); return -ENOMEM; } // INIT_LIST_HEAD(&pQueue->list); pQueue->Mx = Mx; pQueue->DeviceID = DeviceID; pQueue->AddrType = AddrType; pQueue->Speed = Speed; pQueue->Address = Address; pQueue->Length = Length; memcpy(pQueue->Data,pData,Length); spin_lock_irqsave(&I2cDev.Spinlock[I2C_SPIN_LOCK_QUEUE],flags); list_add_tail(&pQueue->list,&I2cDev.pQueueWriteList); spin_unlock_irqrestore(&I2cDev.Spinlock[I2C_SPIN_LOCK_QUEUE],flags); queue_work(I2cDev.i2cWorkQueue,&I2cDev.QueueWork); DebugPrint("WARNING! Queue Mx=%d, ID=%02x, Type=%d, Addr=%08x, Len=%d, Speed=%d" ,Mx,DeviceID,AddrType,Address,Length,Speed); return 0; } /* void RunQueueFun(void *Context) { struct list_head QueueList,*cursor,*next; UINT32 flags; PQUEUE_I2C pQueue; UINT8 Status; INIT_LIST_HEAD(&QueueList); spin_lock_irqsave(&I2cDev.Spinlock[I2C_SPIN_LOCK_QUEUE],flags); list_splice_init(&I2cDev.pQueueWriteList,&QueueList); spin_unlock_irqrestore(&I2cDev.Spinlock[I2C_SPIN_LOCK_QUEUE],flags); list_for_each_safe(cursor,next,&QueueList) { list_del(cursor); pQueue = container_of(cursor,QUEUE_I2C,list); Status = I2C_STATUS_SUCCESS; // DebugPrint("RunQueue Mx=%d, ID=%02x, Type=%d, Addr=%08x, Len=%d, Speed=%d" // ,pQueue->Mx,pQueue->DeviceID,pQueue->AddrType // ,pQueue->Address,pQueue->Length,pQueue->Speed); DRV_I2C_WriteFun(pQueue->Mx ,pQueue->DeviceID ,pQueue->AddrType ,pQueue->Address ,pQueue->Data,pQueue->Length ,pQueue->Speed,&Status); drv_kfree(pQueue, MODULEID_I2C); } } */ //20100209 lwhite modified for new kernel void RunQueueFun(struct work_struct *work) { PI2C_DEV pI2cDev = container_of(work, I2C_DEV, QueueWork); struct list_head QueueList,*cursor = NULL,*next = NULL; unsigned long flags; UINT8 Status; INIT_LIST_HEAD(&QueueList); spin_lock_irqsave(&pI2cDev->Spinlock[I2C_SPIN_LOCK_QUEUE],flags); list_splice_init(&pI2cDev->pQueueWriteList,&QueueList); spin_unlock_irqrestore(&pI2cDev->Spinlock[I2C_SPIN_LOCK_QUEUE],flags); list_for_each_safe(cursor,next,&QueueList) { PQUEUE_I2C pQueue; list_del(cursor); pQueue = container_of(cursor,QUEUE_I2C,list); Status = I2C_STATUS_SUCCESS; // DebugPrint("RunQueue Mx=%d, ID=%02x, Type=%d, Addr=%08x, Len=%d, Speed=%d" // ,pQueue->Mx,pQueue->DeviceID,pQueue->AddrType // ,pQueue->Address,pQueue->Length,pQueue->Speed); DRV_I2C_WriteFun(pQueue->Mx ,pQueue->DeviceID ,pQueue->AddrType ,pQueue->Address ,pQueue->Data,pQueue->Length ,pQueue->Speed,&Status); drv_kfree(pQueue, MODULEID_I2C); } } #if SOFTWARE_MODE_MASTER #define newdelay(time2) {\ UINT32 TargetA,curA,refA;\ MmioReadFun(M0_CONTROL0);\ refA = read_c0_count();\ TargetA = (time2)*100 + refA;\ if(TargetArefA||(curArefA);\ }\ } #define WaitClk(time,hl) {\ UINT32 limit;\ if(hl==1)\ {\ for(limit=0;limit<12 && (SW_MASTER_SCL_IN&MmioReadWordFun(Control))==0;limit++)\ {\ udelay(1);\ }\ }\ else\ {\ for(limit=0;limit<12 && (SW_MASTER_SCL_IN&MmioReadWordFun(Control))!=0;limit++)\ {\ udelay(1);\ }\ }\ if(time>limit)\ newdelay(time-limit);\ } void MxI2CStart(UINT8 Mx,UINT32 lag) { PVOID Control; UINT16 Data; if(Mx==0) { Control = (PVOID)SW_MASTER0; } else { Control = (PVOID)SW_MASTER1; } Data = MmioReadWordFun(Control); Data |= SW_MASTER_ENABLE | SW_MASTER_SCL_OUT_OEN | SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:1 newdelay(2); Data &= ~SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:0, Clk:1 newdelay(lag); Data &= ~SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:0, Clk:0 WaitClk(lag,0); I2cDev.Status[Mx] = I2C_STATUS_SUCCESS; } void MxI2CStop(UINT8 Mx,UINT32 lag) { PVOID Control; UINT16 Data; if(Mx==0) { Control = (PVOID)SW_MASTER0; } else { Control = (PVOID)SW_MASTER1; } Data = MmioReadWordFun(Control); Data &= ~(SW_MASTER_SDA_OUT_OEN | SW_MASTER_SCL_OUT_OEN); MmioWriteWordFun(Control,Data); // Data:0, Clk:0 newdelay(lag); Data |= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:0, Clk:1 WaitClk(lag,1); Data |= SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:1 newdelay(lag); Data &= ~SW_MASTER_ENABLE; MmioWriteWordFun(Control,Data); newdelay(2); } void MxI2CRestart(UINT8 Mx,UINT32 lag) { PVOID Control; UINT16 Data; if(I2cDev.Status[Mx]!=I2C_STATUS_SUCCESS) return; if(Mx==0) { Control = (PVOID)SW_MASTER0; } else { Control = (PVOID)SW_MASTER1; } Data = MmioReadWordFun(Control); Data &= ~SW_MASTER_SCL_OUT_OEN; Data |= SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:0 newdelay(lag); Data |= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:1 WaitClk(lag,1); Data &= ~SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:0, Clk:1 newdelay(lag); Data &= ~SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:0, Clk:0 WaitClk(lag,0); } void MxI2CWriteByte(UINT8 Mx,UINT8 Value,UINT32 lag) { PVOID Control; UINT16 Data,i; if(I2cDev.Status[Mx]!=I2C_STATUS_SUCCESS) return; if(Mx==0) { Control = (PVOID)SW_MASTER0; } else { Control = (PVOID)SW_MASTER1; } Data = MmioReadWordFun(Control); /* Data &= ~SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:x, Clk:0 newdelay(lag);*/ for(i=0;i<8;i++) { if(Value & 0x80) { Data |= SW_MASTER_SDA_OUT_OEN; } else { Data &= ~SW_MASTER_SDA_OUT_OEN; } MmioWriteWordFun(Control,Data); // Data:x, Clk:0 newdelay(lag); Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:x, Clk:1 WaitClk(lag,1); Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:x, Clk:0 WaitClk(lag,0); Value <<= 1; } Data |= SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:0 newdelay(lag); for(i=0;i<8 && (SW_MASTER_SDA_IN & MmioReadWordFun(Control))!=0;i++) udelay(1); Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:ACK, Clk:1 WaitClk(lag,1); if(SW_MASTER_SDA_IN & MmioReadWordFun(Control)) { I2cDev.Status[Mx] = I2C_STATUS_DATA_ERROR; } Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:0 WaitClk(lag,0); } UINT8 MxI2CReadByte(UINT8 Mx,UINT32 lag,UINT8 bMoreByte) { PVOID Control; UINT16 Data,i; UINT8 Value=0; if(I2cDev.Status[Mx]!=I2C_STATUS_SUCCESS) return -1; if(Mx==0) { Control = (PVOID)SW_MASTER0; } else { Control = (PVOID)SW_MASTER1; } Data = MmioReadWordFun(Control) | SW_MASTER_SDA_OUT_OEN; Data &= ~SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:0 newdelay(lag); for(i=0;i<8;i++) { Value <<= 1; Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:1 WaitClk(lag,1); if(SW_MASTER_SDA_IN & MmioReadWordFun(Control)) { Value |= 1; } Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:1, Clk:0 WaitClk(lag,0); } if(bMoreByte) { Data &= ~SW_MASTER_SDA_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:0, Clk:0 newdelay(lag); } Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:x, Clk:1 WaitClk(lag,1); Data ^= SW_MASTER_SCL_OUT_OEN; MmioWriteWordFun(Control,Data); // Data:x, Clk:0 WaitClk(lag,0); return Value; } #if 0 UINT32 SwI2CReadBasicFun(UINT8 Mx,UINT8 SlaveAddress,UINT8 BaseAddress,UINT8 Length,UINT8 Speed,UINT8 *pStatus) { //UINT32 Data,i; UINT32 Data; UINT8 i; UINT32 lag; UINT8 *pData; if(Length>4) { *pStatus = I2C_STATUS_DATA_ERROR; DbgFunPrint("Invalid Parameter"); return -1; } if(in_atomic()) { DbgFunPrint("ID=%02x Addr=%02x,Invalid Process!!",SlaveAddress,BaseAddress); *pStatus = I2C_STATUS_DATA_ERROR; return -1; } if(Speed==I2C_SPEED_100K) { lag = SW_MASTER_100K; } else { lag = SW_MASTER_400K; } Data = 0; pData = (UINT8 *)&Data; down(&I2cDev.I2cMutex[Mx]); MxI2CStart(Mx,lag); MxI2CWriteByte(Mx,SlaveAddress,lag); MxI2CWriteByte(Mx,BaseAddress,lag); MxI2CRestart(Mx,lag); MxI2CWriteByte(Mx,SlaveAddress|1,lag); for(i=0;i4) { *pStatus = I2C_STATUS_DATA_ERROR; DbgFunPrint("Invalid Parameter"); return; } if(in_atomic()) { if(QueueI2CFun(Mx,SlaveAddress,ADDRESS_TYPE_BYTE,BaseAddress,(UINT8 *)&Data,Length,Speed)<0) { DbgFunPrint("Invalid Process!!"); *pStatus = I2C_STATUS_DATA_ERROR; } else { *pStatus = I2C_STATUS_SUCCESS; } return; } if(Speed==I2C_SPEED_100K) { lag = SW_MASTER_100K; } else { lag = SW_MASTER_400K; } pData = (UINT8 *)&Data; down(&I2cDev.I2cMutex[Mx]); MxI2CStart(Mx,lag); MxI2CWriteByte(Mx,SlaveAddress,lag); MxI2CWriteByte(Mx,BaseAddress,lag); for(i=0;i>24) & 0xFF; if(AddrNum>3 || AddrNum==0) { MxI2CStop(Mx,lag); *pStatus = I2C_STATUS_DATA_ERROR; up(&I2cDev.I2cMutex[Mx]); DbgFunPrint("Invalid AddrNum"); return; } MxI2CWriteByte(Mx,SlaveAddress,lag); for(i=0;i>(8*i)),lag); } MxI2CRestart(Mx,lag); MxI2CWriteByte(Mx,SlaveAddress|1,lag); } for(i=0;i4 || AddrLength==0) { MxI2CStop(Mx,lag); *pStatus = I2C_STATUS_DATA_ERROR; up(&I2cDev.I2cMutex[Mx]); DbgFunPrint("Invalid AddrNum"); return; } MxI2CWriteByte(Mx,SlaveAddress,lag); if (AddrLength==4) { for(i=0;i>(8*i)),lag); } } else if (AddrLength==2) { UINT16 Addr = (UINT16)BaseAddress; for(i=0;i>(8*i)),lag); } } else if (AddrLength==1) { MxI2CWriteByte(Mx,(UINT8)BaseAddress,lag); } MxI2CRestart(Mx,lag); MxI2CWriteByte(Mx,SlaveAddress|1,lag); } for(i=0;i>24) & 0xFF; if(AddrNum>3 || AddrNum==0) { MxI2CStop(Mx,lag); *pStatus = I2C_STATUS_DATA_ERROR; up(&I2cDev.I2cMutex[Mx]); DbgFunPrint("Invalid AddrNum"); return; } for(i=0;i>(8*i)),lag); } } for(i=0;i0 ) #else if( (IntReg==0x09||IntReg==0x0A) && pBuffer!=NULL && Remainder>0 ) #endif { if(Remainder>4) { CopyBytes = 4; } else { CopyBytes = Remainder; } if(I2cDev.IntInfo[0].bRead) { #if ONE_BYTE_INTERRUPT if(IntReg==0x05||IntReg==0x06||IntReg==0x07||IntReg==0x08) #else if(IntReg==0x0A) #endif { Data = MmioReadFun(M0_DATA1); } else { Data = MmioReadFun(M0_DATA0); } memcpy(&pBuffer[I2cDev.IntInfo[0].Completed],&Data,CopyBytes); } else { memcpy(&Data,&pBuffer[I2cDev.IntInfo[0].Completed],CopyBytes); #if ONE_BYTE_INTERRUPT if(IntReg==0x08) #else if(IntReg==0x0A) #endif { MmioWriteFun(M0_DATA1,Data); } else { MmioWriteFun(M0_DATA0,Data); } } I2cDev.IntInfo[0].Completed += CopyBytes; } if(I2cDev.InterruptCounter[0]==0) { complete(&I2cDev.Comp[0]); //del_timer(&I2cDev.ResetTimer[0]); } } MmioWriteFun(M0_CONTROL0,(Control0&0xF0FFFFFF)|MX_CONTROL0_INT_CLEAR); } return IRQ_HANDLED; } static irqreturn_t MasterBI2cInterruptFun(INT32 irq,void *dev_id) { UINT32 BusStatus,Control0,Remainder,Data; UINT8 IntReg,CopyBytes; UINT8* pBuffer; BusStatus = MmioReadFun(M1_BUS_STATUS); // Master 1 Control0 = MmioReadFun(M1_CONTROL0); if(Control0&MX_CONTROL0_INT) { IntReg = (UINT8)(BusStatus& 0xFF); // DebugPrint("BusStatus=0x%08x",BusStatus); if(IntReg==0x00||IntReg==0x0B||IntReg==0xFF) { I2cDev.Status[1] = I2C_STATUS_DEVICE_ID_ERROR; complete(&I2cDev.Comp[1]); DebugPrint("M1 %08x I2C Error!!! 0x%02x",MmioReadFun(M1_CONTROL1),IntReg); } else { I2cDev.InterruptCounter[1]--; pBuffer = I2cDev.IntInfo[1].pBuffer; Remainder = I2cDev.IntInfo[1].Length - I2cDev.IntInfo[1].Completed; #if ONE_BYTE_INTERRUPT if( (I2cDev.InterruptCounter[0]==0||IntReg==0x04||IntReg==0x08) && pBuffer!=NULL && Remainder>0 ) #else if( (IntReg==0x09||IntReg==0x0A) && pBuffer!=NULL && Remainder>0 ) #endif { if(Remainder>4) { CopyBytes = 4; } else { CopyBytes = Remainder; } if(I2cDev.IntInfo[1].bRead) { #if ONE_BYTE_INTERRUPT if(IntReg==0x05||IntReg==0x06||IntReg==0x07||IntReg==0x08) #else if(IntReg==0x0A) #endif { Data = MmioReadFun(M1_DATA1); } else { Data = MmioReadFun(M1_DATA0); } memcpy(&pBuffer[I2cDev.IntInfo[1].Completed],&Data,CopyBytes); } else { memcpy(&Data,&pBuffer[I2cDev.IntInfo[1].Completed],CopyBytes); #if ONE_BYTE_INTERRUPT if(IntReg==0x08) #else if(IntReg==0x0A) #endif { MmioWriteFun(M1_DATA1,Data); } else { MmioWriteFun(M1_DATA0,Data); } } I2cDev.IntInfo[1].Completed += CopyBytes; } if(I2cDev.InterruptCounter[1]==0) { complete(&I2cDev.Comp[1]); } } MmioWriteFun(M1_CONTROL0,(Control0&0xF0FFFFFF)|MX_CONTROL0_INT_CLEAR); } return IRQ_HANDLED; } //static void i2c_dispatch(struct pt_regs *regs) static void i2c_dispatch_A(void) { do_IRQ(MASTER_A_IRQ_FINAL); } static void i2c_dispatch_B(void) { do_IRQ(MASTER_B_IRQ_FINAL); } /* static void i2cM0TimeOutFun(UINT32 data) { UINT32 reg; #ifndef INIT_BY_KMF UINT32 i; #endif DbgFunPrint("Critical Error occurs, InterruptCounter=%d",I2cDev.InterruptCounter[0]); #ifndef INIT_BY_KMF for(i=0;i<0x100;) { if((i&0xF)==0) printk("0x%08X: ",(UINT32)(M0_CONTROL0+i)); printk("%08X ",MmioReadFun(M0_CONTROL0+i)); i += 4; if((i&0xF)==0) printk("\n"); } if((i&0xF)!=0) printk("\n"); printk("\n"); #endif reg = MmioReadFun(M0_CONTROL0); reg &= 0x00FF0000; reg |= 0x000000FF; MmioWriteFun(M0_CONTROL0,reg); I2cDev.Status[0] = I2C_STATUS_HARDWARE_CRASH; complete(&I2cDev.Comp[0]); } static void i2cM1TimeOutFun(UINT32 data) { UINT32 reg; #ifndef INIT_BY_KMF UINT32 i; #endif DebugPrint("i2cM1TimeOutFun, InterruptCounter=%d",I2cDev.InterruptCounter[1]); #ifndef INIT_BY_KMF for(i=0;i<0x100;) { if((i&0xF)==0) printk("0x%08X: ",(UINT32)(M0_CONTROL0+i)); printk("%08X ",MmioReadFun(M0_CONTROL0+i)); i += 4; if((i&0xF)==0) printk("\n"); } if((i&0xF)!=0) printk("\n"); printk("\n"); #endif reg = MmioReadFun(M1_CONTROL0); reg &= 0x00FF0000; reg |= 0x000000FF; MmioWriteFun(M1_CONTROL0,reg); I2cDev.Status[1] = I2C_STATUS_HARDWARE_CRASH; complete(&I2cDev.Comp[1]); }*/ #else // else of #if INTERRUPT_ENABLE void MasterPollingFun(UINT8 MasterIndex,UINT16 Times) { INT32 Count; UINT32 BusStatus,Control0; UINT8 IntReg; PVOID Address; if(MasterIndex==0) { Address = (PVOID)M0_CONTROL0; } else if(MasterIndex==1) { Address = (PVOID)M1_CONTROL0; } else { DbgFunPrint("Invalid Master Index"); return; } Count = 0; Control0 = MmioReadFun(Address); while(Count0) { BusStatus = MmioReadFun(M0_BUS_STATUS); IntReg = (UINT8)(BusStatus >> (16*MasterIndex)); if(IntReg==0x00||IntReg==0x0B||IntReg==0x10||IntReg==0x1B||IntReg==0xFF) { MmioWriteFun(Address,(Control0&0x00FFFFFF)|MX_CONTROL0_INT_CLEAR); DebugPrint("IntReg==0x%02x",IntReg); I2cDev.Status[MasterIndex] = I2C_STATUS_DEVICE_ID_ERROR; break; } else { MmioWriteFun(Address,(Control0&0x00FFFFFF)|MX_CONTROL0_INT_CLEAR); Count++; I2cDev.InterruptCounter[MasterIndex]--; } } } #endif // end of #if INTERRUPT_ENABLE static void MasterAsyncResetFun(UINT8 MasterIndex,UINT8 Speed) { UINT32 RegValue,Scl; if(Speed==I2C_SPEED_25K) { Scl = MX_CONTROL0_SCL_25K; } else if(Speed==I2C_SPEED_100K) { Scl = MX_CONTROL0_SCL_100K; } else if(Speed==I2C_SPEED_200K) { Scl = MX_CONTROL0_SCL_200K; } else if(Speed==I2C_SPEED_300K) { Scl = MX_CONTROL0_SCL_300K; } else if(Speed==I2C_SPEED_400K) { Scl = MX_CONTROL0_SCL_400K; } else { Scl = MX_CONTROL0_SCL_100K; } if(MasterIndex) { RegValue = MmioReadFun(M1_CONTROL0); if((RegValue&0xFFFF)!=Scl) { // DebugPrint("MasterAsyncResetFun"); RegValue &= 0x00FF0000; RegValue |= MX_CONTROL0_ASYNC_RESET|Scl; wmb(); MmioWriteFun(M1_CONTROL0,RegValue|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE); udelay(1); RegValue &= ~MX_CONTROL0_ASYNC_RESET; wmb(); MmioWriteFun(M1_CONTROL0,RegValue|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE); udelay(1); } } else { RegValue = MmioReadFun(M0_CONTROL0); if((RegValue&0xFFFF)!=Scl) { // DebugPrint("MasterAsyncResetFun"); RegValue &= 0x00FF0000; RegValue |= MX_CONTROL0_ASYNC_RESET|Scl; wmb(); MmioWriteFun(M0_CONTROL0,RegValue|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE); udelay(1); RegValue &= ~MX_CONTROL0_ASYNC_RESET; wmb(); MmioWriteFun(M0_CONTROL0,RegValue|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE); udelay(1); } } } void SW_I2C_DummyRead(UINT8 MasterIndex, UINT8 speed) { PVOID MxSWI2CBUS; UINT8 delayTime = 0, index=0; printk("<0>""[I2C][%s]!!\n",__FUNCTION__); if ( MasterIndex == 0) { MxSWI2CBUS = (PVOID)(M0_CONTROL0+0x100); } else { MxSWI2CBUS = (PVOID)(M1_CONTROL0+0x100); } switch (speed) { case I2C_SPEED_25K: delayTime = 20; break; case I2C_SPEED_100K: delayTime = 5; break; case I2C_SPEED_200K: delayTime = 3; break; case I2C_SPEED_300K: case I2C_SPEED_400K: delayTime = 2; break; default: delayTime = 5; // 100K break; } MmioWriteFun(MxSWI2CBUS, 0x0c); for ( index=0;index<9;index++ ) { MmioWriteFun(MxSWI2CBUS, 0x4c); udelay(delayTime); MmioWriteFun(MxSWI2CBUS, 0x48); udelay(delayTime); } MmioWriteFun(MxSWI2CBUS, 0x40); udelay(delayTime); MmioWriteFun(MxSWI2CBUS, 0x44); udelay(delayTime); MmioWriteFun(MxSWI2CBUS, 0x4c); udelay(delayTime); MmioWriteFun(MxSWI2CBUS, 0x0c); } void I2CRead(UINT8 MasterIndex,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed,UINT8 *pStatus) { UINT32 RegValue,ucStatus; PVOID MxControl0,MxControl1,__attribute__((unused)) MxData[2],MxAddress,MxDataLength; #if !INTERRUPT_ENABLE UINT32 Remainder,Completed; UINT8 CopyBytes,Switch=0; #endif UINT8 I2CRead_RETRY_CNT=0; // DebugPrint("DRV_I2C_ReadFun 0x%02x 0x%02x %d",DeviceID,Address,Length); /* if(MasterIndex>=MASTER_NUMBER || AddrType>=ADDRESS_TYPE_INVALID || (AddrType==ADDRESS_TYPE_MULTIPLE&&(Address&0x03000000)==0) || Length == 0 || pData == NULL) { DbgFunPrint("Invalid Parameter"); *pStatus = I2C_STATUS_DATA_ERROR; return; } if(in_atomic()) { DbgFunPrint("ID=%02x,Invalid Process!!",DeviceID); *pStatus = I2C_STATUS_DATA_ERROR; return; } down(&I2cDev.I2cMutex[MasterIndex]); */ /* if(down_interruptible(&I2cDev.I2cMutex[MasterIndex])) { DbgFunPrint("SYSTEM_ERROR"); *pStatus = I2C_STATUS_SYSTEM_ERROR; return; }*/ #if 0 if (bSuspend) { DbgFunPrint("System is suspend!!!!!!!"); // up(&I2cDev.I2cMutex[MasterIndex]); *pStatus = I2C_STATUS_SYSTEM_ERROR; return; } #endif I2CRead_retry: if(g_ucHangNum>1) g_BusyLoop = 2; else g_BusyLoop = 100; RegValue = 0; // BusyCounter = 0; if(MasterIndex==0) { MxControl0 = (PVOID)M0_CONTROL0; MxControl1 = (PVOID)M0_CONTROL1; MxData[0] = (PVOID)M0_DATA0; MxData[1] = (PVOID)M0_DATA1; MxAddress = (PVOID)M0_BASE_ADDRESS; MxDataLength = (PVOID)M0_DATA_LENGTH; M0BusyCounter = 0; while((MmioReadFun(M0_BUS_STATUS) & I2C_BUS_STATUS_BUSY)==I2C_BUS_STATUS_BUSY) { //DbgFunPrint("I2C0BusBusy 0x%08x %d",MmioReadFun(M0_BUS_STATUS),RegValue++); M0BusyCounter++; DbgFunPrint("I2C0BusBusy 0x%08x,BusyCount=%d",MmioReadFun(M0_BUS_STATUS),M0BusyCounter); msleep(10); if (M0BusyCounter > g_BusyLoop) { // printk(KERN_EMERG "[I2C WARNING]I2C0BusBusy!!!!!!!!!!!!\n"); *pStatus = I2C_STATUS_DATA_ERROR; // up(&I2cDev.I2cMutex[MasterIndex]); // if(1000 == g_BusyLoop) { g_ucHangNum++; if(0==(g_ucHangNum%10)) { printk("<0>""[I2C][%s]0_I2C BUS BUSY!!,g_ucHangNum=%d\n",__FUNCTION__,g_ucHangNum); printk("<0>""MasterIndex = %d",MasterIndex); printk("<0>""DeviceID = 0x%x",DeviceID); printk("<0>""AddrType = %d",AddrType); printk("<0>""Address = %d",Address); printk("<0>""Length = %d",Length); printk("<0>""Speed = %d",Speed); } } return; //break; } } g_ucHangNum = 0; } else// if(MasterIndex==1) { MxControl0 = (PVOID)M1_CONTROL0; MxControl1 = (PVOID)M1_CONTROL1; MxData[0] = (PVOID)M1_DATA0; MxData[1] = (PVOID)M1_DATA1; MxAddress = (PVOID)M1_BASS_ADDRESS; MxDataLength = (PVOID)M1_DATA_LENGTH; M1BusyCounter = 0; while((MmioReadFun(M1_BUS_STATUS) & I2C_BUS_STATUS_BUSY)==I2C_BUS_STATUS_BUSY) { //DbgFunPrint("I2C1BusBusy %d",RegValue++); M1BusyCounter++; DbgFunPrint("I2C1BusBusy,BusyCount=%d",M1BusyCounter); #if 0//UMF_OPT_INTERNETMONITOR_SPEC #else msleep(10); #endif if (M1BusyCounter > g_BusyLoop) { // printk(KERN_EMERG "[I2C WARNING]I2C1BusBusy!!!!!!!!!!!!\n"); *pStatus = I2C_STATUS_DATA_ERROR; // up(&I2cDev.I2cMutex[MasterIndex]); // if(1000 == g_BusyLoop) { g_ucHangNum++; if(0==(g_ucHangNum%10)) { printk("<0>""[I2C][%s]0_I2C BUS BUSY!!,g_ucHangNum=%d\n",__FUNCTION__,g_ucHangNum); printk("<0>""MasterIndex = %d",MasterIndex); printk("<0>""DeviceID = 0x%x",DeviceID); printk("<0>""AddrType = %d",AddrType); printk("<0>""Address = %d",Address); printk("<0>""Length = %d",Length); printk("<0>""Speed = %d",Speed); } } return; //break; } } g_ucHangNum = 0; } MasterAsyncResetFun(MasterIndex,Speed); // Asynchronous reset // to avoid warning message // MxData[0] = MxData[0]; // MxData[1] = MxData[1]; // To Do DeviceID &= 0xFE; if(AddrType==ADDRESS_TYPE_BYTE) { RegValue = ((UINT32)Length)<<16; MmioWriteFun(MxDataLength,RegValue); // Data Length RegValue = 0x01000000 | (Address & 0xFF); MmioWriteFun(MxAddress,RegValue); // Address RegValue = ((UINT32)DeviceID) | (((UINT32)DeviceID | 0x01)<<16); MmioWriteFun(MxControl1,RegValue); RegValue = 0x03800000; //I2cDev.InterruptCounter[MasterIndex] = 1; } /* else if(AddrType==ADDRESS_TYPE_WORD) { }*/ else if(AddrType==ADDRESS_TYPE_NONE) { MmioWriteFun(MxDataLength,(UINT32)Length); // Data Length RegValue = ((UINT32)DeviceID | 0x01); MmioWriteFun(MxControl1,RegValue); RegValue = 0x02800000; // RegValue = 0x02800000 | MX_CONTROL0_NO_ADDRESS; //I2cDev.InterruptCounter[MasterIndex] = 0; } else if(AddrType==ADDRESS_TYPE_MULTIPLE) { RegValue = ((UINT32)Length)<<16; MmioWriteFun(MxDataLength,RegValue); // Data Length MmioWriteFun(MxAddress,Address&0x03FFFFFF); // Address RegValue = ((UINT32)DeviceID) | (((UINT32)DeviceID | 0x01)<<16); MmioWriteFun(MxControl1,RegValue); RegValue = 0x03800000; //I2cDev.InterruptCounter[MasterIndex] = 1; } I2cDev.InterruptCounter[MasterIndex] = 0; if(Speed==I2C_SPEED_25K) { RegValue |= MX_CONTROL0_SCL_25K; } else if(Speed==I2C_SPEED_100K) { RegValue |= MX_CONTROL0_SCL_100K; } else if(Speed==I2C_SPEED_200K) { RegValue |= MX_CONTROL0_SCL_200K; } else if(Speed==I2C_SPEED_300K) { RegValue |= MX_CONTROL0_SCL_300K; } else if(Speed==I2C_SPEED_400K) { RegValue |= MX_CONTROL0_SCL_400K; } I2cDev.Status[MasterIndex] = I2C_STATUS_SUCCESS; #if INTERRUPT_ENABLE I2cDev.IntInfo[MasterIndex].pBuffer = pData; I2cDev.IntInfo[MasterIndex].Length = Length; I2cDev.IntInfo[MasterIndex].Completed = 0; I2cDev.IntInfo[MasterIndex].bRead = TRUE; #if ONE_BYTE_INTERRUPT I2cDev.InterruptCounter[MasterIndex] += Length; RegValue |= MX_CONTROL0_INT_EN|MX_CONTROL0_ONE_BYTE_INT|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE; #else I2cDev.InterruptCounter[MasterIndex] += (Length+3)/4; RegValue |= MX_CONTROL0_INT_EN|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE; #endif //if(MasterIndex==0) // mod_timer(&I2cDev.ResetTimer[0],jiffies+(Length+49)/50*(HZ/25)); wmb(); MmioWriteFun(MxControl0,RegValue); //20120720 DylanWang, use timeout to avoid watch dog reboot the system //wait 2s //wait_for_completion(&I2cDev.Comp[MasterIndex]); ucStatus = wait_for_completion_timeout(&I2cDev.Comp[MasterIndex], 2*HZ); if(ucStatus<2) { g_ucHangNum++; printk("<0>""[I2C][%s]wait completion timeout!!\n",__FUNCTION__); *pStatus = I2C_STATUS_SYSTEM_TIMEOUT; #if 1 SW_I2C_DummyRead(MasterIndex, Speed); udelay(100*1000);//wait 100 ms to clear remain interrupts init_completion(&I2cDev.Comp[MasterIndex]); //reset complete count if(I2CRead_RETRY_CNT == 0) { I2CRead_RETRY_CNT += 1; goto I2CRead_retry; } #else return; #endif } #if 0 if (bSuspend) { DbgFunPrint("System is suspend!!!!!!!"); // up(&I2cDev.I2cMutex[MasterIndex]); *pStatus = I2C_STATUS_SYSTEM_ERROR; return; } #endif MmioWriteFun(0xbe070054,500); //20110120 lwhite add 20us delay between two commands (stop and next start) MmioWriteFun(0xbe110054,500); /* if(I2cDev.Status[MasterIndex]!=I2C_STATUS_SUCCESS) { DbgFunPrint("I2C Read %d/%d",I2cDev.IntInfo[MasterIndex].Completed,Length); }*/ #else // else of #if INTERRUPT_ENABLE Completed = 0; Remainder = Length; I2cDev.InterruptCounter[MasterIndex] += Length; RegValue |= MX_CONTROL0_ONE_BYTE_INT; wmb(); MmioWriteFun(MxControl0,RegValue); if(Length>4) { CopyBytes = 4; } else { CopyBytes = Length; } MasterPollingFun(MasterIndex,CopyBytes+1); RegValue = MmioReadFun(MxData[Switch]); Switch ^= 1; memcpy(&pData[Completed],&RegValue,CopyBytes); Completed += CopyBytes; Remainder -= CopyBytes; while(Remainder > 0) { if(Remainder>4) { CopyBytes = 4; } else { CopyBytes = Remainder; } MasterPollingFun(MasterIndex,CopyBytes); RegValue = MmioReadFun(MxData[Switch]); Switch ^= 1; memcpy(&pData[Completed],&RegValue,CopyBytes); Remainder -= CopyBytes; Completed += CopyBytes; } #endif // end of #if INTERRUPT_ENABLE *pStatus = I2cDev.Status[MasterIndex]; } void DRV_I2C_ReadFun( UINT8 MasterIndex, UINT8 DeviceID, UINT8 AddrType, UINT32 Address, UINT8 *pData, UINT16 Length, UINT8 Speed, UINT8 *pStatus) { if(MasterIndex>=MASTER_NUMBER || AddrType>=ADDRESS_TYPE_INVALID || (AddrType==ADDRESS_TYPE_MULTIPLE&&(Address&0x03000000)==0) || Length == 0 || pData == NULL) { DbgFunPrint("Invalid Parameter"); *pStatus = I2C_STATUS_DATA_ERROR; return; } if(in_atomic()) { DbgFunPrint("ID=%02x,Invalid Process!!",DeviceID); *pStatus = I2C_STATUS_DATA_ERROR; return; } down(&I2cDev.I2cMutex[MasterIndex]); I2CRead(MasterIndex,DeviceID,AddrType,Address,pData,Length,Speed,pStatus); up(&I2cDev.I2cMutex[MasterIndex]); } void I2CWrite(UINT8 MasterIndex,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed,UINT8 *pStatus) { UINT32 RegValue,Completed,ucStatus; PVOID MxControl0,MxControl1,MxData[2],MxAddress,MxDataLength; UINT8 __attribute__((unused)) Remainder,CopyBytes; #if !INTERRUPT_ENABLE UINT8 Switch=0; #endif // DebugPrint("DRV_I2C_WriteFun 0x%02x 0x%02x %d",DeviceID,Address,Length); /* if(MasterIndex>=MASTER_NUMBER || AddrType>=ADDRESS_TYPE_INVALID || (AddrType==ADDRESS_TYPE_MULTIPLE&&(Address&0x03000000)==0) || (Length!=0 && pData==NULL) || (Length==0 && AddrType==ADDRESS_TYPE_NONE) ) { DbgFunPrint("Invalid Parameter"); *pStatus = I2C_STATUS_DATA_ERROR; return; } if(in_atomic()) { if(QueueI2CFun(MasterIndex,DeviceID,AddrType,Address,pData,Length,Speed)<0) { DbgFunPrint("Invalid Process!!"); *pStatus = I2C_STATUS_DATA_ERROR; } else { *pStatus = I2C_STATUS_SUCCESS; } return; } down(&I2cDev.I2cMutex[MasterIndex]); */ /* if(down_interruptible(&I2cDev.I2cMutex[MasterIndex])) { DbgFunPrint("SYSTEM_ERROR"); *pStatus = I2C_STATUS_SYSTEM_ERROR; return; }*/ #if 0 if (bSuspend) { DbgFunPrint("System is suspend!!!!!!!"); // up(&I2cDev.I2cMutex[MasterIndex]); *pStatus = I2C_STATUS_SYSTEM_ERROR; return; } #endif if(g_ucHangNum>1) g_BusyLoop = 2; else g_BusyLoop = 100; // BusyCounter = 0; if(MasterIndex==0) { MxControl0 = (PVOID)M0_CONTROL0; MxControl1 = (PVOID)M0_CONTROL1; MxData[0] = (PVOID)M0_DATA0; MxData[1] = (PVOID)M0_DATA1; MxAddress = (PVOID)M0_BASE_ADDRESS; MxDataLength = (PVOID)M0_DATA_LENGTH; M0BusyCounter = 0; while((MmioReadFun(M0_BUS_STATUS) & I2C_BUS_STATUS_BUSY)==I2C_BUS_STATUS_BUSY) { //DbgFunPrint("I2C0BusBusy %d",RegValue++); M0BusyCounter++; DbgFunPrint("I2C0BusBusy,BusyCount=%d",M0BusyCounter); msleep(10); if (M0BusyCounter > g_BusyLoop) { // printk(KERN_EMERG "[I2C WARNING]I2C0BusBusy!!!!!!!!!!!!\n"); *pStatus = I2C_STATUS_DATA_ERROR; // up(&I2cDev.I2cMutex[MasterIndex]); // if(1000 == g_BusyLoop) { g_ucHangNum++; if(0==(g_ucHangNum%10)) { printk("<0>""[I2C][%s]0_I2C BUS BUSY!!,g_ucHangNum=%d\n",__FUNCTION__,g_ucHangNum); printk("<0>""MasterIndex = %d",MasterIndex); printk("<0>""DeviceID = 0x%x",DeviceID); printk("<0>""AddrType = %d",AddrType); printk("<0>""Address = %d",Address); printk("<0>""Length = %d",Length); printk("<0>""Speed = %d",Speed); } } return; //break; } } g_ucHangNum = 0; } else// if(MasterIndex==1) { MxControl0 = (PVOID)M1_CONTROL0; MxControl1 = (PVOID)M1_CONTROL1; MxData[0] = (PVOID)M1_DATA0; MxData[1] = (PVOID)M1_DATA1; MxAddress = (PVOID)M1_BASS_ADDRESS; MxDataLength = (PVOID)M1_DATA_LENGTH; M1BusyCounter = 0; while((MmioReadFun(M1_BUS_STATUS) & I2C_BUS_STATUS_BUSY)==I2C_BUS_STATUS_BUSY) { //DbgFunPrint("I2C1BusBusy %d",RegValue++); M1BusyCounter++; DbgFunPrint("I2C1BusBusy,BusyCount=%d",M1BusyCounter); #if 0 //UMF_OPT_INTERNETMONITOR_SPEC #else msleep(10); #endif if (M1BusyCounter > g_BusyLoop) { // printk(KERN_EMERG "[I2C WARNING]I2C1BusBusy!!!!!!!!!!!!\n"); *pStatus = I2C_STATUS_DATA_ERROR; // up(&I2cDev.I2cMutex[MasterIndex]); // if(1000 == g_BusyLoop) { g_ucHangNum++; if(0==(g_ucHangNum%10)) { printk("<0>""[I2C][%s]0_I2C BUS BUSY!!,g_ucHangNum=%d\n",__FUNCTION__,g_ucHangNum); printk("<0>""MasterIndex = %d",MasterIndex); printk("<0>""DeviceID = 0x%x",DeviceID); printk("<0>""AddrType = %d",AddrType); printk("<0>""Address = %d",Address); printk("<0>""Length = %d",Length); printk("<0>""Speed = %d",Speed); } } return; //break; } } g_ucHangNum = 0; } MasterAsyncResetFun(MasterIndex,Speed); // Asynchronous reset // To Do Completed = 0; if(Length == 0) { if(AddrType==ADDRESS_TYPE_MULTIPLE) { CopyBytes = (UINT8)(Address>>24)&3; } else { CopyBytes = 1; } Completed = CopyBytes; Length = CopyBytes; Remainder = 0; memcpy(&RegValue,&Address,CopyBytes); MmioWriteFun(MxData[0],RegValue); // Data AddrType = ADDRESS_TYPE_NONE; } else { if(Length > 4) { Remainder = Length - 4; CopyBytes = 4; } else { Remainder = 0; CopyBytes = Length; } memcpy(&RegValue,&pData[Completed],CopyBytes); Completed += CopyBytes; MmioWriteFun(MxData[0],RegValue); // Data if(Remainder > 0) { if(Remainder > 4) { CopyBytes = 4; } else { CopyBytes = Remainder; } Remainder -= CopyBytes; memcpy(&RegValue,&pData[Completed],CopyBytes); Completed += CopyBytes; MmioWriteFun(MxData[1],RegValue); // Data } } if(AddrType==ADDRESS_TYPE_BYTE) { MmioWriteFun(MxDataLength,(UINT32)Length); // Data Length RegValue = 0x01000000 | (Address & 0xFF); MmioWriteFun(MxAddress,RegValue); // Address RegValue = (UINT32)DeviceID&0xFE; MmioWriteFun(MxControl1,RegValue); RegValue = 0x02800000; //I2cDev.InterruptCounter[MasterIndex] = 1; } /* else if(AddrType==ADDRESS_TYPE_WORD) { RegValue = 0x02800000; }*/ else if(AddrType==ADDRESS_TYPE_NONE) { MmioWriteFun(MxDataLength,(UINT32)Length); // Data Length RegValue = (UINT32)DeviceID&0xFE; MmioWriteFun(MxControl1,RegValue); RegValue = 0x02800000 | MX_CONTROL0_NO_ADDRESS; //I2cDev.InterruptCounter[MasterIndex] = 0; } else if(AddrType==ADDRESS_TYPE_MULTIPLE) { RegValue = ((UINT32)Length)<<16; MmioWriteFun(MxDataLength,RegValue); // Data Length MmioWriteFun(MxAddress,Address&0x03FFFFFF); // Address RegValue = ((UINT32)DeviceID&0xFE) | (((UINT32)DeviceID&0xFE)<<16); MmioWriteFun(MxControl1,RegValue); RegValue = 0x03800000; //I2cDev.InterruptCounter[MasterIndex] = 1; } I2cDev.InterruptCounter[MasterIndex] = 0; if(Speed==I2C_SPEED_25K) { RegValue |= MX_CONTROL0_SCL_25K; } else if(Speed==I2C_SPEED_100K) { RegValue |= MX_CONTROL0_SCL_100K; } else if(Speed==I2C_SPEED_200K) { RegValue |= MX_CONTROL0_SCL_200K; } else if(Speed==I2C_SPEED_300K) { RegValue |= MX_CONTROL0_SCL_300K; } else if(Speed==I2C_SPEED_400K) { RegValue |= MX_CONTROL0_SCL_400K; } I2cDev.Status[MasterIndex] = I2C_STATUS_SUCCESS; #if INTERRUPT_ENABLE I2cDev.IntInfo[MasterIndex].pBuffer = pData; I2cDev.IntInfo[MasterIndex].Length = Length; I2cDev.IntInfo[MasterIndex].Completed = Completed; I2cDev.IntInfo[MasterIndex].bRead = FALSE; #if ONE_BYTE_INTERRUPT I2cDev.InterruptCounter[MasterIndex] += Length; RegValue |= MX_CONTROL0_INT_EN|MX_CONTROL0_ONE_BYTE_INT|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE; #else I2cDev.InterruptCounter[MasterIndex] += (Length+3)/4; RegValue |= MX_CONTROL0_INT_EN|MX_CONTROL0_BUSY_WAIT_EN|MX_CONTROL0_ADDR_INT_DISABLE; #endif //if(MasterIndex==0) // mod_timer(&I2cDev.ResetTimer[0],jiffies+(Length+49)/50*(HZ/25)); wmb(); MmioWriteFun(MxControl0,RegValue); //20120720 DylanWang, use timeout to avoid watch dog reboot the system //wait 2s //wait_for_completion(&I2cDev.Comp[MasterIndex]); ucStatus = wait_for_completion_timeout(&I2cDev.Comp[MasterIndex], 2*HZ); if(ucStatus<2) { g_ucHangNum++; printk("<0>""[I2C][%s]wait completion timeout!!\n",__FUNCTION__); *pStatus = I2C_STATUS_SYSTEM_TIMEOUT; return; } #if 0 if (bSuspend) { DbgFunPrint("System is suspend!!!!!!!"); // up(&I2cDev.I2cMutex[MasterIndex]); *pStatus = I2C_STATUS_SYSTEM_ERROR; return; } #endif MmioWriteFun(0xbe070054,500); //20110120 lwhite add 20us delay between two commands (stop and next start) MmioWriteFun(0xbe110054,500); /* if(I2cDev.Status[MasterIndex]!=I2C_STATUS_SUCCESS) { DbgFunPrint("I2C Write %d/%d",I2cDev.IntInfo[MasterIndex].Completed,Length); }*/ #else // else of #if INTERRUPT_ENABLE I2cDev.InterruptCounter[MasterIndex] += Length; RegValue |= MX_CONTROL0_ONE_BYTE_INT; wmb(); MmioWriteFun(MxControl0,RegValue); if(Length>4) { if(AddrType==ADDRESS_TYPE_NONE) { MasterPollingFun(MasterIndex,4); } else { MasterPollingFun(MasterIndex,5); } } else { if(AddrType==ADDRESS_TYPE_NONE) { MasterPollingFun(MasterIndex,Length); } else { MasterPollingFun(MasterIndex,Length+1); } } while(Remainder > 0) { if(Remainder>4) { CopyBytes = 4; } else { CopyBytes = Remainder; } memcpy(&RegValue,&pData[Completed],CopyBytes); MmioWriteFun(MxData[Switch],RegValue); // Data Switch ^= 1; Remainder -= CopyBytes; Completed += CopyBytes; MasterPollingFun(MasterIndex,CopyBytes); } MasterPollingFun(MasterIndex,I2cDev.InterruptCounter[MasterIndex]); #endif // end of #if INTERRUPT_ENABLE *pStatus = I2cDev.Status[MasterIndex]; } void DRV_I2C_WriteFun( UINT8 MasterIndex, UINT8 DeviceID , UINT8 AddrType , UINT32 Address , UINT8 *pData , UINT16 Length , UINT8 Speed , UINT8 *pStatus) { if(MasterIndex>=MASTER_NUMBER || AddrType>=ADDRESS_TYPE_INVALID || (AddrType==ADDRESS_TYPE_MULTIPLE&&(Address&0x03000000)==0) || (Length!=0 && pData==NULL) || (Length==0 && AddrType==ADDRESS_TYPE_NONE) ) { DbgFunPrint("Invalid Parameter"); *pStatus = I2C_STATUS_DATA_ERROR; return; } if(in_atomic()) { if(QueueI2CFun(MasterIndex,DeviceID,AddrType,Address,pData,Length,Speed)<0) { DbgFunPrint("Invalid Process!!"); *pStatus = I2C_STATUS_DATA_ERROR; } else { *pStatus = I2C_STATUS_SUCCESS; } return; } down(&I2cDev.I2cMutex[MasterIndex]); I2CWrite(MasterIndex,DeviceID,AddrType,Address,pData,Length,Speed,pStatus); up(&I2cDev.I2cMutex[MasterIndex]); } UINT32 DRV_I2C_M0BasicReadFun(UINT8 DeviceID,UINT8 Address,UINT8 Length,UINT8 Speed,UINT8 *pStatus) { UINT32 RegValue; // DebugPrint("DRV_I2C_M0BasicReadFun 0x%02x 0x%02x %d %d",DeviceID,Address,Length,Speed); if(Length>4) { *pStatus = I2C_STATUS_DATA_ERROR; DbgFunPrint("Invalid Parameter"); return -1; } DRV_I2C_ReadFun(0,DeviceID,ADDRESS_TYPE_BYTE,Address,(UINT8*)(&RegValue),(UINT32)(Length),Speed,(UINT8*)(pStatus)); return RegValue; } void DRV_I2C_M0BasicWriteFun(UINT8 DeviceID,UINT8 Address,UINT32 Data,UINT8 Length,UINT8 Speed,UINT8 *pStatus) { // DebugPrint("DRV_I2C_M0BasicWriteFun 0x%02x 0x%02x 0x%08x %d %d",DeviceID,Address,Data,Length,Speed); if(Length>4) { *pStatus = I2C_STATUS_DATA_ERROR; DbgFunPrint("Invalid Parameter"); return; } DRV_I2C_WriteFun(0,DeviceID,ADDRESS_TYPE_BYTE,(UINT32)(Address),(UINT8*)(&Data),(UINT16)(Length),Speed,(UINT8*)(pStatus)); } UINT32 DRV_I2C_M1BasicReadFun(UINT8 DeviceID,UINT8 Address,UINT8 Length,UINT8 Speed,UINT8 *pStatus) { UINT32 RegValue; // DebugPrint("DRV_I2C_M1BasicReadFun 0x%02x 0x%02x %d %d",DeviceID,Address,Length,Speed); if(Length>4) { *pStatus = I2C_STATUS_DATA_ERROR; DbgFunPrint("Invalid Parameter"); return -1; } DRV_I2C_ReadFun(1,DeviceID,ADDRESS_TYPE_BYTE,Address,(UINT8*)(&RegValue),(UINT32)(Length),Speed,(UINT8*)(pStatus)); return RegValue; } void DRV_I2C_M1BasicWriteFun(UINT8 DeviceID,UINT8 Address,UINT32 Data,UINT8 Length,UINT8 Speed,UINT8 *pStatus) { // DebugPrint("DRV_I2C_M1BasicWriteFun 0x%02x 0x%02x 0x%08x %d %d",DeviceID,Address,Data,Length,Speed); if(Length>4) { *pStatus = I2C_STATUS_DATA_ERROR; DbgFunPrint("Invalid Parameter"); return; } DRV_I2C_WriteFun(1,DeviceID,ADDRESS_TYPE_BYTE,(UINT32)(Address),(UINT8*)(&Data),(UINT16)(Length),Speed,(UINT8*)(pStatus)); } #endif INT32 DRV_I2C_QueueCmdFun(UINT8 Mx,UINT8 DeviceID,UINT8 AddrType,UINT32 Address,UINT8 *pData,UINT16 Length,UINT8 Speed, INT8 bRead) { PI2C_CMD_LIST pI2CCmdList; //printk(KERN_INFO "[lwhite] DRV_I2C_QueueCmdFun===>\n"); pI2CCmdList = drv_kmalloc(sizeof(I2C_CMD_LIST)+Length-1,GFP_ATOMIC, MODULEID_I2C); // Cannot sleep if(!pI2CCmdList) { DbgFunPrint("Cannot allocate I2C_CMD_LIST"); return -ENOMEM; } if (bRead) { pI2CCmdList->bRead = bRead; pI2CCmdList->Mx = Mx; pI2CCmdList->DeviceID = DeviceID; pI2CCmdList->AddrType = AddrType; pI2CCmdList->Speed = Speed; pI2CCmdList->Address = Address; pI2CCmdList->Length = Length; } else { pI2CCmdList->bRead = bRead; pI2CCmdList->Mx = Mx; pI2CCmdList->DeviceID = DeviceID; pI2CCmdList->AddrType = AddrType; pI2CCmdList->Speed = Speed; pI2CCmdList->Address = Address; pI2CCmdList->Length = Length; memcpy(pI2CCmdList->Data,pData,Length); } list_add_tail(&pI2CCmdList->list, &CmdList); //printk(KERN_INFO "[lwhite] DRV_I2C_QueueCmdFun<===\n"); return 0; } INT32 DRV_I2C_RunCmdFun(UINT8 Mx,UINT8 *pData) { struct list_head QueueList,*cursor = NULL,*next = NULL; PI2C_CMD_LIST pQueue; UINT8 Status; INT8 bLast = 0; INT8 result= 0; //printk(KERN_INFO "[lwhite] DRV_I2C_RunCmdFun===>\n"); if (Mx > 1) { DbgFunPrint("[lwhite] DRV_I2C_RunCmdFun ERROR===> Mx error!!!!"); result = 1; return result; } down(&I2cDev.I2cMutex[Mx]); INIT_LIST_HEAD(&QueueList); list_splice_init(&CmdList,&QueueList); list_for_each_safe(cursor,next,&QueueList) { if (cmd_list_is_last(cursor,&QueueList)) { //printk(KERN_INFO "[lwhite] DRV_I2C_RunCmdFun===>this is the last one!!!!\n"); bLast = 1; } list_del(cursor); pQueue = container_of(cursor,I2C_CMD_LIST,list); //Status = I2C_STATUS_SUCCESS; if (pQueue->bRead && bLast) { I2CRead(pQueue->Mx ,pQueue->DeviceID ,pQueue->AddrType ,pQueue->Address ,pQueue->Data,pQueue->Length ,pQueue->Speed,&Status); if (Status) { result = 1; DbgFunPrint("[lwhite] DRV_I2C_RunCmdFun ERROR===> Read Status error!!!!"); } //printk(KERN_EMERG "[lwhite] DRV_I2C_RunCmdFun===> pQueue->Data[0]=0x%02x\n",pQueue->Data[0]); memcpy(pData,&pQueue->Data,pQueue->Length); //printk(KERN_EMERG "[lwhite] DRV_I2C_RunCmdFun===> pData[0]=0x%02x\n",pData[0]); } else if (pQueue->bRead && bLast==0) { DbgFunPrint("[lwhite] DRV_I2C_RunCmdFun ERROR===> the Read Command is not the last one!!!!"); result = 1; } else { I2CWrite(pQueue->Mx ,pQueue->DeviceID ,pQueue->AddrType ,pQueue->Address ,pQueue->Data,pQueue->Length ,pQueue->Speed,&Status); if (Status) { result = 1; DbgFunPrint("[lwhite] DRV_I2C_RunCmdFun ERROR===> Write Status error!!!!"); } } drv_kfree(pQueue, MODULEID_I2C); } //printk(KERN_INFO "[lwhite] DRV_I2C_RunCmdFun<===\n"); up(&I2cDev.I2cMutex[Mx]); return result; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8) static long I2cIoctlFun(struct file *file, unsigned int cmd, unsigned long arg) #else static int I2cIoctlFun(struct inode *inode, struct file *pFile,unsigned int cmd, unsigned long arg) #endif { // PI2C_DEV pDev; INT32 retval; UINT8 Status; // DebugPrint("I2cIoctlFun"); if (_IOC_TYPE(cmd) != I2C_IOC_MAGIC) { DbgFunPrint("Invalid command"); return -ENOTTY; } // pDev = (PI2C_DEV)pFile->private_data; retval = 0; Status = 0; switch(cmd) { //#ifndef RELEASE_VER case IOC_I2C_MASTER0_WRITE_BYTE_100K: { UINT8 Data[3]; // DebugPrint("IOC_I2C_MASTER0_WRITE_BYTE_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M0_WRITE_BYTE_100K(Data[0],Data[1],Data[2],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_READ_BYTE_100K: { UINT8 Data[2]; // DebugPrint("IOC_I2C_MASTER0_READ_BYTE_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } Data[0] = DRV_I2C_M0_READ_BYTE_100K(Data[0],Data[1],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data[0],(UINT8 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_WRITE_BYTE_400K: { UINT8 Data[3]; // DebugPrint("IOC_I2C_MASTER0_WRITE_BYTE_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M0_WRITE_BYTE_400K(Data[0],Data[1],Data[2],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_READ_BYTE_400K: { UINT8 Data[2]; // DebugPrint("IOC_I2C_MASTER0_READ_BYTE_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } Data[0] = DRV_I2C_M0_READ_BYTE_400K(Data[0],Data[1],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data[0],(UINT8 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_WRITE_BYTE_100K: { UINT8 Data[3]; // DebugPrint("IOC_I2C_MASTER1_WRITE_BYTE_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M1_WRITE_BYTE_100K(Data[0],Data[1],Data[2],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_READ_BYTE_100K: { UINT8 Data[2]; // DebugPrint("IOC_I2C_MASTER1_READ_BYTE_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } Data[0] = DRV_I2C_M1_READ_BYTE_100K(Data[0],Data[1],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data[0],(UINT8 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_WRITE_WORD_100K: { UINT8 Data[4]; // DebugPrint("IOC_I2C_MASTER0_WRITE_WORD_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M0_WRITE_WORD_100K(Data[0],Data[1],*((UINT16 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_READ_WORD_100K: { UINT16 Data; // DebugPrint("IOC_I2C_MASTER0_READ_WORD_100K"); if( get_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M0_READ_WORD_100K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_WRITE_DWORD_100K: { UINT8 Data[6]; // DebugPrint("IOC_I2C_MASTER0_WRITE_DWORD_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M0_WRITE_DWORD_100K(Data[0],Data[1],*((UINT32 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_READ_DWORD_100K: { UINT32 Data; // DebugPrint("IOC_I2C_MASTER0_READ_DWORD_100K"); if( get_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M0_READ_DWORD_100K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_WRITE_WORD_400K: { UINT8 Data[4]; // DebugPrint("IOC_I2C_MASTER0_WRITE_WORD_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M0_WRITE_WORD_400K(Data[0],Data[1],*((UINT16 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_READ_WORD_400K: { UINT16 Data; // DebugPrint("IOC_I2C_MASTER0_READ_WORD_400K"); if( get_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M0_READ_WORD_400K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_WRITE_DWORD_400K: { UINT8 Data[6]; // DebugPrint("IOC_I2C_MASTER0_WRITE_DWORD_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M0_WRITE_DWORD_400K(Data[0],Data[1],*((UINT32 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER0_READ_DWORD_400K: { UINT32 Data; // DebugPrint("IOC_I2C_MASTER0_READ_DWORD_400K"); if( get_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M0_READ_DWORD_400K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_WRITE_WORD_100K: { UINT8 Data[4]; // DebugPrint("IOC_I2C_MASTER1_WRITE_WORD_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M1_WRITE_WORD_100K(Data[0],Data[1],*((UINT16 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_READ_WORD_100K: { UINT16 Data; // DebugPrint("IOC_I2C_MASTER1_READ_WORD_100K"); if( get_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M1_READ_WORD_100K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_WRITE_DWORD_100K: { UINT8 Data[6]; // DebugPrint("IOC_I2C_MASTER1_WRITE_DWORD_100K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M1_WRITE_DWORD_100K(Data[0],Data[1],*((UINT32 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_READ_DWORD_100K: { UINT32 Data; // DebugPrint("IOC_I2C_MASTER1_READ_DWORD_100K"); if( get_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M1_READ_DWORD_100K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_WRITE_BYTE_400K: { UINT8 Data[3]; // DebugPrint("IOC_I2C_MASTER1_WRITE_BYTE_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M1_WRITE_BYTE_400K(Data[0],Data[1],Data[2],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_READ_BYTE_400K: { UINT8 Data[2]; // DebugPrint("IOC_I2C_MASTER1_READ_BYTE_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } Data[0] = DRV_I2C_M1_READ_BYTE_400K(Data[0],Data[1],&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data[0],(UINT8 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_WRITE_WORD_400K: { UINT8 Data[4]; // DebugPrint("IOC_I2C_MASTER1_WRITE_WORD_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M1_WRITE_WORD_400K(Data[0],Data[1],*((UINT16 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_READ_WORD_400K: { UINT16 Data; // DebugPrint("IOC_I2C_MASTER1_READ_WORD_400K"); if( get_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M1_READ_WORD_400K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT16 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_WRITE_DWORD_400K: { UINT8 Data[6]; // DebugPrint("IOC_I2C_MASTER1_WRITE_DWORD_400K"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } DRV_I2C_M1_WRITE_DWORD_400K(Data[0],Data[1],*((UINT32 *)(&Data[2])),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_I2C_MASTER1_READ_DWORD_400K: { UINT32 Data; // DebugPrint("IOC_I2C_MASTER1_READ_DWORD_400K"); if( get_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("get_user fail"); retval = -EFAULT; break; } Data = DRV_I2C_M1_READ_DWORD_400K((UINT8)Data,(UINT8)(Data>>8),&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } if( put_user(Data,(UINT32 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } #if SOFTWARE_MODE_MASTER #if 0 case IOC_SW_I2C_MASTER0_WRITE_BYTE: { UINT8 Data[3]; // DebugPrint("IOC_SW_I2C_MASTER0_WRITE_BYTE"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } SwI2CWriteBasicFun(0,Data[0],Data[1],Data[2],1,I2C_SPEED_100K,&Status); break; } case IOC_SW_I2C_MASTER0_READ_BYTE: { UINT8 Data[2]; // DebugPrint("IOC_SW_I2C_MASTER0_READ_BYTE"); if(copy_from_user(Data, (void __user *)arg, sizeof(Data))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } Data[0] = SwI2CReadBasicFun(0,Data[0],Data[1],1,I2C_SPEED_100K,&Status); if( put_user(Data[0],(UINT8 __user *)arg) ) { DbgFunPrint("put_user fail"); retval = -EFAULT; break; } break; } case IOC_SW_I2C_MASTER_READ_TEMP: // 20081112 lwhite test { I2C_TEMP_INFO I2cTempInfo; UINT8 *pData; if(copy_from_user(&I2cTempInfo, (void __user *)arg, sizeof(I2C_TEMP_INFO))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } pData = drv_kmalloc(I2cTempInfo.DataLength, GFP_KERNEL, MODULEID_I2C); if(!pData) { DbgFunPrint("No resource"); retval = -ENOMEM; break; } // memset(pData,0,I2cInfo.DataLength); I2CReadTempFun(I2cTempInfo.MasterIndex ,I2cTempInfo.SlaveAddress // DeviceID ,I2cTempInfo.BaseAddrType ,I2cTempInfo.BaseAddress // Offset ,I2cTempInfo.AddrLength ,pData, I2cTempInfo.DataLength ,I2cTempInfo.Speed ,&Status); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } if(copy_to_user((void __user *)I2cTempInfo.Data,pData,I2cTempInfo.DataLength)) { DbgFunPrint("__copy_to_user fail"); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } drv_kfree(pData, MODULEID_I2C); break; } #endif case IOC_SW_I2C_MASTER_READ: { I2C_INFO I2cInfo; UINT8 *pData; if(copy_from_user(&I2cInfo, (void __user *)arg, sizeof(I2C_INFO))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } pData = drv_kmalloc(I2cInfo.DataLength, GFP_KERNEL, MODULEID_I2C); if(!pData) { DbgFunPrint("No resource"); retval = -ENOMEM; break; } // memset(pData,0,I2cInfo.DataLength); DRV_SwI2C_ReadFun(I2cInfo.MasterIndex ,I2cInfo.SlaveAddress // DeviceID ,I2cInfo.BaseAddrType ,I2cInfo.BaseAddress // Offset ,pData, I2cInfo.DataLength ,I2cInfo.Speed ,&Status); // copy_to_user((void __user *)&I2cInfo.Status,Status,sizeof(Status)); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } if(copy_to_user((void __user *)I2cInfo.Data,pData,I2cInfo.DataLength)) { DbgFunPrint("__copy_to_user fail"); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } drv_kfree(pData, MODULEID_I2C); break; } #endif // SOFTWARE_MODE_MASTER #ifdef GPIO_I2C case IOC_GPIOI2C_MASTER_WRITE: { I2C_INFO I2cInfo; UINT8 *pData; if(copy_from_user(&I2cInfo, (void __user *)arg, sizeof(I2C_INFO))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } pData = drv_kmalloc(I2cInfo.DataLength, GFP_KERNEL, MODULEID_I2C); if(!pData) { DbgFunPrint("No resource"); retval = -ENOMEM; break; } if(copy_from_user(pData, (void __user *)I2cInfo.Data, I2cInfo.DataLength)) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } DRV_GPIOI2C_WriteFun(I2cInfo.MasterIndex ,I2cInfo.SlaveAddress // DeviceID ,I2cInfo.BaseAddrType ,I2cInfo.BaseAddress // Offset ,pData, I2cInfo.DataLength ,I2cInfo.Speed ,&Status); // copy_to_user((void __user *)&I2cInfo.Status,Status,sizeof(Status)); drv_kfree(pData, MODULEID_I2C); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } case IOC_GPIOI2C_MASTER_READ: { I2C_INFO I2cInfo; UINT8 *pData; if(copy_from_user(&I2cInfo, (void __user *)arg, sizeof(I2C_INFO))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } pData = drv_kmalloc(I2cInfo.DataLength, GFP_KERNEL, MODULEID_I2C); if(!pData) { DbgFunPrint("No resource"); retval = -ENOMEM; break; } // memset(pData,0,I2cInfo.DataLength); DRV_GPIOI2C_ReadFun(I2cInfo.MasterIndex ,I2cInfo.SlaveAddress // DeviceID ,I2cInfo.BaseAddrType ,I2cInfo.BaseAddress // Offset ,pData, I2cInfo.DataLength ,I2cInfo.Speed ,&Status); // copy_to_user((void __user *)&I2cInfo.Status,Status,sizeof(Status)); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } if(copy_to_user((void __user *)I2cInfo.Data,pData,I2cInfo.DataLength)) { DbgFunPrint("__copy_to_user fail"); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } drv_kfree(pData, MODULEID_I2C); break; } case IOC_I2C_MASTER_WRITE: { I2C_INFO I2cInfo; UINT8 *pData; if(copy_from_user(&I2cInfo, (void __user *)arg, sizeof(I2C_INFO))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } pData = drv_kmalloc(I2cInfo.DataLength, GFP_KERNEL, MODULEID_I2C); if(!pData) { DbgFunPrint("No resource"); retval = -ENOMEM; break; } if(copy_from_user(pData, (void __user *)I2cInfo.Data, I2cInfo.DataLength)) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } DRV_I2C_WriteFun(I2cInfo.MasterIndex ,I2cInfo.SlaveAddress // DeviceID ,I2cInfo.BaseAddrType ,I2cInfo.BaseAddress // Offset ,pData, I2cInfo.DataLength ,I2cInfo.Speed ,&Status); // copy_to_user((void __user *)&I2cInfo.Status,Status,sizeof(Status)); drv_kfree(pData, MODULEID_I2C); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; break; } break; } #endif case IOC_I2C_MASTER_READ: { I2C_INFO I2cInfo; UINT8 *pData; if(copy_from_user(&I2cInfo, (void __user *)arg, sizeof(I2C_INFO))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } pData = drv_kmalloc(I2cInfo.DataLength, GFP_KERNEL, MODULEID_I2C); if(!pData) { DbgFunPrint("No resource"); retval = -ENOMEM; break; } // memset(pData,0,I2cInfo.DataLength); DRV_I2C_ReadFun(I2cInfo.MasterIndex ,I2cInfo.SlaveAddress // DeviceID ,I2cInfo.BaseAddrType ,I2cInfo.BaseAddress // Offset ,pData, I2cInfo.DataLength ,I2cInfo.Speed ,&Status); // copy_to_user((void __user *)&I2cInfo.Status,Status,sizeof(Status)); if(Status) { DbgFunPrint("Status Error:%d",Status); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } if(copy_to_user((void __user *)I2cInfo.Data,pData,I2cInfo.DataLength)) { DbgFunPrint("__copy_to_user fail"); retval = -EFAULT; drv_kfree(pData, MODULEID_I2C); break; } drv_kfree(pData, MODULEID_I2C); break; } case IOC_I2C_DUMP_MEM: { I2C_DUMP I2cDump; UINT32 *Addr, Length,i; if(copy_from_user(&I2cDump, (void __user *)arg, sizeof(I2C_DUMP))) { DbgFunPrint("copy_from_user fail"); retval = -EFAULT; break; } Addr = (UINT32 *)((UINT32)I2cDump.Addr & ~0x3); //4 bytes alignment Length = I2cDump.Length & ~0x3; //4 bytes alignment // DebugPrint("dump:Addr=0x%08x Length=%u",(UINT32)Addr,Length); if(Length==0) break; printk("????????????????????\n"); for(i=0;iprivate_data = (void*) &I2cDev; return 0; } static int I2cCloseFun(struct inode *inode, struct file *pFile) { // DebugPrint("I2cCloseFun"); return 0; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,8) static struct file_operations I2cFops = { .owner = THIS_MODULE, // .read = NsmReadFun, // .write = NsmWriteFun, .unlocked_ioctl = I2cIoctlFun, .open = I2cOpenFun, .release = I2cCloseFun, }; #else static struct file_operations I2cFops = { .owner = THIS_MODULE, // .read = NsmReadFun, // .write = NsmWriteFun, .ioctl = I2cIoctlFun, .open = I2cOpenFun, .release = I2cCloseFun, }; #endif #if 1 //330 did ot supprt suspend/resume #else INT32 I2CSuspend(pm_message_t state) { printk(KERN_EMERG "[I2C]I2CSuspend!!\n"); UINT32 RegValue; bSuspend = 1; RegValue &= ~MX_CONTROL0_INT_EN; MmioWriteFun(M0_CONTROL0,RegValue); MmioWriteFun(M1_CONTROL0,RegValue); complete(&I2cDev.Comp[0]); complete(&I2cDev.Comp[1]); //cdev_del(&I2cDev.cdev); //destroy_workqueue(I2cDev.i2cWorkQueue); cancel_work_sync(&I2cDev.QueueWork); //flush_delayed_work(I2cDev.i2cWorkQueue); MmioWriteFun(M0_CONTROL0,0x00000000); MmioWriteFun(M1_CONTROL0,0x00000000); MmioWriteFun(SW_MASTER0,0x000C000C); // disable software mode #if (I2C_MODE==I2C_HARDWARE_MODE_MASTER) && INTERRUPT_ENABLE //del_timer_sync(&I2cDev.ResetTimer[0]); //free_irq(MASTER_IRQ_FINAL,NULL); #endif return 1; } INT32 I2CResume(void) { printk(KERN_EMERG "[I2C]I2CResume!!\n"); INT32 i,result=0; INT32 ret; dev_t devno; // UINT8 bData; #if (I2C_MODE==I2C_HARDWARE_MODE_MASTER) DebugPrint("I2cInit hardware mode"); #elif (I2C_MODE==I2C_SOFTWARE_MODE_MASTER) DebugPrint("I2cInit software master mode"); #endif memset(&I2cDev,0,sizeof(I2C_DEV)); for(i=0;iQueueWork); flush_workqueue(pI2cDev->i2cWorkQueue); destroy_workqueue(pI2cDev->i2cWorkQueue); */ // struct work_struct *testWork; // cancel_delayed_work(&testWork); // INIT_DELAYED_WORK(&delaywork,RunQueueFun); // cancel_delayed_work(&delaywork); // flush_workqueue(I2cDev.i2cWorkQueue); destroy_workqueue(I2cDev.i2cWorkQueue); MmioWriteFun(M0_CONTROL0,0x00000000); MmioWriteFun(M1_CONTROL0,0x00000000); MmioWriteFun(SW_MASTER0,0x000C000C); // disable software mode #if (I2C_MODE==I2C_HARDWARE_MODE_MASTER) && INTERRUPT_ENABLE /*INT32 i; for(i=0;i