• 3.0.35 platform 总线、设备与驱动


    在该内核的设备驱动模型中,关心总线、设备和驱动这三个实体。

    在系统每注册一个设备的时候,由总线寻找与之匹配的驱动;在系统每注册一个驱动的时候,会由总线寻找与之匹配的设备。

    一个现实的linux设备和驱动通常都需要挂载在一种总线上,对于本身依附于PCI,USB,I2C,SPI等的设备而言,这不是问题

    但在嵌入式系统中,SoC系统中集成了独立的外设控制器,集成于SoC中的外设却不依赖于这类总线。基于这一背景,linux

    发明了一种虚拟总线,称为platform总线,platform 所描述的资源有一个共同点:在 CPU 的总线上直接取址。相应的,

    设备称为platform_device,驱动称为platform_driver。

    两者的工作顺序是

    • 先定义 platform_device -> 注册 platform_device
    • 再定义 platform_driver -> 注册 platform_driver

    注意:所谓的platform_device并不是与字符设备、块设备、网络设备并列的概念,而是linux系统提供的一种附加手段。

    platform_device 结构体的定义(include/linux/platform_device.h),如下示:

    struct platform_device {
        const char    * name; // 设备名用于和驱动进行绑定
        int        id;         // 设备ID
        struct device    dev;
        u32        num_resources; // 设备所使用各类资源数量
        struct resource    * resource; // 资源
    
        const struct platform_device_id    *id_entry;
    
        /* MFD cell pointer */
        struct mfd_cell *mfd_cell;
    
        /* arch specific additions */
        struct pdev_archdata    archdata;
    };

    platform_driver 结构体的定义(include/linux/platform_device.h),如下示:

    struct platform_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;
    };

    该结构体中包含 probe(), remove(), shutdown, suspend(), resume函数,通常也需要由驱动实现。

    系统中为platform 总线定义了一个bus_type 的实例 platform_bus_type(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,
    };
    EXPORT_SYMBOL_GPL(platform_bus_type);

    这里要重点关注 match() 成员函数,正是此函数确定了 platform_device 和 platform_driver 之间是如何配置的。

    platform_match 定义(drivers/base/platform.c)如下:

    /**
     * platform_match - bind platform device to platform driver.
     * @dev: device.
     * @drv: driver.
     *
     * Platform device IDs are assumed to be encoded 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 the platform_device structure,
     * and compare it against the name of the driver. Return whether they match
     * or not.
     */
    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);
    
        /* Attempt an OF style match first */
        if (of_driver_match_device(dev, drv))
            return 1;
    
        /* 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);
    }

    由上可知, 匹配platform_device 和 platform_driver 主要看两者的 name字段是否相同。

    对platform_device 的定义通常在BSP的板文件中实现,在板文件中,将platform_device 归纳为一个数组,最终通过

    platform_add_devices() 函数统一注册。其定义(drivers/base/platform.c)如下:

    /**
     * platform_add_devices - add a numbers of platform devices
     * @devs: array of platform devices to add
     * @num: number of platform devices in array
     */
    int platform_add_devices(struct platform_device **devs, int num)
    {
        int i, ret = 0;
    
        for (i = 0; i < num; i++) {
            ret = platform_device_register(devs[i]);
            if (ret) {
                while (--i >= 0)
                    platform_device_unregister(devs[i]);
                break;
            }
        }
    
        return ret;
    }
    EXPORT_SYMBOL_GPL(platform_add_devices);

    platform_add_devices() 函数可以将平台设备添加到系统中,该函数的第一个参数为平台设备数组的指针,第二个参数为平台设备

    的数量,它内部调用了platform_device_register() 函数,用于注册单个的平台设备。

  • 相关阅读:
    C# Dictionary 字典
    int.Parse()与int.TryParse()
    jquery 随机数
    DateGradeView分页绑定
    使用tcpdump抓Android网络包
    Android快速开发框架——AndroidAnnotations(Code Diet)
    浅谈 android-query
    Android网络框架技术
    PHP: 深入了解一致性哈希
    png图片压缩优化
  • 原文地址:https://www.cnblogs.com/aqing1987/p/4353969.html
Copyright © 2020-2023  润新知