// kernel/drivers/i2c/busses/i2c_sc8810.c
static int __init i2c_adap_sc8810_init(void)
{
printk(KERN_INFO"I2c:sc8810 driver$Revision:1.0 $\n");
return platform_driver_register(&sc8810_i2c_driver);
}
/*platform_driver_register - register a driver for platform-level devices
* @drv: platform driver structure
*/
//kernel/drivers/base/platform.c
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus =&platform_bus_type;
if (drv->probe)
drv->driver.probe =platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown =platform_drv_shutdown;
return driver_register(&drv->driver);
}
/**
* driver_register - register driver with bus
* @drv: driver to register
* We pass off most of the work to thebus_add_driver() call,
* since most of the things we have to do dealwith the bus
* structures.
*/
//kernel\drivers\base\driver.c
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_typemethods\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 = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv,drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}
/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
*/
//kernel/drivers/base/bus.c
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;
}
klist_init(&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 = driver_attach(drv);
if (error)
goto out_unregister;
}
klist_add_tail(&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: ueventattr (%s) failed\n",
__func__, drv->name);
}
//如果有 device 和 platform_driver->device_driver 匹配,就把 platform_driver->device_driver添加到总线中。
error = driver_add_attrs(bus, drv);
if (error) {
/* How the hell do we get out ofthis pickle? Give up */
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) {
/* Ditto */
printk(KERN_ERR "%s:add_bind_files(%s) failed\n",
__func__,drv->name);
}
}
kobject_uevent(&priv->kobj,KOBJ_ADD);
return 0;
out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p = NULL;
out_put_bus:
bus_put(bus);
return error;
}
/**
* driver_attach - try to bind driver todevices.
* @drv: driver.
*
* Walk the list of devices that the bus has onit and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set,we've found a
* compatible pair.
*/
//kernel/drivers/base/dd.c
intdriver_attach(structdevice_driver *drv)
{
return bus_for_each_dev(drv->bus,NULL, drv, __driver_attach);
}
/**
* bus_for_each_dev - device iterator.
* @bus: bus type.
* @start: device to start iterating from.
* @data: data for the callback.
* @fn: function to be called for each device.
*
* Iterate over @bus's list of devices, andcall @fn for each,
* passing it @data. If @start is not NULL, weuse that device to
* begin iterating from.
*
* We check the return of @fn each time. If itreturns anything
* other than 0, we break out and return thatvalue.
*
* NOTE: The device that returns a non-zerovalue is not retained
* in any way, nor is its refcount incremented.If the caller needs
* to retain this data, it should do so, andincrement the reference
* count in the supplied callback.
*/
//kernel/drivers/base/bus.c
int bus_for_each_dev(structbus_type *bus, struct device *start,
void *data, int (*fn)(structdevice *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus)
return -EINVAL;
//在bus_add_driver()函数中可知bus = bus_get(drv->bus); bus是由platform_bus_type而来,而platform_bus_type并未初始化p 变量,不知&bus->p->klist_devices从何而来?
klist_iter_init_node(&bus->p->klist_devices,&i,
(start ? &start->p->knode_bus :NULL));
//为总线上的所有device调用__driver_attach,不知这里的dev是不是platform_device,如果是的话应该会进行4次match,然后运行4次probe函数。
while ((dev = next_device(&i))&& !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
//kernel\drivers\base\dd.c
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
/*
*Lock device and try to bind to it. We drop the error
*here and always return 0, because we need to keep trying
*to bind to devices and some drivers will return an error
*simply if it didn't support the device.
*
*driver_probe_device() will spit a warning if there
*is an error.
*/
if (!driver_match_device(drv, dev))
return 0;
if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
先执行 driver_match_device,当device 和driver 匹配时,再调用driver_probe_device。下面我们先看看driver_match_device
//kernel\drivers\base\base.h
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
return drv->bus->match ?drv->bus->match(dev, drv) : 1;
//当总线的match 函数存在时,调用总线的match函数
}
还记得在 platform_driver_register 中对总线的初始化吗?
//kernel/drivers/base/platform.c
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
… …
}
//kernel/drivers/base/platform.c
struct bus_type platform_bus_type = {
.name ="platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent =platform_uevent,
.pm = &platform_dev_pm_ops,
};
/**
* platform_match - bind platform device toplatform driver.
* @dev: device.
* @drv: driver.
*
* Platform device IDs are assumed to beencoded like this:
* "<name><instance>",where <name> is a short description of the type of
* device, like "pci" or"floppy", and <instance> is the enumerated
* instance of the device, like '0' or'42'. Driver IDs are simply
* "<name>". So, extract the <name> from theplatform_device structure,
* and compare it against the name of thedriver. Return whether they match
* or not.
*/
//kernel/drivers/base/platform.c
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 */
//如果platform_driver结构体中有 id_table ,就用 id_table 中的 name 和 platform_device结构体中的 name 做比较,详见platform_match_id()。
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */
//如果platform_driver结构体中没有 id_table,就用platform_device
//和platform_driver->device_driver结构体中的 name 做比较。
//想想之前的platform_device_register()函数。
return (strcmp(pdev->name, drv->name) == 0);
}
我们首先来看一下 platform_driver 结构体的定义
//kernel/include/linux/platform_device.h
structplatform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device*);
int (*suspend)(struct platform_device *,pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id*id_table;
};
接下来再看一下我们为该结构体定义的变量
// kernel/drivers/i2c/busses/i2c_sc8810.c
static structplatform_driver sc8810_i2c_driver = {
.probe =sc8810_i2c_probe,
.remove =sc8810_i2c_remove,
.driver ={
.owner = THIS_MODULE,
.name = "sc8810-i2c",
},
};
如上所示在实际定义中,我们只定义了 device_driver结构体,没有定义 id_table,因此会走下面的strcmp(pdev->name, drv->name),比较 platform_device和platform_driver->device_driver中的name("sc8810-i2c") 。
driver_match_device完了后,接下来我们再看看 driver_probe_device
/**//driver_probe_device 的作用
* driver_probe_device - attempt to bind device& driver together
* @drv: driver to bind a device to
* @dev: device to try to bind to the driver
*
* This function returns -ENODEV if the deviceis not registered,
* 1 if the device is bound successfully and 0otherwise.
*
* This function must be called with @dev lockheld. When called for a
* USB interface, @dev->parent lock must beheld as well.
*/
//kernel\drivers\base\dd.c
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: matcheddevice %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev),drv->name);
pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
pm_runtime_put_sync(dev);
return ret;
}
//kernel\drivers\base\dd.c
static int really_probe(struct device *dev, struct device_driver*drv)
{
int ret = 0;
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probingdriver %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;
}
//如果device结构相关联的总线的 probe 函数存在,先调用此 probe 函数。虽然在platform_device_add() 函数中为dev->bus赋过值:pdev->dev.bus =&platform_bus_type;但由于platform_bus_type中没有probe函数,因此此流程不走。
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
}
//如果不存在就调用 device_driver 结构体中的 probe 函数,会走这个流程。
else if (drv->probe) {
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bounddevice %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) {
/* driver matched but the probefailed */
printk(KERN_WARNING
"%s: probe of %s failed with error%d\n",
drv->name, dev_name(dev), ret);
}
/*
*Ignore errors returned by ->probe so that the next driver can try
*its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
还记得在 platform_driver_register 中对device_driver结构体中的probe 函数的初始化吗?
/**
* platform_driver_register - register a driverfor platform-level devices
* @drv: platform driver structure
*/
//kernel/drivers/base/platform.c
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus =&platform_bus_type;
//如果platform_driver中的probe 函数存在,就将device_driver
//结构体中的 probe 函数赋值为platform_drv_probe
if (drv->probe)
drv->driver.probe =platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown =platform_drv_shutdown;
return driver_register(&drv->driver);
}
// kernel/drivers/i2c/busses/i2c_sc8810.c
static structplatform_driver sc8810_i2c_driver = {
.probe = sc8810_i2c_probe,
.remove =sc8810_i2c_remove,
.driver ={
.owner = THIS_MODULE,
.name = "sc8810-i2c",
},
};
由此可见platform_driver中的probe 函数是存在的,因此最后会调用 platform_drv_probe 函数。
//kernel/drivers/base/platform.c
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver*drv=to_platform_driver(_dev->driver);
struct platform_device *dev =to_platform_device(_dev);
return drv->probe(dev);
}
首先我们来看一下_dev->drive 究竟是什么,回头看 really_probe 函数可知,_dev->drive实际上就是device_driver。因此drv 就是包含device_driver的 platform_driver,既sc8810_i2c_driver。则drv->probe就是sc8810_i2c_probe,如下所示:
//kernel\drivers\base\dd.c
static int really_probe(struct device *dev, struct device_driver*drv)
{
… …
dev->driver = drv;
… …
}
// kernel/drivers/i2c/busses/i2c_sc8810.c
static struct platform_driver sc8810_i2c_driver = {
.probe = sc8810_i2c_probe,
.remove =sc8810_i2c_remove,
.driver ={
.owner = THIS_MODULE,
.name = "sc8810-i2c",
},
};
当platform_driver 和 platform_device匹配成功后会进入 sc8810_i2c_probe 函数,进行 i2c_adapter 和 i2c_client 的创建工作。