在设备树中描述platform_device

背景

在高通平台做gpio按键配置的时候,根据之前的经验,想从设备树中对应的关键字找到实际的驱动解析实现,以此加深对设备树属性配置的理解。

但是我并没有找到,只是知道在drivers/input/keyboard/gpio_keys.c解析了那一段的配置。翻阅以前自己整理的文章,也没发现一个所以然。

看来,对设备树的学习还是不能停下。

Reference:

介绍

定义:在设备树的dts文件里,带有compatible属性的节点就是表示一个platform_device.

用法:在设备树里增加一个设备节点,在内核里的dts文件里描述设备节点;此后,编写驱动代码完成对其的解析即可。

接口函数

在设备驱动里获取设备树中的设备资源需要一套接口函数来实现:

#include <linux/property.h>

函数以device开头表示读取设备的属性, 以fwnode开头表示读取子节点的属性。

参数propname代表指定要获取值的属性名。

设备属性

判断属性是否存在

bool device_property_present(struct device *dev, const char *propname);

常见用法1:作为指定的属性

    nvmem->read_only = device_property_present(config->dev, "read-only") |
config->read_only;
//...; if (nvmem->read_only) {
//...;
}

    /* Retrieve the PHY configuration properties */
if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
ret = device_property_read_u32_array(pdata->phy_dev,
XGBE_BLWC_PROPERTY,
phy_data->blwc,
XGBE_SPEEDS);
if (ret) {
dev_err(pdata->dev, "invalid %s property\n",
XGBE_BLWC_PROPERTY);
return ret;
}
} else {
memcpy(phy_data->blwc, xgbe_phy_blwc,
sizeof(phy_data->blwc));
}

获取整数值

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);

nval 代表 返回的数组成员个数。

文本值

获取
int device_property_read_string(struct device *dev, const char *propname,
const char **val);

注:获取到的值会放进val中;

常见用法:

    device_property_read_string(dev, "label", &pdata->name);

		my_key {
label = "btn1";
gpios = <&tlmm 102 0x1>; linux,input-type = <1>;
linux,code = <59>; debounce-interval = <15>; linux,can-disable;
gpio-key,wakeup;
};
判断文本值是否匹配
int device_property_match_string(struct device *dev,
const char *propname, const char *string);

例如:

    if (!device_property_match_string(dev, "rotary-encoder,encoding",
"binary")) {
dev_info(dev, "binary");
encoder->encoding = ROTENC_BINARY;
} else {
dev_err(dev, "unknown encoding setting\n");
return -EINVAL;
}

获取子节点

/* 获取个数 */
unsigned int device_get_child_node_count(struct device *dev); //获取设备的子节点个数 /* 获取下一个子节点 */
struct fwnode_handle *device_get_next_child_node(struct device *dev,
struct fwnode_handle *child);

子节点属性

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);

例子

设备树

举一个例子,如在某个被编译的.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=...

再把编译出来的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 name123456

在dst设备树文件描述设备后就需要与platform_driver进行匹配和驱动了。

驱动代码

用于获取mynodes设备资源的驱动源码:

/* mydrv.c */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h> //产生一个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)) 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");

编译驱动模块加载后的输出结果:

[  111.222065] child node count : 2
[ 111.222429] 1
[ 111.223054] label = btn1
[ 111.223690] code = 11
[ 111.224000] label = btn2
[ 111.224623] code = 22

