linux通过platform_match()匹配platform总线上的device和driver
\kernel\msm-4.9\drivers\base\platform.c定義了platform_match()的實(shí)現(xiàn),先來看定義
/*** 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);/* 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類型匹配,設(shè)備樹采用的匹配方式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種匹配方式,直接比較驅(qū)動和設(shè)備的name字段return (strcmp(pdev->name, drv->name) == 0); }可以看到,platform_match可以使用四種匹配方式
第1種:OF類型匹配,設(shè)備樹采用的匹配方式
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; }調(diào)用of_match_device(drv->of_match_table, dev)來實(shí)現(xiàn)匹配,此函數(shù)在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);這里調(diào)用of_match_node(),此函數(shù)在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);調(diào)用__of_match_node(),此函數(shù)在kernel\msm-4.9\drivers\of\base.c中定義
static const 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需要有一個(gè)非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; }調(diào)用?__of_device_is_compatible(node, matches->compatible,?matches->type, matches->name),此函數(shù)在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; }先判斷設(shè)備節(jié)點(diǎn)compatible屬性的值和驅(qū)動中of_match_table的compatible成員是否相等
下面是設(shè)備節(jié)點(diǎn)的compatible屬性:
gpio_control {compatible = "gpio-control";... }下面是驅(qū)動中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()的實(shí)現(xiàn)
第3種:id_table匹配
kernel\msm-4.9\drivers\base\platform.c定義了platform_match_id的實(shí)現(xiàn)()
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和設(shè)備節(jié)點(diǎn)名稱是否相同
第4種:直接比較驅(qū)動和設(shè)備的name字段
?
總結(jié)
以上是生活随笔為你收集整理的linux通过platform_match()匹配platform总线上的device和driver的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 展会收集
- 下一篇: 机器人差速驱动方式(Differenti