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

📄 i2c-algo-ip0105.c

📁 PNX8550 I2C总线驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ------------------------------------------------------------------------- *//* i2c-algo-IP0105.c i2c driver algorithms for PNX8550 Fast I2C ports        *//* ------------------------------------------------------------------------- *//* This module is the work of Willem van Beek, * evidently inspired by Simon G. Vogl. * * Restriction : * Slave Transmitter functionality not working (yet) * 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/fs.h>/*-------------------------------------------------------------------------------Project include files:-------------------------------------------------------------------------------*/#include <linux/i2c.h>#include "i2c-algo-IP0105.h"#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/philips/pnx8550/pnx8550_int.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 Fast I2C ports */#define I2C_HW_IP0105               0x00 /* IP0105 Controller on the Viper */#define FAST_I2C_PORT_3             0x00 /* IP0105 Controller on the Viper */#define FAST_I2C_PORT_4             0x01 /* IP0105 Controller on the Viper */#define IP0105_UNIT0                0xBBE69000#define IP0105_UNIT1                0xBBE4C000#define MODULE_CLOCK                27000 /* I2C module clock speed in KHz */#define I2CADDRESS( address )       ((address) & 0x00FE) /* only 7 bits I2C address implemented */#define TIMER_OFF                   0typedef enum{    Idle = 0u,    MasterTransmitter,    MasterReceiver,    SlaveTransmitter,    SlaveReceiver} 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;    struct  fasync_struct ** slv_usr_notify;};/* declaration of static functions *//* Local functions for IP0105 */static __inline void STAOUT(struct I2cBusObject * a, int p){        int val = read_IP0105_I2C_CONTROL(a);        if (p) { val |= IP0105_STA; } else { val &= ~IP0105_STA; }        write_IP0105_I2C_CONTROL(a, val);}static __inline void STOOUT(struct I2cBusObject * a, int p){        write_IP0105_I2C_STOP(a, p);}static __inline void AAOUT(struct I2cBusObject * a, int p){        int val = read_IP0105_I2C_CONTROL(a);        if (p) { val |= IP0105_AA; } else { val &= ~IP0105_AA; }        write_IP0105_I2C_CONTROL(a, val);}static __inline void ENABLE_I2C_CONTROLLER(struct I2cBusObject * a){        int val = read_IP0105_I2C_CONTROL(a);        val |= IP0105_EN;        write_IP0105_I2C_CONTROL(a, val);}static __inline void DISABLE_I2C_CONTROLLER(struct I2cBusObject * a){        int val = read_IP0105_I2C_CONTROL(a);        val &= ~IP0105_EN;        write_IP0105_I2C_CONTROL(a, val);}static __inline void CLEAR_I2C_INTERRUPT(struct I2cBusObject * a){        write_IP0105_I2C_INT_CLR(a, 1);}static __inline void ENABLE_I2C_INTERRUPT(struct I2cBusObject * a){        write_IP0105_I2C_INT_EN(a, IP0105_INTBIT);}static __inline void DISABLE_I2C_INTERRUPT(struct I2cBusObject * a){        write_IP0105_I2C_INT_EN(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 */static __inline void SETSPEED100(struct I2cBusObject * a){        int val = read_IP0105_I2C_CONTROL(a);        val &= 0x00F0;        val |= 0x00F4;        write_IP0105_I2C_CONTROL(a, val);}static __inline void SETSPEED25(struct I2cBusObject * a){        int val = read_IP0105_I2C_CONTROL(a);        val |= 0x00F7;        write_IP0105_I2C_CONTROL(a, val);}static __inline void SETSPEED400(struct I2cBusObject * a){        int val = read_IP0105_I2C_CONTROL(a);        val |= 0x00F0;        write_IP0105_I2C_CONTROL(a, val);}/* Local Types */static unsigned long IP0105_Controller[2] = {  IP0105_UNIT0, IP0105_UNIT1 };static unsigned long IP0105_INTPIN[2] = { PNX8550_INT_I2C3, PNX8550_INT_I2C4 };static struct i2c_adapter * slave_device = NULL;static void do_slave_tasklet(unsigned long);DECLARE_TASKLET(IP0105_slave_tasklet, do_slave_tasklet, 0);static struct I2cBusObject IP0105_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 ) )        {                disable_irq(busptr->int_pin);                busptr->mst_status = errids_IsI2cHardwareError;                busptr->isr_event |= evMasterReady;                enable_irq(busptr->int_pin);  //isv_SwExtSet( INTERRUPT_ID( device ) );                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_IP0105_I2C_DAT(busptr, myaddr); /* Read bit cleared */                        busptr->mode = MasterTransmitter;                }                else                {                        int myaddr = ((busptr->mst_address & 0xFE) | 0x01);                        dev_dbg(&i2c_adap->dev, "START TRANSMITTED, Read bit set(%x)\n", myaddr);                        write_IP0105_I2C_DAT(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(&IP0105_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(&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:             recover_from_hardware_error( i2c_adap );            break;        }}

⌨️ 快捷键说明

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