linux通过platform_match()匹配platform总线上的device和driver
发布日期:2021-06-30 21:47:00 浏览次数:2 分类:技术文章

本文共 6999 字,大约阅读时间需要 23 分钟。

\kernel\msm-4.9\drivers\base\platform.c定义了platform_match()的实现,先来看定义

/** * 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); /* When driver_override is set, only bind to the matching driver */ if (pdev->driver_override) return !strcmp(pdev->driver_override, drv->name); /* Attempt an OF style match first */ //第1种匹配方式,OF类型匹配,设备树采用的匹配方式 if (of_driver_match_device(dev, drv)) return 1; /* Then try ACPI style match */ //第2种匹配方式,ACPI匹配 if (acpi_driver_match_device(dev, drv)) return 1; /* Then try to match against the id table */ //第3种匹配方式,id_table匹配 if (pdrv->id_table) return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */ //第4种匹配方式,直接比较驱动和设备的name字段 return (strcmp(pdev->name, drv->name) == 0);}

可以看到,platform_match可以使用四种匹配方式

第1种:OF类型匹配,设备树采用的匹配方式

kernel\msm-4.9\include\linux\of_device.h\of_driver_match_device()定义如下:

/** * of_driver_match_device - Tell if a driver's of_match_table matches a device. * @drv: the device_driver structure to test * @dev: the device structure to match against */static inline int of_driver_match_device(struct device *dev,					 const struct device_driver *drv){	return of_match_device(drv->of_match_table, dev) != NULL;}

调用of_match_device(drv->of_match_table, dev)来实现匹配,此函数在kernel\msm-4.9\drivers\of\device.c种定义

/** * of_match_device - Tell if a struct device matches an of_device_id list * @ids: array of of device match structures to search in * @dev: the of device structure to match against * * Used by a driver to check whether an platform_device present in the * system is in its list of supported devices. */const struct of_device_id *of_match_device(const struct of_device_id *matches,					   const struct device *dev){	if ((!matches) || (!dev->of_node))		return NULL;	return of_match_node(matches, dev->of_node);}EXPORT_SYMBOL(of_match_device);

这里调用of_match_node(),此函数在kernel\msm-4.9\drivers\of\base.c中定义

/** * of_match_node - Tell if a device_node has a matching of_match structure *	@matches:	array of of device match structures to search in *	@node:		the of device structure to match against * *	Low level utility function used by device matching. */const struct of_device_id *of_match_node(const struct of_device_id *matches,					 const struct device_node *node){	const struct of_device_id *match;	unsigned long flags;    raw_spin_lock_irqsave(&devtree_lock, flags);	match = __of_match_node(matches, node);	raw_spin_unlock_irqrestore(&devtree_lock, flags);	return match;}EXPORT_SYMBOL(of_match_node);

调用__of_match_node(),此函数在kernel\msm-4.9\drivers\of\base.c中定义

staticconst struct of_device_id *__of_match_node(const struct of_device_id *matches,					   const struct device_node *node){	const struct of_device_id *best_match = NULL;	int score, best_score = 0;    if (!matches)		return NULL;    //name,type,compatible需要有一个非NULL。	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {		score = __of_device_is_compatible(node, matches->compatible,						  matches->type, matches->name);		if (score > best_score) {			best_match = matches;			best_score = score;		}	}    	return best_match;}

调用 __of_device_is_compatible(node, matches->compatible, matches->type, matches->name),此函数在kernel\msm-4.9\drivers\of\base.c中定义

/** * __of_device_is_compatible() - Check if the node matches given constraints * @device: pointer to node * @compat: required compatible string, NULL or "" for any match * @type: required device_type value, NULL or "" for any match * @name: required node name, NULL or "" for any match * * Checks if the given @compat, @type and @name strings match the * properties of the given @device. A constraints can be skipped by * passing NULL or an empty string as the constraint. * * Returns 0 for no match, and a positive integer on match. The return * value is a relative score with larger values indicating better * matches. The score is weighted for the most specific compatible value * to get the highest score. Matching type is next, followed by matching * name. Practically speaking, this results in the following priority * order for matches: * * 1. specific compatible && type && name * 2. specific compatible && type * 3. specific compatible && name * 4. specific compatible * 5. general compatible && type && name * 6. general compatible && type * 7. general compatible && name * 8. general compatible * 9. type && name * 10. type * 11. name */static int __of_device_is_compatible(const struct device_node *device,				     const char *compat, const char *type, const char *name){	struct property *prop;	const char *cp;	int index = 0, score = 0;    /* Compatible match has highest priority */    if (compat && compat[0]) {		prop = __of_find_property(device, "compatible", NULL);        for (cp = of_prop_next_string(prop, NULL); cp;		     cp = of_prop_next_string(prop, cp), index++) {			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {				score = INT_MAX/2 - (index << 2);				break;			}		}        	if (!score)			return 0;	}    /* Matching type is better than matching name */	if (type && type[0]) {		if (!device->type || of_node_cmp(type, device->type))			return 0;		score += 2;	}    /* Matching name is a bit better than not */	if (name && name[0]) {		if (!device->name || of_node_cmp(name, device->name))			return 0;		score++;	}	return score;}

先判断设备节点compatible属性的值和驱动中of_match_table的compatible成员是否相等

下面是设备节点的compatible属性:

gpio_control {		compatible = "gpio-control";        ...}

下面是驱动中of_match_table的compatible成员

static const struct of_device_id gpio_control_of_match[] = {	{ .compatible = "gpio-control", },	{ },};static struct platform_driver gpio_control_device_driver = {	.probe		= gpio_control_probe,	.remove		= gpio_control_remove,    .driver		= {		.name	= "gpio-control",		.owner	= THIS_MODULE,		.pm	= &gpio_control_pm_ops,		.of_match_table = of_match_ptr(gpio_control_of_match),	}};

后面判断type和name。

第2种:ACPI匹配

kernel\msm-4.9\drivers\acpi\bus.c定义了acpi_driver_match_device()的实现

第3种:id_table匹配

kernel\msm-4.9\drivers\base\platform.c定义了platform_match_id的实现()

static const struct platform_device_id *platform_match_id(			const struct platform_device_id *id,			struct platform_device *pdev){    	while (id->name[0]) {		if (strcmp(pdev->name, id->name) == 0) {			pdev->id_entry = id;			return id;		}		id++;	}	return NULL;}

判断id_table->name和设备节点名称是否相同

第4种:直接比较驱动和设备的name字段

 

转载地址:https://loongembedded.blog.csdn.net/article/details/115723883 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:ROS系统相关链接
下一篇:展会收集

发表评论

最新留言

感谢大佬
[***.8.128.20]2024年05月02日 05时13分30秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章