📄 i2c-algo-ip3203.c
字号:
/* fall through; */ case 0x90: /* Previously addressed with General call; DATA byte has been received; ACK has been returned */ /* fall through; */ case 0x98: /* Previously addressed with General call; DATA byte has been received; NOT ACK has been returned */ /* fall through; */ default: recover_from_hardware_error( i2c_adap ); break; }}static __inline void iic_interrupt_slave_transmitter(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){ switch (i2c_state) { case 0xA0: /* A STOP condition or repeated START has been received while still address as SLV/TRX */ // Slave will be enabled again when data is out of the buffer AAOUT( busptr, 0 ); /* NOT ACK bit will be returned after slave address reception */ busptr->isr_event |= evSlaveStopCondition; slave_device = i2c_adap; tasklet_schedule(&IP3203_slave_tasklet); CLEAR_I2C_INTERRUPT( busptr ); /* Reset i2c interrupt */ break; case 0xB8: /* Data byte in I2DAT has been transmitted; ACK has been received */ if ( busptr->slv_bufindex < busptr->slv_bufsize ) { write_IP3203_I2CDAT(busptr, *( busptr->slv_buf + busptr->slv_bufindex )); busptr->slv_bufindex++; if ( busptr->slv_bufindex < busptr->slv_buflen ) { AAOUT( busptr, 1 ); /* Data byte will be transmitted */ } else { AAOUT( busptr, 0 ); /* Last data byte will be transmitted */ }#ifdef USE_DMA { int dmalen; if( ( busptr->slv_buflen - 1 - busptr->slv_bufindex ) > div_DmaBufSize ) { dmalen = div_DmaBufSize; } else { dmalen = busptr->slv_buflen - 1 - busptr->slv_bufindex; } if( dmalen > 0 ) { dma_start( busptr->slv_buf + busptr->slv_bufindex, i2c_adap, dmalen, SlaveTransmitter ); busptr->slv_bufindex += dmalen; } }#endif CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */ } else { busptr->isr_event |= evSlaveReadRequest; slave_device = i2c_adap; tasklet_schedule(&IP3203_slave_tasklet); /* Don't reset i2c interrupt */ } break; case 0xC0: /* Data byte in I2DAT has been transmitted; NOT ACK has been received */ /* fall through; */ case 0xC8: /* Last data byte in I2DAT has been transmitted (AA=0); ACK has been received */ AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned, or not, after slave address reception */ busptr->isr_event |= evSlaveTransmitterReady; slave_device = i2c_adap; tasklet_schedule(&IP3203_slave_tasklet); /* Don't reset i2c interrupt */ break; case 0x70: /* General call address (0x00) has been received; ACK has been returned */ /* fall through; */ case 0x78: /* Arbitration lost in SLA+R/~W as master; General call address (0x00) has been received; ACK has been returned */ /* fall through; */ default: /* Miscellaneous: No relevant state information available; SI=0 */ recover_from_hardware_error( i2c_adap ); break; }}static irqreturn_t IP3203_iic_interrupt(int irq, void *dev_id, struct pt_regs *regs){ // get the BusObject struct i2c_adapter * i2c_adap = (struct i2c_adapter *)dev_id; struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data; int i2c_state;#ifdef USE_DMA if( Idle != read_IP3203_DMA_CONTROL( busptr ) ) /* DMA was active */ { dma_end( i2c_adap ); }#endif // Get State of Iic Bus i2c_state = read_IP3203_I2CSTAT(busptr); switch (busptr->mode) { case Idle: iic_interrupt_idle(i2c_adap, busptr, i2c_state); break; case MasterTransmitter: iic_interrupt_master_transmitter(i2c_adap, busptr, i2c_state); break; case MasterReceiver: iic_interrupt_master_receiver(i2c_adap, busptr, i2c_state); break; case SlaveReceiver: iic_interrupt_slave_receiver(i2c_adap, busptr, i2c_state); break; case SlaveTransmitter: iic_interrupt_slave_transmitter(i2c_adap, busptr, i2c_state); break; } return IRQ_HANDLED;}static void do_slave_tasklet(unsigned long unused){ struct I2cBusObject * busptr = (struct I2cBusObject *)slave_device->algo_data; if (busptr->mode == SlaveReceiver) { if (busptr->isr_event & evSlaveRxIntermediateNtf) { dev_dbg(&slave_device->dev, "Slave Receiver : Intermediate Ntf\n"); busptr->isr_event &= ~evSlaveRxIntermediateNtf; } if (busptr->isr_event & evSlaveReceiverReady) { busptr->slv_bufindex = 1; busptr->isr_event &= ~evSlaveReceiverReady; } if (busptr->isr_event & evSlaveReadRequest) { dev_dbg(&slave_device->dev, "Slave Receiver : ReadRequest\n"); busptr->isr_event &= ~evSlaveReadRequest; } if (busptr->isr_event & evSlaveTransmitterReady) { dev_dbg(&slave_device->dev, "Slave Receiver : TransmitterReady\n"); busptr->isr_event &= ~evSlaveTransmitterReady; } if (busptr->isr_event & evSlaveStopCondition) { dev_dbg(&slave_device->dev, "Slave Receiver : SlaveStopCondition\n"); if (busptr->slv_usr_notify) {dev_dbg(&slave_device->dev, "Slave Receiver : Sending kill\n"); kill_fasync(busptr->slv_usr_notify, SIGIO, POLL_IN); } else if (busptr->slv_enabled) {dev_dbg(&slave_device->dev, "Slave Receiver : AAOUT\n"); AAOUT(busptr, 1); }dev_dbg(&slave_device->dev, "Slave Receiver : Idle\n"); busptr->mode = Idle; busptr->isr_event &= ~evSlaveStopCondition; } } else if (busptr->mode == SlaveTransmitter) { if (busptr->isr_event & evSlaveRxIntermediateNtf) dev_dbg(&slave_device->dev, "Slave Transmitter : Intermediate Ntf\n"); if (busptr->isr_event & evSlaveReceiverReady) dev_dbg(&slave_device->dev, "Slave Transmitter : Ready\n"); if (busptr->isr_event & evSlaveReadRequest) dev_dbg(&slave_device->dev, "Slave Transmitter : ReadRequest\n"); if (busptr->isr_event & evSlaveTransmitterReady) dev_dbg(&slave_device->dev, "Slave Transmitter : TransmitterReady\n"); if (busptr->isr_event & evSlaveStopCondition) dev_dbg(&slave_device->dev, "Slave Transmitter : SlaveStopCondition\n"); }}#define WAIT_IP3203INT() do{ int t = TIMEOUT; \ while(!(read_IP3203_INT_STATUS(busptr) & IP3203_INTBIT) \ && (t-->0)){} \ }while(0)#define WAIT_IP3203_STO_OR_INT() do{ int t = TIMEOUT; \ while(!(read_IP3203_INT_STATUS(busptr) & IP3203_INTBIT) \ &&(read_IP3203_INTROG(busptr) & IP3203_INTRO_STO) \ &&(t-->0)){} \ }while(0)/******************************************************************************* This function resets IP3203. The parameter "a" indicates base address* of the IP3203 Block.*******************************************************************************/static void IP3203_reset(struct i2c_adapter *i2c_adap){ struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data; dev_dbg(&i2c_adap->dev, "Reset the IP3203\n");#ifdef USE_DMA dev_dbg(&i2c_adap->dev, "Stop DMA\n"); write_IP3203_DMA_CONTROL(busptr, 0); /* *IP3203_DMA_CONTROL(a) = 0; Disable DMA */ write_IP3203_DMA_LENGTH(busptr, 0);#endif DISABLE_I2C_INTERRUPT(busptr); /* *IP3203_INT_ENABLE(a) = 0; Disable I2C interrupts */ AAOUT(busptr, 0); /* *IP3203_I2CCON(a) &= ~IP3203_AA; Disable slave mode */ STAOUT(busptr, 0); /* *IP3203_I2CCON(a) &= ~IP3203_STA; Remove start request */ if(read_IP3203_INTROG(busptr) & IP3203_INTRO_BB) { /* Bus is busy */ dev_dbg(&i2c_adap->dev, "I2C bus is busy\n"); WAIT_IP3203INT();dev_dbg(&i2c_adap->dev, "int_status = 0x%x\n", read_IP3203_INT_STATUS(busptr)); if(read_IP3203_INT_STATUS(busptr) & IP3203_INTBIT) {/* Interrupt flag is set */ unsigned int i2c_state = read_IP3203_I2CSTAT(busptr); if((i2c_state == 0x08) || (i2c_state == 0x10)) { write_IP3203_I2CDAT(busptr, 0xEE); /* *IP3203_I2CDAT(a) = 0xEE; Transmit dummy address */ CLEAR_I2C_INTERRUPT(busptr); /* *IP3203_INT_CLEAR(a) = IP3203_INTBIT; Clear I2C interrupt */ } else if((i2c_state == 0x40) || (i2c_state == 0x50)) { /* One byte must be read which should be NACKed */ AAOUT(busptr, 0); /* *IP3203_I2CCON(a) &= ~IP3203_AA; NACK next byte */ CLEAR_I2C_INTERRUPT(busptr); /* *IP3203_INT_CLEAR(a) = IP3203_INTBIT; Clear I2C interrupt */ } else { /* For rest of the states just generating stop condition is enough */ } WAIT_IP3203INT(); STOOUT(busptr, 1); /* *IP3203_I2CCON(a) |= IP3203_SETSTO; Generate stop condition */ CLEAR_I2C_INTERRUPT(busptr); /* *IP3203_INT_CLEAR(a) = IP3203_INTBIT; Clear I2C interrupt: Not necessary but no harm */ WAIT_IP3203_STO_OR_INT(); } else {/* Interrupt flag did not set, May be due to clock stretching */ STOOUT(busptr, 1); /* *IP3203_I2CCON(a) |= IP3203_SETSTO; Generate stop condition */ CLEAR_I2C_INTERRUPT(busptr); /* *IP3203_INT_CLEAR(a) = IP3203_INTBIT; Clear I2C interrupt: Not necessary but no harm */ WAIT_IP3203_STO_OR_INT(); } } else { /* Bus is free, do nothing */ dev_dbg(&i2c_adap->dev, "I2C bus is free\n");// STOOUT(busptr, 1); /* *IP3203_I2CCON(a) |= IP3203_SETSTO; Generate stop condition */// CLEAR_I2C_INTERRUPT(busptr); /* *IP3203_INT_CLEAR(a) = IP3203_INTBIT; Clear I2C interrupt: Not necessary but no harm */// WAIT_IP3203_STO_OR_INT(); } if(read_IP3203_INTROG(busptr) & IP3203_INTRO_STO) { ASSERT(FALSE); /* Could not free I2C bus */ } /* Set default values */ DISABLE_I2C_CONTROLLER(busptr); /* *IP3203_I2CCON(a) &= ~IP3203_EN; Disable I2C controller */#ifdef USE_DMA write_IP3203_DMA_CONTROL(busptr, 0); /* *IP3203_DMA_CONTROL(a) = 0; Disable DMA */#endif DISABLE_I2C_INTERRUPT(busptr); /* *IP3203_INT_ENABLE(a) = 0; Disable I2C interrupts */ AAOUT(busptr, 0); /* *IP3203_I2CCON(a) &= ~IP3203_AA; Disable slave mode */ STAOUT(busptr, 0); /* *IP3203_I2CCON(a) &= ~IP3203_STA; Remove start request */ CLEAR_I2C_INTERRUPT(busptr); /* *IP3203_INT_CLEAR(a) = IP3203_INTBIT; Clear I2C interrupt */ dev_dbg(&i2c_adap->dev, "Reset done, re-init\n");// enable_irq(busptr->int_pin); /* re-init again */ ENABLE_I2C_CONTROLLER(busptr); ENABLE_I2C_INTERRUPT(busptr); if (busptr->slv_enabled == TRUE) { AAOUT(busptr, 1); } dev_dbg(&i2c_adap->dev, "re-init done\n");}/* * */static void calc_speed_values (unsigned int fsSpeed, unsigned int hsSpeed, unsigned int * pfsbir, unsigned int * phsbir){ unsigned int fsBitRate, hsBitRate; unsigned int clockFreqKHz = MODULE_CLOCK; union _i2cFSBIR IP3203_i2cFSBIR; union _i2cHSBIR IP3203_i2cHSBIR; /* calculate register values */ fsBitRate = clockFreqKHz/(8*fsSpeed) - 1; if (clockFreqKHz%(8*fsSpeed) != 0) { fsBitRate++; } hsBitRate = clockFreqKHz/(3*hsSpeed) - 1; if (clockFreqKHz%(3*hsSpeed) != 0) { hsBitRate++; } /* limit upper boundary of register value = lower limit of speed */ if (fsBitRate > 127) { fsBitRate = 127; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -