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

📄 i2c-algo-ip0105.c

📁 PNX8550 I2C总线驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        retval = interruptible_sleep_on_timeout(&(busptr->iic_wait_master), (5*HZ));        if (retval == 0)        {                int i2c_state = read_IP0105_I2C_STATUS(busptr);  // I2CSTATIN( device );                int i2c_intstate = read_IP0105_I2C_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;        }static int IP0105_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, "IP0105 xfer nr %d\n", num);        ASSERT(num > 0 && num <= 2);        for (i = 0; i < num; i++)         {                pmsg = &msgs[i];                if (i == 0)                {                        if (pmsg->flags & I2C_M_TEN)                        {                                // addr = 10 bit addr, not supported yet                        }                        else                        {                                // addr = 7 bit addr                                addr &= 0x7f;                                addr <<= 1;                        }                }                /*  wr_write handles all master read/write commands, including repeat start (I2C_M_NOSTART)                */                if (pmsg->flags & I2C_M_RD )                {                        /* read bytes into buffer*/                        rd_buf = pmsg->buf;                        rd_len = pmsg->len;                }                else                {                        /* write bytes from buffer */                        wr_buf = pmsg->buf;                        wr_len = pmsg->len;                }        }        if (num != 0)        {                switch(ret = i2c_write_read(i2c_adap, addr, wr_buf, wr_len, rd_buf, rd_len))                {                case errids_Ok:                        break;                case errids_IsI2cHardwareError:                        num = -1;                        dev_dbg(&i2c_adap->dev, "Hardware error\n");                        IP0105_reset(i2c_adap);                        break;                case errids_IsI2cDeviceError:                        num = -1;                        dev_dbg(&i2c_adap->dev, "Device error\n");                        IP0105_reset(i2c_adap);                        break;                case errids_IsI2cWriteError:                        num = -1;                        dev_dbg(&i2c_adap->dev, "Write error\n");                        IP0105_reset(i2c_adap);                        break;                default:                        num = -1;                        dev_dbg(&i2c_adap->dev, "Error Unkonwn\n");                        IP0105_reset(i2c_adap);                        break;                }        }            return num;}static int algo_control(struct i2c_adapter *i2c_adap, unsigned int cmd, unsigned long arg){        struct I2cBusObject * busptr =  (struct I2cBusObject *)i2c_adap->algo_data;        switch (cmd)        {        case I2C_SET_SLAVE_ADDRESS:                if (busptr->slv_enabled)                        return -EBUSY;                else                {                        write_IP0105_I2C_ADDRESS( busptr, I2CADDRESS( arg )); /* >> 1 */; /* 7 bits address, No General call support */dev_dbg(&i2c_adap->dev, "Set Own adress to %x\n", read_IP0105_I2C_ADDRESS(busptr));                }                break;        case I2C_SET_SLAVE_ENABLE:                if (arg)                {                        if( !busptr->slv_enabled )                        {                               unsigned int len = (unsigned int)arg;                               len++;  // Need an extra byte for the length                               busptr->slv_buf = kmalloc(len, GFP_KERNEL);                               if (NULL != busptr->slv_buf)                               {                                       busptr->slv_usr_notify = &i2c_adap->fasync;                                       busptr->slv_bufindex = 1;                                       busptr->slv_buflen = 0; // todo : slave transmitter, but we can only reveive                                       busptr->slv_bufsize = len;                                       busptr->slv_enabled = TRUE;                                       AAOUT( busptr, 1 ); /* ACK bit will be returned after slave address reception */                                       dev_dbg(&i2c_adap->dev, "Enable Slave\n");                               }                               else return -ENOMEM;                        }                        else return -EBUSY;                }                else                {                        busptr->slv_usr_notify = NULL;                        busptr->slv_bufsize    = 0;                        AAOUT( busptr, 0 ); /* ACK will not be sent after slave address reception */                        busptr->slv_enabled = FALSE;                        if (NULL != busptr->slv_buf)                        {                            kfree(busptr->slv_buf);  // kfree returns void, no check needed                        }                        busptr->slv_bufindex  = 0;                        busptr->slv_buflen    = 0;dev_dbg(&i2c_adap->dev, "Disable Slave\n");                }                break;      case I2C_GET_SLAVE_DATA:                {                        unsigned long ret;                        unsigned char * user_data = (unsigned char *)arg;                        unsigned char nr_of_bytes = busptr->slv_bufindex -1;                        busptr->slv_buf[0] = nr_of_bytes;                        ret = copy_to_user(user_data, busptr->slv_buf, busptr->slv_bufindex);                        busptr->slv_bufindex = 1;                        if (busptr->slv_enabled == TRUE)                        {                                AAOUT( busptr, 1);  /* ACK bit will be returned after slave address reception */                        }                        if (0 == busptr->slv_buf[0])                        {                                return -ENODATA;                        }                }                break;        }        return 0;}static u32 IP0105_func(struct i2c_adapter *adap){        return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |                I2C_FUNC_PROTOCOL_MANGLING; }/* -----exported algorithm data: -------------------------------------  */static struct i2c_algorithm IP0105_algo_0 = {        .name = "IP0105 dev0",         .id = I2C_ALGO_EXP,        .master_xfer = IP0105_xfer,        .algo_control = algo_control,                   /* ioctl                */        .functionality = IP0105_func,                     /* functionality        */};static struct i2c_algorithm IP0105_algo_1 = {        .name = "IP0105 dev1",        .id = I2C_ALGO_EXP,        .master_xfer = IP0105_xfer,        .algo_control = algo_control,        .functionality = IP0105_func,};static struct i2c_algorithm * IP0105_algo[NR_I2C_DEVICES] = { &IP0105_algo_0, &IP0105_algo_1 };/*  * registering functions to load algorithms at runtime  */int i2c_IP0105_add_bus(int device, struct i2c_adapter * i2c_adap){        int res;        dev_dbg(&i2c_adap->dev, "i2c-algo-IP0105.o: i2c IP0105 algorithm module\n");        DEB2(printk("i2c-algo-viper.o: hw routines for %s registered.\n", i2c_adap->name));        /* register new adapter to i2c module... */        i2c_adap->algo = IP0105_algo[device];        i2c_adap->id |= i2c_adap->algo->id;        i2c_adap->timeout = 100;            /* default values, should       */        i2c_adap->retries = 3;              /* be replaced by defines       */        dev_dbg(&i2c_adap->dev, "Initialise IP0105 device %d\n", device);        IP0105_init(i2c_adap, device);        if ((res = i2c_add_adapter(i2c_adap)) < 0)        {                dev_dbg(&i2c_adap->dev, "i2c-algo-IP0105 %d: Unable to register with I2C\n", device);                return -ENODEV;        }        dev_dbg(&i2c_adap->dev, "add adapter %d returned %x\n", device, res);        /* Todo : scan bus */        return 0;}int i2c_IP0105_del_bus(struct i2c_adapter *i2c_adap){        struct I2cBusObject *busptr;        int res;        dev_dbg(&i2c_adap->dev, "exit bus %x\n", device);        busptr = (struct I2cBusObject *)i2c_adap->algo_data;        if ((res = i2c_del_adapter(i2c_adap)) < 0)                return res;        DEB2(dev_dbg(&i2c_adap->dev, "i2c-algo-IP0105.o: adapter unregistered: %s\n",i2c_adap->name));        return 0;}static struct i2c_adapter IP0105_ops_0 = {       .name = "IP0105 0",                        // name       .id = FAST_I2C_PORT_3,                // id       .algo_data = &IP0105_i2cbus[0], // algo_data};static struct i2c_adapter IP0105_ops_1 = {       .name = "IP0105 1",       .id = FAST_I2C_PORT_4,       .algo_data = &IP0105_i2cbus[1], // algo_data};static struct i2c_adapter * IP0105_ops[NR_I2C_DEVICES] = { &IP0105_ops_0, &IP0105_ops_1 };int __init i2c_algo_IP0105_init (void){    printk("i2c-algo-IP0105.o: i2c IP0105 algorithm module\n");    int device;    for (device = 0; device < NR_I2C_DEVICES; device++)    {        if (i2c_IP0105_add_bus(device, IP0105_ops[device]) < 0)        {                printk("i2c-algo-IP0105 %d: Unable to register with I2C\n", device);                return -ENODEV;        }    }    return 0;}void __exit i2c_algo_IP0105_exit(void){    struct I2cBusObject *busptr;    int device;    for( device = 0; device < NR_I2C_DEVICES; device++ )    {        printk("exit bus %x\n", device);        busptr = &IP0105_i2cbus[device];        DISABLE_I2C_INTERRUPT( busptr );        DISABLE_I2C_CONTROLLER( busptr ); /* Disable I2C controller */        disable_irq(busptr->int_pin);   /* Enable i2c interrupt in Interrupt controller */        free_irq(busptr->int_pin, (void *)&IP0105_i2cbus[device]);        enable_irq(busptr->int_pin);   /* Enable i2c interrupt in Interrupt controller */        i2c_IP0105_del_bus(IP0105_ops[device]);    }}MODULE_AUTHOR("Willem van Beek <willem.van.beek@philips.com>");MODULE_DESCRIPTION("I2C-Bus adapter routines for IP0105");MODULE_LICENSE("GPL");/* Called when module is loaded or when kernel is initialized. * If MODULES is defined when this file is compiled, then this function will * resolve to init_module (the function called when insmod is invoked for a * module).  Otherwise, this function is called early in the boot, when the * kernel is intialized.  Check out /include/init.h to see how this works. */subsys_initcall(i2c_algo_IP0105_init);/* Resolves to module_cleanup when MODULES is defined. */module_exit(i2c_algo_IP0105_exit);

⌨️ 快捷键说明

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