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

📄 i2c-algo-ip3203.c

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