<form id="bpvnp"></form>

            <address id="bpvnp"><listing id="bpvnp"><meter id="bpvnp"></meter></listing></address>

                <address id="bpvnp"><nobr id="bpvnp"><menuitem id="bpvnp"></menuitem></nobr></address>

                    技术文摘

                    Linux I2C驱动分析(二)——I2C板级设备扫描和数据传输












                    一、板级设备扫描

                    针对上一篇文章最后的i2c_scan_static_board_info(adap)函数处,首先先看下在系统启动的时候板级设备的注册。

                    针对我现在使用的开发板,对于I2C设备注册程序如下:

                    1.     static struct i2c_board_info i2c_devices_info[] = {

                    2.     #ifdef CONFIG_SND_SOC_ALC5623

                    3.             {

                    4.                     I2C_BOARD_INFO("alc5623", 0x1a),

                    5.                     .platform_data = &alc5623_data,

                    6.             },

                    7.     #endif

                    8.     #ifdef CONFIG_RTC_DRV_DS3231M

                    9.             {

                    10.                    I2C_BOARD_INFO("ds3231m", 0x68),

                    11.                    .platform_data = NULL,

                    12.            },

                    13.    #endif

                    14.    #ifdef CONFIG_RTC_DRV_PCF8563

                    15.            {

                    16.                    I2C_BOARD_INFO("pcf8563", 0x51),

                    17.                    .platform_data = NULL,

                    18.            },

                    19.    #endif

                    20.    };

                    21.    static int __init gsc3280_i2c_devices_init(void)

                    22.    {

                    23.        i2c_register_board_info(0, i2c_devices_info, ARRAY_SIZE(i2c_devices_info));

                    24.        return 0;

                    25.    }

                    26.    device_initcall(gsc3280_i2c_devices_init);


                    在这里总共有三个I2C设备,名称分别为alc5623、ds3231m和pcf8563。宏I2C_BOARD_INFO的功能就是设置I2C设备的名称和地址,由device_initcall可以看出,gsc3280_i2c_devices_init()函数在系统启动的时候就会被调用,i2c_register_board_info()函数完成板级设备的注册,程序如下:

                    1.     DECLARE_RWSEM(__i2c_board_lock);

                    2.     EXPORT_SYMBOL_GPL(__i2c_board_lock);

                    3.      

                    4.     LIST_HEAD(__i2c_board_list);

                    5.     EXPORT_SYMBOL_GPL(__i2c_board_list);

                    6.      

                    7.     int __i2c_first_dynamic_bus_num;

                    8.     EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);

                    9.      

                    10.    int __init

                    11.    i2c_register_board_info(int busnum,

                    12.        struct i2c_board_info const *info, unsigned len)

                    13.    {

                    14.        int status;

                    15.        down_write(&__i2c_board_lock);

                    16.        /* dynamic bus numbers will be assigned after the last static one */

                    17.        if (busnum >= __i2c_first_dynamic_bus_num)

                    18.            __i2c_first_dynamic_bus_num = busnum + 1;

                    19.        for (status = 0; len; len--, info++) {

                    20.            struct i2c_devinfo    *devinfo;

                    21.            devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);

                    22.            if (!devinfo) {

                    23.                pr_debug("i2c-core: can't register boardinfo!\n");

                    24.                status = -ENOMEM;

                    25.                break;

                    26.            }

                    27.            devinfo->busnum = busnum;

                    28.            devinfo->board_info = *info;

                    29.            list_add_tail(&devinfo->list, &__i2c_board_list);

                    30.        }

                    31.        up_write(&__i2c_board_lock);

                    32.        return status;

                    33.    }


                    上面的程序位于i2c-boardinfo.c中,i2c_register_board_info()函数的for循环中,首先会申请I2C设备信息结构体,如果申请成功,将I2C总线号和设备信息赋值给设备信息结构体,并且将设备信息结构体的链表插入到__i2c_board_list中,此处尤为重要,在本文的开头中所提的函数i2c_scan_static_board_info(adap);,此函数就是通过__i2c_board_list链表找到上面注册的设备信息,结合gsc3280_i2c_devices_init()函数和i2c_devices_info结构体,此处for循环的len为3,即正常情况下需要创建三个devinfo结构体,for循环结束后,__i2c_board_list链表中也就有了三个I2C设备的链表项,在程序的其他地方如果需要使用这里注册的设备结构信息,只需要遍历链表__i2c_board_list,通过总线号即可找到相应的设备信息。

                    接下来就可以看下函数i2c_scan_static_board_info(adap):

                    1.   static void i2c_scan_static_board_info(struct i2c_adapter *adapter)

                    2.   {

                    3.       struct i2c_devinfo    *devinfo;

                    4.       down_read(&__i2c_board_lock);

                    5.       list_for_each_entry(devinfo, &__i2c_board_list, list) {

                    6.           if (devinfo->busnum == adapter->nr

                    7.                   && !i2c_new_device(adapter,

                    8.                           &devinfo->board_info))

                    9.               dev_err(&adapter->dev,

                    10.                  "Can't create device at 0x%02x\n",

                    11.                  devinfo->board_info.addr);

                    12.      }

                    13.      up_read(&__i2c_board_lock);

                    14.  }


                    从上面程序可以看到,语句list_for_each_entry(devinfo, &__i2c_board_list, list) 实现对__i2c_board_list的遍历,if语句的前半部分“devinfo->busnum ==adapter->nr”判断是否是需要寻找的结构体,如果是,就调用函数i2c_new_device()创建新的I2C设备,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.       client = kzalloc(sizeof *client, GFP_KERNEL);

                    7.       if (!client)

                    8.           return NULL;

                    9.       client->adapter = adap;

                    10.      client->dev.platform_data = info->platform_data;

                    11.      if (info->archdata)

                    12.          client->dev.archdata = *info->archdata;

                    13.      client->flags = info->flags;

                    14.      client->addr = info->addr;

                    15.      client->irq = info->irq;

                    16.      strlcpy(client->name, info->type, sizeof(client->name));

                    17.      /* Check for address validity */

                    18.      status = i2c_check_client_addr_validity(client);

                    19.      if (status) {

                    20.          dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",

                    21.              client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);

                    22.          goto out_err_silent;

                    23.      }

                    24.      /* Check for address business */

                    25.      status = i2c_check_addr_busy(adap, client->addr);

                    26.      if (status)

                    27.          goto out_err;

                    28.      client->dev.parent = &client->adapter->dev;

                    29.      client->dev.bus = &i2c_bus_type;

                    30.      client->dev.type = &i2c_client_type;

                    31.      client->dev.of_node = info->of_node;

                    32.      dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),

                    33.           client->addr);

                    34.      status = device_register(&client->dev);

                    35.      if (status)

                    36.          goto out_err;

                    37.      dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",

                    38.          client->name, dev_name(&client->dev));

                    39.      return client;

                    40.  out_err:

                    41.      dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "

                    42.          "(%d)\n", client->name, client->addr, status);

                    43.  out_err_silent:

                    44.      kfree(client);

                    45.      return NULL;

                    46.  }

                    47.  EXPORT_SYMBOL_GPL(i2c_new_device);


                    从函数i2c_new_device()中可以看到,此函数创建了i2c_client结构体,对结构体的内容进行了注册,设备信息进行了填充,对于本文所使用的开发板,如果程序执行正常,系统启动成功后,在内存中就有了三个

                    i2c_client结构体了,分别对应alc5623、ds3231m和pcf8563。

                    到此位置,I2C总线驱动,I2C设备的注册和相应结构体的申请就已经完成了,接下来看下常用的I2C数据传输函数,I2C设备驱动主要调用这些数据传输接口完成数据的传输。







                    二、I2C数据传输

                    I2C数据传输分为两种,一种为符合I2C协议的普通数据传输,另外一种为符合SMBUS协议的数据传输,接下来我们首先看下符合I2C协议的普通数据传输。

                    1、I2C协议的普通数据传输

                    I2C协议普通数据传输的接口函数基本为i2c_master_send和i2c_master_recv,查看其函数发现,最后都是调用i2c_transfer函数实现传输的,i2c_transfer函数如下:

                    1.     int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)

                    2.     {

                    3.         int ret;

                    4.         if (adap->algo->master_xfer) {

                    5.     #ifdef DEBUG

                    6.             for (ret = 0; ret < num; ret++) {

                    7.                 dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "

                    8.                     "len=%d%s/n", ret, (msgs[ret].flags & I2C_M_RD)

                    9.                     ? 'R' : 'W', msgs[ret].addr, msgs[ret].len,

                    10.                    (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : "");

                    11.            }

                    12.    #endif

                    13.            if (in_atomic() || irqs_disabled()) {

                    14.                ret = mutex_trylock(&adap->bus_lock);

                    15.                if (!ret)

                    16.                    /* I2C activity is ongoing. */

                    17.                    return -EAGAIN;

                    18.            } else {

                    19.                mutex_lock_nested(&adap->bus_lock, adap->level);

                    20.            }

                    21.            ret = adap->algo->master_xfer(adap,msgs,num);

                    22.            mutex_unlock(&adap->bus_lock);

                    23.            return ret;

                    24.        } else {

                    25.            dev_dbg(&adap->dev, "I2C level transfers not supported/n");

                    26.            return -ENOSYS;

                    27.        }

                    28.    }


                    因为在这里的同步用的是mutex。首先判断是否允许睡眠,如果不允许,尝试获锁,如果获锁失败,则返回。这样的操作是避免进入睡眠,我们在后面也可以看到,实际的传输工作交给了adap->algo->master_xfer()完成,也就是我们在(一)中注册的algorithm中的i2c_gsc_func函数。


                    2、SMBUS协议I2C数据传输

                    SMBUS协议的具体内容可以参考网络,在I2C驱动中,符合SMBUS协议传输的函数很多,包括i2c_smbus_read_byte、i2c_smbus_write_byte、i2c_smbus_read_byte_data、i2c_smbus_write_byte_data、i2c_smbus_read_word_data和i2c_smbus_write_word_data等,阅读这些函数发现,程序里面都是根据SMBUS协议和函数功能,完成对函数i2c_smbus_xfer形参的赋值,最后调用此函数来实现传输。接下来看下i2c_smbus_xfer函数:

                    1.   s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,

                    2.            char read_write, u8 command, int protocol,

                    3.            union i2c_smbus_data *data)

                    4.   {

                    5.       unsigned long orig_jiffies;

                    6.       int try;

                    7.       s32 res;

                    8.       flags &= I2C_M_TEN | I2C_CLIENT_PEC;

                    9.       if (adapter->algo->smbus_xfer) {

                    10.          i2c_lock_adapter(adapter);

                    11.          /* Retry automatically on arbitration loss */

                    12.          orig_jiffies = jiffies;

                    13.          for (res = 0, try = 0; try <= adapter->retries; try++) {

                    14.              res = adapter->algo->smbus_xfer(adapter, addr, flags,

                    15.                              read_write, command,

                    16.                              protocol, data);

                    17.              if (res != -EAGAIN)

                    18.                  break;

                    19.              if (time_after(jiffies,

                    20.                   orig_jiffies + adapter->timeout))

                    21.                  break;

                    22.          }

                    23.          i2c_unlock_adapter(adapter);

                    24.      } else

                    25.          res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,

                    26.                       command, protocol, data);

                    27.      return res;

                    28.  }


                    如果adapter有smbus_xfer()函数,则直接调用它发送数据。否则也就是在adapter不支持smbus协议的情况下,调用i2c_smbus_xfer_emulated()继续处理。根据(一)中的总线驱动是不支持smbus协议的。继续看函数i2c_smbus_xfer_emulated。

                    1.    static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,

                    2.                                      unsigned short flags,

                    3.                                      char read_write, u8 command, int size,

                    4.                                      union i2c_smbus_data * data)

                    5.    {

                    6.        /* So we need to generate a series of msgs. In the case of writing, we

                    7.          need to use only one message; when reading, we need two. We initialize

                    8.          most things with sane defaults, to keep the code below somewhat

                    9.          simpler. */

                    10.      //写操作只会进行一次交互,而读操作,有时会有两次操作.

                    11.      //因为有时候读操作要先写command,再从总线上读数据

                    12.      //在这里为了代码的简洁,使用了两个缓存区,将两种情况统一起来.

                    13.      unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];

                    14.      unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];

                    15.      //一般来说,读操作要交互两次,例外的情况我们在下面会接着分析

                    16.      int num = read_write == I2C_SMBUS_READ?2:1;

                    17.      //与设备交互的数据,一般在msg[0]存放写入设备的信息,在msb[1]里存放接收到的

                    18.      //信息,不过也有例外的

                    19.      //msg[2]的初始化,默认发送缓存区占一个字节,无接收缓存

                    20.      struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },

                    21.                                { addr, flags | I2C_M_RD, 0, msgbuf1 }

                    22.                              };

                    23.      int i;

                    24.      u8 partial_pec = 0;

                    25.      //将要发送的信息copy到发送缓存区的第一字节

                    26.      msgbuf0[0] = command;

                    27.      switch(size) {

                    28.          //quick类型,它并不传输有效数据,只是将地址写到总线上,等待应答即可

                    29.          //所以将发送缓存区长度置为0。再根据读/写操作,调整msg[0]的标志位

                    30.          //这类传输只需要一次总线交互

                    31.      case I2C_SMBUS_QUICK:

                    32.          msg[0].len = 0;

                    33.          /* Special case: The read/write field is used as data */

                    34.          msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0;

                    35.          num = 1;

                    36.          break;

                    37.      case I2C_SMBUS_BYTE:

                    38.          //BYTE类型指一次写和读只有一个字节.这种情况下,读和写都只会交互一次

                    39.          //这种类型的读有例外,它读取出来的数据不是放在msg[1]中的,而是存放在msg[0]

                    40.          if (read_write == I2C_SMBUS_READ) {

                    41.              /* Special case: only a */

                    42.              msg[0].flags = I2C_M_RD | flags;

                    43.              num = 1;

                    44.          }

                    45.          break;

                    46.      case I2C_SMBUS_BYTE_DATA:

                    47.          //Byte_Data是指命令+数据的传输形式,在这种情况下,写只需要一次交互,读却要两次

                    48.          //第一次将command写到总线上,第二次要转换方向,要将设备地址和read标志写入总线.

                    49.          //应回答之后再进行read操作

                    50.          //写操作占两字节,分别是command+data,读操作的有效数据只有一个字节

                    51.          //交互次数用初始化值就可以了

                    52.          if (read_write == I2C_SMBUS_READ)

                    53.              msg[1].len = 1;

                    54.          else {

                    55.              msg[0].len = 2;

                    56.              msgbuf0[1] = data->byte;

                    57.          }

                    58.          break;

                    59.      case I2C_SMBUS_WORD_DATA:

                    60.          //Word_Data是指命令+双字节的形式.这种情况跟Byte_Data的情况类似

                    61.          //两者相比只是交互的数据大小不同

                    62.          if (read_write == I2C_SMBUS_READ)

                    63.              msg[1].len = 2;

                    64.          else {

                    65.              msg[0].len=3;

                    66.              msgbuf0[1] = data->word & 0xff;

                    67.              msgbuf0[2] = data->word >> 8;

                    68.          }

                    69.          break;

                    70.      case I2C_SMBUS_PROC_CALL:

                    71.          //Proc_Call的方式与write 的Word_Data相似,只不过写完Word_Data之后,要等待它的应答

                    72.          //应该它需要交互两次,一次写一次读

                    73.          num = 2; /* Special case */

                    74.          read_write = I2C_SMBUS_READ;

                    75.          msg[0].len = 3;

                    76.          msg[1].len = 2;

                    77.          msgbuf0[1] = data->word & 0xff;

                    78.          msgbuf0[2] = data->word >> 8;

                    79.          break;

                    80.      case I2C_SMBUS_BLOCK_DATA:

                    81.          //Block_Data:指command+N段数据的情况.

                    82.          //如果是读操作,它首先要写command到总线,然后再读N段数据,要写的command已经

                    83.          //放在msg[0]了,现在只需要将msg[1]的标志置I2C_M_RECV_LEN位,msg[1]有效长度为1字节,因为

                    84.          //adapter驱动会处理好的,现在还不知道要传多少段数据.

                    85.          //对于写的情况:msg[1]照例不需要.将要写的数据全部都放到msb[0]中.相应的也要更新

                    86.          //msg[0]中的缓存区长度

                    87.          if (read_write == I2C_SMBUS_READ) {

                    88.              msg[1].flags |= I2C_M_RECV_LEN;

                    89.              msg[1].len = 1; /* block length will be added by

                    90.                        the underlying bus driver */

                    91.          } else {

                    92.              //data->block[0]表示后面有多少段数据.总长度要加2是因为command+count+N段数据

                    93.              msg[0].len = data->block[0] + 2;

                    94.              if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {

                    95.                  dev_err(&adapter->dev, "smbus_access called with "

                    96.                        "invalid block write size (%d)/n",

                    97.                        data->block[0]);

                    98.                  return -1;

                    99.              }

                    100.            for (i = 1; i < msg[0].len; i++)

                    101.                msgbuf0 = data->block[i-1];

                    102.        }

                    103.        break;

                    104.    case I2C_SMBUS_BLOCK_PROC_CALL:

                    105.        //Proc_Call:表示写完Block_Data之后,要等它的应答消息它和Block_Data相比,只是多了一部份应答而已

                    106.        num = 2; /* Another special case */

                    107.        read_write = I2C_SMBUS_READ;

                    108.        if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {

                    109.            dev_err(&adapter->dev, "%s called with invalid "

                    110.                "block proc call size (%d)/n", __func__,

                    111.                data->block[0]);

                    112.            return -1;

                    113.        }

                    114.        msg[0].len = data->block[0] + 2;

                    115.        for (i = 1; i < msg[0].len; i++)

                    116.            msgbuf0 = data->block[i-1];

                    117.        msg[1].flags |= I2C_M_RECV_LEN;

                    118.        msg[1].len = 1; /* block length will be added by

                    119.                  the underlying bus driver */

                    120.        break;

                    121.    case I2C_SMBUS_I2C_BLOCK_DATA:

                    122.        //I2c Block_Data与Block_Data相似,只不过read的时候,数据长度是预先定义好了的.另外

                    123.        //与Block_Data相比,中间不需要传输Count字段.(Count表示数据段数目)

                    124.        if (read_write == I2C_SMBUS_READ) {

                    125.            msg[1].len = data->block[0];

                    126.        } else {

                    127.            msg[0].len = data->block[0] + 1;

                    128.            if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {

                    129.                dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "

                    130.                      "invalid block write size (%d)/n",

                    131.                      data->block[0]);

                    132.                return -1;

                    133.            }

                    134.            for (i = 1; i <= data->block[0]; i++)

                    135.                msgbuf0 = data->block;

                    136.        }

                    137.        break;

                    138.    default:

                    139.        dev_err(&adapter->dev, "smbus_access called with invalid size (%d)/n",

                    140.              size);

                    141.        return -1;

                    142.    }

                    143.    //如果启用了PEC.Quick和I2c Block_Data是不支持PEC的

                    144.    i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK

                    145.                      && size != I2C_SMBUS_I2C_BLOCK_DATA);

                    146.    if (i) {

                    147.        /* Compute PEC if first message is a write */

                    148.        //如果第一个操作是写操作

                    149.        if (!(msg[0].flags & I2C_M_RD)) {

                    150.            //如果只是写操作

                    151.            if (num == 1) /* Write only */

                    152.                //如果只有写操作,写缓存区要扩充一个字节,用来存放计算出来的PEC

                    153.                i2c_smbus_add_pec(&msg[0]);

                    154.            else /* Write followed by read */

                    155.                //如果后面还有读操作,先计算前面写部份的PEC(注意这种情况下不需要

                    156.                //扩充写缓存区,因为不需要发送PEC.只会接收到PEC)

                    157.                partial_pec = i2c_smbus_msg_pec(0, &msg[0]);

                    158.        }

                    159.        /* Ask for PEC if last message is a read */

                    160.        //如果最后一次是读消息.还要接收到来自slave的PEC.所以接收缓存区要扩充一个字节

                    161.        if (msg[num-1].flags & I2C_M_RD)

                    162.            msg[num-1].len++;

                    163.    }

                    164.    if (i2c_transfer(adapter, msg, num) < 0)

                    165.        return -1;

                    166.    /* Check PEC if last message is a read */

                    167.    //操作完了之后,如果最后一个操作是PEC的读操作.检验后面的PEC是否正确

                    168.    if (i && (msg[num-1].flags & I2C_M_RD)) {

                    169.        if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)

                    170.            return -1;

                    171.    }

                    172.    //操作完了,现在可以将数据放到data部份返回了.

                    173.    if (read_write == I2C_SMBUS_READ)

                    174.        switch(size) {

                    175.            case I2C_SMBUS_BYTE:

                    176.                data->byte = msgbuf0[0];

                    177.                break;

                    178.            case I2C_SMBUS_BYTE_DATA:

                    179.                data->byte = msgbuf1[0];

                    180.                break;

                    181.            case I2C_SMBUS_WORD_DATA:

                    182.            case I2C_SMBUS_PROC_CALL:

                    183.                data->word = msgbuf1[0] | (msgbuf1[1] << 8);

                    184.                break;

                    185.            case I2C_SMBUS_I2C_BLOCK_DATA:

                    186.                for (i = 0; i < data->block[0]; i++)

                    187.                    data->block[i+1] = msgbuf1;

                    188.                break;

                    189.            case I2C_SMBUS_BLOCK_DATA:

                    190.            case I2C_SMBUS_BLOCK_PROC_CALL:

                    191.                for (i = 0; i < msgbuf1[0] + 1; i++)

                    192.                    data->block = msgbuf1;

                    193.                break;

                    194.        }

                    195.    return 0;

                    196.}


                    此处也是调用i2c_transfer函数实现数据的最终传输的,在上面已经讲述了此函数。







                    原文请参见:http://blog.chinaunix.net/uid-25445243-id-3916323.html




















                     
                    彩神ll【中国】股份有限公司