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

📄 i2c-algo-ip3203.c

📁 PNX8550 I2C总线驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -------------------------------------------------------------------------- *//* i2c-algo-IP3203.c i2c driver algorithms for PNX8550 High Performance ports *//* -------------------------------------------------------------------------- *//* This module is the work of Willem van Beek, * evidently inspired by Simon G. Vogl. * * Restriction : * Slave Transmitter functionality not working (yet) * Slave Receiver doesn't use DMA functionality * No time-out (or watchdog) on Slave functionality * * *//*-------------------------------------------------------------------------------Standard include files:-------------------------------------------------------------------------------*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/version.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/string.h>#include <linux/fs.h>#include <linux/mm.h>/*-------------------------------------------------------------------------------Project include files:-------------------------------------------------------------------------------*/#include <linux/i2c.h>#include "i2c-algo-IP3203.h"#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/philips/pnx8550/pnx8550_int.h>#include <asm/io.h>#ifndef FALSE#define FALSE 0#define TRUE  1#endif#define errids_Ok 0#define errids_IsI2cHardwareError 0x01#define errids_IsI2cDeviceError   0x02#define errids_IsI2cWriteError    0x03#define evMasterReady               0x0001#define evSlaveRxIntermediateNtf    0x0002#define evSlaveReceiverReady        0x0004#define evSlaveReadRequest          0x0008#define evSlaveTransmitterReady     0x0010#define evSlaveStopCondition        0x0020#ifndef BOOL#define BOOL       int#endif/* --- adapters                                        */#define NR_I2C_DEVICES 2 /* Two High Performance controllers : Don't change this value */#define I2C_HIGH_PERFORMANCE_PORT_1 0x00 /* IP3203 Controller on the Viper */#define I2C_HIGH_PERFORMANCE_PORT_2 0x01 /* IP3203 Controller on the Viper */#define IP3203_UNIT0                0xBBE45000#define IP3203_UNIT1                0xBBE46000#define MODULE_CLOCK                27000 /* I2C module clock speed in KHz */#define I2CADDRESS( address )       ((address) & 0x00FE) /* only 7 bits I2C address implemented */#define TIMER_OFF                   0//#define USE_DMAtypedef enum{    Idle = 0x00,    MasterTransmitter = 0x01,    MasterReceiver = 0x02,    SlaveReceiver = 0x04,    SlaveTransmitter = 0x08,} I2cMode;struct I2cBusObject{    unsigned char  *  mst_txbuf; /* Master mode variables */    int               mst_txbuflen;    int               mst_txbufindex;    unsigned char  *  mst_rxbuf;    int               mst_rxbuflen;    int               mst_rxbufindex;    int               mst_address;    wait_queue_head_t iic_wait_master;    unsigned long     int_pin;    unsigned int           mst_status;//    int               mst_timer;//    int               mst_timeout;//    BOOL              mst_timeout_valid;    unsigned char  *  slv_buf; /* Slave mode variables */    int               slv_bufsize;    int               slv_buflen;    int               slv_bufindex;    BOOL              slv_enabled;//    int               slv_timer;//    int               slv_timeout;//    BOOL              slv_timeout_valid;    int               offset; /* I2C HW controller address offset, required by HAL */    I2cMode           mode;    int               isr_event;//    BOOL    bus_blocked;#ifdef USE_DMA    unsigned char  *  dma_bufptr;    unsigned char  *  dma_clientbuf;    int               dma_len;    I2cMode           dma_transmit;#endif    struct  fasync_struct ** slv_usr_notify;};/* Local Macros for IP3203 */static __inline void STAOUT(struct I2cBusObject * a, int p){        int val = read_IP3203_I2CCON(a);        if (p) { val |= IP3203_STA; } else { val &= ~IP3203_STA; }        write_IP3203_I2CCON(a, val);}static __inline void STOOUT(struct I2cBusObject * a, int p){        int val = read_IP3203_I2CCON(a);        if (p) { val |= IP3203_SETSTO; } else { val &= ~IP3203_SETSTO; }        write_IP3203_I2CCON(a, val);}static __inline void AAOUT(struct I2cBusObject * a, int p){        int val = read_IP3203_I2CCON(a);        if (p) { val |= IP3203_AA; } else { val &= ~IP3203_AA; }        write_IP3203_I2CCON(a, val);}static __inline void ENABLE_I2C_CONTROLLER(struct I2cBusObject * a){        int val = read_IP3203_I2CCON(a);        val |= IP3203_EN;        write_IP3203_I2CCON(a, val);}static __inline void DISABLE_I2C_CONTROLLER(struct I2cBusObject * a){        int val = read_IP3203_I2CCON(a);        val &= ~IP3203_EN;        write_IP3203_I2CCON(a, val);}static __inline void CLEAR_I2C_INTERRUPT(struct I2cBusObject * a){        write_IP3203_INT_CLEAR(a, 1);}static __inline void ENABLE_I2C_INTERRUPT(struct I2cBusObject * a){        write_IP3203_INT_ENABLE(a, IP3203_INTBIT);}static __inline void DISABLE_I2C_INTERRUPT(struct I2cBusObject * a){        write_IP3203_INT_ENABLE(a, 0);}/* ----- global defines ----------------------------------------------- */#define DEB(x) if (i2c_debug>=1) x#define DEB2(x) if (i2c_debug>=2) x#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/#define ASSERT(x) if (!(x)) dev_dbg(&i2c_adap->dev, "ASSERTION FAILED at line %d in file %s\n", __LINE__, __FILE__);/* Types and defines: */#define TIMEOUT     200 /* Should be wait period of >100us i.e 1 byte @100KHz *//* Local Types */static unsigned long IP3203_controller[NR_I2C_DEVICES] = {  IP3203_UNIT0, IP3203_UNIT1 };static unsigned long IP3203_intpin[NR_I2C_DEVICES] = { PNX8550_INT_I2C1, PNX8550_INT_I2C2 };static struct i2c_adapter * slave_device = NULL;static void do_slave_tasklet(unsigned long);DECLARE_TASKLET(IP3203_slave_tasklet, do_slave_tasklet, 0);#ifdef USE_DMAstatic void dma_start( unsigned char *clientbuf, struct i2c_adapter * i2c_adap, int len, I2cMode transmitmode );static void dma_end( struct i2c_adapter * i2c_adap );static void __inline local_memcpy( void *dest, void *src, int len );static void __inline local_memcpy_receive( void *dest, void *src, int len ); /* Temp, find a better solution */#endif#define div_DmaBufSize 128static struct I2cBusObject IP3203_i2cbus[NR_I2C_DEVICES];static int i2c_debug = 0;/* This function is called from Primary ISR */static void recover_from_hardware_error(struct i2c_adapter * i2c_adap){        struct I2cBusObject * busptr = (struct I2cBusObject *)i2c_adap->algo_data;        dev_dbg(&i2c_adap->dev, "Recover from HW Error\n");        DISABLE_I2C_CONTROLLER( busptr );        STAOUT( busptr, 0 ); /* Don't generate START condition */        STOOUT( busptr, 1 ); /* Recover from error condition */        if( ( busptr->mode == MasterReceiver ) || ( busptr->mode == MasterTransmitter ) )        {                busptr->mst_status = errids_IsI2cHardwareError;                busptr->isr_event |= evMasterReady;                wake_up_interruptible(&(busptr->iic_wait_master));        }        if ( busptr->slv_enabled )        {                AAOUT( busptr, 1 ); /* ACK bit will be returned after slave address reception */        }        else        {                AAOUT( busptr, 0 ); /* NOT ACK bit will be returned after slave address reception */        }        busptr->mode = Idle;        CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */        ENABLE_I2C_CONTROLLER( busptr ); /* Enable I2C controller */}static __inline void iic_interrupt_idle(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){        switch (i2c_state)        {        case 0x08: /* Master Transmitter or Master Receiver: A START condition has been transmitted */                if( ( busptr->mst_txbufindex < busptr->mst_txbuflen ) || ( busptr->mst_rxbufindex == busptr->mst_rxbuflen ) ) /* if bytes to transmit or no bytes to receive  ? */                {                        int myaddr = (busptr->mst_address & 0xFE);                        dev_dbg(&i2c_adap->dev, "START TRANSMITTED, Read bit cleared addr = %x\n", myaddr);                        write_IP3203_I2CDAT(busptr, myaddr); /* Read bit cleared */                        busptr->mode = MasterTransmitter;#ifdef USE_DMA                        {                                int dmalen;                                if( busptr->mst_txbuflen <= div_DmaBufSize )                                {                                        dmalen = busptr->mst_txbuflen;                                }                                else                                {                                        dmalen = div_DmaBufSize;                                }                                dma_start( busptr->mst_txbuf, i2c_adap, dmalen,  MasterTransmitter);                                busptr->mst_txbufindex = dmalen;                        }#endif                }                else                {                        int myaddr = ((busptr->mst_address & 0xFE) | 0x01);                        dev_dbg(&i2c_adap->dev, "START TRANSMITTED, Read bit set(%x)\n", myaddr);                        write_IP3203_I2CDAT(busptr, myaddr); /* Read bit set */                        busptr->mode = MasterReceiver;                }                STAOUT( busptr, 0 );/* Clear STA flag */                CLEAR_I2C_INTERRUPT( busptr ); /* Reset interrupt */	        break;        case 0x60: /* Own SLA+W has been received; ACK has been returned */                busptr->slv_bufindex = 1; /* reset buffer pointer !!! */                AAOUT( busptr, busptr->slv_enabled ); /* ACK bit will be returned after next byte reception */                busptr->mode = SlaveReceiver;//                Todo : Start timeout timer in tasklet//                tasklet_schedule(&IP3203_slave_tasklet);                CLEAR_I2C_INTERRUPT(busptr); /* Don't reset i2c interrupt */                break;        case 0xA8: /* Own SLA+R has been received; ACK has been returned */                busptr->mode = SlaveTransmitter;                busptr->isr_event |= evSlaveReadRequest;                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:                recover_from_hardware_error( i2c_adap );		    	break;        }}static __inline void iic_interrupt_master_transmitter(struct i2c_adapter * i2c_adap, struct I2cBusObject * busptr, int i2c_state){        switch (i2c_state)		{        case 0x10: /* Master Transmitter or Master Receiver: A repeated START condition has been transmitted */               /* Note : A repeated START should not occur when in MasterReceiver mode in this implementation */                if( ( busptr->mst_txbufindex < busptr->mst_txbuflen ) || ( busptr->mst_rxbufindex == busptr->mst_rxbuflen ) ) /* if bytes to transmit or no bytes to receive  ? */                {                        int myaddr = (busptr->mst_address & 0xFE);dev_dbg(&i2c_adap->dev, "START TRANSMITTED, Read bit cleared addr = %x\n", myaddr);                        write_IP3203_I2CDAT(busptr, myaddr); /* Read bit cleared */

⌨️ 快捷键说明

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