300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Linux 设备树 DTS 语法

Linux 设备树 DTS 语法

时间:2021-10-26 22:17:58

相关推荐

Linux 设备树 DTS 语法

DTS 语法

.dtsi 头文件

设备树支持头文件,设备树的头文件扩展名为.dtsi

//linux-5.5.4\linux-5.5.4\arch\arm\boot\dts\s5pv210-smdkv210.dts// SPDX-License-Identifier: GPL-2.0/** Samsung's S5PV210 SoC device tree source** Copyright (c) - Samsung Electronics, Co. Ltd.** Mateusz Krawczuk <m.krawczuk@>* Tomasz Figa <t.figa@>** Board device tree source for YIC System SMDV210 board.** NOTE: This file is completely based on original board file for mach-smdkv210* available in Linux 3.15 and intends to provide equivalent level of hardware* support. Due to lack of hardware, _no_ testing has been performed.*//dts-v1/;// #include 来引用.h .dtsi .dts 文件#include <dt-bindings/input/input.h>#include "s5pv210.dtsi"//...

.dtsi 文件 描述 SOC 的内部外设信息 (CPU架构 主频 外设寄存器地址范围)

// linux-5.5.4\linux-5.5.4\arch\arm\boot\dts\s5pv210.dtsi// SPDX-License-Identifier: GPL-2.0/** Samsung's S5PV210 SoC device tree source** Copyright (c) - Samsung Electronics, Co. Ltd.* 版权所有(c)-三星电子有限公司** Mateusz Krawczuk <m.krawczuk@>* Tomasz Figa <t.figa@>** Samsung's S5PV210 SoC device nodes are listed in this file. S5PV210* based board files can include this file and provide values for board specfic* bindings.* 三星的S5PV210 SoC设备节点列在这个文件中* 基于S5PV210的板文件可以包含此文件并为板特定绑定提供值** Note: This file does not include device nodes for all the controllers in* S5PV210 SoC. As device tree coverage for S5PV210 increases, additional* nodes can be added to this file.* 注意:此文件不包括S5PV210 SoC中所有控制器的设备节点* 随着S5PV210的设备树覆盖率的增加,可以向该文件添加额外的节点*/#include <dt-bindings/clock/s5pv210.h>#include <dt-bindings/clock/s5pv210-audss.h>/ { // 根节点 /#address-cells = <1>;#size-cells = <1>;aliases {//子节点csis0 = &csis0;//...};cpus { //子节点#address-cells = <1>;#size-cells = <0>;cpu@0 {// cpus 的子节点device_type = "cpu";compatible = "arm,cortex-a8"; //架构信息// reg 属性为 0,数据形式:32 位无符号整数reg = <0>;};};soc {// : 前为 节点标签(label)// :后为 节点名 是 ASCII 字符串// @ 后为 设备的地址 或 寄存器首地址// 可 &spi0 访问该节点spi0: spi@e1300000 { // compatible 属性为 "samsung,s5pv210-spi",数据形式:字符串compatible = "samsung,s5pv210-spi";// reg属性为 一组值reg = <0xe1300000 0x1000>;interrupt-parent = <&vic1>;interrupts = <15>;dmas = <&pdma0 7>, <&pdma0 6>;dma-names = "tx", "rx";clocks = <&clocks SCLK_SPI0>, <&clocks CLK_SPI0>;clock-names = "spi", "spi_busclk0";pinctrl-names = "default";pinctrl-0 = <&spi0_bus>;#address-cells = <1>;#size-cells = <0>;status = "disabled";};};//...};#include "s5pv210-pinctrl.dtsi"

标准属性

节点是很多属性组成,节点是具体的设备

不同的设备有属性不同,用户可自定义属性

compatible 属性

static const struct of_device_id imx_wm8960_dt_ids[] = //匹配表{{// compatible 属性 也叫 “兼容性”属性// compatible 属性将 设备 和 驱动 绑定起来// 厂商:fsl // 驱动名字:imx-dudio-patible = "fsl, imx-dudio-wm8960", //配置值},{/*sentinel*/}};MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids);static struct platform_driver imx_wm8960_driver ={.driver ={.name = "imx-wm8960",.pm = &snd_soc_pm_ops,.of_match_table = imx_wm8960_dt_ids, //platform_driver驱动模式,使用OF匹配表},.probe = imx_wm8960_probe,.remore = imx_wm8960_remore,};

model属性

model = "wm8960-audio"; //设备模块信息

status 属性

表示 设备的状态信息

#address-cells #size-cells 属性

#address-cells 属性值 决定 子节点reg属性的 地址信息 占用字长(32位)

