probe()函數是什麼時候被調用,裝置和驅動是怎麼聯系起來的??
platform_add_devices(ldd6410_devices, ARRAY_SIZE(ldd6410_devices)); //這是bsp中添加所有的裝置--》 platform_device_register(devs[i]);//注冊平台裝置---》platform_device_add(pdev);将平台裝置加入到platform_bus中---》device_add(&pdev->dev);
下面是驅動
static int __init gpio_led_init(void)
{
return platform_driver_register(&gpio_led_driver); //注冊平台驅動
}
platform_driver_register(&gpio_led_driver) ----》driver_register(&drv->driver);----》bus_add_driver(drv); //添加驅動到總線 ---》driver_attach(drv);//為驅動尋找相應的裝置----》
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); //周遊裝置總線尋找驅動
}
-----》__driver_attach()
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
if (drv->bus->match && !drv->bus->match(dev, drv)) //通過match判斷驅動和裝置是否比對,這裡通過比較dev和drv中的裝置名來判斷,是以裝置名需要唯一
return 0;
if (dev->parent)
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;
}
driver_probe_device(drv, dev); ---》really_probe(dev, drv);
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->bus_id);
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->bus_id);
goto probe_failed;
}
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev); //這裡才真正調用了驅動的probe
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->bus_id, 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->bus_id, ret);
}
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}