08 在设备树里描述platform_device【转】

转自:https://blog.csdn.net/jklinux/article/details/78575281

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/jklinux/article/details/78575281 在设备树的dts文件里,带有compatible属性的节点就是表示一个platform_device.

在设备树里增加一个设备,则在内核里的dts文件里描述设备节点即可. 在H5方案里,则在arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts文件里。 如在dts文件里加入以下内容:

mynodes@77885566 { /* 则创建出来的platform_device的名为mynodes@77885566 */ compatible = "mynodes"; /* 设备节点的属性 */ autorepeat = <1>;

btn1 { /* 设备子节点 */ label = "btn1"; /* 设备子节点的属性 */ code = <0x11>; }; btn2 { label = "btn2"; code = <0x22>; }; }; 增加内容后,则重编设备树:

make dtbs ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 1 再把编译出来的sun50i-h5-nanopi-neo2.dtb替换板上所用的dtb文件,重启系统后,可以查看到内容:

^_^ / # ls /sys/bus/platform/devices/mynodes@77885566/ driver_override of_node/ subsystem/ modalias power/ uevent

^_^ / # ls /sys/bus/platform/devices/mynodes@77885566/of_node/ autorepeat btn1/ btn2/ compatible name 1 2 3 4 5 6 在dst设备树文件描述设备后就需要与platform_driver进行匹配和驱动了. 在设备驱动里获取设备树中的设备资源需要一套接口函数来实现:

#include <linux/property.h>

//用于获取设备节点的属性成员值函数, propname用于指定要获取值的属性名 bool device_property_present(struct device *dev, const char *propname); int device_property_read_u8_array(struct device *dev, const char *propname, u8 *val, size_t nval); int device_property_read_u16_array(struct device *dev, const char *propname, u16 *val, size_t nval); int device_property_read_u32_array(struct device *dev, const char *propname, u32 *val, size_t nval); int device_property_read_u64_array(struct device *dev, const char *propname, u64 *val, size_t nval); int device_property_read_string_array(struct device *dev, const char *propname, const char **val, size_t nval); int device_property_read_string(struct device *dev, const char *propname, const char **val); int device_property_match_string(struct device *dev, const char *propname, const char *string);

//用于获取设备子节点的属性值函数. fwnode是表示子节点的对象地址 bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname); int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, const char *propname, u8 *val, size_t nval); int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, const char *propname, u16 *val, size_t nval); int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, const char *propname, u32 *val, size_t nval); int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, const char *propname, u64 *val, size_t nval); int fwnode_property_read_string_array(struct fwnode_handle *fwnode, const char *propname, const char **val, size_t nval); int fwnode_property_read_string(struct fwnode_handle *fwnode, const char *propname, const char **val); int fwnode_property_match_string(struct fwnode_handle *fwnode, const char *propname, const char *string);

struct fwnode_handle *device_get_next_child_node(struct device *dev, struct fwnode_handle *child);

---------- unsigned int device_get_child_node_count(struct device *dev); //获取设备的子节点个数

//产生一个for循环用于检查所有的子节点 #define device_for_each_child_node(dev, child) \ for (child = device_get_next_child_node(dev, NULL); child; \ child = device_get_next_child_node(dev, child))

//注意函数以"device"开头表示读取设备的属性, 以"fwnode"开头表示读取子节点的属性. 用于获取mynodes设备资源的驱动源码:

/* mydrv.c */

#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/property.h>

int myprobe(struct platform_device *pdev) { struct fwnode_handle *fwhandle; const char *str; u32 val;

//获取设备子节点的个数 printk("child node count : %d\n", device_get_child_node_count(&pdev->dev)); //获取设备属性autorepeat的值 printk("%d\n", device_property_read_bool(&pdev->dev, "autorepeat"));

//遍历设备的每个子节点 device_for_each_child_node(&pdev->dev, fwhandle) { //获取设备子节点的label属性值 fwnode_property_read_string(fwhandle, "label", &str); printk("label = %s\n", str); //获取设备子节点的code属性值 fwnode_property_read_u32(fwhandle, "code", &val); printk("code = %x\n", val); };

return 0; }

int myremove(struct platform_device *pdev) { printk("in myremove ...\n"); return 0; }

struct of_device_id ids[] = { {.compatible = "mynodes"}, {}, };

struct platform_driver mydrv = { .probe = myprobe, .remove = myremove,

.driver = { .owner = THIS_MODULE, .name = "mydrv" ,

.of_match_table = ids, }, };

module_platform_driver(mydrv); MODULE_LICENSE("GPL"); 1 2 编译驱动模块加载后的输出结果:

[ 419.424065] child node count : 2 [ 419.427429] 1 [ 419.429054] label = btn1 [ 419.431690] code = 11 [ 419.434000] label = btn2 [ 419.436623] code = 22 ———————————————— 版权声明:本文为CSDN博主「jklinux」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/jklinux/article/details/78575281

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端小课堂

前端面试题

2年工作经验出去接受社会的毒打,参与的前端社招的公司和题目的记录如下,后续可能还会有增加,先暂时记录这么多:

12520
来自专栏web秀

JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式!

在单线程环境中编程的缺陷以及如何解决这些缺陷来构建健壮的JavaScript UI。按照惯例,在本文的最后,分享5个如何使用async/ wait编写更简洁代码...

7420
来自专栏WalkingCloud

CentOS6中RHCS集群的简单实践

先搭建三台如下CentOS6.9的虚拟主机节点,已配置好双机互信,参考之前文章高可用集群Heartbeat配置实践

9230
来自专栏美团技术团队

JVM CPU Profiler技术原理及源码深度解析

研发人员在遇到线上报警或需要优化系统性能时,常常需要分析程序运行行为和性能瓶颈。Profiling技术是一种在应用运行时收集程序相关信息的动态分析手段,常用的J...

13420
来自专栏趣谈前端

基于nodeJS从0到1实现一个CMS全栈项目的服务端启动细节

我们可以去redis官网下载redis安装程序,我主要介绍window和 linux系统下的安装,如果你是其他系统,可以去官网查看相关资料。

8830
来自专栏包子铺里聊IT

Baozi Training Leetcode solution 199:Binary Tree Right Side View

Leetcode solution 199:Binary Tree Right Side View

9030
来自专栏咖啡拿铁

异步技巧之CompletableFuture

在上面的注释中我们能知道Future用来代表异步的结果,并且提供了检查计算完成,等待完成,检索结果完成等方法。简而言之就是提供一个异步运算结果的一个建模。它可以...

10140
来自专栏咖啡拿铁

并行化-你的高并发大杀器

想必热爱游戏的同学小时候,都幻想过要是自己要是能像鸣人那样会多重影分身之术,就能一边打游戏一边上课了,可惜漫画就是漫画,现实中并没有这个技术,你要么只有老老实实...

12310
来自专栏WalkingCloud

CentOS6下配置基于CHAP认证的iSCSI网络存储服务

之前有简单介绍过iscsi网络存储的基本配置CentOS配置iSCSI网络存储服务,下面再详细介绍iSCSI服务端与客户端的常用命令tgtadm和iscsiad...

13720
来自专栏前端迷

Babel 的工作原理以及怎么写一个 Babel 插件

在前端圈子里,对于 Babel,大家肯定都比较熟悉了。如果哪天少了它,对于前端工程师来说肯定是个噩梦。Babel 的工作原理是怎样的可能了解的人就不太多了。

18330

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励