一、linux I2C体系结构
上图中分为用户空间部分、内核空间、硬件。
应用程序是要求实现的应用功能,通过调用系统调用(i2c-dev.c虚拟的I2C设备驱动),内核进行交互。
硬件包括实际的I2C总线和挂接在I2C总线上的设备
内核是描述设备与总线是如何通信的。
举个例子:
假设上层要给设备某地址写值,调用如下
应用层序调用系统函数write>(client)i2cdev_write->(i2c-core.c)i2c_master_send->(适配器)(adap->algo->master_xfer)->(硬件)使I2C产生特定的信号与设备交互
内核的实现:
内核分三大块 1、core 2、适配器管理+总线驱动 3、设备管理+驱动
1、core是核心模块,将适配端与外设相隔离。提供一组不依赖具体硬件的接口函数,实现各种适配器、总线驱动、设备驱动等相同的部分。一种外设可以在不同适配器上使用,一个适配器可以接不同的外设。
具体表现:
1、int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)//接收发送函数
2、int i2c_add_numbered_adapter(struct i2c_adapter *adap)//注册适配器
3、int i2c_del_adapter(struct i2c_adapter *adap)//删除适配器
。。。
2、适配器可以简单理解为cpu上的I2C接口,总线驱动是其工作软件的实现。
3、外设驱动即描述该设备怎么工作。
理解几个结构体:
struct i2c_adapter { struct module *owner; unsigned int id; unsigned int class; /* classes to allow probing for */ const struct i2c_algorithm *algo; /* the algorithm to access the bus */ void *algo_data; //指向某变量或开辟的结构体 /* data fields that are valid for all devices */ struct rt_mutex bus_lock; int timeout; /* in jiffies */ int retries; //重做次数 struct device dev; /* the adapter device */ int nr; //编号 char name[48]; //名称 struct completion dev_released; struct mutex userspace_clients_lock; struct list_head userspace_clients; }; struct i2c_algorithm {//通信方法,产生特定的信号 /* master_xfer should return the number of messages successfully processed, or a negative value on error */ int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);//发送接收函数 。。。 /* To determine what the adapter supports */ u32 (*functionality) (struct i2c_adapter *); 。。。 } struct i2c_driver{ unsigned int class; /* Notifies the driver that a new bus has appeared or is about to be * removed. You should avoid using this if you can, it will probably * be removed in a near future. */ int (*attach_adapter)(struct i2c_adapter *);//attach to a i2c adapter int (*detach_adapter)(struct i2c_adapter *);//deattach an adapter which attached /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); /* driver model interfaces that don't relate to enumeration */ void (*shutdown)(struct i2c_client *); int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*resume)(struct i2c_client *); /* Alert callback, for example for the SMBus alert protocol. * The format and meaning of the data value depends on the protocol. * For the SMBus alert protocol, there is a single bit of data passed * as the alert response's low bit ("event flag"). */ void (*alert)(struct i2c_client *, unsigned int data); /* a ioctl like command that can be used to perform specific functions * with the device. */ int (*command)(struct i2c_client *client, unsigned int cmd, void *arg); struct device_driver driver; const struct i2c_device_id *id_table; /* Device detection callback for automatic device creation */ int (*detect)(struct i2c_client *, struct i2c_board_info *); const unsigned short *address_list; struct list_head clients; }; struct i2c_client {//外设描述 unsigned short flags; /* div., see below */ unsigned short addr; /* chip address - NOTE: 7bit */ /* addresses are stored in the */ /* _LOWER_ 7 bits */ char name[I2C_NAME_SIZE]; struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_driver *driver; /* and our access routines */ struct device dev; /* the device structure */ int irq; /* irq issued by device */ struct list_head detected; }; /*另外再了解一个重要结构体,*/ struct i2c_msg { //通信的基本载体 __u16 addr; /* slave address-器件地址*/ __u16 flags; #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ #define I2C_M_RD 0x0001 /* read data, from slave to master */ #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ __u16 len; /* msg length--描述buf长度*/ __u8 *buf; /* pointer to msg data--指向数据缓存*/ };
现在说明如何构造i2c_msg,现以write为例说明。 msgs[0].addr = address; msgs[0].flags = 0; /* write */ msgs[0].buf = (unsigned char *)data;//包含的数据是上图2段,本例中buf包含两个值:register address+data msgs[0].len = len; //本例中len=2 msgs[0].scl_rate = I2C_RATE; 因此, 1、系统开始时先将7位的地址左移1位,并判断msg为WRITE,所以第8位位0. 2、将地址传输出去,进入中断。在中断函数里判断传输是否正确(比如是否收到ACK信号等) 3、再依次将buf中的值发送,并用len判断是否传输完毕 现在说明如何构造i2c_msg,现以read为例说明。 分两个msg传输: msg0对应上图第一段,是写msg。 msg1对应上图第二段,是读msg。 msgs[0].addr = address;//启动传输时发送 msgs[0].flags = 0; /* write */ msgs[0].buf = reg;//reg表示片内地址 msgs[0].len = 1;//发送长度 msgs[0].scl_rate = SENSOR_I2C_RATE; msgs[1].addr = address;//重新启动后再发送(见上图段2,见下面分析)。 msgs[1].flags = I2C_M_RD;//上图段2,第一字节第8位。 msgs[1].buf = data;//接收缓存 msgs[1].len = len;//接受长度 msgs[1].scl_rate = SENSOR_I2C_RATE
按部分讲解
1、适配器
dev-i2c0.c
struct platform_device s3c_device_i2c0 = { .name = "s3c2410-i2c", #ifdef CONFIG_S3C_DEV_I2C1 .id = 0, #else .id = -1, #endif .num_resources = ARRAY_SIZE(s3c_i2c_resource), .resource = s3c_i2c_resource, }; static struct s3c2410_platform_i2c default_i2c_data0 __initdata = { .flags = 0, .slave_addr = 0x10, .frequency = 100*1000, .sda_delay = 100, }; void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd) { struct s3c2410_platform_i2c *npd; if (!pd) pd = &default_i2c_data0; npd = kmemdup(pd, sizeof(struct s3c2410_platform_i2c), GFP_KERNEL); if (!npd) printk(KERN_ERR "%s: no memory for platform data\n", __func__); else if (!npd->cfg_gpio) npd->cfg_gpio = s3c_i2c0_cfg_gpio;//set GPIO as I2C func s3c_device_i2c0.dev.platform_data = npd;}//作私有变量
mach-mini2440.c //描述板子上的硬件设备信息
static struct i2c_board_info mini2440_i2c_devs[] __initdata = { { I2C_BOARD_INFO("24c08", 0x50), //type=24c08--device name .platform_data = &at24c08, //addr=0x50--device addr }, }; i2c_register_board_info(0, mini2440_i2c_devs, ARRAY_SIZE(mini2440_i2c_devs));//添加i2c外设 。。。 platform_add_devices(&s3c_device_i2c0); 。。。
i2c-s3c2410.c
/* device driver for platform bus bits */ static struct platform_device_id s3c24xx_driver_ids[] = { { .name = "s3c2410-i2c", .driver_data = TYPE_S3C2410, }, { .name = "s3c2440-i2c", .driver_data = TYPE_S3C2440, }, { }, }; static struct platform_driver s3c24xx_i2c_driver = { .probe = s3c24xx_i2c_probe, .remove = s3c24xx_i2c_remove, .id_table = s3c24xx_driver_ids, .driver = { .owner = THIS_MODULE, .name = "s3c-i2c", .pm = S3C24XX_DEV_PM_OPS, }, };
<pre name="code" class="cpp">/*platform_bus_type的match函数*/ static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); struct platform_driver *pdrv = to_platform_driver(drv); /* match against the id table first */ if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0); } static const struct platform_device_id *platform_match_id( struct platform_device_id *id, struct platform_device *pdev) { while (id->name[0]) { /*比较pdev设备名和驱动支持列表*/ if (strcmp(pdev->name, id->name) == 0) { pdev->id_entry = id; return id; } id++; } return NULL; } 由上面可以看出,设备名要在驱动支持列表里头才可以配对 /* s3c24xx_i2c_probe * * called by the bus driver when a suitable device is found */ static int s3c24xx_i2c_probe(struct platform_device *pdev) { struct s3c24xx_i2c *i2c; struct s3c2410_platform_i2c *pdata; struct resource *res; int ret; /*取得私有变量--有时是获得指针,有时是获得变量,这里是获得已经初始化好的变量*/ pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data\n"); return -EINVAL; } i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL); if (!i2c) { dev_err(&pdev->dev, "no memory for state\n"); return -ENOMEM; } /*初始化adapter*/ strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); i2c->adap.owner = THIS_MODULE; i2c->adap.algo = &s3c24xx_i2c_algorithm;//通信方法,当有数据要传输时都会调用该函数 i2c->adap.retries = 2; i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; i2c->tx_setup = 50; spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wait); /* find the clock and enable it */ i2c->dev = &pdev->dev; i2c->clk = clk_get(&pdev->dev, "i2c"); if (IS_ERR(i2c->clk)) { dev_err(&pdev->dev, "cannot get clock\n"); ret = -ENOENT; goto err_noclk; } dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); clk_enable(i2c->clk); /* map the registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "cannot find IO resource\n"); ret = -ENOENT; goto err_clk; } i2c->ioarea = request_mem_region(res->start, resource_size(res), pdev->name); if (i2c->ioarea == NULL) { dev_err(&pdev->dev, "cannot request IO\n"); ret = -ENXIO; goto err_clk; } i2c->regs = ioremap(res->start, resource_size(res)); if (i2c->regs == NULL) { dev_err(&pdev->dev, "cannot map IO\n"); ret = -ENXIO; goto err_ioarea; } dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); /* setup info block for the i2c core */ i2c->adap.algo_data = i2c; i2c->adap.dev.parent = &pdev->dev; /* initialise the i2c controller */ ret = s3c24xx_i2c_init(i2c);//初始化i2c频率 if (ret != 0) goto err_iomap; /* find the IRQ for this unit (note, this relies on the init call to * ensure no current IRQs pending */ i2c->irq = ret = platform_get_irq(pdev, 0); if (ret <= 0) { dev_err(&pdev->dev, "cannot find IRQ\n"); goto err_iomap; } /*注册中断,每当发送或者接受一个完整的字节时就会进入中断*/ ret = request_irq(i2c->irq, s3c24xx_i2c_irq, IRQF_DISABLED, dev_name(&pdev->dev), i2c); if (ret != 0) { dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); goto err_iomap; } /* Note, previous versions of the driver used i2c_add_adapter() * to add the bus at any number. We now pass the bus number via * the platform data, so if unset it will now default to always * being bus 0. */ i2c->adap.nr = pdata->bus_num; /*向系统添加i2c适配器*/ ret = i2c_add_numbered_adapter(&i2c->adap); if (ret < 0) { dev_err(&pdev->dev, "failed to add bus to i2c core\n"); goto err_cpufreq; } platform_set_drvdata(pdev, i2c); dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); return 0; err_cpufreq: s3c24xx_i2c_deregister_cpufreq(i2c); err_irq: free_irq(i2c->irq, i2c); err_iomap: iounmap(i2c->regs); err_ioarea: release_resource(i2c->ioarea); kfree(i2c->ioarea); err_clk: clk_disable(i2c->clk); clk_put(i2c->clk); err_noclk: kfree(i2c); return ret; } /* i2c bus registration info */ static const struct i2c_algorithm s3c24xx_i2c_algorithm = { .master_xfer = s3c24xx_i2c_xfer,//通信方法 .functionality = s3c24xx_i2c_func, }; /* s3c24xx_i2c_xfer * * first port of call from the i2c bus code when an message needs * transferring across the i2c bus. */ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; int retry; int ret; for (retry = 0; retry < adap->retries; retry++) { ret = s3c24xx_i2c_doxfer(i2c, msgs, num);//继续往下调用 if (ret != -EAGAIN) return ret; dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); udelay(100); } return -EREMOTEIO; } /* s3c24xx_i2c_doxfer * * this starts an i2c transfer */ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { unsigned long timeout; unsigned long iicstat; int ret; if (i2c->suspended) return -EIO; ret = s3c24xx_i2c_set_master(i2c); if (ret != 0) { dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); ret = -EAGAIN; goto out; } spin_lock_irq(&i2c->lock); //获取待传输的msg i2c->msg = msgs;// i2c->msg_num = num; i2c->msg_ptr = 0; i2c->msg_idx = 0; i2c->state = STATE_START; s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs);//启动发送,发送address。当address传输完后,进入中断,在中断里判断是否传输错误 spin_unlock_irq(&i2c->lock); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 1);//等待超时或者传输完成。 ret = i2c->msg_idx; /* having these next two as dev_err() makes life very * noisy when doing an i2cdetect */ if (timeout == 0) { dev_dbg(i2c->dev, "timeout\n"); iicstat = readl(i2c->regs + S3C2410_IICSTAT); /* stop the transfer */ iicstat &= ~(S3C2410_IICSTAT_START | S3C2410_IICSTAT_TXRXEN); writel(iicstat, i2c->regs + S3C2410_IICSTAT); i2c->state = STATE_STOP; s3c24xx_i2c_master_complete(i2c, ret); s3c24xx_i2c_disable_irq(i2c); goto out; } else if (ret != num) dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); /* ensure the stop has been through the bus */ udelay(50); out: return ret; } /* s3c24xx_i2c_message_start * * put the start of a message onto the bus */ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, struct i2c_msg *msg) { unsigned int addr = (msg->addr & 0x7f) << 1;//获取address并左移一位,第8位表示读写 unsigned long stat; unsigned long iiccon; stat = 0; stat |= S3C2410_IICSTAT_TXRXEN; if (msg->flags & I2C_M_RD) { stat |= S3C2410_IICSTAT_MASTER_RX; addr |= 1;//赋值第8位 } else stat |= S3C2410_IICSTAT_MASTER_TX; if (msg->flags & I2C_M_REV_DIR_ADDR) addr ^= 1; /* todo - check for wether ack wanted or not */ s3c24xx_i2c_enable_ack(i2c); iiccon = readl(i2c->regs + S3C2410_IICCON); writel(stat, i2c->regs + S3C2410_IICSTAT);//启动传输 dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); writeb(addr, i2c->regs + S3C2410_IICDS);//将地址写到IICDS,通过SDA发送 /* delay here to ensure the data byte has gotten onto the bus * before the transaction is started */ ndelay(i2c->tx_setup); //dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); //writel(iiccon, i2c->regs + S3C2410_IICCON); stat |= S3C2410_IICSTAT_START; writel(stat, i2c->regs + S3C2410_IICSTAT); } /*发送完一字节进中断*/ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) { struct s3c24xx_i2c *i2c = dev_id; unsigned long status; unsigned long tmp; status = readl(i2c->regs + S3C2410_IICSTAT);//以下是判断是否传输有错误 if (status & S3C2410_IICSTAT_ARBITR) { /* deal with arbitration loss */ dev_err(i2c->dev, "deal with arbitration loss\n"); } if (i2c->state == STATE_IDLE) { dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); tmp = readl(i2c->regs + S3C2410_IICCON); tmp &= ~S3C2410_IICCON_IRQPEND; writel(tmp, i2c->regs + S3C2410_IICCON); goto out; } /* pretty much this leaves us with the fact that we've * transmitted or received whatever byte we last sent */ i2c_s3c_irq_nextbyte(i2c, status);//传送下一个字节 out: return IRQ_HANDLED; } static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) { unsigned long tmp; unsigned char byte; int ret = 0; switch (i2c->state) { case STATE_IDLE: dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); goto out; break; case STATE_STOP: dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); s3c24xx_i2c_disable_irq(i2c); goto out_ack; case STATE_START://标志为START有两种情况:1、刚开始,2、READ的重启时候 /* last thing we did was send a start condition on the * bus, or started a new i2c message */ if (iicstat & S3C2410_IICSTAT_LASTBIT && !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { /* ack was not received... */ dev_dbg(i2c->dev, "ack was not received\n"); s3c24xx_i2c_stop(i2c, -ENXIO); goto out_ack; } if (i2c->msg->flags & I2C_M_RD) i2c->state = STATE_READ;//READ的重启时候 else i2c->state = STATE_WRITE;//刚开始传输 /* terminate the transfer if there is nothing to do * as this is used by the i2c probe to find devices. */ if (is_lastmsg(i2c) && i2c->msg->len == 0) { s3c24xx_i2c_stop(i2c, 0); goto out_ack; } if (i2c->state == STATE_READ)//如果是READ,先要未读准备一下。如只读一个字节,如果是则要设置读完后主机不发送ACK等 goto prepare_read; /* fall through to the write state, as we will need to * send a byte as well */ case STATE_WRITE: /* we are writing data to the device... check for the * end of the message, and if so, work out what to do */ if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { if (iicstat & S3C2410_IICSTAT_LASTBIT) { dev_dbg(i2c->dev, "WRITE: No Ack\n"); s3c24xx_i2c_stop(i2c, -ECONNREFUSED); goto out_ack; } } retry_write: if (!is_msgend(i2c)) {//msg是否传完数据 byte = i2c->msg->buf[i2c->msg_ptr++];//指针自加1 writeb(byte, i2c->regs + S3C2410_IICDS);//未传完数据,则要将数据写到CDS,通过SDA发送 /* delay after writing the byte to allow the * data setup time on the bus, as writing the * data to the register causes the first bit * to appear on SDA, and SCL will change as * soon as the interrupt is acknowledged */ ndelay(i2c->tx_setup); } else if (!is_lastmsg(i2c)) {//如果msg数据传完,且后面还有msg,则要跳到下一个msg /* we need to go to the next i2c message */ dev_dbg(i2c->dev, "WRITE: Next Message\n"); i2c->msg_ptr = 0; i2c->msg_idx++; i2c->msg++;//跳到下一个msg /* check to see if we need to do another message */ if (i2c->msg->flags & I2C_M_NOSTART) { if (i2c->msg->flags & I2C_M_RD) { /* cannot do this, the controller * forces us to send a new START * when we change direction */ s3c24xx_i2c_stop(i2c, -EINVAL); } goto retry_write; } else { /* send the new start */ s3c24xx_i2c_message_start(i2c, i2c->msg);//这里是在case WRITE里,该msg数据传完(片内地址传完),且后面还有msg待传输,说明是主机要向从机读数据。因此重启I2C i2c->state = STATE_START;//设置I2C状态 } } else { /* send stop */ s3c24xx_i2c_stop(i2c, 0); } break; case STATE_READ: /* we have a byte of data in the data register, do * something with it, and then work out wether we are * going to do any more read/write */ byte = readb(i2c->regs + S3C2410_IICDS);//(接受一个字节会进中断,且将值放在CDS里),获取数据 i2c->msg->buf[i2c->msg_ptr++] = byte;//ptr指向下一个字节 prepare_read: if (is_msglast(i2c)) {//仅剩最后一个字节未读取 /* last byte of buffer */ if (is_lastmsg(i2c)) s3c24xx_i2c_disable_ack(i2c);//到时不发送ACK } else if (is_msgend(i2c)) //数据接受完毕 { /* ok, we've read the entire buffer, see if there * is anything else we need to do */ if (is_lastmsg(i2c)) {//最后一个msg ? /* last message, send stop and complete */ dev_dbg(i2c->dev, "READ: Send Stop\n"); s3c24xx_i2c_stop(i2c, 0);//说明已经全部接受完毕,主机给从机发送停止信号 } else { /* go to the next transfer */ dev_dbg(i2c->dev, "READ: Next Transfer\n"); i2c->msg_ptr = 0; i2c->msg_idx++; i2c->msg++; } } break; } /* acknowlegde the IRQ and get back on with the work */ //清中断,重新传输 out_ack: tmp = readl(i2c->regs + S3C2410_IICCON); tmp &= ~S3C2410_IICCON_IRQPEND; writel(tmp, i2c->regs + S3C2410_IICCON); out: return ret; }2、core
//除了添加adapter外还初始化并注册了挂接在这个adapter上的设备
int i2c_add_numbered_adapter(struct i2c_adapter *adap) {//we have already set the adap->nr int id; int status; if (adap->nr & ~MAX_ID_MASK) return -EINVAL; retry: if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) return -ENOMEM; mutex_lock(&core_lock); /* "above" here means "above or equal to", sigh; * we need the "equal to" result to force the result */ status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);//建立id与adap的关系 if (status == 0 && id != adap->nr) { status = -EBUSY; idr_remove(&i2c_adapter_idr, id); } mutex_unlock(&core_lock); if (status == -EAGAIN) goto retry; if (status == 0) <span style="color:#ff0000;">status = i2c_register_adapter(adap);</span> return status; } static int i2c_register_adapter(struct i2c_adapter *adap) { int res = 0; /* Can't register until after driver model init */ if (unlikely(WARN_ON(!i2c_bus_type.p))) { res = -EAGAIN; goto out_list; } rt_mutex_init(&adap->bus_lock); mutex_init(&adap->userspace_clients_lock); INIT_LIST_HEAD(&adap->userspace_clients); /* Set default timeout to 1 second if not already set */ if (adap->timeout == 0) adap->timeout = HZ; //adap->dev.name=i2c0 dev_set_name(&adap->dev, "i2c-%d", adap->nr);//i2c-0 adap->dev.bus = &i2c_bus_type; adap->dev.type = &i2c_adapter_type; res = device_register(&adap->dev);//register adapter 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) //will call this <span style="color:#ff0000;"><strong>i2c_scan_static_board_info(adap);</strong></span> /* Notify drivers */ mutex_lock(&core_lock); //will not do this part bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_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; } static void i2c_scan_static_board_info(struct i2c_adapter *adapter) { struct i2c_devinfo *devinfo; down_read(&__i2c_board_lock); list_for_each_entry(devinfo, &__i2c_board_list, list) { if (devinfo->busnum == adapter->nr && !i2c_new_device(adapter, &devinfo->board_info)) //initilize the device dev_err(&adapter->dev, "Can't create device at 0x%02x\n", devinfo->board_info.addr); } up_read(&__i2c_board_lock); } struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) { struct i2c_client *client; int status; client = kzalloc(sizeof *client, GFP_KERNEL); if (!client) return NULL; 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; client->irq = info->irq; strlcpy(client->name, info->type, sizeof(client->name));//set client name /* Check for address validity */ status = i2c_check_client_addr_validity(client); if (status) { dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); goto out_err_silent; } /* Check for address business */ status = i2c_check_addr_busy(adap, client->addr);//check the addr occupied? if (status) goto out_err; client->dev.parent = &client->adapter->dev;//add on adapter client->dev.bus = &i2c_bus_type; client->dev.type = &i2c_client_type; #ifdef CONFIG_OF client->dev.of_node = info->of_node; #endif dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), client->addr);//set clinet->dev.name=0-0x45 status = device_register(&client->dev);//add the device first 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); out_err_silent: kfree(client); return NULL; } int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { unsigned long orig_jiffies; int ret, try; if (adap->algo->master_xfer) { #ifdef DEBUG for (ret = 0; ret < num; ret++) { dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); } #endif if (in_atomic() || irqs_disabled()) { ret = i2c_trylock_adapter(adap); if (!ret) /* I2C activity is ongoing. */ return -EAGAIN; } else { i2c_lock_adapter(adap); }/* Retry automatically on arbitration loss */ orig_jiffies = jiffies; for (ret = 0, try = 0; try <= adap->retries; try++) { ret = adap->algo->master_xfer(adap, msgs, num);//transfer msg--见上面 if (ret != -EAGAIN) break; if (time_after(jiffies, orig_jiffies + adap->timeout)) break; } i2c_unlock_adapter(adap); return ret; } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); return -EOPNOTSUPP; } }