分享

linux gpio模拟i2c的使用/用GPIO模拟I2C总线

 dwlinux_gs 2017-04-18

这个结构专门用于数据传输相关的addrI2C设备地址,flags为一些标志位,len为数据的长度,buf为数据。这里宏定义的一些标志还是需要了解一下。

I2C_M_TEN表示10位设备地址

I2C_M_RD读标志

I2C_M_NOSTART无起始信号标志

I2C_M_IGNORE_NAK忽略应答信号标志

回到for,这里的num代表有几个struct i2c_msg,进入for语句,接下来是个if语句,判断这个设备是否定义了I2C_M_NOSTART标志,这个标志主要用于写操作时,不必重新发送起始信号和设备地址,但是对于读操作就不同了,要调用i2c_repstart这个函数去重新发送起始信号,调用bit_doAddress函数去重新构造设备地址字节,来看这个函数。

  1. static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)  
  2. {  
  3.     unsigned short flags = msg->flags;  
  4.     unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;  
  5.     struct i2c_algo_bit_data *adap = i2c_adap->algo_data;  
  6.   
  7.     unsigned char addr;  
  8.     int ret, retries;  
  9.   
  10.     retries = nak_ok ? 0 : i2c_adap->retries;  
  11.   
  12.     if (flags & I2C_M_TEN) {  
  13.         /* a ten bit address */  
  14.         addr = 0xf0 | ((msg->addr >> 7) & 0x03);  
  15.         bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);  
  16.         /* try extended address code...*/  
  17.         ret = try_address(i2c_adap, addr, retries);  
  18.         if ((ret != 1) && !nak_ok)  {  
  19.             dev_err(&i2c_adap->dev,  
  20.                 "died at extended address code\n");  
  21.             return -EREMOTEIO;  
  22.         }  
  23.         /* the remaining 8 bit address */  
  24.         ret = i2c_outb(i2c_adap, msg->addr & 0x7f);  
  25.         if ((ret != 1) && !nak_ok) {  
  26.             /* the chip did not ack / xmission error occurred */  
  27.             dev_err(&i2c_adap->dev, "died at 2nd address code\n");  
  28.             return -EREMOTEIO;  
  29.         }  
  30.         if (flags & I2C_M_RD) {  
  31.             bit_dbg(3, &i2c_adap->dev, "emitting repeated "  
  32.                 "start condition\n");  
  33.             i2c_repstart(adap);  
  34.             /* okay, now switch into reading mode */  
  35.             addr |= 0x01;  
  36.             ret = try_address(i2c_adap, addr, retries);  
  37.             if ((ret != 1) && !nak_ok) {  
  38.                 dev_err(&i2c_adap->dev,  
  39.                     "died at repeated address code\n");  
  40.                 return -EREMOTEIO;  
  41.             }  
  42.         }  
  43.     } else {        /* normal 7bit address  */  
  44.         addr = msg->addr << 1;  
  45.         if (flags & I2C_M_RD)  
  46.             addr |= 1;  
  47.         if (flags & I2C_M_REV_DIR_ADDR)  
  48.             addr ^= 1;  
  49.         ret = try_address(i2c_adap, addr, retries);  
  50.         if ((ret != 1) && !nak_ok)  
  51.             return -ENXIO;  
  52.     }  
  53.   
  54.     return 0;  
  55. }  
