这个结构专门用于数据传输相关的addr为I2C设备地址,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函数去重新构造设备地址字节,来看这个函数。
- static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
- {
- unsigned short flags = msg->flags;
- unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
- struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-
- unsigned char addr;
- int ret, retries;
-
- retries = nak_ok ? 0 : i2c_adap->retries;
-
- if (flags & I2C_M_TEN) {
- /* a ten bit address */
- addr = 0xf0 | ((msg->addr >> 7) & 0x03);
- bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
- /* try extended address code...*/
- ret = try_address(i2c_adap, addr, retries);
- if ((ret != 1) && !nak_ok) {
- dev_err(&i2c_adap->dev,
- "died at extended address code\n");
- return -EREMOTEIO;
- }
- /* the remaining 8 bit address */
- ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
- if ((ret != 1) && !nak_ok) {
- /* the chip did not ack / xmission error occurred */
- dev_err(&i2c_adap->dev, "died at 2nd address code\n");
- return -EREMOTEIO;
- }
- if (flags & I2C_M_RD) {
- bit_dbg(3, &i2c_adap->dev, "emitting repeated "
- "start condition\n");
- i2c_repstart(adap);
- /* okay, now switch into reading mode */
- addr |= 0x01;
- ret = try_address(i2c_adap, addr, retries);
- if ((ret != 1) && !nak_ok) {
- dev_err(&i2c_adap->dev,
- "died at repeated address code\n");
- return -EREMOTEIO;
- }
- }
- } else { /* normal 7bit address */
- addr = msg->addr << 1;
- if (flags & I2C_M_RD)
- addr |= 1;
- if (flags & I2C_M_REV_DIR_ADDR)
- addr ^= 1;
- ret = try_address(i2c_adap, addr, retries);
- if ((ret != 1) && !nak_ok)
- return -ENXIO;
- }
-
- return 0;
- }
这里先做了一个判断,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. static int try_address(struct i2c_adapter *i2c_adap,
-
2. unsigned char addr, int retries)
-
3. {
-
4. struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-
5. int i, ret = 0;
-
6.
-
7. for (i = 0; i <= retries; i++) {
-
8. ret = i2c_outb(i2c_adap, addr);
-
9. if (ret == 1 || i == retries)
-
10. break;
-
11. bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
-
12. i2c_stop(adap);
-
13. udelay(adap->udelay);
-
14. yield();
-
15. bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
-
16. i2c_start(adap);
-
17. }
-
18. if (i && ret)
-
19. bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
-
20. "0x%02x: %s\n", i + 1,
-
21. addr & 1 ? "read from" : "write to", addr >> 1,
-
22. ret == 1 ? "success" : "failed, timeout?");
-
23. return ret;
-
24. }
最主要的就是调用i2c_outb发送一个字节,retries为重复次数,看前面adap->retries=
3;
如果发送失败,也就是设备没有给出应答信号,那就发送停止信号,发送起始信号,再发送这个地址字节,这就叫retries。来看这个具体的i2c_outb函数
-
1. static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
-
2. {
-
3. int i;
-
4. int sb;
-
5. int ack;
-
6. struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-
7.
-
8. /* assert: scl is low */
-
9. for (i = 7; i >= 0; i--) {
-
10. sb = (c >> i) & 1;
-
11. setsda(adap, sb);
-
12. udelay((adap->udelay + 1) / 2);
-
13. if (sclhi(adap) < 0) { /* timed out */
-
14. bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
-
15. "timeout at bit #%d\n", (int)c, i);
-
16. return -ETIMEDOUT;
-
17. }
-
18. /* FIXME do arbitration here:
-
19. * if (sb && !getsda(adap)) -> ouch! Get out of here.
-
20. *
-
21. * Report a unique code, so higher level code can retry
-
22. * the whole (combined) message and *NOT* issue STOP.
-
23. */
-
24. scllo(adap);
-
25. }
-
26. sdahi(adap);
-
27. if (sclhi(adap) < 0) { /* timeout */
-
28. bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
-
29. "timeout at ack\n", (int)c);
-
30. return -ETIMEDOUT;
-
31. }
-
32.
-
33. /* read ack: SDA should be pulled down by slave, or it may
-
34. * NAK (usually to report problems with the data we wrote).
-
35. */
-
36. ack = !getsda(adap); /* ack: sda is pulled low -> success */
-
37. bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
-
38. ack ? "A" : "NA");
-
39.
-
40. scllo(adap);
-
41. return ack;
-
42. /* assert: scl is low (sda undef) */
-
43. }
这个函数有两个参数,一个是structi2c_adapter代表I2C主机,一个是发送的字节数据。那么I2C是怎样将一个字节数据发送出去的呢,那再来看看协议。
首先是发送字节数据的最高位,在时钟为高电平期间将一位数据发送出去,最后是发送字节数据的最低位。发送完成之后,我们需要一个ACK信号,要不然我怎么知道发送成功没有,ACK信号就是在第九个时钟周期时数据线为低,所以在一个字节数据传送完成后,还要将数据线拉高,我们看程序中就是这一句sdahi(adap);等待这个ACK信号的到来,这样一个字节数据就发送完成。
回到bit_xfer函数中,前面只是将设备地址字节发送出去了,那么接下来就是该发送数据了。
注意:这里的数据包括操作设备的基地址
如果是读则调用readbytes函数去读,如果是写则调用sendbytes去写,先看readbytes函数
-
1. static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
-
2. {
-
3. int inval;
-
4. int rdcount = 0; /* counts bytes read */
-
5. unsigned char *temp = msg->buf;
-
6. int count = msg->len;
-
7. const unsigned flags = msg->flags;
-
8.
-
9. while (count > 0) {
-
10. inval = i2c_inb(i2c_adap);
-
11. if (inval >= 0) {
-
12. *temp = inval;
-
13. rdcount++;
-
14. } else { /* read timed out */
-
15. break;
-
16. }
-
17.
-
18. temp++;
-
19. count--;
-
20.
-
21. /* Some SMBus transactions require that we receive the
-
22. transaction length as the first read byte. */
-
23. if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) {
-
24. if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
-
25. if (!(flags & I2C_M_NO_RD_ACK))
-
26. acknak(i2c_adap, 0);
-
27. dev_err(&i2c_adap->dev, "readbytes: invalid "
-
28. "block length (%d)\n", inval);
-
29. return -EREMOTEIO;
-
30. }
-
31. /* The original count value accounts for the extra
-
32. bytes, that is, either 1 for a regular transaction,
-
33. or 2 for a PEC transaction. */
-
34. count += inval;
-
35. msg->len += inval;
-
36. }
-
37.
-
38. bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n",
-
39. inval,
-
40. (flags & I2C_M_NO_RD_ACK)
-
41. ? "(no ack/nak)"
-
42. : (count ? "A" : "NA"));
-
43.
-
44. if (!(flags & I2C_M_NO_RD_ACK)) {
-
45. inval = acknak(i2c_adap, count);
-
46. if (inval < 0)
-
47. return inval;
-
48. }
-
49. }
-
50. return rdcount;
-
51. }
其中一个大的while循环,调用i2c_inb去读一个字节,count为数据的长度,单位为多少个字节,
那就来看i2c_inb函数。
- static int i2c_inb(struct i2c_adapter *i2c_adap)
- {
- /* read byte via i2c port, without start/stop sequence */
- /* acknowledge is sent in i2c_read. */
- int i;
- unsigned char indata = 0;
- struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-
- /* assert: scl is low */
- sdahi(adap);
- for (i = 0; i < 8; i++) {
- if (sclhi(adap) < 0) { /* timeout */
- bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
- "#%d\n", 7 - i);
- return -ETIMEDOUT;
- }
- indata *= 2;
- if (getsda(adap))
- indata |= 0x01;
- setscl(adap, 0);
- udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
- }
- /* assert: scl is low */
- return indata;
- }
再来看sendbytes函数
-
1. static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
-
2. {
-
3. const unsigned char *temp = msg->buf;
-
4. int count = msg->len;
-
5. unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
-
6. int retval;
-
7. int wrcount = 0;
-
8.
-
9. while (count > 0) {
-
10. retval = i2c_outb(i2c_adap, *temp);
-
11.
-
12. /* OK/ACK; or ignored NAK */
-
13. if ((retval > 0) || (nak_ok && (retval == 0))) {
-
14. count--;
-
15. temp++;
-
16. wrcount++;
-
17.
-
18. /* A slave NAKing the master means the slave didn't like
-
19. * something about the data it saw. For example, maybe
-
20. * the SMBus PEC was wrong.
-
21. */
-
22. } else if (retval == 0) {
-
23. dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n");
-
24. return -EIO;
-
25.
-
26. /* Timeout; or (someday) lost arbitration
-
27. *
-
28. * FIXME Lost ARB implies retrying the transaction from
-
29. * the first message, after the "winning" master issues
-
30. * its STOP. As a rule, upper layer code has no reason
-
31. * to know or care about this ... it is *NOT* an error.
-
32. */
-
33. } else {
-
34. dev_err(&i2c_adap->dev, "sendbytes: error %d\n",
-
35. retval);
-
36. return retval;
-
37. }
-
38. }
-
39. return wrcount;
-
40. }
也是一个大的while循环,同发送地址字节一样,也是调用i2c_outb去发送一个字节,count也是数据长度,由于i2c_outb函数在前面发送设备地址那里已经介绍了,这里也就不贴出来了。
还是回到bit_xfer函数,数据传输完成后,调用i2c_stop函数发送停止信号。我们看停止信号函数怎么去实现的。
-
1. static void i2c_stop(struct i2c_algo_bit_data *adap)
-
2. {
-
3. /* assert: scl is low */
-
4. sdalo(adap);
-
5. sclhi(adap);
-
6. setsda(adap, 1);
-
7. udelay(adap->udelay);
-
8. }
看前面发送起始信号的那张图,停止信号就是在时钟为高电平期间,数据线从低到高的跳变。我们看程序是先将数据线拉低,将时钟线拉高,最后将数据拉高,这样就够成了一个停止信号。
还是回到i2c_bit_add_numbered_bus这个函数中来,看另外一个函数调用i2c_add_numbered_adapter。
-
1. int i2c_add_numbered_adapter(struct i2c_adapter *adap)
-
2. {
-
3. int id;
-
4. int status;
-
5.
-
6. if (adap->nr & ~MAX_ID_MASK)
-
7. return -EINVAL;
-
8.
-
9. retry:
-
10. if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
-
11. return -ENOMEM;
-
12.
-
13. mutex_lock(&core_lock);
-
14. /* "above" here means "above or equal to", sigh;
-
15. * we need the "equal to" result to force the result
-
16. */
-
17. status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
-
18. if (status == 0 && id != adap->nr) {
-
19. status = -EBUSY;
-
20. idr_remove(&i2c_adapter_idr, id);
-
21. }
-
22. mutex_unlock(&core_lock);
-
23. if (status == -EAGAIN)
-
24. goto retry;
-
25.
-
26. if (status == 0)
-
27. status = i2c_register_adapter(adap);
-
28. return status;
-
29. }
最重要的是这句i2c_register_adapter,注册这条I2C总线,进去看看
- static int i2c_register_adapter(struct i2c_adapter *adap)
- {
- int res = 0, dummy;
-
- /* Can't register until after driver model init */
- if (unlikely(WARN_ON(!i2c_bus_type.p))) {
- res = -EAGAIN;
- goto out_list;
- }
-
- mutex_init(&adap->bus_lock);
-
- /* Set default timeout to 1 second if not already set */
- if (adap->timeout == 0)
- adap->timeout = HZ;
-
- dev_set_name(&adap->dev, "i2c-%d", adap->nr);
- adap->dev.bus = &i2c_bus_type;
- adap->dev.type = &i2c_adapter_type;
- res = device_register(&adap->dev);
- if (res)
- goto out_list;
-
- dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
-
- #ifdef CONFIG_I2C_COMPAT
- res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
- adap->dev.parent);
- if (res)
- dev_warn(&adap->dev,
- "Failed to create compatibility class link\n");
- #endif
-
- /* create pre-declared device nodes */
- if (adap->nr < __i2c_first_dynamic_bus_num)
- i2c_scan_static_board_info(adap);
-
- /* Notify drivers */
- mutex_lock(&core_lock);
- dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
- i2c_do_add_adapter);
- mutex_unlock(&core_lock);
-
- return 0;
-
- out_list:
- mutex_lock(&core_lock);
- idr_remove(&i2c_adapter_idr, adap->nr);
- mutex_unlock(&core_lock);
- return res;
- }
看内核代码有时就会这样,会陷入内核代码的汪洋大海中,而拔不出来,直接后果是最后都忘记看这段代码的目的,丧失继续看下去的信心。所以为了避免这样情况出现,所以最好在开始看代码的时候要明确目标,我通过这段代码到底要了解什么东西,主干要抓住,其它枝叶就不要看了。
在这里我认为主要的有
1.注册这个I2C总线设备
-
1. adap->dev.bus = &i2c_bus_type;
-
2. adap->dev.type = &i2c_adapter_type;
-
3. res = device_register(&adap->dev);
这个设备的总线类型为i2c_bus_type
-
1. struct bus_type i2c_bus_type = {
-
2. .name = "i2c",
-
3. .match = i2c_device_match,
-
4. .probe = i2c_device_probe,
-
5. .remove = i2c_device_remove,
-
6. .shutdown = i2c_device_shutdown,
-
7. .suspend = i2c_device_suspend,
-
8. .resume = i2c_device_resume,
-
9. };
看一下它的match函数
-
1. static int i2c_device_match(struct device *dev, struct device_driver *drv)
-
2. {
-
3. struct i2c_client *client = i2c_verify_client(dev);
-
4. struct i2c_driver *driver;
-
5.
-
6. if (!client)
-
7. return 0;
-
8.
-
9. driver = to_i2c_driver(drv);
-
10. /* match on an id table if there is one */
-
11. if (driver->id_table)
-
12. return i2c_match_id(driver->id_table, client) != NULL;
-
13.
-
14. return 0;
-
15. }
这个match函数主要用来匹配我们的I2C设备和I2C驱动的,如果匹配成功,最后会调用驱动的probe函数,来看它如何匹配的。
-
1. static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
-
2. const struct i2c_client *client)
-
3. {
-
4. while (id->name[0]) {
-
5. if (strcmp(client->name, id->name) == 0)
-
6. return id;
-
7. id++;
-
8. }
-
9. return NULL;
-
0. }
就是判断I2C设备的name字段和驱动中id_table中定义的name字段是否相等。
-
1. static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
-
2. {
-
3. struct i2c_devinfo *devinfo;
-
4.
-
5. down_read(&__i2c_board_lock);
-
6. list_for_each_entry(devinfo, &__i2c_board_list, list) {
-
7. if (devinfo->busnum == adapter->nr
-
8. && !i2c_new_device(adapter,
-
9. &devinfo->board_info))
-
10. dev_err(&adapter->dev,
-
11. "Can't create device at 0x%02x\n",
-
12. devinfo->board_info.addr);
-
13. }
-
14. up_read(&__i2c_board_lock);
-
15. }
遍历__i2c_board_list这条链表,看下面的if语句,首先要让struct i2c_devinfo结构中的busnum等于struct
i2c_adapter中的nr,我们前面也说了,这个nr就是i2c总线的总线号,这里可以理解为是在往这条总线上添加设备。所以,如果我们要向I2C注册一个I2C设备的话,直接向__i2c_board_list添加一个设备信息就可以了,先来看这个设备信息结构是怎么定义的。
-
1. struct i2c_board_info {
-
2. char type[I2C_NAME_SIZE];
-
3. unsigned short flags;
-
4. unsigned short addr;
-
5. void *platform_data;
-
6. struct dev_archdata *archdata;
-
7. int irq;
-
8. };
定义这样一个信息呢一般使用一个宏I2C_BOARD_INFO
-
# #define I2C_BOARD_INFO(dev_type, dev_addr) \
-
# .type = dev_type, .addr = (dev_addr)
-
dev_type为设备的名字,前面也说了,这个name一定要和I2C驱动相同。addr为设备的地址。
-
-
定义了这样一组信息之后呢,接下来当然是往链表添加这些信息了。
-
1. int __init
-
2. i2c_register_board_info(int busnum,
-
3. struct i2c_board_info const *info, unsigned len)
-
4. {
-
5. int status;
-
6.
-
7. down_write(&__i2c_board_lock);
-
8.
-
9. /* dynamic bus numbers will be assigned after the last static one */
-
10. if (busnum >= __i2c_first_dynamic_bus_num)
-
11. __i2c_first_dynamic_bus_num = busnum + 1;
-
12.
-
13. for (status = 0; len; len--, info++) {
-
14. struct i2c_devinfo *devinfo;
-
15.
-
16. devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
-
17. if (!devinfo) {
-
18. pr_debug("i2c-core: can't register boardinfo!\n");
-
19. status = -ENOMEM;
-
20. break;
-
21. }
-
22.
-
23. devinfo->busnum = busnum;
-
24. devinfo->board_info = *info;
-
25. list_add_tail(&devinfo->list, &__i2c_board_list);
-
26. }
-
27.
-
28. up_write(&__i2c_board_lock);
-
29.
-
30. return status;
-
31. }
第一个参数呢需要注意,它是I2C总线号,一定要和具体的I2C总线对应。我们看又定义了这样一个结构struct i2c_devinfo。
最后是调用list_add_tail往__i2c_board_list这条链表添加设备信息。
然后是i2c_new_device
-
# struct i2c_client *
-
# i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
-
# {
-
# struct i2c_client *client;
-
# int status;
-
#
-
# /*为I2C设备申请内存*/
-
# client = kzalloc(sizeof *client, GFP_KERNEL);
-
# if (!client)
-
# return NULL;
-
#
-
# /*指定I2C设备的总线*/
-
# client->adapter = adap;
-
#
-
# client->dev.platform_data = info->platform_data;
-
#
-
# if (info->archdata)
-
# client->dev.archdata = *info->archdata;
-
#
-
# client->flags = info->flags;
-
# client->addr = info->addr; /*I2C设备地址*/
-
# client->irq = info->irq;
-
#
-
# strlcpy(client->name, info->type, sizeof(client->name));
-
#
-
# /*检查这个地址有没有被设备占用*/
-
# /* Check for address business */
-
# status = i2c_check_addr(adap, client->addr);
-
# if (status)
-
# goto out_err;
-
#
-
# client->dev.parent = &client->adapter->dev; /*指定设备的父设备*/
-
# client->dev.bus = &i2c_bus_type; /*指定设备的总线类型*/
-
# client->dev.type = &i2c_client_type;
-
#
-
# dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
-
# client->addr);
-
# status = device_register(&client->dev); /*注册设备*/
-
# if (status)
-
# goto out_err;
-
#
-
# dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
-
# client->name, dev_name(&client->dev));
-
#
-
# return client;
-
#
-
# out_err:
-
# dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "
-
# "(%d)\n", client->name, client->addr, status);
-
# kfree(client);
-
# return NULL;
这个函数的功能是新建一个I2C设备并注册它,在I2C子系统中,I2C设备使用结构structi2c_client描述,那么首先要申请内存空间,I2C设备的主机是谁,必须知道挂载到哪条总线上的,然后就是一些赋值操作,最后就是注册设备,那么这个设备就实实在在的挂在到这条总线上了,这也是新的I2C设备注册方式。
3.i2c_do_add_adapter
你看说着说着就跑远了
-
1. static int i2c_do_add_adapter(struct device_driver *d, void *data)
-
2. {
-
3. struct i2c_driver *driver = to_i2c_driver(d);
-
4. struct i2c_adapter *adap = data;
-
5.
-
6. /* Detect supported devices on that bus, and instantiate them */
-
7. i2c_detect(adap, driver);
-
8.
-
9. /* Let legacy drivers scan this bus for matching devices */
-
10. if (driver->attach_adapter) {
-
11. /* We ignore the return code; if it fails, too bad */
-
12. driver->attach_adapter(adap);
-
13. }
-
14. return 0;
-
15. }
前面通过i2c_scan_static_board_info往I2C总线上添加设备是新的方式,而这里调用每个I2C设备驱动的attach_adapter函数,然后在attach_adapter函数中去实现设备的注册,这是老的方式,i2c-dev.c中就是采用的这种方式。至此,总线这块就看完了。
|