Linux kernel下c语言解析dts
一、inux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设备树配置,当需要改变波特率时,就不用修改驱动,直接修改配置文件则可。设备树源文件扩展名为.dts(device tree source),一般放置在内核的"arch/arm64/boot/dts/"目录内。设备树源文件的通用部分用.dtsi文件描述,一般用于描述SOC的内部外设信息,如CPU架构,主频等。差异部分用.dts文件描述,一般用于描述设备上的其它设备,如IIC设备,SPI设备。
二、kernel下c语言解析dts实例学习。
1、添加dts panel节点。
panel: panel {
compatible = "simple-panel";
backlight = <&backlight>;
power-supply = <&vcc_lcd>;
enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
prepare-delay-ms = <20>;
enable-delay-ms = <20>;
reg = <0Xff8ff600 0x800>;
status = "disabled";
rockchip,key_table =
<0xFF KEY_POWER>,
<0xF4 KEY_MENU>,
<0xF6 KEY_BACK>,
<0xE9 KEY_HOME>,
<0xF1 KEY_ENTER>,
<0xEE KEY_VOLUMEUP>,
<0xEB KEY_VOLUMEDOWN>,
<0xE9 KEY_REPLY>,
<0xF3 KEY_UP>,
<0xEF KEY_DOWN>,
<0xF2 KEY_LEFT>,
<0xF0 KEY_RIGHT>,
<0xFA KEY_PLAY>,
<0xE6 KEY_PLAYCD>,
<0xE7 KEY_STOP>,
<0xEC KEY_MUTE>,
<0xE5 KEY_1>,
<0xE4 KEY_2>,
<0xE3 KEY_3>,
<0xE2 KEY_4>,
<0xE1 KEY_5>,
<0xE0 KEY_6>,
<0xBF KEY_7>,
<0xBE KEY_8>,
<0xBD KEY_9>,
<0xBB KEY_0>,
<0xE8 KEY_APPSELECT>,
<0xBC KEY_NUMERIC_STAR>,
<0xBA KEY_NUMERIC_POUND>,
<0xB6 KEY_TRIGGER_DUALSCREEN>;
display-timings {
native-mode = <&timing0>;
timing0: timing0 {
clock-frequency = <200000000>;
//hactive = <1536>;
//vactive = <2048>;
hactive = <3840>;
vactive = <2160>;
//hactive = <1920>;
//vactive = <1080>;
hfront-porch = <12>;
hsync-len = <16>;
hback-porch = <48>;
vfront-porch = <8>;
vsync-len = <4>;
vback-porch = <8>;
hsync-active = <0>;
vsync-active = <0>;
de-active = <0>;
pixelclk-active = <0>;
};
};
ports {
panel_in: endpoint {
remote-endpoint = <&edp_out>;
};
};
};
2、c语言解析代码
struct device_node *panel_nd;//设备节点
struct property *proper;
struct device_node *entry;
struct device_node *timings_np;
int res=-1;
unsigned int regdata[2];
const char *str;
int val = 0;
int loop;
//u32 *phy_config;
struct rkxx_remote_key_table key_table[50];
/*获取设备树中的属性数据*/
/*1.获取设备节点:panel*/
panel_nd = of_find_node_by_path("/panel");
if(panel_nd == NULL)
{
printk("panel_nd node not find\r\n");
}
else
{
printk("panel_nd node find\r\n");
}
/*2.获取compatible属性内容*/
proper = of_find_property(panel_nd,"compatible",NULL);
if(proper == NULL)
{
printk("panel_nd compatible property find failed\r\n");
}
else
{
printk("panel_nd compatible =%s\r\n",(char *)proper->value);
}
/*3.获取status属性内容*/
res = of_property_read_string(panel_nd,"status",&str);
if(res < 0)
{
printk("panel_nd status read failed\r\n");
}
else
{
printk("panel_nd status =%s\r\n",str);
}
/*4.获取reg属性内容*/
res = of_property_read_u32_array(panel_nd,"reg",regdata,2);
if(res <0 )
{
printk("panel_nd reg property read failed\r\n");
}
else
{
printk("panel_nd regdata[0]=0x%x\r\n",regdata[0]);
printk("panel_nd regdata[1]=0x%x\r\n",regdata[1]);
}
if (of_get_property(panel_nd, "rockchip,key_table", &val))
{
printk("panel_nd rockchip,rockchip,key_table val=%d\r\n",val);
of_property_read_u32_array(panel_nd, "rockchip,key_table",
(u32 *)key_table, val / sizeof(u32));
for (loop=0; loop<(val / sizeof(u32)/2); loop++) {
printk("key_table[%d]=[0x%x,0x%x]\n", loop,
key_table[loop].scancode,key_table[loop].keycode);
}
}
timings_np = of_find_node_by_name(panel_nd, "display-timings");
if (!timings_np) {
printk("%s: could not find timings_np node\n",
of_node_full_name(panel_nd));
}else
printk("finded timings_np node\n");
entry = of_parse_phandle(timings_np, "native-mode", 0);
if (!of_property_read_u32(entry, "hback-porch", &val))
printk("\nhback-porch=%d\n",val);
if (!of_property_read_u32(entry, "hfront-porch", &val))
printk("\nhfront-porch=%d\n",val);
if (!of_property_read_u32(entry, "hactive", &val))
printk("\nhactive=%d\n",val);
if (!of_property_read_u32(entry, "hsync-len", &val))
printk("\nhsync-len=%d\n",val);
if (!of_property_read_u32(entry, "vback-porch", &val))
printk("\nvback-porch=%d\n",val);
if (!of_property_read_u32(entry, "vfront-porch", &val))
printk("\nvfront-porch=%d\n",val);
if (!of_property_read_u32(entry, "vactive", &val))
printk("\nvactive=%d\n",val);
if (!of_property_read_u32(entry, "vsync-len", &val))
printk("\nvsync-len=%d\n",val);
if (!of_property_read_u32(entry, "clock-frequency", &val))
printk("\nclock-frequency=%d\n",val);
3、运行后看打印信息如下,解析ok。