这里先做了一个判断,10位设备地址和7位设备地址分别做不同的处理,通常一条I2C总线上不会挂那么多I2C设备,所以10位地址不常用,直接看对7位地址的处理。struct i2c_msg中addr中是真正的设备地址,而这里发送的addr高7位才是设备地址,最低位为读写位,如果为读,最低位为1,如果为写,最低位为0。所以要将struct i2c_msg中addr向左移1位,如果定义了I2C_M_RD标志,就将addr或上1,前面就说过,这个标志就代表读,如果是写,这里就不用处理,因为最低位本身就是0。最后调用try_address函数将这个地址字节发送出去。
  1.  1. static int try_address(struct i2c_adapter *i2c_adap,    
  2.  2.                unsigned char addr, int retries)    
  3.  3. {    
  4.  4.     struct i2c_algo_bit_data *adap = i2c_adap->algo_data;    
  5.  5.     int i, ret = 0;    
  6.  6.     
  7.  7.     for (i = 0; i <= retries; i++) {    
  8.  8.         ret = i2c_outb(i2c_adap, addr);    
  9.  9.         if (ret == 1 || i == retries)    
  10. 10.             break;    
  11. 11.         bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");    
  12. 12.         i2c_stop(adap);    
  13. 13.         udelay(adap->udelay);    
  14. 14.         yield();    
  15. 15.         bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");    
  16. 16.         i2c_start(adap);    
  17. 17.     }    
  18. 18.     if (i && ret)    
  19. 19.         bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "    
  20. 20.             "0x%02x: %s\n", i + 1,    
  21. 21.             addr & 1 ? "read from" : "write to", addr >> 1,    
  22. 22.             ret == 1 ? "success" : "failed, timeout?");    
  23. 23.     return ret;    
  24. 24. }    

最主要的就是调用i2c_outb发送一个字节,retries为重复次数,看前面adap->retries= 3;

如果发送失败,也就是设备没有给出应答信号,那就发送停止信号,发送起始信号,再发送这个地址字节,这就叫retries。来看这个具体的i2c_outb函数

  1.  1. static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)    
  2.  2. {    
  3.  3.     int i;    
  4.  4.     int sb;    
  5.  5.     int ack;    
  6.  6.     struct i2c_algo_bit_data *adap = i2c_adap->algo_data;    
  7.  7.     
  8.  8.     /* assert: scl is low */    
  9.  9.     for (i = 7; i >= 0; i--) {    
  10. 10.         sb = (c >> i) & 1;    
  11. 11.         setsda(adap, sb);    
  12. 12.         udelay((adap->udelay + 1) / 2);    
  13. 13.         if (sclhi(adap) < 0) { /* timed out */    
  14. 14.             bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "    
  15. 15.                 "timeout at bit #%d\n", (int)c, i);    
  16. 16.             return -ETIMEDOUT;    
  17. 17.         }    
  18. 18.         /* FIXME do arbitration here:   
  19. 19.          * if (sb && !getsda(adap)) -> ouch! Get out of here.   
  20. 20.          *   
  21. 21.          * Report a unique code, so higher level code can retry   
  22. 22.          * the whole (combined) message and *NOT* issue STOP.   
  23. 23.          */    
  24. 24.         scllo(adap);    
  25. 25.     }    
  26. 26.     sdahi(adap);    
  27. 27.     if (sclhi(adap) < 0) { /* timeout */    
  28. 28.         bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "    
  29. 29.             "timeout at ack\n", (int)c);    
  30. 30.         return -ETIMEDOUT;    
  31. 31.     }    
  32. 32.     
  33. 33.     /* read ack: SDA should be pulled down by slave, or it may   
  34. 34.      * NAK (usually to report problems with the data we wrote).   
  35. 35.      */    
  36. 36.     ack = !getsda(adap);    /* ack: sda is pulled low -> success */    
  37. 37.     bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,    
  38. 38.         ack ? "A" : "NA");    
  39. 39.     
  40. 40.     scllo(adap);    
  41. 41.     return ack;    
  42. 42.     /* assert: scl is low (sda undef) */    
  43. 43. }    

这个函数有两个参数,一个是structi2c_adapter代表I2C主机,一个是发送的字节数据。那么I2C是怎样将一个字节数据发送出去的呢,那再来看看协议。



首先是发送字节数据的最高位,在时钟为高电平期间将一位数据发送出去,最后是发送字节数据的最低位。发送完成之后,我们需要一个ACK信号,要不然我怎么知道发送成功没有,ACK信号就是在第九个时钟周期时数据线为低,所以在一个字节数据传送完成后,还要将数据线拉高,我们看程序中就是这一句sdahi(adap);等待这个ACK信号的到来,这样一个字节数据就发送完成。

