我是靠谱客的博主 大意蜗牛,这篇文章主要介绍Linux fwnode和device_node的区别,现在分享给大家,希望可以做个参考。

Linux fwnode和device_node的区别


废话不多说,直接开干。
fwnode_property_read_u32(dev_fwnode(&client->dev), “rotation”, &rotation);为例子
先看dev_fwnode();

复制代码
1
2
3
4
5
6
7
8
9
struct fwnode_handle *dev_fwnode(struct device *dev) { return IS_ENABLED(CONFIG_OF) && dev->of_node ? &dev->of_node->fwnode : dev->fwnode; } EXPORT_SYMBOL_GPL(dev_fwnode); dev_fwnodes如果支持设备树,就从设备树节点中获取并返回fwnode
复制代码
1
2
3
4
5
6
7
static inline int fwnode_property_read_u32(const struct fwnode_handle *fwnode, const char *propname, u32 *val) { return fwnode_property_read_u32_array(fwnode, propname, val, 1); } 调用了fwnode_property_read_u32_array,很合理,继续
复制代码
1
2
3
4
5
6
7
8
int fwnode_property_read_u32_array(const struct fwnode_handle *fwnode, const char *propname, u32 *val, size_t nval) { return fwnode_property_read_int_array(fwnode, propname, sizeof(u32), val, nval); } EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);

没问题,继续

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode, const char *propname, unsigned int elem_size, void *val, size_t nval) { int ret; ret = fwnode_call_int_op(fwnode, property_read_int_array, propname, elem_size, val, nval); if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) && !IS_ERR_OR_NULL(fwnode->secondary)) ret = fwnode_call_int_op( fwnode->secondary, property_read_int_array, propname, elem_size, val, nval); return ret; }
复制代码
1
2
3
4
5
6
7
#define fwnode_has_op(fwnode, op) ((fwnode) && (fwnode)->ops && (fwnode)->ops->op) #define fwnode_call_int_op(fwnode, op, ...) (fwnode ? (fwnode_has_op(fwnode, op) ? (fwnode)->ops->op(fwnode, ## __VA_ARGS__) : -ENXIO) : -EINVAL)
复制代码
1
2
3
fwnode_property_read_int_array()fwnode_call_int_op()调用了fwnode中fwnode_operations的 property_read_int_array(),并把参数传进property_read_int_array。

fwnode_operations回调函数的设置是在内核初始化发生的
追踪到内核初始化的代码,里面有一句。

复制代码
1
2
3
4
5
6
static inline void of_node_init(struct device_node *node) { kobject_init(&node->kobj, &of_node_ktype); node->fwnode.ops = &of_fwnode_ops; }

继续

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const struct fwnode_operations of_fwnode_ops = { .get = of_fwnode_get, .put = of_fwnode_put, .device_is_available = of_fwnode_device_is_available, .device_get_match_data = of_fwnode_device_get_match_data, .property_present = of_fwnode_property_present, .property_read_int_array = of_fwnode_property_read_int_array, .property_read_string_array = of_fwnode_property_read_string_array, .get_parent = of_fwnode_get_parent, .get_next_child_node = of_fwnode_get_next_child_node, .get_named_child_node = of_fwnode_get_named_child_node, .get_reference_args = of_fwnode_get_reference_args, .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint, .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint, .graph_get_port_parent = of_fwnode_graph_get_port_parent, .graph_parse_endpoint = of_fwnode_graph_parse_endpoint, }; EXPORT_SYMBOL_GPL(of_fwnode_ops);
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
static int of_fwnode_property_read_int_array(const struct fwnode_handle *fwnode, const char *propname, unsigned int elem_size, void *val, size_t nval) { const struct device_node *node = to_of_node(fwnode); if (!val) return of_property_count_elems_of_size(node, propname, elem_size); switch (elem_size) { case sizeof(u8): return of_property_read_u8_array(node, propname, val, nval); case sizeof(u16): return of_property_read_u16_array(node, propname, val, nval); case sizeof(u32): return of_property_read_u32_array(node, propname, val, nval); case sizeof(u64): return of_property_read_u64_array(node, propname, val, nval); } return -ENXIO; }

看见最后一个函数,都明白了,const struct device_node *node = to_of_node(fwnode);
fwnode就是of_node,所有的fwnode_函数都是二次封装的of_函数。
所以在驱动中,有的人喜欢有fwnode对设备树进行解析,有的人喜欢用of,功能都是一样的,没必要纠结。

最后

以上就是大意蜗牛最近收集整理的关于Linux fwnode和device_node的区别的全部内容,更多相关Linux内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(99)

评论列表共有 0 条评论

立即
投稿
返回
顶部