美文网首页
Linux DRM那些事-平台驱动匹配和探测

Linux DRM那些事-平台驱动匹配和探测

作者: 小田BSP | 来源:发表于2021-02-27 19:49 被阅读0次

    Linux内核通过module_platform_driver(rockchip_drm_platform_driver)函数注册RK3399 DRM框架驱动代码,该宏展开如下:

    static int __init rockchip_drm_platform_driver_init(void)
    {
        return platform_driver_register(&rockchip_drm_platform_driver);
    }
    ...
    

    下面通过分析函数platform_driver_register()的调用流程,展示RK3399 DRM框架platform_deviceplatform_driver匹配过程和驱动探测过程。

    具体调用流程如下:

    rockchip_drm_platform_driver_init()->                                      ## rockchip_drm_drv.c
        platform_driver_register()->                                           ## platform_device.h
            __platform_driver_register()->                                     ## platform.c            
                driver_register()->                                            ## driver.c
                    bus_add_driver()->                                         ## bus.c
                        driver_attach()->                                      ## dd.c
                            bus_for_each_dev()->                               ## bus.c
                                __driver_attach()->                            ## dd.c
                                    1.driver_match_device()->                  ## base.h match
                                        platform_match()                       ## platform.c        开始match
                                    2.driver_probe_device()->                  ## dd.c probe
                                        really_probe()->                       ## dd.c
                                            platform_drv_probe()->             ## platform.c        开始probe
                                                rockchip_drm_platform_probe()  ## rockchip_drm_drv.c 
    

    一、match实现

    在注册Linux内核platform总线时,相关的总线类型定义如下:

    struct bus_type platform_bus_type = {
        .name       = "platform",
        .dev_groups = platform_dev_groups,
        .match      = platform_match,
        .uevent     = platform_uevent,
        .pm     = &platform_dev_pm_ops,
    };
    EXPORT_SYMBOL_GPL(platform_bus_type);
    

    bus_type结构体中定义了platform deviceplatform driver的匹配函数platform_match(),具体实现如下:

    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);
    
        /* When driver_override is set, only bind to the matching driver */
        if (pdev->driver_override)
            return !strcmp(pdev->driver_override, drv->name);
    
        ## 1.设备树匹配
        /* Attempt an OF style match first */
        if (of_driver_match_device(dev, drv))
            return 1;
    
        ## 2.ACPI类型匹配(无)
        /* Then try ACPI style match */
        if (acpi_driver_match_device(dev, drv))
            return 1;
    
        ## 3.id table匹配
        /* Then try to match against the id table */
        if (pdrv->id_table)
            return platform_match_id(pdrv->id_table, pdev) != NULL;
    
        ## 4.device和driver名字匹配
        /* fall-back to driver name match */
        return (strcmp(pdev->name, drv->name) == 0);
    }
    

    platform deviceplatform driver的匹配方法包括:

    1、设备树匹配

    匹配方法:比较dts设备节点的compatible属性定义和驱动文件中of_device_id中的compatible定义是否相同。

    注:RK3399 DRM驱动使用的是设备树匹配.

    #1. rockchip_drm_drv.c compatible定义
    static const struct of_device_id rockchip_drm_dt_ids[] = {
        { .compatible = "rockchip,display-subsystem", },
        ...
    };
    MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids);
    
    static struct platform_driver rockchip_drm_platform_driver = {
        ...
        .driver = {
            .name = "rockchip-drm",
            .of_match_table = rockchip_drm_dt_ids,
            ...
        },
    };
    
    #2. rk3399.dtsi compatible定义
        display_subsystem: display-subsystem {
            compatible = "rockchip,display-subsystem";
            ...
        };
    

    2、ACPI类型匹配 (无)

    3、id table匹配

    4、device和driver名字匹配

    二、probe实现

    在实现了DRM的platform deviceplatform driver匹配后,会进入Linux内核的platform_driver中的probe探测函数进行DRM驱动探测函数的调用。platform_driver初始化如下:

    int __platform_driver_register(struct platform_driver *drv,
                    struct module *owner)
    {
        drv->driver.owner = owner;
        drv->driver.bus = &platform_bus_type;
        drv->driver.probe = platform_drv_probe;
        drv->driver.remove = platform_drv_remove;
        drv->driver.shutdown = platform_drv_shutdown;
    
        return driver_register(&drv->driver);
    }
    

    platform_drv_probe实现如下:

    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);
        int ret;
    
        ...
    
        ret = dev_pm_domain_attach(_dev, true);
        if (ret != -EPROBE_DEFER) {
            if (drv->probe) {
                ## 调用各驱动的probe函数(例:DRM的rockchip_drm_platform_driver())
                ret = drv->probe(dev);
                if (ret)
                    dev_pm_domain_detach(_dev, true);
            } else {
                /* don't fail if just dev_pm_domain_attach failed */
                ret = 0;
            }
        }
        ...
    }
    

    小结:

    1、RK3399 DRM框架的platform deviceplatform driver在Linux内核platform busmatch函数中实现匹配。

    2、RK3399 DRM驱动的probe是在Linux内核platform driverprobe中调用。

    注:本文基于RockPI 4A单板的Debian系统 Linux4.4内核。

    注:本文仅在简书、OSCHINA和今日头条发布过,转载请标注原作者和链接。

    相关文章

      网友评论

          本文标题:Linux DRM那些事-平台驱动匹配和探测

          本文链接:https://www.haomeiwen.com/subject/gmbifltx.html