回到bit_xfer函数中,前面只是将设备地址字节发送出去了,那么接下来就是该发送数据了。

注意:这里的数据包括操作设备的基地址

如果是读则调用readbytes函数去读,如果是写则调用sendbytes去写,先看readbytes函数

  1.  1. static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)    
  2.  2. {    
  3.  3.     int inval;    
  4.  4.     int rdcount = 0;    /* counts bytes read */    
  5.  5.     unsigned char *temp = msg->buf;    
  6.  6.     int count = msg->len;    
  7.  7.     const unsigned flags = msg->flags;    
  8.  8.     
  9.  9.     while (count > 0) {    
  10. 10.         inval = i2c_inb(i2c_adap);    
  11. 11.         if (inval >= 0) {    
  12. 12.             *temp = inval;    
  13. 13.             rdcount++;    
  14. 14.         } else {   /* read timed out */    
  15. 15.             break;    
  16. 16.         }    
  17. 17.     
  18. 18.         temp++;    
  19. 19.         count--;    
  20. 20.     
  21. 21.         /* Some SMBus transactions require that we receive the   
  22. 22.            transaction length as the first read byte. */    
  23. 23.         if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) {    
  24. 24.             if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {    
  25. 25.                 if (!(flags & I2C_M_NO_RD_ACK))    
  26. 26.                     acknak(i2c_adap, 0);    
  27. 27.                 dev_err(&i2c_adap->dev, "readbytes: invalid "    
  28. 28.                     "block length (%d)\n", inval);    
  29. 29.                 return -EREMOTEIO;    
  30. 30.             }    
  31. 31.             /* The original count value accounts for the extra   
  32. 32.                bytes, that is, either 1 for a regular transaction,   
  33. 33.                or 2 for a PEC transaction. */    
  34. 34.             count += inval;    
  35. 35.             msg->len += inval;    
  36. 36.         }    
  37. 37.     
  38. 38.         bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n",    
  39. 39.             inval,    
  40. 40.             (flags & I2C_M_NO_RD_ACK)    
  41. 41.                 ? "(no ack/nak)"    
  42. 42.                 : (count ? "A" : "NA"));    
  43. 43.     
  44. 44.         if (!(flags & I2C_M_NO_RD_ACK)) {    
  45. 45.             inval = acknak(i2c_adap, count);    
  46. 46.             if (inval < 0)    
  47. 47.                 return inval;    
  48. 48.         }    
  49. 49.     }    
  50. 50.     return rdcount;    
  51. 51. }    

其中一个大的while循环,调用i2c_inb去读一个字节,count为数据的长度,单位为多少个字节,

那就来看i2c_inb函数。

  1. static int i2c_inb(struct i2c_adapter *i2c_adap)  
  2. {  
  3.     /* read byte via i2c port, without start/stop sequence  */  
  4.     /* acknowledge is sent in i2c_read.         */  
  5.     int i;  
  6.     unsigned char indata = 0;  
  7.     struct i2c_algo_bit_data *adap = i2c_adap->algo_data;  
  8.   
  9.     /* assert: scl is low */  
  10.     sdahi(adap);  
  11.     for (i = 0; i < 8; i++) {  
  12.         if (sclhi(adap) < 0) { /* timeout */  
  13.             bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "  
  14.                 "#%d\n", 7 - i);  
  15.             return -ETIMEDOUT;  
  16.         }  
  17.         indata *= 2;  
  18.         if (getsda(adap))  
  19.             indata |= 0x01;  
  20.         setscl(adap, 0);  
  21.         udelay(i == 7 ? adap->udelay / 2 : adap->udelay);  
  22.     }  
  23.     /* assert: scl is low */  
  24.     return indata;  
  25. }  