#size-cells 属性值 决定 子节点reg属性的 长度信息 占用字长(32位)

// address length组合表示一个地址的范围// address 表示 起始地址// length 表示 地址长度// #address-cells 表明 address 数据占用的字长// #size-cells 表明 length 数据占用的字长reg = <address1 length1 address2 length2 ...>

spi4{compatible = "spi-gpio";#address-cells = <1>; //起始地址为1 字节#size-cells = <0>; //地址长度为 0 字节gpio_spi:gpio_spi@0{compatible = "fairchild, 74hc595";reg = <0>; // reg属性为 0};};aips3:aips-bus@02200000{comptible = "fsl, aips-bus", "simple-bus";#address-cells = <1>;// 起始地址长度占用 为 1 字节#size-cells = <1>; // 地址长度占用 为 1字节dcp:dcp@02280000{compatible = "fsl, imx6sl-dcp";//起始地址:0x02280000//地址长度:0x40000reg = <0x02280000 0x4000>; // 描述设备地址空间资源信息};};

ranges 属性

ranges属性值 可为 空 或者 按照(child-bus-address , parent-bus-address , length)格式编写的数字矩阵

ranges :地址映射 / 转换表

ranges 属性每个项目 由 子地址、父地址和 地址空间长度 三部分组成:

child-bus-address:子总线地址空间的物理地址,由父节点 #address-cells 确定 物理地址 的占用字长

parent-bus-address:父总线地址空间的物理地址,由父节点 #address-cells 确定 物理地址 的占用字长

length:子地址空间的长度,由 父节点#size-cells确定 地址长度 的占用字长

ranges 属性值为空,说明 子地址空间 和 父地址空间 一样

soc{compatible = "simple-bus";#address-cells = <1>;#size-cells = <1>;// 子地址空间的物理起始地址为 0x0// 父地址空间的物理起始地址为 0xe0000000// 地址范围 0x00100000(1024KB)ranges = <0x0 0xe0000000 0x00100000>; serial // 串口设备节点{device_type = "serial";compatible = "ns16550";// 起始地址 0x4600// 寄存器长度 0x100// serial设备从 0xe0004600(0x4600 + 0xe0000000)开始读写reg = <0x4600 0x100>;clock-frequency = <0>;interrupts = <0xA 0x8>;interrupt-parent = <&ipic>;};};

device_type 属性

device_type 描述设备的 FCode

IEEE 1275 会用到 device_type

device_type属性只用于 cpu 节点 或者 memory 节点

cpu0:cpu@0{compatible = "arm, cortex-a7";device_type = "cpu";reg = <0>;//...}

根节点 compatible 属性

/{model = "Freescale i.MX6_ULL_14x14_EVK_Board";compatible = "fsl,imx6ull-14x14-evk","fsl, imx6ull"; //匹配Linux内核中的驱动程序//...}

没用设备树时设备匹配方法

// arch/arm/mach-imx/machmx35_3ds.cMACHINE_START(MX35_3DS, "Freescale MX35PDK")/* Maintainer: Freescale Semiconductor, Inc *//* 维护者:飞思卡尔半导体公司 */.atag_offset = 0x100,.map_io = mx35_map_io,.init_early = imx35_init_early,.init_irq = mx35_init_irq,.init_time = mx35pdk_timer_init,.init_machine = mx35_3ds_init,.init_late = mx35_3ds_late_init,.restart = mxc_restart,MACHINE_END

MACHINE_START 和 MACHINE_END 定义

// arch/arm/include/asm/mach/arch.h/** Set of macros to define architecture features. * This is built into a table by the linker.* 宏定义体系结构功能* 这是由链接器内置到表中*/#define MACHINE_START(_type, _name) \static const struct machine_desc __mach_desc_##_type \__used \__attribute__((__section__(".arch.info.init"))) = { \.nr = MACH_TYPE_##_type, \ // machine id 设备ID.name = _name,#define MACHINE_END };

设备树的引入,已经不使用这个方法了

用设备树的设备匹配方法

// arch/arm/include/asm/mach/arch.h#define DT_MACHINE_START(_name, _namestr) \static const struct machine_desc __mach_desc_##_name \__usend\__attribute__((__section__(".arch.info.init"))) = { \.nr = ~0, //设备树不靠machine id 检查Linux内核是否支持某设备.name = _namestr,

// linux-5.5.4/arch/arm/mach-s5pv210/s5pv210.cstatic char const *const s5pv210_dt_compat[] __initconst={"samsung, s5pc110","samsung, s5pv210",NULL};DT_MACHINE_START(SSPV210_DT, "Samsung SSPC110/SSPV210-based board")// 保存着本设备兼容属性// 判断根节点compatible属性值与它是否相等// 相等,Linux内核支持该设备.dt_compat = s5pv210_dt_compat, .map_io = s5pv210_dt_map_io,.restart = s5pv210_dt_restart,.init_late = s5pv210_dt_init_late,MACHINE_END

Linux 内核调用 start_kernel 函数启动内核

// linux-5.5.4/init/main.casmlinkage __visible void __init start_kernel(void){char *command_line;char *after_dashes;/** Interrupts are still disabled. Do necessary setups, then* enable them.* 中断禁用 设置启动函数*/setup_arch(&command_line);// ...}

start_kernel 函数会调用setup_arch 函数来匹配 machine_desc

// arch/arm/kernel/setup.cvoid __init setup_arch(char **cmdline_p){const struct machine_desc *mdesc;setup_processor();// 获取匹配的machine_desc// atags的首地址(Linux 内核的 dtb 文件首地址):__atags_pointermdesc = setup_machine_fdt(__atags_pointer); if(!mdesc){mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);}if(!mdesc){early_printf(" \nError:invalid dtb and unrecognized/unsupported machine ID\n");early_printf(" r1 = 0x%08x, r2 = 0x%08x\n",__machine_arch_type, __atags_pointer);if(__atags_pointer){early_print("")}dump_machine_table();}machine_desc = mdesc;machine_name = madesc->name;dump_stack_set_arch_desc("%s",mdesc->name);}

// arch/arm/kernel/devtree.c/*** setup_machine_fdt - Machine setup when an dtb was passed to the kernel* setup_machine_fdt-将dtb传递到内核的 machine 设置** @dt_phys: physical address of dt blob* @dt_phys: dt blob的物理地址** If a dtb was passed to the kernel in r2, then use it to choose the* correct machine_desc and to setup the system.* 如果在r2中将dtb传递给内核,则使用它来选择正确的machine_desc并设置系统*/const struct machine_desc *__init setup_machine_fdt(unsigned int dt_phys){const struct machine_desc *__init setup_best = NULL;if(!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys))){return NULL;}mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);//获取匹配的machine_descif(!mdesc){//...}//.../* Change machine number to match the mdesc we're using */__machine_arch_type = mdesc->nr;}// linux-5.5.4/arch/arm/kernel/devtree.c// 获取 Linux 内核中下一个 machine_desc 结构体static const void * __init arch_get_next_mach(const char *const **match){static const struct machine_desc *mdesc = __arch_info_begin;const struct machine_desc *m = mdesc;if(m >= __arch_info_end){return NULL;}mdesc++;*match = m->dt_compat;return m;}// linux-5.5.4/drivers/of/fdt.c/*** of_flat_dt_match_machine - Iterate match tables to find matching machine.* 迭代匹配表以找到匹配的 machine** @default_match: A machine specific ptr to return in case of no match.*在不匹配的情况下返回的 machine 具体 ptr* @get_next_compat: callback function to return next compatible match table.* 返回下一个兼容匹配表的回调函数** Iterate through machine match tables to find the best match for the machine* compatible string in the FDT.* 遍历machine 匹配表以在FDT中找到与 machine 兼容的字符串的最佳匹配*/const void * __init of_flat_dt_match_machine(const void *default_match,const void *(*get_next_compat)(const char *const**)){const void *data = NULl;const void *best_data = default_match;const char *const *compat;unsigned long dt_root;unsigned int best_score = ~1,score = 0;dt_root =of_get_flat_dt_root(); // 获取设备树根节点while(( data = get_next_compat(&compet) )) // 查找匹配的 machine_desc {score = of_flag_dt_match(dt_root,compat); //根节点 compatible 与每个dt_compat 比较if(score > 0 && score < best_score){best_data = data;best_score = score;}}if(!best_data){const char *prop;int size;if(prop){//...}return NULL;}pr_info("Machine model: %s\n", of_flat_dt_get_machine_name() );return best_data;}

Linux 内核通过根节点 compatible 属性找到对应的设备的函数调用过程

向节点追加或修改内容

设备树是描述板子硬件信息的文件

追加节点不能在 xxx.dtsi

xxx.dtsi 是设备树头文件

// xxx.dts&i2cl //访问 i2c1{clock-frequency = <100000>; // 时钟为 100KHzpinctrl-names = "defaulft";pinctrl-0 = <&pinctrl_i2cl>;status = "okay";mag31100@0e // 子节点{compatible = "fsl, mag3110";reg = <0x0e>;position = <2>;};fxls8471@1e //子节点{compatible = "fsl,fxls8471";reg = <0x1e>;position = <0>;interrupt-parent = <&gpio5>;interrupts = <0 8>;};};

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。