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);
我们先从注册开始:
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);