再来看sendbytes函数
  1.  1. static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)    
  2.  2. {    
  3.  3.     const unsigned char *temp = msg->buf;    
  4.  4.     int count = msg->len;    
  5.  5.     unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;    
  6.  6.     int retval;    
  7.  7.     int wrcount = 0;    
  8.  8.     
  9.  9.     while (count > 0) {    
  10. 10.         retval = i2c_outb(i2c_adap, *temp);    
  11. 11.     
  12. 12.         /* OK/ACK; or ignored NAK */    
  13. 13.         if ((retval > 0) || (nak_ok && (retval == 0))) {    
  14. 14.             count--;    
  15. 15.             temp++;    
  16. 16.             wrcount++;    
  17. 17.     
  18. 18.         /* A slave NAKing the master means the slave didn't like   
  19. 19.          * something about the data it saw.  For example, maybe   
  20. 20.          * the SMBus PEC was wrong.   
  21. 21.          */    
  22. 22.         } else if (retval == 0) {    
  23. 23.             dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n");    
  24. 24.             return -EIO;    
  25. 25.     
  26. 26.         /* Timeout; or (someday) lost arbitration   
  27. 27.          *   
  28. 28.          * FIXME Lost ARB implies retrying the transaction from   
  29. 29.          * the first message, after the "winning" master issues   
  30. 30.          * its STOP.  As a rule, upper layer code has no reason   
  31. 31.          * to know or care about this ... it is *NOT* an error.   
  32. 32.          */    
  33. 33.         } else {    
  34. 34.             dev_err(&i2c_adap->dev, "sendbytes: error %d\n",    
  35. 35.                     retval);    
  36. 36.             return retval;    
  37. 37.         }    
  38. 38.     }    
  39. 39.     return wrcount;    
  40. 40. }    

也是一个大的while循环,同发送地址字节一样,也是调用i2c_outb去发送一个字节,count也是数据长度,由于i2c_outb函数在前面发送设备地址那里已经介绍了,这里也就不贴出来了。

还是回到bit_xfer函数,数据传输完成后,调用i2c_stop函数发送停止信号。我们看停止信号函数怎么去实现的。

  1. 1. static void i2c_stop(struct i2c_algo_bit_data *adap)    
  2. 2. {    
  3. 3.     /* assert: scl is low */    
  4. 4.     sdalo(adap);    
  5. 5.     sclhi(adap);    
  6. 6.     setsda(adap, 1);    
  7. 7.     udelay(adap->udelay);    
  8. 8. }    

看前面发送起始信号的那张图,停止信号就是在时钟为高电平期间,数据线从低到高的跳变。我们看程序是先将数据线拉低,将时钟线拉高,最后将数据拉高,这样就够成了一个停止信号。

还是回到i2c_bit_add_numbered_bus这个函数中来,看另外一个函数调用i2c_add_numbered_adapter

  1.  1. int i2c_add_numbered_adapter(struct i2c_adapter *adap)    
  2.  2. {    
  3.  3.     int id;    
  4.  4.     int status;    
  5.  5.     
  6.  6.     if (adap->nr & ~MAX_ID_MASK)    
  7.  7.         return -EINVAL;    
  8.  8.     
  9.  9. retry:    
  10. 10.     if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)    
  11. 11.         return -ENOMEM;    
  12. 12.     
  13. 13.     mutex_lock(&core_lock);    
  14. 14.     /* "above" here means "above or equal to", sigh;   
  15. 15.      * we need the "equal to" result to force the result   
  16. 16.      */    
  17. 17.     status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);    
  18. 18.     if (status == 0 && id != adap->nr) {    
  19. 19.         status = -EBUSY;    
  20. 20.         idr_remove(&i2c_adapter_idr, id);    
  21. 21.     }    
  22. 22.     mutex_unlock(&core_lock);    
  23. 23.     if (status == -EAGAIN)    
  24. 24.         goto retry;    
  25. 25.     
  26. 26.     if (status == 0)    
  27. 27.         status = i2c_register_adapter(adap);    
  28. 28.     return status;    
  29. 29. }    
