平台总线

platform总线是Linux虚拟的一条总线,总线类型定义如下:

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方法,match方法定义如下:

/**
 * 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 ACPI style match */
        if (acpi_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);
}

平台总线在匹配设备和驱动的时候,首先是看驱动中是否有id_table成员,如果有,则调用platform_match_id去匹配,如果没有,则只是简单的比较平台设备和平台驱动的name字段是否相同。


一、platform设备
平台设备使用struct platform_device来描述,该结构体定义在linux/platform_device.h中,注册平台设备使用platform_device_register函数,原型如下:
int platform_device_register(struct platform_device *pdev);
注销平台设备使用platform_device_unregister函数,原型如下:
void platform_device_unregister(struct platform_device *pdev);
平台设备操作实例如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>

MODULE_LICENSE("GPL");

static void my_platform_device_release(struct device *dev)
{
        printk("My platform device released.\n");
}

struct platform_device my_platform_device = {
        .name = "my_platform_device",
        .dev = {
                .release = my_platform_device_release,
        },
};

static int __init my_platform_device_init(void)
{
        int ret = 0;

        ret = platform_device_register(&my_platform_device);
        if (ret) {
                printk("Can't register my platform device!\n");
        }

        return ret;
}

static void __exit my_platform_device_exit(void)
{
        platform_device_unregister(&my_platform_device);
}

module_init(my_platform_device_init);
module_exit(my_platform_device_exit);

注意这里并没有指定设备的总线类型,platform_device_register函数会给我们去设置总线类型为platform_bus_type。

二、platform驱动
平台驱动使用struct platform_driver来描述,注册平台驱动使用platform_driver_register函数,原型如下:
int platform_driver_register(struct platform_driver *drv)
注销平台驱动使用platform_driver_unregister函数,原型如下:
void platform_driver_unregister(struct platform_driver *drv);

平台驱动实例如下:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>

MODULE_LICENSE("GPL");

static int my_platform_driver_probe(struct platform_device *dev)
{
        printk("Platform driver found device which my platform driver can handle.\n");
        return 0;
}

static int my_platform_driver_remove(struct platform_device *dev)
{
        printk("Platform driver found device unpluged.\n");
        return 0;
}

static struct platform_driver my_platform_driver = {
        .probe = my_platform_driver_probe,
        .remove = my_platform_driver_remove,
        .driver = {
                .owner = THIS_MODULE,
                .name = "my_platform_device",
        }
};

static int __init my_platform_driver_init(void)
{
        return platform_driver_register(&my_platform_driver);
}

static void __exit my_platform_driver_exit(void)
{
        platform_driver_unregister(&my_platform_driver);
}

module_init(my_platform_driver_init);
module_exit(my_platform_driver_exit);

同样也不需要指定总线类型,platform_driver_register函数会去给我们设置,这里并没有使用id_table,只是将平台设备和驱动的name字段设置为相同,平台总线会匹配成功,最终调用驱动中的probe函数。
以后还可以看到许多总线,比如i2c,usb,pci等,它们都有自己的设备和驱动注册方法,但是最终都是调用device_register和driver_register函数去完成设备和驱动的注册,在匹配成功之后,都会去调用驱动中的probe函数,只是match方法可能不相同而已,原理都是类似的。

你可能感兴趣的:(平台总线)