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

📄 i2c-algo-ip0105.c

📁 PNX8550 I2C总线驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
                {                        busptr->isr_event |= evSlaveReadRequest;                        slave_device = i2c_adap;                        tasklet_schedule(&IP0105_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(&IP0105_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 IP0105_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;        // Get State of Iic Bus        i2c_state = read_IP0105_I2C_STATUS(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_IP0105INT()                do{ int t = TIMEOUT;                                       \                                            while(!(read_IP0105_I2C_INT_STATUS(busptr) & IP0105_INTBIT)     \                                                   && (t-->0)){}                               \                                          }while(0)                                     #define WAIT_IP0105_STO_OR_INT()        do{ int t = TIMEOUT;                                       \                                            while(!(read_IP0105_I2C_INT_STATUS(busptr) & IP0105_INTBIT)     \                                                 &&(read_IP0105_I2C_CONTROL(busptr) & IP0105_STO)      \                                                 &&(t-->0)){}                                  \                                          }while(0)/*******************************************************************************   This function resets IP0105. The parameter "i2c_adap" indicates base address *   of the IP0105 Block.*******************************************************************************/static void IP0105_reset(struct i2c_adapter *i2c_adap){    struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data;    dev_dbg(&i2c_adap->dev, "Reset the IP0105\n");    DISABLE_I2C_INTERRUPT(busptr);    AAOUT(busptr, 0);    STAOUT(busptr, 0);    if(1 /*read_IP0105_INTROG(busptr) & IP0105_INTRO_BB*/)    {   /* Bus is busy */        dev_dbg(&i2c_adap->dev, "I2C bus is busy\n");        WAIT_IP0105INT();dev_dbg(&i2c_adap->dev, "int_status = 0x%x\n", read_IP0105_I2C_INT_STATUS(busptr));        if(read_IP0105_I2C_INT_STATUS(busptr) & IP0105_INTBIT)        {/* Interrupt flag is set */            unsigned int i2c_state = read_IP0105_I2C_STATUS(busptr);            if((i2c_state == 0x08) || (i2c_state == 0x10))            {                write_IP0105_I2C_DAT(busptr, 0xEE);    /*  Transmit dummy address */                CLEAR_I2C_INTERRUPT(busptr);           /* Clear I2C interrupt    */            }            else if((i2c_state == 0x40) || (i2c_state == 0x50))            {   /* One byte must be read which should be NACKed */                AAOUT(busptr, 0);                      /*  NACK next byte      */                CLEAR_I2C_INTERRUPT(busptr);           /*  Clear I2C interrupt    */            }            else            {                /* For rest of the states just generating stop condition is enough */            }            WAIT_IP0105INT();            STOOUT(busptr, 1);                         /*  Generate stop condition */            CLEAR_I2C_INTERRUPT(busptr);               /*  Clear I2C interrupt: Not necessary but no harm */            WAIT_IP0105_STO_OR_INT();        }        else        {/* Interrupt flag did not set, May be due to clock stretching */            STOOUT(busptr, 1);                         /*  Generate stop condition */            CLEAR_I2C_INTERRUPT(busptr);               /*  Clear I2C interrupt: Not necessary but no harm */            WAIT_IP0105_STO_OR_INT();        }    }    else    { /* Bus is free, do nothing */        dev_dbg(&i2c_adap->dev, "I2C bus is free\n");//        STOOUT(busptr, 1);                           /*  Generate stop condition *///        CLEAR_I2C_INTERRUPT(busptr);                 /* Clear I2C interrupt: Not necessary but no harm *///        WAIT_IP0105_STO_OR_INT();    }    if(read_IP0105_I2C_CONTROL(busptr) & IP0105_STO)    {        ASSERT(FALSE); /* Could not free I2C bus */    }    /* Set default values */    DISABLE_I2C_CONTROLLER(busptr);      /*  Disable I2C controller */    DISABLE_I2C_INTERRUPT(busptr);       /*  Disable I2C interrupts */    AAOUT(busptr, 0);                    /*  Disable slave mode     */    STAOUT(busptr, 0);                   /*  Remove start request   */    CLEAR_I2C_INTERRUPT(busptr);         /*  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 IP0105_init(struct i2c_adapter * i2c_adap, int device){        struct I2cBusObject *busptr;        dev_dbg(&i2c_adap->dev, "Init i2c bus %x\n", device);        busptr                    = &IP0105_i2cbus[device];        busptr->offset            = IP0105_Controller[device];        busptr->int_pin           = IP0105_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 */        init_waitqueue_head(&(busptr->iic_wait_master));        DISABLE_I2C_CONTROLLER( busptr ); /* Disable I2C controller */        SETSPEED100(busptr);        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. */        // Todo : find out which pin I2c interrupt line        if (0 != request_irq(busptr->int_pin, IP0105_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;        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 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -