内核版本:Linux-3.10.46
platform的mach函数如下:
/**
* platform_match - bind platform device to platform driver.
* @dev: device.
* @drv: driver.
*
* Platform device IDs are assumed to be encoded like this:
* "", where is a short description of the type of
* device, like "pci" or "floppy", and is the enumerated
* instance of the device, like '0' or '42'. Driver IDs are simply
* "". So, extract the 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)) //ACPI风格匹配
return 1;
/* Then try to match against the id table */
if (pdrv->id_table) //匹配ID表(device设备名是否出现在driver的ID表中)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);//匹配设备名和驱动名
}
从match函数中可以看到,platform总线匹配设备和驱动有4种方法:
一是通过platform_driver中的id_table,如果id_table不存在,则只是简单的比较设备中的name字段和驱动中的name字段是否相同。
后面一种方法呢,已经见过无数次了,这里也就不再举例了,这里主要是看前一种方法。例如s3c-fb.c:
static struct platform_device_id s3c_fb_driver_ids[] = {
{
.name = "s3c-fb",
.driver_data = (unsigned long)&s3c_fb_data_64xx,
}, {
.name = "s5pc100-fb",
.driver_data = (unsigned long)&s3c_fb_data_s5pc100,
}, {
.name = "s5pv210-fb",
.driver_data = (unsigned long)&s3c_fb_data_s5pv210,
}, {
.name = "exynos4-fb",
.driver_data = (unsigned long)&s3c_fb_data_exynos4,
}, {
.name = "exynos5-fb",
.driver_data = (unsigned long)&s3c_fb_data_exynos5,
}, {
.name = "s3c2443-fb",
.driver_data = (unsigned long)&s3c_fb_data_s3c2443,
}, {
.name = "s5p64x0-fb",
.driver_data = (unsigned long)&s3c_fb_data_s5p64x0,
},
{},
};
上面就是platform_device_id,可以看到支持的不只一种,包括2410、2416等等。而Platform_driver定义如下:
static struct platform_driver s3c_fb_driver = {
.probe = s3c_fb_probe,
.remove = s3c_fb_remove,
.id_table = s3c_fb_driver_ids,
.driver = {
.name = "s3c-fb",
.owner = THIS_MODULE,
.pm = &s3cfb_pm_ops,
},
};
Louis210的platfrom_device定义如下:
struct platform_device s3c_device_fb = {
.name = "s3c-fb",//作为平台设备的LCD设备名
.id = -1,
.num_resources = ARRAY_SIZE(s3c_fb_resource),//资源数量
.resource = s3c_fb_resource,
.dev = {
.dma_mask = &samsung_device_dma_mask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
那么在匹配的时候,match函数会在驱动的id_table表里面查找同platform device的name字段是否相同,如果相同则返回true,否则返回false。那么通过id_table这种方式有什么好处呢,如果只是简单的比较name字段是否相同,那么一个驱动只能支持特定的一个设备,而如果通过id_table的方式呢,一个驱动可以支持很多个设备,而它们只是name字段不同而已。