Linux下i2c驱动的加载过程,分为i2c设备层、i2c
i2c设备驱动层也就是我们为特定i2c设备编写的驱动,下面是我自己理解的i2c驱动的注册过程
在我们写的i2c设备驱动中,我们会调用i2c_add_driver()开始i2c设备驱动的注册,该函数调用i2c_register_driver完成所有注册操作
[plain] view plaincopyprint?
-
static
inline int i2c_add_driver(struct i2c_driver *driver) -
{
-
return
i2c_register_driver(THIS_MODULE, driver); -
}
i2c_register_driver会调用driver_register() 来将设备驱动添加到总线的设备驱动链表中:
[plain] view plaincopyprint?
-
int
i2c_register_driver(struct module *owner, struct i2c_driver *driver) -
{
-
int
res; -
-
if
(unlikely(WARN_ON(!i2c_bus_type.p))) -
return
-EAGAIN; -
driver->driver.owner
= owner; -
driver->driver.bus
= &i2c_bus_type; -
-
res
= <strong>driver_register</strong>(&driver->driver); -
if
(res) -
return
res; -
pr_debug("i2c-core:
driver [%s] registered\n", driver->driver.name); -
INIT_LIST_HEAD(&driver->clients);
-
-
mutex_lock(&core_lock);
-
bus_for_each_dev(&i2c_bus_type,
NULL, driver, __attach_adapter); -
mutex_unlock(&core_lock);
-
return
0; -
}
在driver_register中,通过driver_find来判断驱动是否已经注册,然后会调用
bus_add_drive
将设备驱动添加到总线上
[plain] view plaincopyprint?
-
int
driver_register(struct device_driver *drv) -
{
-
int
ret; -
struct
device_driver *other; -
BUG_ON(!drv->bus->p);
-
if
((drv->bus->probe && drv->probe) || -
(drv->bus->remove && drv->remove) || -
(drv->bus->shutdown && drv->shutdown)) -
printk(KERN_WARNING
"Driver '%s' needs updating - please use " -
"bus_type
methods\n", drv->name); -
other
= driver_find(drv->name, drv->bus); -
if
(other) { -
put_driver(other);
-
printk(KERN_ERR
"Error: Driver '%s' is already registered, " -
"aborting...\n",
drv->name); -
return
-EBUSY; -
}
-
ret
= <strong>bus_add_driver</strong>(drv); -
if
(ret) -
return
ret; -
ret
= driver_add_groups(drv, drv->groups); -
if
(ret) -
bus_remove_driver(drv);
-
return
ret; -
}
在bus_add_driver中初始化priv->klist_devices的值,并将priv赋值给drv->p
通过调用klist_add_tail(&priv->knode_bus,
[plain] view plaincopyprint?
-
int
bus_add_driver(struct device_driver *drv) -
{
-
struct
bus_type *bus; -
struct
driver_private *priv; -
int
error = 0; -
bus
= bus_get(drv->bus); -
if
(!bus) -
return
-EINVAL; -
pr_debug("bus:
'%s': add driver %s\n", bus->name, drv->name); -
priv
= kzalloc(sizeof(*priv), GFP_KERNEL); -
if
(!priv) { -
error
= -ENOMEM; -
goto
out_put_bus; -
}
-
<strong>klist_init</strong>(&priv->klist_devices,
NULL, NULL); -
priv->driver
= drv; -
drv->p
= priv; -
priv->kobj.kset
= bus->p->drivers_kset; -
error
= kobject_init_and_add(&priv->kobj, &driver_ktype, NULL, -
"%s", drv->name); -
if
(error) -
goto
out_unregister; -
if
(drv->bus->p->drivers_autoprobe) { -
error
= <strong>driver_attach</strong>(drv); -
if
(error) -
goto
out_unregister; -
}
-
<strong>klist_add_tail</strong>(&priv->knode_bus,
&bus->p->klist_drivers); -
module_add_driver(drv->owner,
drv); -
error
= driver_create_file(drv, &driver_attr_uevent); -
if
(error) { -
printk(KERN_ERR
"%s: uevent attr (%s) failed\n", -
__func__,
drv->name); -
}
-
error
= driver_add_attrs(bus, drv); -
if
(error) { -
-
printk(KERN_ERR
"%s: driver_add_attrs(%s) failed\n", -
__func__,
drv->name); -
}
-
if
(!drv->suppress_bind_attrs) { -
error
= add_bind_files(drv); -
if
(error) { -
-
printk(KERN_ERR
"%s: add_bind_files(%s) failed\n", -
__func__,
drv->name); -
}
-
}
-
kobject_uevent(&priv->kobj,
KOBJ_ADD); -
return
0; -
out_unregister:
-
kfree(drv->p);
-
drv->p
= NULL; -
kobject_put(&priv->kobj);
-
out_put_bus:
-
bus_put(bus);
-
return
error; -
}
在driver_attach中,通过调用bus_for_each_dev,遍历在总线上挂载的所有设备,并对每个设备(dev)调用__driver_attach()
[plain] view plaincopyprint?
-
int
driver_attach(struct device_driver *drv) -
{
-
return
bus_for_each_dev(drv->bus, NULL, drv, <strong>__driver_attach</strong>); -
}
在__driver_attach里会调用driver_match_device()来判断dev与driv的id是否相同,在i2c驱动里就会调用i2c_bus_type->match程序进行判断,
当id相同时,将会调用driver_probe_device()
[plain] view plaincopyprint?
-
static
int __driver_attach(struct device *dev, void *data) -
{
-
struct
device_driver *drv = data; -
-
if
(!<strong>driver_match_device</strong>(drv, dev)) -
return
0; -
if
(dev->parent) -
down(&dev->parent->sem);
-
down(&dev->sem);
-
if
(!dev->driver) -
<strong>driver_probe_device</strong>(drv,
dev); -
up(&dev->sem);
-
if
(dev->parent) -
up(&dev->parent->sem);
-
return
0; -
}
在driver_probe_device(),首先会调用device_is_registered()判断dev是否注册,若没注册则返回;若已经注册,则调用really_probe
[plain] view plaincopyprint?
-
int
driver_probe_device(struct device_driver *drv, struct device *dev) -
{
-
int
ret = 0; -
if
(!device_is_registered(dev)) -
return
-ENODEV; -
pr_debug("bus:
'%s': %s: matched device %s with driver %s\n", -
drv->bus->name, __func__, dev_name(dev), drv->name); -
pm_runtime_get_noresume(dev);
-
pm_runtime_barrier(dev);
-
ret
= <strong>really_probe</strong>(dev, drv); -
pm_runtime_put_sync(dev);
-
return
ret; -
}
在really_probe()里,首先将drv赋值给dev->driver,然后会调用总线的probe函数,在i2c驱动里,
此时将会调用i2c总线的probe函数:i2c_device_probe
[plain] view plaincopyprint?
-
static
int really_probe(struct device *dev, struct device_driver *drv) -
{
-
int
ret = 0; -
atomic_inc(&probe_count);
-
pr_debug("bus:
'%s': %s: probing driver %s with device %s\n", -
drv->bus->name, __func__, drv->name, dev_name(dev)); -
WARN_ON(!list_empty(&dev->devres_head));
-
dev->driver
= drv; -
if
(driver_sysfs_add(dev)) { -
printk(KERN_ERR
"%s: driver_sysfs_add(%s) failed\n", -
__func__,
dev_name(dev)); -
goto
probe_failed; -
}
-
if
(dev->bus->probe) -
{
-
//此处调用i2c总线的probe函数
-
ret
= dev->bus->probe(dev); -
if
(ret) -
goto
probe_failed; -
}
-
else
if (drv->probe) -
{
-
ret
= drv->probe(dev); -
if
(ret) -
goto
probe_failed; -
}
-
driver_bound(dev);
-
ret
= 1; -
pr_debug("bus:
'%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); -
goto
done; -
probe_failed:
-
devres_release_all(dev);
-
driver_sysfs_remove(dev);
-
dev->driver
= NULL; -
if
(ret != -ENODEV && ret != -ENXIO) -
{
-
-
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n", drv->name, dev_name(dev), ret); -
}
-
-
ret
= 0; -
done:
-
atomic_dec(&probe_count);
-
wake_up(&probe_waitqueue);
-
return
ret; -
}
在i2c_device_probe()里,会根据to_i2c_driver(dev->driver)获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体i2c_driver,即
[plain] view plaincopyprint?
-
static
struct i2c_driver XXX_driver = { -
.driver
= { -
.name
= "XXXX_name", -
.owner
= THIS_MODULE, -
},
-
.probe
= XXX_probe, -
.remove
= XXX_remove, -
.id_table
= XXX_id, -
};
这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe()
[plain] view plaincopyprint?
-
static
int i2c_device_probe(struct device *dev) -
{
-
struct
i2c_client *client = i2c_verify_client(dev); -
struct
i2c_driver *driver; -
int
status; -
if
(!client) -
return
0; -
driver
= to_i2c_driver(dev->driver); -
if
(!driver->probe || !driver->id_table) -
return
-ENODEV; -
client->driver
= driver; -
if
(!device_can_wakeup(&client->dev)) -
device_init_wakeup(&client->dev,
-
client->flags
& I2C_CLIENT_WAKE); -
dev_dbg(dev,
"probe\n"); -
status
= <strong>driver->probe</strong>(client, i2c_match_id(driver->id_table, client));//执行我们写的probe函数 -
if
(status) -
client->driver
= NULL; -
return
status; -
}