⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c-algo-ip3203.c

📁 PNX8550 I2C总线驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
                /* 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 + -