本文共 19391 字,大约阅读时间需要 64 分钟。
i2c设备是非常普遍的一种设备,我们现在开始i2c子系统的分析。 我们先从注册开始: static const struct i2c_device_id IT7260_ts_id[] = { { IT7260_I2C_NAME, 0 }, { } }; static struct i2c_driver IT7260_ts_driver = { .probe = IT7260_ts_probe, .remove = IT7260_ts_remove, #ifdef CONFIG_PM .resume = IT7260_ts_resume, .suspend = IT7260_ts_suspend, #endif .id_table = IT7260_ts_id, .driver = { .name = "IT7260-ts", }, }; i2c_add_driver(&IT7260_ts_driver)我们看这是典型的具体i2c添加驱动实例。 static inline int i2c_add_driver(struct i2c_driver *driver) { return i2c_register_driver(THIS_MODULE, driver); } 转而i2c_register_driver(THIS_MODULE, driver): int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { int res; /* Can't register until after driver model init */ if (unlikely(WARN_ON(!i2c_bus_type.p))) return -EAGAIN; /* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; /* When registration returns, the driver core * will have called probe() for all matching-but-unbound devices. */ res = driver_register(&driver->driver);//这个我们在driver_register中分析过了,它会去匹配总线(这里就是i2c了)上的的所有设备的client,如果找到,则执行bus的probe函数,我们下面去看下bus的probe函数 if (res) return res; pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); INIT_LIST_HEAD(&driver->clients);//初始化clients列表 /* Walk the adapters that are already present */ mutex_lock(&core_lock); class_for_each_device(&i2c_adapter_class, NULL, driver, __attach_adapter);//对i2c_adapter_class下的每个设备都进行匹配 mutex_unlock(&core_lock); return 0; } 我们看下__attach_adapter: static int __attach_adapter(struct device *dev, void *data) { struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; i2c_detect(adapter, driver); /* Legacy drivers scan i2c busses directly */ if (driver->attach_adapter)//没有定义 driver->attach_adapter(adapter); return 0; } 转到i2c_detect(adapter, driver): static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) { const struct i2c_client_address_data *address_data; struct i2c_client *temp_client; int i, err = 0; int adap_id = i2c_adapter_id(adapter);//总线序号 address_data = driver->address_data; if (!driver->detect || !address_data)//我们系统中这两个都为null,故在这里就返回了 return 0; ...... } 可以看出__attach_adapter没有做具体的工作对于i2c。 我们回到i2c_register_driver看driver_register(&driver->driver),它去匹配设备的client,匹配上后会执行bus的probe函数,我们看下i2c_bus的probe: struct bus_type i2c_bus_type = { .name = "i2c", .dev_attrs = i2c_dev_attrs, .match = i2c_device_match, .uevent = i2c_device_uevent, .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, .suspend = i2c_device_suspend, .resume = i2c_device_resume, }; 这里我们先看下bus的match函数,因为driver_register这个寻找设备的时候会执行bus的match函数: static int i2c_device_match(struct device *dev, struct device_driver *drv) { struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver = to_i2c_driver(drv); /* match on an id table if there is one */ if (driver->id_table) return i2c_match_id(driver->id_table, client) != NULL;//只匹配id的名字和client的名字,跟驱动的名字没有关系,注意这里的client是设备转换过来,而不是设备的本身!!! return 0; } 转而调用i2c_match_id(); static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, const struct i2c_client *client) { while (id->name[0]) { if (strcmp(client->name, id->name) == 0) //匹配设备client名字和id_table中的名字 return id; id++; } return NULL; } 所以i2c总线根据设备client名字和id_table中的名字进行匹配的。如果匹配了,则返回id值。然后会执行bus的probe函数,对应了i2c_device_probe: static int i2c_device_probe(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver = to_i2c_driver(dev->driver); int status; if (!driver->probe || !driver->id_table)//i2c driver这两个是必须要定义的 return -ENODEV; client->driver = driver;//赋值给client if (!device_can_wakeup(&client->dev)) device_init_wakeup(&client->dev, client->flags & I2C_CLIENT_WAKE); dev_dbg(dev, "probe\n"); status = driver->probe(client, i2c_match_id(driver->id_table, client));//执行i2c的driver的probe函数,这个就是开头具体驱动中的probe(如IT7260_ts_probe) if (status) client->driver = NULL; return status; } 那这里我们看到了i2c驱动怎么执行的了。 至此,我们只看了i2c driver的注册分析,那i2c device呢? 我们到平台文件里面可以看到这样的代码: static struct i2c_board_info mxc_i2c0_board_info[] __initdata = { ...... { .type = "IT7260", .addr = 0x46, .irq = IOMUX_TO_IRQ_V3(F101_TP_INT), .platform_data = &it7260_data, }, ...... }; i2c_register_board_info(0, mxc_i2c0_board_info, ARRAY_SIZE(mxc_i2c0_board_info)); 这是具体i2c驱动设备的信息注册,我们看下定义: int __init i2c_register_board_info(int busnum,//这个busnum就是i2c的序号 struct i2c_board_info const *info, unsigned len)//len表示有几个info,也就是有i2c上挂几个外设 { int status; down_write(&__i2c_board_lock);//i2c core的读写锁 /* dynamic bus numbers will be assigned after the last static one */ if (busnum >= __i2c_first_dynamic_bus_num) __i2c_first_dynamic_bus_num = busnum + 1;//比最大的busnum大1 for (status = 0; len; len--, info++) { struct i2c_devinfo *devinfo; devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); if (!devinfo) { pr_debug("i2c-core: can't register boardinfo!\n"); status = -ENOMEM; break; } devinfo->busnum = busnum;//该外设所挂的i2c号 devinfo->board_info = *info;//该外设的基本信息(如名字,地址,私有数据等) list_add_tail(&devinfo->list, &__i2c_board_list);//这里__i2c_board_list是一个全局变量,记录着所有i2c外设的信息,然后adapter注册的时候会使用这个列表,所以这个函数要放在adapter注册之前 } up_write(&__i2c_board_lock); return status; } 这个函数主要就是将i2c驱动设备信息整理到__i2c_board_list列表里面。那这个信息列表什么时候用呢?别忘了,我们还有一个没分析,就是cpu自身的i2c控制器。它是怎么注册的呢?怎么跟具体的i2c驱动联系起来的呢?下面我们就看下i2c控制器的驱动。 static struct platform_driver mxci2c_driver = {//我们在tty分析中已经分析过platform注册过程了,它是先匹配id_table中的名字,然后在匹配driver的名字,有一个匹配即可 .driver = { .name = "mxc_i2c", .owner = THIS_MODULE, }, .probe = mxci2c_probe, .remove = mxci2c_remove, .suspend_late = mxci2c_suspend, .resume_early = mxci2c_resume, }; 这就是这个平台的i2c控制器驱动结构定义。 static int __init mxc_i2c_init(void) { /* Register the device driver structure. */ return platform_driver_register(&mxci2c_driver); } 我们看到在init函数里面有对它的注册,platform总线以前就分析过了,相信大家不陌生了。它注册的时候会先按照id_table去找设备,然后按驱动名字去找。这里没id_table,那就按驱动名字去找了,我们可以看到平台设备定义下有这样的定义: struct platform_device mxci2c_devices[] = { { .name = "mxc_i2c", .id = 0, .num_resources = ARRAY_SIZE(mxci2c1_resources), .resource = mxci2c1_resources, }, { .name = "mxc_i2c", .id = 1, .num_resources = ARRAY_SIZE(mxci2c2_resources), .resource = mxci2c2_resources, }, { .name = "mxc_i2c", .id = 2, .num_resources = ARRAY_SIZE(mxci2c3_resources), .resource = mxci2c3_resources, }, }; 同样还有这样的注册设备的代码: mxc_register_device(&mxci2c_devices[0], &mxci2c_data); mxc_register_device(&mxci2c_devices[1], &mxci2c_data); 这样,mxci2c就可以顺利注册了。注册成功后,会调用paltform总线的probe,最终会执行driver的probe。我们看到mxci2c_driver的probe对应为: static int mxci2c_probe(struct platform_device *pdev) { mxc_i2c_device *mxc_i2c; struct mxc_i2c_platform_data *i2c_plat_data = pdev->dev.platform_data;//在dev注册的时候有赋值 struct resource *res; int id = pdev->id; u32 clk_freq; int ret = 0; int i; mxc_i2c = kzalloc(sizeof(mxc_i2c_device), GFP_KERNEL); if (!mxc_i2c) { return -ENOMEM; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { ret = -ENODEV; goto err1; } mxc_i2c->membase = ioremap(res->start, res->end - res->start + 1); /* * Request the I2C interrupt */ mxc_i2c->irq = platform_get_irq(pdev, 0); if (mxc_i2c->irq < 0) { ret = mxc_i2c->irq; goto err2; } ret = request_irq(mxc_i2c->irq, mxc_i2c_handler, 0, pdev->name, mxc_i2c); if (ret < 0) { goto err2; } init_waitqueue_head(&mxc_i2c->wq); mxc_i2c->low_power = false; gpio_i2c_active(id); mxc_i2c->clk = clk_get(&pdev->dev, "i2c_clk"); clk_freq = clk_get_rate(mxc_i2c->clk); mxc_i2c->clkdiv = -1; if (i2c_plat_data->i2c_clk) { /* Calculate divider and round up any fractional part */ int div = (clk_freq + i2c_plat_data->i2c_clk - 1) / i2c_plat_data->i2c_clk; for (i = 0; i2c_clk_table[i].div != 0; i++) { if (i2c_clk_table[i].div >= div) { mxc_i2c->clkdiv = i2c_clk_table[i].reg_value; break; } } } if (mxc_i2c->clkdiv == -1) { i--; mxc_i2c->clkdiv = 0x1F; /* Use max divider */ } dev_dbg(&pdev->dev, "i2c speed is %d/%d = %d bps, reg val = 0x%02X\n", clk_freq, i2c_clk_table[i].div, clk_freq / i2c_clk_table[i].div, mxc_i2c->clkdiv); /* * Set the adapter information */ strlcpy(mxc_i2c->adap.name, pdev->name, 48);//adapter名字最长是48 mxc_i2c->adap.id = mxc_i2c->adap.nr = id;//总线编号 mxc_i2c->adap.algo = &mxc_i2c_algorithm;//向adapter赋值i2c_algorithm结构,后面传输函数分析会用到 mxc_i2c->adap.timeout = 1; platform_set_drvdata(pdev, mxc_i2c); i2c_set_adapdata(&mxc_i2c->adap, mxc_i2c);//从设备定义那边获得的数据保存起来 if ((ret = i2c_add_numbered_adapter(&mxc_i2c->adap)) < 0) {//为每条i2c注册一个adapter goto err3; } printk(KERN_INFO "MXC I2C driver\n"); return 0; err3: free_irq(mxc_i2c->irq, mxc_i2c); gpio_i2c_inactive(id); err2: iounmap(mxc_i2c->membase); err1: dev_err(&pdev->dev, "failed to probe i2c adapter\n"); kfree(mxc_i2c); return ret; } 在初始化了mxc_i2c结构体后会执行i2c_add_numbered_adapter(&mxc_i2c->adap): int i2c_add_numbered_adapter(struct i2c_adapter *adap) { int id; int status; if (adap->nr & ~MAX_ID_MASK) return -EINVAL; //idr机制我们这里不去深究,知道意思就行了,也就是将整数ID号和特定指针关联在一起的机制,这样很方便查找,查找到id也就查找到对应的指针了 retry: if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)//为i2c的idr准备空间 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);//根据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) status = i2c_register_adapter(adap);//注册adapter return status; } 转到i2c_register_adapter(adap): 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)//mxc_i2c中设为1,即1个jiffies adap->timeout = HZ; dev_set_name(&adap->dev, "i2c-%d", adap->nr);//形如i2c-0,i2c-1等 adap->dev.release = &i2c_adapter_dev_release; adap->dev.class = &i2c_adapter_class; res = device_register(&adap->dev);//在device_register中已分析,这里是将adapter注册到/sys/系统中,属于i2c-adapter类,在/sys/class/i2c-adapter/下注册具体的adapter,如i2c-0,i2c-1等,同时键一些属性文件 if (res) goto out_list; dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); /* create pre-declared device nodes */ if (adap->nr < __i2c_first_dynamic_bus_num)//__i2c_first_dynamic_bus_num总比i2c总数目大1 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); //对bus上注册的驱动执行该函数 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; } 好,我们看下i2c_scan_static_board_info(adap): 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) {//__i2c_board_list是所有i2c外设组成的列表,所以这个列表必须在这之前准备好 if (devinfo->busnum == adapter->nr //匹配总线序号 && !i2c_new_device(adapter,//在该总线上添加外设 &devinfo->board_info)) dev_err(&adapter->dev, "Can't create device at 0x%02x\n", devinfo->board_info.addr); } up_read(&__i2c_board_lock); } __i2c_board_list?!想起来了吧,就上面注册的所有i2c驱动设备信息列表。这里将按照设备所属的i2c总线,然后添加到对应的i2c上,我们下面看下i2c_new_device(adapter, &devinfo->board_info): struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) { struct i2c_client *client; int status; //client是一个很重要的结构,它联系了adapter,driver,dev,在i2c架构中起到纽带作用 client = kzalloc(sizeof *client, GFP_KERNEL); if (!client) return NULL; client->adapter = adap; //赋值给client,驱动会通过client使用adapter之前开始时初始化的变量,包括i2c_algorithm 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)); //上面主要是对client初始化 /* 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.release = i2c_client_dev_release; dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),//可以知道client名字为总线号加地址 client->addr); status = device_register(&client->dev);//注册client的dev到i2c bus下的device列表 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_register_adapter中的i2c_do_add_adapter: static int i2c_do_add_adapter(struct device_driver *d, void *data) { struct i2c_driver *driver = to_i2c_driver(d); struct i2c_adapter *adap = data; /* Detect supported devices on that bus, and instantiate them */ i2c_detect(adap, driver); /* Let legacy drivers scan this bus for matching devices */ if (driver->attach_adapter) {//driver没有定义 /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); } return 0; } 跟上面的__attach_adapter一样呢!没什么具体作用的。仔细想想也是有道理的,i2c驱动已经可以通过client访问adapter了,所以驱动再去匹配adapter是多此一举。可能有的驱动通过其它方式注册的,是需要匹配adapter的,这个另当别论吧。 我们下面开始分析i2c的通信,即读写过程。
我们先看读函数,对应i2c core中的i2c_master_recv:
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
{
struct i2c_adapter *adap=client->adapter;//通过client访问adapter
struct i2c_msg msg;//i2c传输的单位
int ret;
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.flags |= I2C_M_RD;//读标记,如果没有就是写
msg.len = count;//数据字节数
msg.buf = buf;//数据保存的地方
ret = i2c_transfer(adap, &msg, 1);//传输1个msg
/* If everything went ok (i.e. 1 msg transmitted), return #bytes
transmitted, else error code. */
return (ret == 1) ? count : ret;
}
在看下写函数,对应i2c core中的i2c_master_send:
int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
{
int ret;
struct i2c_adapter *adap=client->adapter;//通过client访问adapter
struct i2c_msg msg;//这个就是i2c传输的单位
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;//没有读标记就代表写操作
msg.len = count;//数据字节数
msg.buf = (char *)buf;//要写的buf
ret = i2c_transfer(adap, &msg, 1);//传输1个msg
/* If everything went ok (i.e. 1 msg transmitted), return #bytes
transmitted, else error code. */
return (ret == 1) ? count : ret;
}
我们发现无论读还是写函数最终都使用i2c_transfer()进行传输msg,下面具体分析一下i2c_transfer:
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;
/* REVISIT the fault reporting model here is weak:
*
* - When we get an error after receiving N bytes from a slave,
* there is no way to report "N".
*
* - When we get a NAK after transmitting N bytes to a slave,
* there is no way to report "N" ... or to let the master
* continue executing the rest of this combined message, if
* that's the appropriate response.
*
* - When for example "num" is two and we successfully complete
* the first message but get an error part way through the
* second, it's unclear whether that should be reported as
* one (discarding status on the second message) or errno
* (discarding status on the first one).
*/
if (adap->algo->master_xfer) {//显然这个i2c_transfer依赖i2c_algorithm中的master_xfer是否被定义,我们在注册分析中知道它已经被赋值为.master_xfer = mxc_i2c_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 = mutex_trylock(&adap->bus_lock);
if (!ret)
/* I2C activity is ongoing. */
return -EAGAIN;
} else {
mutex_lock_nested(&adap->bus_lock, adap->level);//给bus上锁了
}
/* 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);//最终转换为i2c_algorithm中的master_xfer传输
if (ret != -EAGAIN)
break;
if (time_after(jiffies, orig_jiffies + adap->timeout))//retry间隔时间
break;
}
mutex_unlock(&adap->bus_lock);
return ret;
} else {
dev_dbg(&adap->dev, "I2C level transfers not supported\n");
return -EOPNOTSUPP;
}
}
我们在注册分析中知道adap->algo被赋值为&mxc_i2c_algorithm,而mxc_i2c_algorithm定义为:
static struct i2c_algorithm mxc_i2c_algorithm = {
.master_xfer = mxc_i2c_xfer,//传输函数
.functionality = mxc_i2c_func//功能支持
};
所以adap->algo->master_xfer实际为mxc_i2c_xfer,这个函数即为i2c控制器的传输函数:
static int mxc_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
int num)
{
mxc_i2c_device *dev = (mxc_i2c_device *) (i2c_get_adapdata(adap));
int i, ret = 0, addr_comp = 0;
volatile unsigned int sr;
int retry = 5, retry_start = 5;
retry:
if (dev->low_power) {
dev_err(&dev->adap.dev, "I2C Device in low power mode\n");
return -EREMOTEIO;
}
if (num < 1) {
return 0;
}
mxc_i2c_module_en(dev, msgs[0].flags);
sr = readw(dev->membase + MXC_I2SR);//读i2c的状态寄存器
/*
* Check bus state
*/
while ((sr & MXC_I2SR_IBB) && retry--) {//检查i2c总线状态是否处于忙
udelay(5);
sr = readw(dev->membase + MXC_I2SR);
}
if ((sr & MXC_I2SR_IBB) && retry < 0) {
mxc_i2c_module_dis(dev);
dev_err(&dev->adap.dev, "Bus busy\n");
return -EREMOTEIO;
}
//gpio_i2c_active(dev->adap.id);
dev->transfer_done = false;
dev->tx_success = false;
for (i = 0; i < num && ret >= 0; i++) {//num是要传输的msg个数
addr_comp = 0;
/*
* Send the slave address and transfer direction in the
* address cycle
*/
if (i == 0) {
/*
* Send a start or repeat start signal
*/
if (mxc_i2c_start(dev, &msgs[0])){//发送开始信号
if(retry_start-- != 0)
goto retry;
return -EREMOTEIO;
}
/* Wait for the address cycle to complete */
if (mxc_i2c_wait_for_tc(dev, msgs[0].flags)) {//等待地址周期完成
mxc_i2c_stop(dev);
//gpio_i2c_inactive(dev->adap.id);
mxc_i2c_module_dis(dev);
return -EREMOTEIO;
}
addr_comp = 1;
} else {
/*
* Generate repeat start only if required i.e the address
* changed or the transfer direction changed
*/
if ((msgs[i].addr != msgs[i - 1].addr) ||
((msgs[i].flags & I2C_M_RD) !=
(msgs[i - 1].flags & I2C_M_RD))) {//从if条件可以看出是判断地址和读写方向
mxc_i2c_repstart(dev, &msgs[i]);
/* Wait for the address cycle to complete */
if (mxc_i2c_wait_for_tc(dev, msgs[i].flags)) {
mxc_i2c_stop(dev);
//gpio_i2c_inactive(dev->adap.id);
mxc_i2c_module_dis(dev);
return -EREMOTEIO;
}
addr_comp = 1;
}
}
/* Transfer the data */
if (msgs[i].flags & I2C_M_RD) {//根据读写标记决定是读操作还是写操作
/* Read the data */
ret = mxc_i2c_readbytes(dev, &msgs[i], (i + 1 == num),
addr_comp);
if (ret < 0) {
dev_err(&dev->adap.dev, "mxc_i2c_readbytes:"
" fail.\n");
break;
}
} else {
/* Write the data */
ret = mxc_i2c_writebytes(dev, &msgs[i], (i + 1 == num));
if (ret < 0) {
dev_err(&dev->adap.dev, "mxc_i2c_writebytes:"
" fail.\n");
break;
}
}
}
//gpio_i2c_inactive(dev->adap.id);
mxc_i2c_module_dis(dev);
/*
* Decrease by 1 as we do not want Start message to be included in
* the count
*/
return (i < 0 ? ret : i);
}
我们看到控制器的传输函数是按照i2c协议的传输过程。在这里我们要看下mxc_i2c_start(dev, &msgs[0]):
static int mxc_i2c_start(mxc_i2c_device *dev, struct i2c_msg *msg)
{
volatile unsigned int cr, sr;
unsigned int addr_trans;
int retry = 16;
retry:
/*
* Set the slave address and the requested transfer mode
* in the data register
*/
addr_trans = msg->addr << 1;//地址x2,所以设备开始设置地址时要设为写地址的1/2
if (msg->flags & I2C_M_RD) {//如果是读操作,这地址加1
addr_trans |= 0x01;
}
......
}
我们注意一下这里的地址转换,所以设备信息设置的时候注意一下地址大小需要除以2 。
上面就是i2c读写过程:driver->i2c_core->adapter 转载地址:http://nzbsi.baihongyu.com/