分类: LINUX
2010-07-22 20:17:18
platform设备这端的就分析完了,下面开始platform驱动端,还是以spi为例。
初始化代码
static struct platform_driver atmel_spi_driver = {
.driver = {
.name = "atmel_spi",
.owner = THIS_MODULE,
},
.suspend = atmel_spi_suspend,
.resume = atmel_spi_resume,
.remove = __exit_p(atmel_spi_remove),
};
static int __init atmel_spi_init(void)
{
return platform_driver_probe(&atmel_spi_driver, atmel_spi_probe);
}
module_init(atmel_spi_init);
static void __exit atmel_spi_exit(void)
{
platform_driver_unregister(&atmel_spi_driver);
}
module_exit(atmel_spi_exit);
上节中at91sam9263_spi0_device结构体里面的.name= "atmel_spi",刚好与这里的.driver = {
.name = "atmel_spi",
.owner = THIS_MODULE,
},对应起来了,这样就把总线的设备和驱动联系起来了。
进入platform_driver_probe看看,代码很少
/**
* platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure :platform 驱动结构体
* @probe: the driver probe routine, probably from an __init section :driver probe
*
* Use this instead of when you know the device
* is not hotpluggable and has already been registered, and you want to
* remove its run-once probe() infrastructure from memory after the driver
* has bound to the device.
当你知道设备不是可热插拔的,设备已经被注册,并且你想在驱动被绑定到设备 之后,运行一次probe()就删除掉probe时,就用这个来代替platform_driver_register()
* One typical use for this would be with drivers for controllers integrated
* into system-on-chip processors, where the controller devices have been
* configured as part of board setup.
*一个典型的应用就是SOC上的驱动控制器,因为这些控制器设备在板子启动时就已经配置好了。
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
*/如果驱动注册且绑定到设备成功则返回1,否则返回错误代码,并且驱动没有不会被注册。
int __init_or_module platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
{
int retval, code;
/* temporary section violation during probe() */
drv->probe = probe;
retval = code = platform_driver_register(drv);
/* Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of
* new devices fail.
*/
spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
drv->probe = NULL;
if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
retval = -ENODEV;
drv->driver.probe = platform_drv_probe_fail;
spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
if (code != retval)
platform_driver_unregister(drv);
return retval;
}
接下来进入retval = code = platform_driver_register(drv);这个函数很简单,就是简单的函数指针赋地址,最后再注册驱动
/**
* platform_driver_register
* @drv: platform driver structure
*/
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;
if (drv->suspend)
drv->driver.suspend = platform_drv_suspend;
if (drv->resume)
drv->driver.resume = platform_drv_resume;
if (drv->pm)
drv->driver.pm = &drv->pm->base;
return driver_register(&drv->driver);
}
分析下driver_register
/**
* driver_register - register driver with bus
* @drv: driver to register
*
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
*/
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
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); // 寻找drv是否已经注册
if (other) { // 如果注册,则返回错误
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EEXIST;
}
ret = bus_add_driver(drv); // 没有注册则在总线上寻找驱动
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}
跟踪ret = bus_add_driver(drv);
/**
* bus_add_driver - Add a driver to the bus.
* @drv: driver.
*/在总线上增加一个驱动
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
bus = bus_get(drv->bus); // bus计数加1
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); //增加show和store属性
if (error)
goto out_unregister;
if (drv->bus->p->drivers_autoprobe) { // 需要自动探测
error = driver_attach(drv); // 尝试把driver绑定到设备上
if (error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
module_add_driver(drv->owner, drv); // 配置模块下的driver属性
error = driver_create_file(drv, &driver_attr_uevent); // 为driver创建sysfs
if (error) {
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_attrs(bus, drv); // 增加driver属性
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name);
}
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); // 增加uevent属性
return error;
out_unregister:
kobject_put(&priv->kobj);
out_put_bus:
bus_put(bus);
return error;
}
我们把重点放在error = driver_attach(drv);
/**
* driver_attach - try to bind driver to devices.
* @drv: driver.
*
* Walk the list of devices that the bus has on it 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.
*/遍历总线上的设备
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
看到函数bus_for_each_dev了吧,是不是有种似曾相识的感觉
/**
* 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, and call @fn for each,
* passing it @data. If @start is not NULL, we use that device to
* begin iterating from.
*
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*
* NOTE: The device that returns a non-zero value is not retained
* in any way, nor is its refcount incremented. If the caller needs
* to retain this data, it should do, and increment the reference
* count in the supplied callback.
*/该函数迭代了在总线上的每个设备,并将相关的设备结构传递给fn,同时传递给data值,如果start是NULL,则将从总线上的第一个设备迭代,否则将从start后的第一个设备迭代。如果fn返回一个非零值,则停止迭代,而这个值也会返回
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
看看bus_for_each_dev的fn参数,调用了__driver_attach
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 (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
if (!dev->driver)
driver_probe_device(drv, dev);
up(&dev->sem);
if (dev->parent)
up(&dev->parent->sem);
return 0;
}
该函数与__device_attach一样也调用了driver_probe_device()。
从以上分析我们可以看出平台驱动注册的流程
platform_driver_probe->platform_driver_register->driver_register-> bus_add_driver
匹配总线上的设备的流程如下
bus_add_driver->driver_attach->bus_for_each_dev->__driver_attach->driver_probe_device->really_probe-> driver_bound
至此,平台设备的分析就结束了。