最重要的是这句i2c_register_adapter,注册这条I2C总线,进去看看

  1. static int i2c_register_adapter(struct i2c_adapter *adap)  
  2. {  
  3.     int res = 0, dummy;  
  4.   
  5.     /* Can't register until after driver model init */  
  6.     if (unlikely(WARN_ON(!i2c_bus_type.p))) {  
  7.         res = -EAGAIN;  
  8.         goto out_list;  
  9.     }  
  10.   
  11.     mutex_init(&adap->bus_lock);  
  12.   
  13.     /* Set default timeout to 1 second if not already set */  
  14.     if (adap->timeout == 0)  
  15.         adap->timeout = HZ;  
  16.   
  17.     dev_set_name(&adap->dev, "i2c-%d", adap->nr);  
  18.     adap->dev.bus = &i2c_bus_type;  
  19.     adap->dev.type = &i2c_adapter_type;  
  20.     res = device_register(&adap->dev);  
  21.     if (res)  
  22.         goto out_list;  
  23.   
  24.     dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);  
  25.   
  26. #ifdef CONFIG_I2C_COMPAT  
  27.     res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,  
  28.                        adap->dev.parent);  
  29.     if (res)  
  30.         dev_warn(&adap->dev,  
  31.              "Failed to create compatibility class link\n");  
  32. #endif  
  33.   
  34.     /* create pre-declared device nodes */  
  35.     if (adap->nr < __i2c_first_dynamic_bus_num)  
  36.         i2c_scan_static_board_info(adap);  
  37.   
  38.     /* Notify drivers */  
  39.     mutex_lock(&core_lock);  
  40.     dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,  
  41.                  i2c_do_add_adapter);  
  42.     mutex_unlock(&core_lock);  
  43.   
  44.     return 0;  
  45.   
  46. out_list:  
  47.     mutex_lock(&core_lock);  
  48.     idr_remove(&i2c_adapter_idr, adap->nr);  
  49.     mutex_unlock(&core_lock);  
  50.     return res;  
  51. }  

看内核代码有时就会这样,会陷入内核代码的汪洋大海中,而拔不出来,直接后果是最后都忘记看这段代码的目的,丧失继续看下去的信心。所以为了避免这样情况出现,所以最好在开始看代码的时候要明确目标,我通过这段代码到底要了解什么东西,主干要抓住,其它枝叶就不要看了。

在这里我认为主要的有

1.注册这个I2C总线设备

  1. 1. adap->dev.bus = &i2c_bus_type;    
  2. 2. adap->dev.type = &i2c_adapter_type;    
  3. 3. res = device_register(&adap->dev);    
这个设备的总线类型为i2c_bus_type
  1. 1. struct bus_type i2c_bus_type = {    
  2. 2.     .name       = "i2c",    
  3. 3.     .match      = i2c_device_match,    
  4. 4.     .probe      = i2c_device_probe,    
  5. 5.     .remove     = i2c_device_remove,    
  6. 6.     .shutdown   = i2c_device_shutdown,    
  7. 7.     .suspend    = i2c_device_suspend,    
  8. 8.     .resume     = i2c_device_resume,    
  9. 9. };    

看一下它的match函数
  1.  1. static int i2c_device_match(struct device *dev, struct device_driver *drv)    
  2.  2. {    
  3.  3.     struct i2c_client   *client = i2c_verify_client(dev);    
  4.  4.     struct i2c_driver   *driver;    
  5.  5.     
  6.  6.     if (!client)    
  7.  7.         return 0;    
  8.  8.     
  9.  9.     driver = to_i2c_driver(drv);    
  10. 10.     /* match on an id table if there is one */    
  11. 11.     if (driver->id_table)    
  12. 12.         return i2c_match_id(driver->id_table, client) != NULL;    
  13. 13.     
  14. 14.     return 0;    
  15. 15. }    

