嵌入式Linux驱动开发 —— 从DTS到代码的桥梁与简单OF系列API(3)
接前一篇文章嵌入式Linux驱动开发 —— 从DTS到代码的桥梁与简单OF系列API2节点查找 API如何在设备树中定位目标节点有了数据结构基础现在我们可以开始讲具体的API了。第一步是找到你要操作的节点。就像你想操作一个文件得先找到它的路径一样你想操作设备树里的某个节点也得先定位到它。内核提供了好几种查找节点的方法适用于不同的场景。我们一个一个来看。of_find_node_by_path按路径查找这是最直接的方法。如果你知道节点的完整路径用这个函数最快struct device_node *of_find_node_by_path(const char *path);参数path是节点的完整路径比如/imx_aes_led。返回值是找到的节点指针如果没找到就返回NULL。这个函数在我们的LED驱动里用到了/* 从 /home/charliechen/imx-forge/driver/device_tree_try_03/alpha-board/led_hw.c */ static const char* kIMX_AES_LED /imx_aes_led; led.device_tree_node of_find_node_by_path(kIMX_AES_LED); if (led.device_tree_node NULL) { pr_err(dtsled node can not found!\n); return -EINVAL; }这里我们直接用路径/imx_aes_led去找节点。这个路径对应设备树里的定义/* 从 /home/charliechen/imx-forge/driver/device_tree/alpha-board/device_tree_try_03/imx6ull-aes-led.dts */ / { imx_aes_led { #address-cells 1; #size-cells 1; compatible atkalpha-led; status okay; reg ...; }; };of_find_node_by_path()的好处是简单直接缺点是你要知道确切的路径。如果你只是想找某个类型的设备比如所有的 GPIO 控制器这个方法就不太方便了。of_find_node_by_name按节点名查找struct device_node *of_find_node_by_name(struct device_node *from, const char *name);这个函数按节点名查找。注意节点名不是compatible属性而是节点本身的名字。比如节点gpio1 { ... }的名字就是gpio1。from参数指定从哪里开始找。如果传NULL就从根节点开始遍历整棵树。如果传一个具体的节点就从那个节点之后继续找这个设计允许你多次调用来遍历所有同名节点。这个函数在实际驱动里用得不多因为节点名往往不够具体。同一个设备树上可能有很多叫gpio的节点你很难确定找到的是哪一个。of_find_compatible_node按兼容性查找这是驱动里最常用的查找函数struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible);参数说明这个函数会遍历设备树找到第一个compatible属性包含指定字符串的节点。比如你可以用fsl,imx6ul-gpio来找NXP的GPIO控制器。这里需要注意一点compatible属性可以包含多个字符串用逗号分隔。of_find_compatible_node()会检查所有这些字符串只要有一个匹配就认为找到了。of_find_matching_node_and_match按匹配表查找这是最强大的查找函数它直接拿驱动里的of_device_id匹配表去过滤节点struct device_node *of_find_matching_node_and_match( struct device_node *from, const struct of_device_id *matches, const struct of_device_id **match);matches参数就是驱动里的.of_match_table比如static const struct of_device_id led_of_match[] { { .compatible atkalpha-led, }, { /* sentinel */ } };这个函数会遍历匹配表找到第一个匹配的节点。match是输出参数告诉你具体匹配上了表里的哪一项。在实际的platform驱动框架里这个函数通常不需要你手动调用。驱动核心会自动帮你匹配。但如果你在写一些特殊逻辑比如在驱动初始化时主动查找某个设备这个函数就很有用了。更多内容请看下回。from起始节点NULL表示从根开始typedevice_type属性值可以传NULL表示不检查compatible要匹配的compatible属性字符串