Linux内核模块解析设备树内容

1. 前言

设备树中添加设备节点后,驱动可以根据节点中的属性进行一些设置。那么,驱动如何获取设备节点的属性信息呢?

答案是通过 of_xxx() 函数。

这些函数在 /include/linux/of.h 中声明,/drivers/of/property.c 中定义。

简单说明:

of_property_read_bool()查询某个属性是否存在;

of_property_read_xx() 读取单个值;

of_property_read_xx_array() 读取一个数组;

of_property_read_xx_index() 按照索引读取数组中的某一个;

of_property_read_variable_xx_array()读取数组中的几个;

下面的例子会展示上面函数的用法。

2. 操练一把

2.1 新建 module

我基于这里的步骤在 petalinux 工程中创建 hkm-devtree 模块。

设备树中的节点:

/{

hkm-devtree {

compatible = “sdc,hkm”;

hkm,name = “hkm-device-tree”;

uint-value = < 100 >;

uint-array = < 0x11 0x22 0x33 0x44 >;

dev-enable;

};

};

hkm-devtree.c:

#include < linux/module.h >

#include < linux/string.h >

#include < linux/of_device.h >

#include < linux/of_platform.h >

#define DRIVER_NAME (“hkm-device-tree”)

static int hkm_devtree_probe(struct platform_device *pdev)

{

struct device_node *node = pdev- >dev.of_node;

u32 i = 0;

s32 ret = 0;

u32 value = 0;

u32 arr[4] = {0};

const char *name = NULL;

printk(KERN_DEBUG “call hkm device tree driver probe functionn”);

if(NULL != node)

{

ret = of_property_read_string(node, “hkm,name”, &name);

if(0 == ret)

{

printk(KERN_DEBUG “hkm name is ‘%s’ in device treen”, name);

}

ret = of_property_read_u32(node, “uint-value”, &value);

if(0 == ret)

{

printk(KERN_DEBUG “value is %u in device treen”, value);

}

ret = of_property_read_bool(node, “dev-enable”);

if(true == ret)

{

printk(KERN_DEBUG “device is enablen”);

}

ret = of_property_read_u32_array(node, “uint-array”, arr, 4);

if(0 == ret)

{

printk(KERN_DEBUG “value array, 0x%x, 0x%x, 0x%x, 0x%xn”, arr[0], arr[1], arr[2], arr[3]);

}

ret = of_property_read_u32_index(node, “uint-array”, 3, &value);

if(0 == ret)

{

printk(KERN_DEBUG “index 3 item of array:0x%xn”, value);

}

memset(arr, 0, sizeof(arr));

ret = of_property_read_variable_u32_array(node, “uint-array”, arr, 2, 0);

if(2 == ret)

{

printk(KERN_DEBUG “read 2 item of array:0x%x, 0x%xn”, arr[0], arr[1]);

}

}

return 0;

}

static int hkm_devtree_remove(struct platform_device *pdev)

{

printk(KERN_DEBUG “call hkm device tree driver remove functionn”);

return 0;

}

#ifdef CONFIG_OF

static struct of_device_id hkm_devtree_of_match_table[] = {

{.compatible = “sdc,hkm”},

{/*end of list*/},

};

MODULE_DEVICE_TABLE(of, hkm_devtree_of_match_table);

#else

#define hkm_devtree_of_match_table

#endif

static struct platform_driver hkm_devtree_driver = {

.driver = {

.name = DRIVER_NAME,

.owner = THIS_MODULE,

.of_match_table = hkm_devtree_of_match_table,

},

.probe = hkm_devtree_probe,

.remove = hkm_devtree_remove,

};

static int __init hkm_init(void)

{

printk(KERN_DEBUG “hello, sdcn”);

return platform_driver_register(&hkm_devtree_driver);

}

static void __exit hkm_exit(void)

{

printk(KERN_DEBUG “bye, sdcn”);

}

module_init(hkm_init);

module_exit(hkm_exit);

MODULE_DESCRIPTION(“KM in kernel source”);

MODULE_AUTHOR(“sdc”);

MODULE_LICENSE(“GPL”);

工程仓库:https://gitee.com/sdc-coding/device-tree-parse

运行结果:

3. 设备树、内核、驱动之间的关系

驱动和设备树之间通过“设备树协议”进行通信。设备树语法就是协议规则,设备树就是符合协议的内容,内核提供解析协议的能力,驱动使用上述能力解析设备树,获取设备信息。

发表评论