📄 i2c-algo-ip3203.c
字号:
if (hsBitRate > 31) { hsBitRate = 31; } IP3203_i2cFSBIR.u32 = 0; IP3203_i2cHSBIR.u32 = 0; IP3203_i2cFSBIR.bits.fsBitRate = fsBitRate; IP3203_i2cHSBIR.bits.hsBitRate = hsBitRate; if (fsSpeed > TMHW_I2C_MAX_SS_SPEED) {/* SFMode = FS mode */ IP3203_i2cFSBIR.bits.SFMode = I2C_FS_MODE; } else {/* SFMode = SS mode */ IP3203_i2cFSBIR.bits.SFMode = I2C_SS_MODE; } *pfsbir = IP3203_i2cFSBIR.u32; *phsbir = IP3203_i2cHSBIR.u32; /* IP3203 version 2.c and 2.d patch */ switch (*pfsbir) { case (0x00): *pfsbir++; break; case (0x02): *pfsbir = 0x04; break; case (0x03): *pfsbir++; break; case (0x08): *pfsbir =0xa; break; case (0x09): *pfsbir++; break; case (0x0b): *pfsbir++; break; case (0x0e): *pfsbir++; break; case (0x28): *pfsbir++; break; case (0x4f): *pfsbir++; break; case (0x80): *pfsbir++; break; case (0x83): *pfsbir = 0x85; break; case (0x84): *pfsbir++; break; case (0x87): *pfsbir = 0x8a; break; case (0x88): *pfsbir = 0x8a; break; case (0x89): *pfsbir++; break; default: if (*pfsbir >= 0xaa) { *pfsbir = 0xa9; } break; } switch (*phsbir) { case (0x00): *phsbir++; break; case (0x0c): *phsbir++; break; default: break; } /* end IP3203 version 2.c and 2.d patch */}/* i2cConvertSpeedToReg */static void IP3203_init(struct i2c_adapter * i2c_adap, int device){ struct I2cBusObject *busptr; unsigned int fsbir=0, hsbir=0; /* Bit rate */ dev_dbg(&i2c_adap->dev, "Init i2c bus %x\n", device); busptr = &IP3203_i2cbus[device]; busptr->offset = IP3203_controller[device]; busptr->int_pin = IP3203_intpin[device]; busptr->mode = Idle; busptr->isr_event = 0; /* Clear all event flags(bits) */// busptr->bus_blocked = FALSE; busptr->slv_enabled = FALSE; busptr->slv_buf = NULL; //SlaveBuffer[device]; busptr->slv_bufindex = 0; busptr->slv_buflen = 0; busptr->slv_bufsize = 0; //SLAVE_BUF_SIZE; busptr->slv_usr_notify = NULL;// busptr->mst_timer = TIMER_OFF;// busptr->mst_timeout = TIMER_OFF;// busptr->mst_timeout_valid = FALSE;// busptr->slv_timer = TIMER_OFF;// busptr->slv_timeout = TIMER_OFF;// busptr->slv_timeout_valid = FALSE; /* The remaining elements of the struct are initialized when i2c write,read functions are called */#ifdef USE_DMA busptr->dma_bufptr = kmalloc(div_DmaBufSize, GFP_KERNEL | GFP_DMA /* GFP_ATOMIC */ ); ASSERT( NULL != busptr->dma_bufptr ); busptr->dma_transmit = Idle;#endif init_waitqueue_head( &(busptr->iic_wait_master) ); DISABLE_I2C_CONTROLLER( busptr ); /* Disable I2C controller */ calc_speed_values ( TMHW_I2C_MAX_SS_SPEED, TMHW_I2C_MAX_SS_SPEED, &fsbir, &hsbir ); write_IP3203_FSBIR( busptr, fsbir); write_IP3203_HSBIR( busptr, hsbir); AAOUT( busptr, 0 ); /* Slave mode disabled */ STOOUT( busptr, 0 ); /* Do not generate stop condition */ STAOUT( busptr, 0 ); /* Do not generate Start condition */ /* Install interrupt handler. */ if (0 != request_irq( busptr->int_pin, IP3203_iic_interrupt, SA_INTERRUPT, "i2c", (void *)i2c_adap)) { ASSERT( 0 ); } CLEAR_I2C_INTERRUPT( busptr ); /* Clear the interrupt flags if by-chance(if not power up ) they are set */ disable_irq( busptr->int_pin ); /* disable i2c interrupt in Interrupt controller */ enable_irq( busptr->int_pin ); /* Enable i2c interrupt in Interrupt controller */ ENABLE_I2C_CONTROLLER( busptr ); /* Enable I2C Controller */ ENABLE_I2C_INTERRUPT( busptr ); /* Enable both the SI and DMA interrupts */ return;}/* Master ReadWrite interface function */static unsigned int i2c_write_read(struct i2c_adapter *i2c_adap, int address, void *msgwram, int lenw, void *msgr, int lenr ){ struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data; int retval = 0;#ifdef USE_DMA if (busptr->dma_len) { /* Check to see if the previous DMA transfer has completed */ while(read_IP3203_DMA_COUNTER(busptr)!=0) { msleep(1); } dma_end(i2c_adap); }#endif busptr->mst_status = errids_Ok; busptr->mst_address = address; busptr->mst_txbuflen = lenw; busptr->mst_txbufindex = 0; busptr->mst_rxbuf = msgr; busptr->mst_rxbufindex = 0; if( msgwram != NULL ) { busptr->mst_txbuf = msgwram; } else { busptr->mst_txbuflen = 0; /* If both ptrs are NULL, do not write data */ } if( msgr != NULL ) { busptr->mst_rxbuflen = lenr; } else { busptr->mst_rxbuflen = 0; } STAOUT( busptr, 1 ); /* Generate START condition when selected bus is free and start interrupt driven machine */ /* Suspend current task till the event flag is set */ /* Wait for IIC transfer, result of action is written in I2cBusObject */ retval = interruptible_sleep_on_timeout(&(busptr->iic_wait_master), (5*HZ)); if (retval == 0) { int i2c_state = read_IP3203_I2CSTAT(busptr); // I2CSTATIN( device ); int i2c_intstate = read_IP3203_INT_STATUS(busptr); dev_dbg(&i2c_adap->dev, "I2C Status 0%x, int stat %x\n", i2c_state, i2c_intstate); return errids_IsI2cHardwareError; } return busptr->mst_status;}#ifdef USE_DMAstatic void dma_start( unsigned char * clientbuf, struct i2c_adapter * i2c_adap, int len, I2cMode transmitmode ){ struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data; ASSERT( len <= div_DmaBufSize ); /* DMA buffer is not that big, internal error */ if( len != 0 ) { busptr->dma_transmit = transmitmode; busptr->dma_clientbuf = clientbuf; busptr->dma_len = len; if( (MasterTransmitter == transmitmode) || (SlaveTransmitter == transmitmode)) { local_memcpy( busptr->dma_bufptr, clientbuf, len ); /* copy to DMA buffer */ } write_IP3203_DMA_ADDR( busptr, virt_to_phys(busptr->dma_bufptr)); write_IP3203_DMA_LENGTH( busptr, len); write_IP3203_DMA_CONTROL( busptr, transmitmode); /* Allow DMA to handle the interrupt */ }}static void dma_end( struct i2c_adapter * i2c_adap ){ struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data; if( (busptr->dma_transmit == MasterReceiver) || (busptr->dma_transmit == SlaveReceiver) ) { local_memcpy_receive( busptr->dma_clientbuf, busptr->dma_bufptr, busptr->dma_len ); /* May be less bytes should be copied */ } if(!read_IP3203_DMA_STATUS( busptr ) ) { ASSERT( 0 ); /* I2C DMA error occured */ /* DMA_ERROR cleared automatically when the interrupt is cleared */ } else { int correction; correction = read_IP3203_DMA_COUNTER( busptr ) ; switch( busptr->mode ) { case MasterTransmitter: busptr->mst_txbufindex -= correction; /* correction == 0 under normal condition */ break; case MasterReceiver: if( correction != 0) { /* DMA unsuccessful, because of the logic implemented in ADOC DMA -- the correction */ correction--; } busptr->mst_rxbufindex -= correction; /* Correct the pointer */ ASSERT( busptr->mst_rxbufindex >= 0 ); /* How this index could become -ve must be ADOC I2C HW error */ break; case SlaveReceiver: busptr->slv_bufindex = busptr->slv_bufindex - correction; /* correct the pointer */ break; case SlaveTransmitter: busptr->slv_bufindex = busptr->slv_bufindex - correction; /* correct the pointer */ break; default: ASSERT( 0 ); /* I2C is idle, who started the DMA? */ break; } } write_IP3203_DMA_CONTROL( busptr, Idle); /* Allow CPU to handle the interrupts */}static void __inline local_memcpy( void *dest, void *src, int len ){ void * re_dest = (void *)ioremap_nocache(virt_to_phys(dest), len); memcpy(re_dest, src, len);}static void __inline local_memcpy_receive( void *dest, void *src, int len ){ memcpy(dest, src, len);}#endifstatic int IP3203_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num){ struct i2c_msg *pmsg; void * wr_buf = NULL; void * rd_buf = NULL; int i, wr_len = 0, rd_len = 0; unsigned char addr = msgs[0].addr; int ret=0; dev_dbg(&i2c_adap->dev, "IP3203 xfer nr %d\n", num); // when num = 2, assume that first some data must be written to the device // before the actual read can be done. Since we are now working in a multi- // master environment, a repeated start must be used iso stop/start! ASSERT(num > 0 && num <= 2); for (i = 0; i < num; i++) { pmsg = &msgs[i]; if (i == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -