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。
平台驱动实例如下:
#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函数。