Platform总线驱动描述

Linux内核虚拟了platform总线来管理一些没有挂载在真实总线的设备
platform总线也是遵循了总线 设备 驱动模型 总线下面对应设备 和 驱动 链表 无论注册驱动(设备) 都会匹配相应的设备(驱动)

平台设备的模块
static struct platform_device led_dev = {
    .name         = "myled",
};

static int led_dev_init(void)
{
    platform_device_register(&led_dev);
    return 0;
}

static void led_dev_exit(void)
{
    platform_device_unregister(&led_dev);
}
平台驱动的模块
struct platform_driver led_drv = {
    .probe      = led_probe,
    .remove     = led_remove,
    .driver     = {
        .name   = "myled",
    }
};


static int led_drv_init(void)
{
    platform_driver_register(&led_drv);
    return 0;
}
static void led_drv_exit(void)
{
    platform_driver_unregister(&led_drv);
}

首先我们先分析 从驱动发现设备的过程
当注册一个平台driver时

platform_driver_register(&led_drv);

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函数  

int driver_register(struct device_driver *drv)
{

//为总线增加一个驱动
    ret = bus_add_driver(drv);
}


然后进入
int bus_add_driver(struct device_driver *drv)
{
    这里根据总线的相关变量 来判断进入driver_attach 
    if (drv->bus->p->drivers_autoprobe) {//这里等于1 在总线注册bus_register的时候就赋值为1了
        error = driver_attach(drv);
        if (error)
            goto out_unregister;
    }
}

这里是遍历设备为驱动找到合适的设备 而且进入回调函数__driver_attach
int driver_attach(struct device_driver *drv)
{
    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}

int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int (*fn)(struct device *, void *))
{
    while ((dev = next_device(&i)) && !error)
        error = fn(dev, data);//这里的fn也就是传进来的__driver_attach函数
    klist_iter_exit(&i);
    return error;
}

//step 
static int __driver_attach(struct device *dev, void *data)
{
    struct device_driver *drv = data;
    //首先对驱动和设备进行匹配 具体分析如下说明
    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;
}

匹配过程
static inline int driver_match_device(struct device_driver *drv,  struct device *dev)
{
    //调用总线的match函数
    return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
总线的匹配函数再刚开始就已经赋值了 由此可见 设备与驱动的匹配是根据名字来进行
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);
//比较id_table里面是否支持
    /* Then try to match against the id table */
    if (pdrv->id_table)
        return platform_match_id(pdrv->id_table, pdev) != NULL;
//比较驱动的名字和设备的名字是否匹配
    /* fall-back to driver name match */
    return (strcmp(pdev->name, drv->name) == 0);
}

如果匹配成功就返回step 进而调用driver_probe_device(drv, dev); 最终调用
static int really_probe(struct device *dev, struct device_driver *drv)
{
    //如果有总线的probe就调用总线的probe 如果没有就调用驱动的probe函数
    if (dev->bus->probe) {
        ret = dev->bus->probe(dev);
        if (ret)
            goto probe_failed;
    } else if (drv->probe) {
        ret = drv->probe(dev);
        if (ret)
            goto probe_failed;
    }
}

现在谈论设备发现驱动的流程

猜你喜欢

转载自blog.csdn.net/u012855539/article/details/78913201
今日推荐