这个match函数主要用来匹配我们的I2C设备和I2C驱动的,如果匹配成功,最后会调用驱动的probe函数,来看它如何匹配的。
  1. 1. static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,    
  2. 2.                         const struct i2c_client *client)    
  3. 3. {    
  4. 4.     while (id->name[0]) {    
  5. 5.         if (strcmp(client->name, id->name) == 0)    
  6. 6.             return id;    
  7. 7.         id++;    
  8. 8.     }    
  9. 9.     return NULL;    
  10. 0. }    

就是判断I2C设备的name字段和驱动中id_table中定义的name字段是否相等。

2.往这条总线上添加设备

  1.  1. static void i2c_scan_static_board_info(struct i2c_adapter *adapter)    
  2.  2. {    
  3.  3.     struct i2c_devinfo  *devinfo;    
  4.  4.     
  5.  5.     down_read(&__i2c_board_lock);    
  6.  6.     list_for_each_entry(devinfo, &__i2c_board_list, list) {    
  7.  7.         if (devinfo->busnum == adapter->nr    
  8.  8.                 && !i2c_new_device(adapter,    
  9.  9.                         &devinfo->board_info))    
  10. 10.             dev_err(&adapter->dev,    
  11. 11.                 "Can't create device at 0x%02x\n",    
  12. 12.                 devinfo->board_info.addr);    
  13. 13.     }    
  14. 14.     up_read(&__i2c_board_lock);    
  15. 15. }    
遍历__i2c_board_list这条链表,看下面的if语句,首先要让struct i2c_devinfo结构中的busnum等于struct i2c_adapter中的nr,我们前面也说了,这个nr就是i2c总线的总线号,这里可以理解为是在往这条总线上添加设备。所以,如果我们要向I2C注册一个I2C设备的话,直接向__i2c_board_list添加一个设备信息就可以了,先来看这个设备信息结构是怎么定义的。

  1. 1. struct i2c_board_info {    
  2. 2.     char        type[I2C_NAME_SIZE];    
  3. 3.     unsigned short  flags;    
  4. 4.     unsigned short  addr;    
  5. 5.     void        *platform_data;    
  6. 6.     struct dev_archdata *archdata;    
  7. 7.     int     irq;    
  8. 8. };    
定义这样一个信息呢一般使用一个宏I2C_BOARD_INFO
  1. # #define I2C_BOARD_INFO(dev_type, dev_addr) \    
  2. #     .type = dev_type.addr = (dev_addr)   

  1. dev_type为设备的名字,前面也说了,这个name一定要和I2C驱动相同。addr为设备的地址。  
  2.   
  3. 定义了这样一组信息之后呢,接下来当然是往链表添加这些信息了。  

  1.  1. int __init    
  2.  2. i2c_register_board_info(int busnum,    
  3.  3.     struct i2c_board_info const *info, unsigned len)    
  4.  4. {    
  5.  5.     int status;    
  6.  6.     
  7.  7.     down_write(&__i2c_board_lock);    
  8.  8.     
  9.  9.     /* dynamic bus numbers will be assigned after the last static one */    
  10. 10.     if (busnum >= __i2c_first_dynamic_bus_num)    
  11. 11.         __i2c_first_dynamic_bus_num = busnum + 1;    
  12. 12.     
  13. 13.     for (status = 0; len; len--, info++) {    
  14. 14.         struct i2c_devinfo  *devinfo;    
  15. 15.     
  16. 16.         devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);    
  17. 17.         if (!devinfo) {    
  18. 18.             pr_debug("i2c-core: can't register boardinfo!\n");    
  19. 19.             status = -ENOMEM;    
  20. 20.             break;    
  21. 21.         }    
  22. 22.     
  23. 23.         devinfo->busnum = busnum;    
  24. 24.         devinfo->board_info = *info;    
  25. 25.         list_add_tail(&devinfo->list, &__i2c_board_list);    
  26. 26.     }    
  27. 27.     
  28. 28.     up_write(&__i2c_board_lock);    
  29. 29.     
  30. 30.     return status;    
  31. 31. }    

