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 ", device_get_child_node_count(&pdev->dev));
//获取设备属性autorepeat的值
printk("%d ", 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 ", str);
//获取设备子节点的code属性值
fwnode_property_read_u32(fwhandle, "code", &val);
printk("code = %x ", val);
};

return 0;
}

int myremove(struct platform_device *pdev)
{
printk("in myremove ... ");
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

原文地址:https://www.cnblogs.com/sky-heaven/p/11756894.html