在设备树中描述platform_device的更多相关文章

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

    转自:https://blog.csdn.net/jklinux/article/details/78575281 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

  2. 设备树中ranges属性分析(1)

    作者 彭东林 pengdonglin137@163.com   软件环境 Linux-4.10.17 Qemu+vexpress   概述 在设备树中有时会看到ranges属性,这个ranges属性可 ...

  3. of_alias_get_id 函数与设备树中aliases节点的关系【转】

    转自:https://blog.csdn.net/qq_30145093/article/details/78053823?locationNum=10&fps=1 转自http://www. ...

  4. usb设备驱动描述,王明学learn

    usb设备驱动 本章主要内容包含以下:USB总线介绍,USB协议分析,USB系统架构 一.USB总线介绍 1.1USB发展史 USB(Universal Serial Bus)通用串行总线,是一种外部 ...

  5. USB系列之二:读取USB设备的描述符

    在前面的文章中,我们已经给出了USB协议的链接地址,从这篇文章起,我们会涉及到许多USB 1.1的内容,我们的指导思想是先从熟悉USB 1.1协议入手,先使用现成的HCD和USBD,直接面对客户端驱动 ...

  6. USB HID设备报告描述符详解(转)

    转自:http://group.ednchina.com/93/198.aspx. 参考:USB HID usage table 概述:   报告在这里意思是数据传输(data transfer),而 ...

  7. HID类GamePad和兼容HID设备报表描述符

    目录 1.12版本规范的GamePad参考报表描述符,报表格式如下图. 用CH582模拟GamePad,在电脑上显示的HID接口↓ 报表描述符↓,其他描述符可以直接参考JoyStick相关一文,改一下 ...

  8. linux 设备树中 dwc3 节点的phys参数含义

    找了好久今天找到了,记录一下: &dwc3_0 { ... phys = <&lane3 PHY_TYPE_USB3 1 2 26000000>; ... } Requir ...

  9. 设备树中指定的中断触发方式与request_irq中指定的触发方式不一致时,内核会使用哪种中断触发方式呢?

    答:会使用request_irq中指定的触发方式

  10. 设备树中的interrupts属性解析

    interrupts属性会有两种不同的参数: 1. 带两个参数的情形 示例:  interrupt-parent = <&gpio2>; interrupts = <5 1& ...

随机推荐

  1. 开源相机管理库Aravis例程学习(四)——multiple-acquisition-signal

    目录 简介 例程代码 函数说明 g_main_loop_new g_main_loop_run g_main_loop_quit g_signal_connect arv_stream_set_emi ...

  2. 259k+ Star!这是我见过最全的开发者技术学习路线!

    大家好,我是 Java陈序员. 自从上班后,身体是一天不如一天了,也很少有时间可以去学习新技术了.程序员如果技术跟不上,很容易就被淘汰. 而碎片化的学习效率又不高,往往今天学了,明天就忘了.有时候更是 ...

  3. 都2024年了,你还不知道git worktree么?

    三年前 python 大佬吉多·范罗苏姆(为 Python 程序设计语言的最初设计者及主要架构师)才知道 git worktree ,我现在才知道,我觉得没啥丢人的. 应用场景 如果你正在 featu ...

  4. redis-desktop-manager-0.8.0.3844

    redis-desktop-manager-0.8.0.3844 下载地址: https://www.aliyundrive.com/s/Y2fobkVjAdF 链接:https://pan.baid ...

  5. 纯JS实现多张图片无缝滚动和多张图片上下滚动的效果--JavaScript实例集锦(初学)

    我们会看到很多的网站上会使用多张图片无缝滚动的效果. 下面我就介绍几种纯JS实现多张图片的无缝滚动,并实现鼠标移到图片上运动停止的效果,可以控制图片左右滚动.1.效果展示: 代码实现: <!DO ...

  6. three.js教程2-几何体BufferGeomety顶点

    1.网格模型(三角形概念) 网格模型Mesh其实就一个一个三角形(面)拼接构成.使用使用网格模型Mesh渲染几何体geometry,就是几何体所有顶点坐标三个为一组,构成一个三角形,多组顶点构成多个三 ...

  7. objectarx 之让用户自定义插件命令

    #include <iostream> #include <fstream> virtual AcRx::AppRetCode On_kInitAppMsg (void *pk ...

  8. tkinter时钟(实时更新显示)

    from tkinter import * import time root = Tk() root.geometry('300x200') var = StringVar() def show(): ...

  9. 人脸识别库 虹软 客户端 服务端 示例 基于虹软SDK在C/S 模式下的多人脸实时识别(C#)

    https://github.com/18628271760/MultipleFacesProcess 一.前言 虹软开发SDK以来,其免费使用的营销策略,成功降低了中小企业使用人脸识别技术的成本.然 ...

  10. .net core 关于对swagger的UI(Index.html)或接口的权限验证;

    背景: 如何在ASP.Net Core的生产环境中保护swagger ui,也就是index.html页面.其实swagger是自带禁用的功能的,只需要设置开关即可.但是有一些场景,是需要把这些接口进 ...