第一个参数呢需要注意,它是I2C总线号,一定要和具体的I2C总线对应。我们看又定义了这样一个结构struct i2c_devinfo。

最后是调用list_add_tail__i2c_board_list这条链表添加设备信息。

然后是i2c_new_device

  1. # struct i2c_client *    
  2. # i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)    
  3. # {    
  4. #     struct i2c_client   *client;    
  5. #     int         status;    
  6. #     
  7. #     /*为I2C设备申请内存*/    
  8. #     client = kzalloc(sizeof *client, GFP_KERNEL);    
  9. #     if (!client)    
  10. #         return NULL;    
  11. #     
  12. #     /*指定I2C设备的总线*/    
  13. #     client->adapter = adap;    
  14. #     
  15. #     client->dev.platform_data = info->platform_data;    
  16. #     
  17. #     if (info->archdata)    
  18. #         client->dev.archdata = *info->archdata;    
  19. #     
  20. #     client->flags = info->flags;    
  21. #     client->addr = info->addr; /*I2C设备地址*/    
  22. #     client->irq = info->irq;    
  23. #     
  24. #     strlcpy(client->name, info->type, sizeof(client->name));    
  25. #     
  26. #     /*检查这个地址有没有被设备占用*/    
  27. #     /* Check for address business */    
  28. #     status = i2c_check_addr(adap, client->addr);    
  29. #     if (status)    
  30. #         goto out_err;    
  31. #     
  32. #     client->dev.parent = &client->adapter->dev; /*指定设备的父设备*/    
  33. #     client->dev.bus = &i2c_bus_type; /*指定设备的总线类型*/    
  34. #     client->dev.type = &i2c_client_type;    
  35. #     
  36. #     dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),    
  37. #              client->addr);    
  38. #     status = device_register(&client->dev); /*注册设备*/    
  39. #     if (status)    
  40. #         goto out_err;    
  41. #     
  42. #     dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",    
  43. #         client->name, dev_name(&client->dev));    
  44. #     
  45. #     return client;    
  46. #     
  47. # out_err:    
  48. #     dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "    
  49. #         "(%d)\n", client->name, client->addr, status);    
  50. #     kfree(client);    
  51. #     return NULL;   

这个函数的功能是新建一个I2C设备并注册它,在I2C子系统中,I2C设备使用结构structi2c_client描述,那么首先要申请内存空间,I2C设备的主机是谁,必须知道挂载到哪条总线上的,然后就是一些赋值操作,最后就是注册设备,那么这个设备就实实在在的挂在到这条总线上了,这也是新的I2C设备注册方式。

3.i2c_do_add_adapter

你看说着说着就跑远了

  1.  1. static int i2c_do_add_adapter(struct device_driver *d, void *data)    
  2.  2. {    
  3.  3.     struct i2c_driver *driver = to_i2c_driver(d);    
  4.  4.     struct i2c_adapter *adap = data;    
  5.  5.     
  6.  6.     /* Detect supported devices on that bus, and instantiate them */    
  7.  7.     i2c_detect(adap, driver);    
  8.  8.     
  9.  9.     /* Let legacy drivers scan this bus for matching devices */    
  10. 10.     if (driver->attach_adapter) {    
  11. 11.         /* We ignore the return code; if it fails, too bad */    
  12. 12.         driver->attach_adapter(adap);    
  13. 13.     }    
  14. 14.     return 0;    
  15. 15. }    

前面通过i2c_scan_static_board_info往I2C总线上添加设备是新的方式,而这里调用每个I2C设备驱动的attach_adapter函数,然后在attach_adapter函数中去实现设备的注册,这是老的方式,i2c-dev.c中就是采用的这种方式。至此,总线这块就看完了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多