嵌入式Linux--设备树(一)基本概念和基本语法

一、前言

 一个 SOC 可以作出很多不同的板子,这些不同的板子肯定是有共同的信息,将这些共同的信息提取出来作为一个通用的文件,其他的.dts 文件直接引用这个通用文件即可,这个通用文件就是.dtsi 文件,类似于 C 语言中的头文件。一般.dts 描述板级信息(也就是开发板上有哪些 IIC 设备、SPI 设备等),.dtsi 描述 SOC 级信息(也就是 SOC 有几个 CPU、主频是多少、各个外设控制器信息等)。

1、DTS、DTB和DTC

 设备树源文件扩展名为.dts,但是我们在前面移植 Linux 的时候却一直在使用.dtb 文件,那么 DTS 和 DTB 这两个文件是什么关系呢?

 DTS 是设备树源码文件,DTB 是将DTS 编译以后得到的二进制文件。将.c 文件编译为.o 需要用到 gcc 编译器,那么将.dts 编译为.dtb需要什么工具呢?需要用到 DTC 工具!DTC 工具源码在 Linux 内核的 scripts/dtc 目录下,scripts/dtc/Makefile 文件内容如下:

# scripts/dtc makefile

hostprogs-y := dtc
always      := $(hostprogs-y)

dtc-objs    := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
           srcpos.o checks.o util.o
dtc-objs    += dtc-lexer.lex.o dtc-parser.tab.o

# Source files need to get at the userspace version of libfdt_env.h to compile

HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt

HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)

HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)

# dependencies on generated files need to be listed explicitly
$(obj)/dtc-lexer.lex.o: $(obj)/dtc-parser.tab.h

# generated files need to be cleaned explicitly
clean-files := dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h

 DTC 工具依赖于 dtc.c、flattree.c、fstree.c 等文件,最终编译并链接出 DTC 这个主机文件。如果要编译 DTS 文件的话只需要进入到 Linux 源码根目录下,然后执行如下命令:

  • 编译所有包括kernel、dtbs:make dtbs
  • 编译所有的dtbs:make dtbs
  • 编译指定的dtb:make imx6ull-alientek-emmc.dtb

 关于.dtb 文件怎么使用这里就不多说了,前面讲解 Uboot 移植、Linux 内核移植的时候已经无数次的提到如何使用.dtb 文件了(uboot 中使用 bootz 或 bootm命令向 Linux 内核传递二进制设备树文件(.dtb))。

二、基础语法

设备树用树状结构描述设备信息,它有以下几种特性

  • 每个设备树文件都有一个根节点,每个设备都是一个节点。
  • 节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
  • 每个设备的属性都用一组key-value对(键值对)来描述。
  • 每个属性的描述用;结束

 所以,一个设备树的基本框架可以写成下面这个样子,一般来说,/表示板子,它的子节点node1表示SoC上的某个控制器,控制器中的子节点node2表示挂接在这个控制器上的设备(们)。

/{                                  //根节点
    node1{                          //node1是节点名,是/的子节点
        key=value;                  //node1的属性
        ...
        node2{                      //node2是node1的子节点
            key=value;              //node2的属性
            ...
        }
    }                               //node1的描述到此为止
    node3{
        key=value;
        ...
    }

1、设备树语法

(1)dtsi头文件

 和 C 语言一样,设备树也支持头文件,设备树的头文件扩展名为.dtsi。在 imx6ull-alientek-emmc.dts 中有如下所示内容:

#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"
  • 使用“#include”来引用“input.h”这个.h 头文件。
  • 使用“#include”来引用“imx6ull.dtsi”这个.dtsi 头文件。

 看到这里,可能会疑惑,不是说设备树的扩展名是.dtsi 吗?为什么也可以直接引用 C语言中的.h 头文件呢?这里并没有错,.dts 文件引用 C 语言中的.h 文件,甚至也可以引用.dts 文件,打开 imx6ull-14x14-evk-gpmi-weim.dts 这个文件,此文件中有如下内容:

#include "imx6ull-14x14-evk.dts"

 可以看出在上面的.dts 设备树文件中,可以通过“#include”来引用.h、.dtsi 和.dts 文件。只是,我们在编写设备树头文件的时候最好选择.dtsi 后缀。
 一般.dtsi 文件用于描述 SOC 的内部外设信息,比如 CPU 架构、主频、外设寄存器地址范围,比如 UART、IIC 等等。比如 imx6ull.dtsi 就是描述 I.MX6ULL 这颗 SOC 内部外设情况信息的,内容如下:

#include <dt-bindings/clock/imx6ul-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "imx6ull-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
#include "skeleton.dtsi"

/ {
	aliases {
		can0 = &flexcan1;
		......
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

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

	intc: interrupt-controller@00a01000 {
		compatible = "arm,cortex-a7-gic";
		#interrupt-cells = <3>;
		interrupt-controller;
		reg = <0x00a01000 0x1000>,
		<0x00a02000 0x100>;
	};

clocks {
	#address-cells = <1>;
	#size-cells = <0>;
	
	ckil: clock@0 {
		compatible = "fixed-clock";
		reg = <0>;
		#clock-cells = <0>;
		clock-frequency = <32768>;
		clock-output-names = "ckil";
	};
......
};

	soc {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		interrupt-parent = <&gpc>;
		ranges;
	
		busfreq {
			compatible = "fsl,imx_busfreq";
			......
		};

	gpmi: gpmi-nand@01806000{
		compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";
		#address-cells = <1>;
		#size-cells = <1>;
		reg = <0x01806000 0x2000>, <0x01808000 0x4000>;
		......
		};
		......
	};
};

 cpu0 这个设备节点信息,这个节点信息描述了I.MX6ULL 这颗 SOC 所使用的 CPU 信息,比如架构是 cortex-A7,频率支持 996MHz、792MHz、528MHz、396MHz 和 198MHz 等等。在 imx6ull.dtsi 文件中不仅仅描述了 cpu0 这一个节点信息,I.MX6ULL 这颗 SOC 所有的外设都描述的清清楚楚,比如 ecspi1 ~ 4、uart1 ~ 8、usbphy1 ~ 2、i2c1 ~ 4等等,关于这些设备节点信息的具体内容我们稍后在详细的讲解。

(2)设备树节点语法

[label:] node-name[@unit-address] {    
	[properties definitions];    
	[child nodes];
};

解释:

  • label: 可选项,节点别名
  • node-name: 节点名
  • unit-address: 设备地址
  • properties definitions:属性定义
  • child nodes:子节点

 设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键—值对。以下是从imx6ull.dtsi 文件中缩减出来的设备树文件内容:

/ {
	aliases {
		can0 = &flexcan1;
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

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

	intc: interrupt-controller@00a01000 {
		compatible = "arm,cortex-a7-gic";
		#interrupt-cells = <3>;
		interrupt-controller;
		reg = <0x00a01000 0x1000>,
		<0x00a02000 0x100>;
	};
}
  • 第 1 行, “/”是根节点,每个设备树文件只有一个根节点。细心的同学应该会发现,imx6ull.dtsi和 imx6ull-alientek-emmc.dts 这两个文件都有一个“/”根节点,这样不会出错吗?不会的,因为这两个“/”根节点的内容会合并成一个根节点。
  • 第 2、6 和 17 行,aliases、cpus 和 intc 是三个子节点,在设备树中节点命名格式如下:
    node-name@unit-address
    其中“node-name”是节点名字,为 ASCII 字符串,节点名字应该能够清晰的描述出节点的功能,比如“uart1”就表示这个节点是 UART1 外设。“unit-address”一般表示设备的地址或寄存器首地址,如果某个节点没有地址或者寄存器的话“unit-address”可以不要,比如“cpu@0”、“interrupt-controller@00a01000”。

但是在上面的代码中我们看到的节点命名却如下所示:

cpu0:cpu@0

&esmp;上述命令并不是“node-name@unit-address”这样的格式,而是用“:”隔开成了两部分,“:”前面的是节点标签(label),“:”后面的才是节点名字,格式如下所示:

label: node-name@unit-address

 引入 label 的目的就是为了方便访问节点,可以直接通过&label 来访问这个节点,比如通过&cpu0 就可以访问“cpu@0”这个节点,而不需要输入完整的节点名字。再比如节点 intc:interrupt-controller@00a01000,节点 label 是 intc,而节点名字就很长了,为interrupt-controller@00a01000。很明显通过&intc 来访问interrupt-controller@00a01000这个节点要方便很多!

 第 10 行,cpu0 也是一个节点,只是 cpu0 是 cpus 的子节点。每个节点都有不同属性,不同的属性又有不同的内容,属性都是键值对,值可以为空或任意的字节流。设备树源码中常用的几种数据形式如下所示:

  • ①、字符串
    compatible = "arm,cortex-a7";
    上述代码设置 compatible 属性的值为字符串“arm,cortex-a7”。
  • ②、32位无符号整数
    reg = <0>;
    上述代码设置 reg 属性的值为 0,reg 的值也可以设置为一组值,比如:
    reg = <0 0x123456 100>;
  • ③、字符串列表
    属性值也可以为字符串列表,字符串和字符串之间采用“,”隔开,如下所示:
    compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";
    上述代码设置属性 compatible 的值为fsl,imx6ull-gpmi-nandfsl, imx6ul-gpmi-nand

(3)标准属性定义语法

[label:] property-name = value;
[label:] property-name;

 节点是由一堆的属性组成,节点都是具体的设备,不同的设备需要的属性不同,用户可以自定义属性。除了用户自定义属性,有很多属性是标准属性,Linux 下的很多外设驱动都会使用这些标准属性,本节我们就来学习一下几个常用的标准属性。

1 、compatible 属性

compatible 属性也叫做“兼容性”属性,这是非常重要的一个属性!compatible 属性的值是一个字符串列表,compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序,compatible 属性的值格式如下所示:

compatible = "manufacturer,model"

 其中 manufacturer 表示厂商,model 一般是模块对应的驱动名字。比如 imx6ull-alientek-emmc.dts 中 sound 节点是 I.MX6U-ALPHA 开发板的音频设备节点,I.MX6U-ALPHA 开发板上的音频芯片采用的欧胜(WOLFSON)出品的 WM8960,sound 节点的 compatible 属性值如下:

compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960";

 属性值有两个,分别为

  • “fsl,imx6ul-evk-wm8960”
  • “fsl,imx-audio-wm8960”

 其中

  • “fsl”表示厂商是飞思卡尔
  • “imx6ul-evk-wm8960”“imx-audio-wm8960”表示驱动模块名字

 sound这个设备首先使用第一个兼容值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值查。一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。比如在文件 imx-wm8960.c 中有如下内容:

static const struct of_device_id imx_wm8960_dt_ids[] = {
	{ .compatible = "fsl,imx-audio-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,
	},
	.probe = imx_wm8960_probe,
	.remove = imx_wm8960_remove,
};
  • 数组 imx_wm8960_dt_ids 就是 imx-wm8960.c 这个驱动文件的匹配表,此匹配表只有一个匹配值“fsl,imx-audio-wm8960”。如果在设备树中有哪个节点的 compatible 属性值与此相等,那么这个节点就会使用此驱动文件。
  • wm8960 采用了 platform_driver 驱动模式,关于platform_driver 驱动后面会讲解。此行设置.of_match_table 为 imx_wm8960_dt_ids,也就是设置这个 platform_driver 所使用的OF 匹配表。

2、model属性

 model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,比如:

model = "wm8960-audio";

3 、status 属性

 status 属性看名字就知道是和设备状态有关的,status 属性值也是字符串,字符串是设备的状态信息,可选的状态如表所示:

描述
“okay”表示设备是可以操作的
“disable”表示设备当前是不可操作的,但是在未来可以变为可操作的,比如热插拔设备插入以后。至于 disabled 的具体含义还要看设备的绑定文档。
“fail”表示设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可操作。
“fail-sss”含义和“fail”相同,后面的 sss 部分是检测到的错误内容。

4 、#address-cells 和#size-cells 属性

 这两个属性的值都是无符号 32 位整形,#address-cells 和#size-cells 这两个属性可以用在任何拥有子节点的设备中,用于描述子节点的地址信息。

  • #address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位)
  • #size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)。

#address-cells#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度,reg 属性的格式为:

reg = <address1 length1 address2 length2 address3 length3……>

 每个“address length”组合表示一个地址范围,其中 address 是起始地址,length 是地址长度,#address-cells 表明 address 这个数据所占用的字长,#size-cells 表明 length 这个数据所占用的字长,比如:

spi4 {
	compatible = "spi-gpio";
	#address-cells = <1>;
	#size-cells = <0>;

	gpio_spi: gpio_spi@0 {
		compatible = "fairchild,74hc595";
		reg = <0>;
	};
};

aips3: aips-bus@02200000 {
	compatible = "fsl,aips-bus", "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;

	dcp: dcp@02280000 {
		compatible = "fsl,imx6sl-dcp";
		reg = <0x02280000 0x4000>;
	};
};
  • 节点 spi4 的#address-cells = <1>,#size-cells = <0>,说明 spi4 的子节点 reg 属性中起始地址所占用的字长为 1,地址长度所占用的字长为 0。
  • 子节点 gpio_spi: gpio_spi@0 的 reg 属性值为 <0>,因为父节点设置了#address-cells = <1>,#size-cells = <0>,因此 addres=0,没有 length 的值,相当于设置了起始地址,而没有设置地址长度。
  • 设置 aips3: aips-bus@02200000 节点#address-cells = <1>,#size-cells = <1>,说明 aips3: aips-bus@02200000 节点起始地址长度所占用的字长为 1,地址长度所占用的字长也为 1。
  • 子节点 dcp: dcp@02280000 的 reg 属性值为<0x02280000 0x4000>,因为父节点设置了#address-cells = <1>,#size-cells = <1>,address= 0x02280000,length= 0x4000,相当于设置了起始地址为 0x02280000,地址长度为 0x40000。

5 、reg 属性

 reg 属性前面已经提到过了,reg 属性的值一般是(address,length)对。reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息,比如在 imx6ull.dtsi 中有如下内容:

uart1: serial@02020000 {
	compatible = "fsl,imx6ul-uart",
	"fsl,imx6q-uart", "fsl,imx21-uart";
	reg = <0x02020000 0x4000>;
	interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clks IMX6UL_CLK_UART1_IPG>,
	<&clks IMX6UL_CLK_UART1_SERIAL>;
	clock-names = "ipg", "per";
	status = "disabled";
};

 上述代码是节点 uart1,uart1 节点描述了 I.MX6ULL 的 UART1 相关信息,重点是 reg 属性。其中 uart1 的父节点 aips1: aips-bus@02000000 设置了#address-cells = <1>、#size-cells = <1>,因此 reg 属性中 address=0x02020000,length=0x4000。查阅《I.MX6ULL 参考手册》可知,I.MX6ULL 的 UART1 寄存器首地址为 0x02020000,但是 UART1 的地址长度(范围)并没有 0x4000 这么多,这里我们重点是获取 UART1 寄存器首地址。

6 、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 属性值为空值,说明子地址空间和父地址空间完全相同,不需要进行地址转换,对于我们所使用的 I.MX6ULL 来说,子地址空间和父地址空间完全相同,因此会在 imx6ull.dtsi中找到大量的值为空的 ranges 属性,如下所示:

soc {
	#address-cells = <1>;
	#size-cells = <1>;
	compatible = "simple-bus";
	interrupt-parent = <&gpc>;
	ranges;
	......
}
  • ranges 属性,但是 ranges 属性值为空。

ranges 属性不为空的示例代码如下所示:

soc {
	compatible = "simple-bus";
	#address-cells = <1>;
	#size-cells = <1>;
	ranges = <0x0 0xe0000000 0x00100000>;

	serial {
		device_type = "serial";
		compatible = "ns16550";
		reg = <0x4600 0x100>;
		clock-frequency = <0>;
		interrupts = <0xA 0x8>;
		interrupt-parent = <&ipic>;
	};
};
  • 节点 soc 定义的 ranges 属性,值为<0x0 0xe0000000 0x00100000>,此属性值指定了一个 1024KB(0x00100000)的地址范围,子地址空间的物理起始地址为 0x0,父地址空间的物理起始地址为 0xe0000000。
  • serial 是串口设备节点,reg 属性定义了 serial 设备寄存器的起始地址为 0x4600,寄存器长度为 0x100。经过地址转换,serial 设备可以从 0xe0004600 开始进行读写操作,0xe0004600 = 0x4600+0xe0000000。

7 、name 属性

 name 属性值为字符串,name 属性用于记录节点名字,name 属性已经被弃用,不推荐使用name 属性,一些老的设备树文件可能会使用此属性。

8 、device_type 属性

 device_type 属性值为字符串,IEEE 1275 会用到此属性,用于描述设备的 FCode,但是设备树没有 FCode,所以此属性也被抛弃了。此属性只能用于 cpu 节点或者 memory 节点。imx6ull.dtsi 的 cpu0 节点用到了此属性,内容如下所示:

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

 关于标准属性就讲解这么多,其他的比如中断、IIC、SPI 等使用的标准属性等到具体的例程再讲解。

(4)根节点compatible属性

 每个节点都有 compatible 属性,根节点“/”也不例外,imx6ull-alientek-emmc.dts 文件中根节点的 compatible 属性内容如下所示:

/ {
	model = "Freescale i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";
	......
}

 可以看出,compatible 有两个值:“fsl,imx6ull-14x14-evk”“fsl,imx6ull”。前面我们说了,设备节点的 compatible 属性值是为了匹配 Linux 内核中的驱动程序,那么根节点中的 compatible属性是为了做什么工作的?

 通过根节点的 compatible 属性可以知道我们所使用的设备:

  • 一般第一个值描述了所使用的硬件设备名字,比如这里使用的是“imx6ull-14x14-evk”这个设备
  • 第二个值描述了设备所使用的 SOC,比如这里使用的是“imx6ull”这颗 SOC。

 Linux 内核会通过根节点的 compoatible 属性查看是否支持此设备,如果支持的话设备就会启动 Linux 内核。接下来我们就来学习一下 Linux 内核在使用设备树前后是如何判断是否支持某款设备的。

1、使用设备树之前设备匹配方法

 在没有使用设备树以前,uboot 会向 Linux 内核传递一个叫做 machine id 的值,machine id也就是设备 ID,告诉 Linux 内核自己是个什么设备,看看 Linux 内核是否支持。

 Linux 内核是支持很多设备的,针对每一个设备(板子),Linux内核都用MACHINE_STARTMACHINE_END来定义一个 machine_desc 结构体来描述这个设备,比如在文件 arch/arm/mach-imx/mach-mx35_3ds.c 中有如下定义:

MACHINE_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,
	.reserve = mx35_3ds_reserve,
	.restart = mxc_restart,
MACHINE_END

 上述代码就是定义了“Freescale MX35PDK”这个设备,其中 MACHINE_START 和MACHINE_END 定义在文件 arch/arm/include/asm/mach/arch.h 中,内容如下:

#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
	.nr = MACH_TYPE_##_type, \
	.name = _name,
	
#define MACHINE_END \
};

根据 MACHINE_START 和 MACHINE_END 的宏定义:

static const struct machine_desc __mach_desc_MX35_3DS \
	__used \
	__attribute__((__section__(".arch.info.init"))) = {
	.nr = MACH_TYPE_MX35_3DS,
	.name = "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,
	.reserve = mx35_3ds_reserve,
	.restart = mxc_restart,
};

 从上面的代码可以看出,这里定义了一个 machine_desc 类型的结构体变量__mach_desc_MX35_3DS , 这 个 变 量 存 储 在 “ .arch.info.init ” 段 中 。 第 4 行 的MACH_TYPE_MX35_3DS 就 是 “ Freescale MX35PDK ” 这 个 板 子 的 machine id 。MACH_TYPE_MX35_3DS 定义在文件 include/generated/mach-types.h 中,此文件定义了大量的machine id,内容如下所示:

#define MACH_TYPE_EBSA110 0
#define MACH_TYPE_RISCPC 1
#define MACH_TYPE_EBSA285 4
#define MACH_TYPE_NETWINDER 5
#define MACH_TYPE_CATS 6
#define MACH_TYPE_SHARK 15
#define MACH_TYPE_BRUTUS 16
#define MACH_TYPE_PERSONAL_SERVER 17
......
#define MACH_TYPE_MX35_3DS 1645
......
#define MACH_TYPE_PFLA03 4575
  • MACH_TYPE_MX35_3DS 的值,为 1645。

 前面说了,uboot 会给 Linux 内核传递 machine id 这个参数,Linux 内核会检查这个 machine id,其实就是将 machine id 与上面代码中的这些 MACH_TYPE_XXX 宏进行对比,看看有没有相等的,如果相等的话就表示 Linux 内核支持这个设备,如果不支持的话那么这个设备就没法启动 Linux 内核。

2、使用设备树之后的设备匹配方法

当 Linux 内核引入设备树以后就不再使用 MACHINE_START 了,而是换为了DT_MACHINE_START。DT_MACHINE_START 也定义在文件 arch/arm/include/asm/mach/arch.h里面,定义如下:

#define DT_MACHINE_START(_name, _namestr) \
static const struct machine_desc __mach_desc_##_name \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
	.nr = ~0, \
	.name = _namestr,

 可以看出,DT_MACHINE_START 和 MACHINE_START 基本相同,只是.nr 的设置不同,在 DT_MACHINE_START 里面直接将.nr 设置为~0。说明引入设备树以后不会再根据 machineid 来检查 Linux 内核是否支持某个设备了。
 打开文件 arch/arm/mach-imx/mach-imx6ul.c,有如下所示内容:

static const char *imx6ul_dt_compat[] __initconst = {
	"fsl,imx6ul",
	"fsl,imx6ull",
	NULL,
};

DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)")
	.map_io = imx6ul_map_io,
	.init_irq = imx6ul_init_irq,
	.init_machine = imx6ul_init_machine,
	.init_late = imx6ul_init_late,
	.dt_compat = imx6ul_dt_compat,
MACHINE_END

 machine_desc 结构体中有个.dt_compat 成员变量,此成员变量保存着本设备兼容属性,示例代码 43.3.4.5 中设置.dt_compat = imx6ul_dt_compat,imx6ul_dt_compat 表里面有"fsl,imx6ul"
"fsl,imx6ull"这两个兼容值。只要某个设备(板子)根节点“/”的 compatible 属性值与imx6ul_dt_compat 表中的任何一个值相等,那么就表示 Linux 内核支持此设备。imx6ull-alientek-emmc.dts 中根节点的 compatible 属性值如下:

compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

 其中“fsl,imx6ull”与 imx6ul_dt_compat 中的“fsl,imx6ull”匹配,因此 I.MX6U-ALPHA 开发板可以正常启动 Linux 内核。如果将 imx6ull-alientek-emmc.dts 根节点的 compatible 属性改为其他的值,比如:

compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ullll"

 重新编译 DTS,并用新的 DTS 启动 Linux 内核,结果如下所示的错误提示:

done
Bytes transferred = 36298(8dca hex)
Kernel image @ 0x80800000 [ 0x000000 - 0x54a1e0]
## Flattened Device Tree blob at 83000000
	Booting using the fdt blob at 0x83000000
	Using Device Tree in place at 83000000, end 8300bdc9

Starting kernel ...

 输出Starting kernel ...以后再无任何信息输出,Linux Kernel启动失败。

 当我们修改了根节点 compatible 属性内容以后,因为 Linux 内核找不到对应的设备,因此Linux 内核无法启动。在 uboot 输出 Starting kernel…以后就再也没有其他信息输出了。

 接下来我们简单看一下 Linux 内核是如何根据设备树根节点的 compatible 属性来匹配出对应的 machine_desc,Linux 内核调用 start_kernel 函数来启动内核,start_kernel 函数会调用setup_arch 函数来匹配 machine_desc,setup_arch 函数定义在文件arch/arm/kernel/setup.c 中,函数内容如下(有缩减):

void __init setup_arch(char **cmdline_p)
{
	const struct machine_desc *mdesc;
	
	setup_processor();
	mdesc = setup_machine_fdt(__atags_pointer);
	if (!mdesc)
	mdesc = setup_machine_tags(__atags_pointer,
	__machine_arch_type);
	machine_desc = mdesc;
	machine_name = mdesc->name;
	......
}

 调用 setup_machine_fdt 函数来获取匹配的 machine_desc,参数就是 atags 的首地址,也就是 uboot 传递给 Linux 内核的 dtb 文件首地址,setup_machine_fdt 函数的返回值就是找到的最匹配的 machine_desc。

函数 setup_machine_fdt 定义在文件 arch/arm/kernel/devtree.c 中,内容如下(有缩减):

const struct machine_desc * __init setup_machine_fdt(unsigned int
													 dt_phys)
{
	const struct machine_desc *mdesc, *mdesc_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_arch_type = mdesc->nr;
	
	return mdesc;
}

 调用函数 of_flat_dt_match_machine 来获取匹配的 machine_desc,参数 mdesc_best是 默 认的 machine_desc, 参 数 arch_get_next_mach 是 个函 数 , 此函 数定 义 在 定 义在arch/arm/kernel/devtree.c 文件中。找到匹配的 machine_desc 的过程就是用设备树根节点的compatible 属性值和 Linux 内核中保存的所以 machine_desc 结构的. dt_compat 中的值比较,看看那个相等,如果相等的话就表示找到匹配的 machine_desc,arch_get_next_mach 函数的工作就是获取 Linux 内核中下一个 machine_desc 结构体。

 最后再来看一下 of_flat_dt_match_machine 函数,此函数定义在文件 drivers/of/fdt.c 中,内容如下(有缩减):

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(&compat))) {
		score = of_flat_dt_match(dt_root, compat);
		if (score > 0 && score < best_score) {
			best_data = data;
			best_score = score;
		}
	}
......

	pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
	
	return best_data;
}
  • 通过函数 of_get_flat_dt_root 获取设备树根节点。
  • while循环就是查找匹配的 machine_desc 的过程
  • of_flat_dt_match 函数会将根节点 compatible 属性的值和每个machine_desc 结构体中. dt_compat 的值进行比较,直至找到匹配的那个 machine_desc。

 总结一下,Linux 内核通过根节点 compatible 属性找到对应的设备的函数调用过程,如下所示:

在这里插入图片描述

(5)向节点追加或修改内容

 产品开发过程中可能面临着频繁的需求更改,比如第一版硬件上有一个 IIC 接口的六轴芯片 MPU6050,第二版硬件又要把这个 MPU6050 更换为 MPU9250 等。一旦硬件修改了,我们就要同步的修改设备树文件,毕竟设备树是描述板子硬件信息的文件。假设现在有个六轴芯片fxls8471,fxls8471 要接到 I.MX6U-ALPHA 开发板的 I2C1 接口上,那么相当于需要在 i2c1 这个节点上添加一个 fxls8471 子节点。先看一下 I2C1 接口对应的节点,打开文件 imx6ull.dtsi 文件,找到如下所示内容:

i2c1: i2c@021a0000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
	reg = <0x021a0000 0x4000>;
	interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clks IMX6UL_CLK_I2C1>;
	status = "disabled";
};

 以上就是 I.MX6ULL 的 I2C1 节点,现在要在 i2c1 节点下创建一个子节点,这个子节点就是 fxls8471,最简单的方法就是在 i2c1 下直接添加一个名为 fxls8471 的子节点,如下所示:

i2c1: i2c@021a0000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
	reg = <0x021a0000 0x4000>;
	interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&clks IMX6UL_CLK_I2C1>;
	status = "disabled";

	//fxls8471 子节点
		fxls8471@1e {
		compatible = "fsl,fxls8471";
		reg = <0x1e>;
	};
};

 以上就是添加的 fxls8471 这个芯片对应的子节点。但是这样会有个问题!i2c1 节点是定义在 imx6ull.dtsi 文件中的,而 imx6ull.dtsi 是设备树头文件,其他所有使用到 I.MX6ULL这颗 SOC 的板子都会引用 imx6ull.dtsi 这个文件。直接在 i2c1 节点中添加 fxls8471 就相当于在其他的所有板子上都添加了 fxls8471 这个设备,但是其他的板子并没有这个设备啊!因此,按照示例代码 43.3.5.2 这样写肯定是不行的。

 这里就要引入另外一个内容,那就是如何向节点追加数据,我们现在要解决的就是如何向i2c1 节点追加一个名为 fxls8471 的子节点,而且不能影响到其他使用到 I.MX6ULL 的板子。I.MX6U-ALPHA 开发板使用的设备树文件为 imx6ull-alientek-emmc.dts,因此我们需要在imx6ull-alientek-emmc.dts 文件中完成数据追加的内容,方式如下:

&i2c1 {
/* 要追加或修改的内容 */
};
  • ;&i2c1 表示要访问 i2c1 这个 label 所对应的节点,也就是 imx6ull.dtsi 中的“i2c1: i2c@021a0000”
  • 花括号内就是要向 i2c1 这个节点添加的内容,包括修改某些属性的值。

打开 imx6ull-alientek-emmc.dts,找到如下所示内容:

&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";

	mag3110@0e {
		compatible = "fsl,mag3110";
		reg = <0x0e>;
		position = <2>;
	};

	fxls8471@1e {
		compatible = "fsl,fxls8471";
		reg = <0x1e>;
		position = <0>;
		interrupt-parent = <&gpio5>;
		interrupts = <0 8>;
	};
};
  • 以上就是向 i2c1 节点添加/修改数据,比如添加的新属性“clock-frequency”
    就表示 i2c1 时钟为 100KHz。
  • 将 status 属性的值由原来的 disabled 改为 okay
  • i2c1 子节点 mag3110,因为 NXP 官方开发板在 I2C1 上接了一个磁力计芯片 mag3110,正点原子的 I.MX6U-ALPHA 开发板并没有使用mag3110。
  • i2c1 子节点 fxls8471,同样是因为 NXP 官方开发板在 I2C1 上接了 fxls8471这颗六轴芯片。

 因为上面的代码中的内容是 imx6ull-alientek-emmc.dts 这个文件内的,所以不会对使用 I.MX6ULL 这颗 SOC 的其他板子造成任何影响。这个就是向节点追加或修改内容,重点就是通过&label 来访问节点,然后直接在里面编写要追加或者修改的内容。

2、特殊属性

/{
	model = "Freescale i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

	chosen {
		stdout-path = &uart1;
	};

	memory {
		reg = <0x80000000 0x20000000>;
	};

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		linux,cma {
			compatible = "shared-dma-pool";
			reusable;
			size = <0x14000000>;
			linux,cma-default;
		};
	};
};

(1)/根节点

/{

}
  • #address-cells:在子节点的reg属性中, 使用多少个u32整数来描述地址(address)

  • #size-cells:在子节点的reg属性中, 使用多少个u32整数来描述大小(size)

  • compatible:定义一系列的字符串, 用来指定内核中哪个machine_desc可以支持本设备,即这个板子兼容哪些平台

  • model:比如有2款板子配置基本一致, 它们的compatible是一样的 // 那么就通过model来分辨这2款板子

  • cell:一个u32整数

(2) /chosen

chosen 并不是一个真实的设备,chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数。一般.dts 文件中 chosen 节点通常为空或者内容很少,imx6ull-alientek-emmc.dts 中 chosen 节点内容如下所示:

	chosen {
		stdout-path = &uart1;
	};

 从上面的代码中可以看出,chosen 节点仅仅设置了属性“stdout-path”,表示标准输出使用 uart1。但是当我们进入到/proc/device-tree/chosen 目录里面,会发现多了 bootargs 这个属性,如下所示:

/sys/firmware/devicetree/base/chosen # ls
bootargs    name    stdout-path

输入cat命令查看bootargs这个文件的内容,结果如下:

/sys/firmware/devicetree/base/chosen # cat bootargs
console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.0.120:/home/liefyuan/linux/nfs/rootfs,proto=tcp rw ip=192.168.0.121:192.168.1.120:192.168.0.1:255.255.255.0::eth0:off

 从上面可以看出,bootargs 这个文件的内容是“console=ttymxc0,115200……”,这个不就是我们在 uboot 中设置的 bootargs 环境变量的值吗?现在有两个疑点:

  • ①、我们并没有在设备树中设置 chosen 节点的 bootargs 属性,那么图 43.6.2.1 中 bootargs这个属性是怎么产生的?
  • ②、为何 bootargs 文件的内容和 uboot 中 bootargs 环境变量的值一样?它们之间有什么关系?
     前面讲解 uboot 的时候说过,uboot 在启动 Linux 内核的时候会将 bootargs 的值传递给 Linux内核,bootargs 会作为 Linux 内核的命令行参数,Linux 内核启动的时候会打印出命令行参数(也就是 uboot 传递进来的 bootargs 的值),如下所示:

 既然 chosen 节点的 bootargs 属性不是我们在设备树里面设置的,那么只有一种可能,那就是 uboot 自己在 chosen 节点里面添加了 bootargs 属性!并且设置 bootargs 属性的值为 bootargs环境变量的值。因为在启动 Linux 内核之前,只有 uboot 知道 bootargs 环境变量的值,并且 uboot也知道.dtb 设备树文件在 DRAM 中的位置,因此 uboot 的“作案”嫌疑最大。在 uboot 源码中全局搜索“chosen”这个字符串,看看能不能找到一些蛛丝马迹。果然不出所料,在common/fdt_support.c 文件中发现了“chosen”的身影,fdt_support.c 文件中有个 fdt_chosen 函数,此函数内容如下所示:

int fdt_chosen(void *fdt)
{
	int nodeoffset;
	int err;
	char *str; /* used to set string properties */

	err = fdt_check_header(fdt);
	if (err < 0) {
		printf("fdt_chosen: %s\n", fdt_strerror(err));
		return err;
	}

	/* find or create "/chosen" node. */
	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
	if (nodeoffset < 0)
		return nodeoffset;
	
	str = getenv("bootargs");
	if (str) {
		err = fdt_setprop(fdt, nodeoffset, "bootargs", str,
		strlen(str) + 1);
	if (err < 0) {
		printf("WARNING: could not set bootargs %s.\n",
		fdt_strerror(err));
		return err;
	}
}

	return fdt_fixup_stdout(fdt, nodeoffset);
}
  • 调用函数 fdt_find_or_add_subnode 从设备树(.dtb)中找到 chosen 节点,如果没有找到的话就会自己创建一个 chosen 节点。
  • 读取 uboot 中 bootargs 环境变量的内容。
  • 调用函数 fdt_setprop 向 chosen 节点添加 bootargs 属性,并且 bootargs 属性的值就是环境变量 bootargs 的内容。

 证据“实锤”了,就是 uboot 中的 fdt_chosen 函数在设备树的 chosen 节点中加入了 bootargs属性,并且还设置了 bootargs 属性值。接下来我们顺着 fdt_chosen 函数一点点的抽丝剥茧,看看都有哪些函数调用了fdt_chosen,一直找到最终的源头。这里我就不卖关子了,直接告诉大家整个流程是怎么样的,见图 43.6.2.4:

在这里插入图片描述

 上图中框起来的部分就是函数 do_bootm_linux 函数的执行流程,也就是说do_bootm_linux 函数会通过一系列复杂的调用,最终通过 fdt_chosen 函数在 chosen 节点中加入了 bootargs 属性。而我们通过 bootz 命令启动 Linux 内核的时候会运行 do_bootm_linux 函数,至此,真相大白,一切事情的源头都源于如下命令:
bootz 80800000 – 83000000
当我们输入上述命令并执行以后,do_bootz 函数就会执行,然后一切就按照图 43.6.2.4 中所示的流程开始运行。

(3) /cpus

/cpus节点下有1个或多个cpu子节点, cpu子节点中用reg属性用来标明自己是哪一个cpu

所以 /cpus 中有以下2个属性:

  • #address-cells :在它的子节点的reg属性中, 使用多少个u32整数来描述地址(address)

  • #size-cells:在它的子节点的reg属性中, 使用多少个u32整数来描述大小(size) // 必须设置为0

(4) aliases - 别名

打开 imx6ull.dtsi 文件,aliases 节点内容如下所示:

	aliases {
		can0 = &flexcan1;
		can1 = &flexcan2;
		ethernet0 = &fec1;
		ethernet1 = &fec2;
		gpio0 = &gpio1;
		gpio1 = &gpio2;
		gpio2 = &gpio3;
		gpio3 = &gpio4;
		gpio4 = &gpio5;
		i2c0 = &i2c1;
		i2c1 = &i2c2;
		i2c2 = &i2c3;
		i2c3 = &i2c4;
		mmc0 = &usdhc1;
		mmc1 = &usdhc2;
		serial0 = &uart1;
		serial1 = &uart2;
		serial2 = &uart3;
		serial3 = &uart4;
		serial4 = &uart5;
		serial5 = &uart6;
		serial6 = &uart7;
		serial7 = &uart8;
		spi0 = &ecspi1;
		spi1 = &ecspi2;
		spi2 = &ecspi3;
		spi3 = &ecspi4;
		usbphy0 = &usbphy1;
		usbphy1 = &usbphy2;
	};

 单词 aliases 的意思是“别名”,因此 aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。不过我们一般会在节点命名的时候会加上 label,然后通过&label来访问节点,这样也很方便,而且设备树里面大量的使用&label 的形式来访问节点。

源文件

imx6ull.dtsi

/*
 * Copyright 2015-2016 Freescale Semiconductor, Inc.
 * Copyright 2017 NXP.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <dt-bindings/clock/imx6ul-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "imx6ull-pinfunc.h"
#include "imx6ull-pinfunc-snvs.h"
#include "skeleton.dtsi"

/ {
	aliases {
		can0 = &flexcan1;
		can1 = &flexcan2;
		ethernet0 = &fec1;
		ethernet1 = &fec2;
		gpio0 = &gpio1;
		gpio1 = &gpio2;
		gpio2 = &gpio3;
		gpio3 = &gpio4;
		gpio4 = &gpio5;
		i2c0 = &i2c1;
		i2c1 = &i2c2;
		i2c2 = &i2c3;
		i2c3 = &i2c4;
		mmc0 = &usdhc1;
		mmc1 = &usdhc2;
		serial0 = &uart1;
		serial1 = &uart2;
		serial2 = &uart3;
		serial3 = &uart4;
		serial4 = &uart5;
		serial5 = &uart6;
		serial6 = &uart7;
		serial7 = &uart8;
		spi0 = &ecspi1;
		spi1 = &ecspi2;
		spi2 = &ecspi3;
		spi3 = &ecspi4;
		usbphy0 = &usbphy1;
		usbphy1 = &usbphy2;
	};

	cpus {
		#address-cells = <1>;
		#size-cells = <0>;

		cpu0: cpu@0 {
			compatible = "arm,cortex-a7";
			device_type = "cpu";
			reg = <0>;
			clock-latency = <61036>; /* two CLK32 periods */
			operating-points = <
				/* kHz	uV */
				996000	1275000
				792000	1225000
				/*696000	1225000*/
				528000	1175000
				396000	1025000
				198000	950000
			>;
			fsl,soc-operating-points = <
				/* KHz	uV */
				996000	1175000
				792000	1175000
				/*696000	1175000*/
				528000	1175000
				396000	1175000
				198000	1175000
			>;
			fsl,low-power-run;
			clocks = <&clks IMX6UL_CLK_ARM>,
				 <&clks IMX6UL_CLK_PLL2_BUS>,
				 <&clks IMX6UL_CLK_PLL2_PFD2>,
				 <&clks IMX6UL_CA7_SECONDARY_SEL>,
				 <&clks IMX6UL_CLK_STEP>,
				 <&clks IMX6UL_CLK_PLL1_SW>,
				 <&clks IMX6UL_CLK_PLL1_SYS>,
				 <&clks IMX6UL_PLL1_BYPASS>,
				 <&clks IMX6UL_CLK_PLL1>,
				 <&clks IMX6UL_PLL1_BYPASS_SRC>,
				 <&clks IMX6UL_CLK_OSC>;
			clock-names = "arm", "pll2_bus",  "pll2_pfd2_396m", "secondary_sel", "step",
				      "pll1_sw", "pll1_sys", "pll1_bypass", "pll1", "pll1_bypass_src", "osc";
		};
	};

	intc: interrupt-controller@00a01000 {
		compatible = "arm,cortex-a7-gic";
		#interrupt-cells = <3>;
		interrupt-controller;
		reg = <0x00a01000 0x1000>,
		      <0x00a02000 0x100>;
	};

	clocks {
		#address-cells = <1>;
		#size-cells = <0>;

		ckil: clock@0 {
			compatible = "fixed-clock";
			reg = <0>;
			#clock-cells = <0>;
			clock-frequency = <32768>;
			clock-output-names = "ckil";
		};

		osc: clock@1 {
			compatible = "fixed-clock";
			reg = <1>;
			#clock-cells = <0>;
			clock-frequency = <24000000>;
			clock-output-names = "osc";
		};

		ipp_di0: clock@2 {
			compatible = "fixed-clock";
			reg = <2>;
			#clock-cells = <0>;
			clock-frequency = <0>;
			clock-output-names = "ipp_di0";
		};

		ipp_di1: clock@3 {
			compatible = "fixed-clock";
			reg = <3>;
			#clock-cells = <0>;
			clock-frequency = <0>;
			clock-output-names = "ipp_di1";
		};
	};

	soc {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "simple-bus";
		interrupt-parent = <&gpc>;
		ranges;

		busfreq {
			compatible = "fsl,imx_busfreq";
			clocks = <&clks IMX6UL_CLK_PLL2_PFD2>, <&clks IMX6UL_CLK_PLL2_198M>,
				 <&clks IMX6UL_CLK_PLL2_BUS>, <&clks IMX6UL_CLK_ARM>,
				 <&clks IMX6UL_CLK_PLL3_USB_OTG>, <&clks IMX6UL_CLK_PERIPH>,
				 <&clks IMX6UL_CLK_PERIPH_PRE>, <&clks IMX6UL_CLK_PERIPH_CLK2>,
				 <&clks IMX6UL_CLK_PERIPH_CLK2_SEL>, <&clks IMX6UL_CLK_OSC>,
				 <&clks IMX6UL_CLK_AHB>, <&clks IMX6UL_CLK_AXI>,
				 <&clks IMX6UL_CLK_PERIPH2>, <&clks IMX6UL_CLK_PERIPH2_PRE>,
				 <&clks IMX6UL_CLK_PERIPH2_CLK2>, <&clks IMX6UL_CLK_PERIPH2_CLK2_SEL>,
				 <&clks IMX6UL_CLK_STEP>, <&clks IMX6UL_CLK_MMDC_P0_FAST>, <&clks IMX6UL_PLL1_BYPASS_SRC>,
				 <&clks IMX6UL_PLL1_BYPASS>, <&clks IMX6UL_CLK_PLL1_SYS>, <&clks IMX6UL_CLK_PLL1_SW>,
				 <&clks IMX6UL_CLK_PLL1>;
			clock-names = "pll2_pfd2_396m", "pll2_198m", "pll2_bus", "arm", "pll3_usb_otg",
				      "periph", "periph_pre", "periph_clk2", "periph_clk2_sel", "osc",
				      "ahb", "ocram", "periph2", "periph2_pre", "periph2_clk2", "periph2_clk2_sel",
				      "step", "mmdc", "pll1_bypass_src", "pll1_bypass", "pll1_sys", "pll1_sw", "pll1";
			fsl,max_ddr_freq = <400000000>;
		};

		pmu {
			compatible = "arm,cortex-a7-pmu";
			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
			status = "disabled";
		};

		ocrams: sram@00900000 {
			compatible = "fsl,lpm-sram";
			reg = <0x00900000 0x4000>;
		};

		ocrams_ddr: sram@00904000 {
			compatible = "fsl,ddr-lpm-sram";
			reg = <0x00904000 0x1000>;
		};

		ocram: sram@00905000 {
			compatible = "mmio-sram";
			reg = <0x00905000 0x1B000>;
		};

		dma_apbh: dma-apbh@01804000 {
			compatible = "fsl,imx6ul-dma-apbh", "fsl,imx28-dma-apbh";
			reg = <0x01804000 0x2000>;
			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
			interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
			#dma-cells = <1>;
			dma-channels = <4>;
			clocks = <&clks IMX6UL_CLK_APBHDMA>;
		};

		gpmi: gpmi-nand@01806000{
			compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";
			#address-cells = <1>;
			#size-cells = <1>;
			reg = <0x01806000 0x2000>, <0x01808000 0x4000>;
			reg-names = "gpmi-nand", "bch";
			interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
			interrupt-names = "bch";
			clocks = <&clks IMX6UL_CLK_GPMI_IO>,
				 <&clks IMX6UL_CLK_GPMI_APB>,
				 <&clks IMX6UL_CLK_GPMI_BCH>,
				 <&clks IMX6UL_CLK_GPMI_BCH_APB>,
				 <&clks IMX6UL_CLK_PER_BCH>;
			clock-names = "gpmi_io", "gpmi_apb", "gpmi_bch",
				      "gpmi_bch_apb", "per1_bch";
			dmas = <&dma_apbh 0>;
			dma-names = "rx-tx";
			status = "disabled";
		};

		aips1: aips-bus@02000000 {
			compatible = "fsl,aips-bus", "simple-bus";
			#address-cells = <1>;
			#size-cells = <1>;
			reg = <0x02000000 0x100000>;
			ranges;

			spba-bus@02000000 {
				compatible = "fsl,spba-bus", "simple-bus";
				#address-cells = <1>;
				#size-cells = <1>;
				reg = <0x02000000 0x40000>;
				ranges;

				spdif: spdif@02004000 {
					compatible = "fsl,imx6ul-spdif", "fsl,imx35-spdif";
					reg = <0x02004000 0x4000>;
					interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
					dmas = <&sdma 41 18 0>,
					       <&sdma 42 18 0>;
					dma-names = "rx", "tx";
					clocks = <&clks IMX6UL_CLK_SPDIF_GCLK>,
						 <&clks IMX6UL_CLK_OSC>,
						 <&clks IMX6UL_CLK_SPDIF>,
						 <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>,
						 <&clks IMX6UL_CLK_IPG>,
						 <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_DUMMY>,
						 <&clks IMX6UL_CLK_SPBA>;
					clock-names = "core", "rxtx0",
						      "rxtx1", "rxtx2",
						      "rxtx3", "rxtx4",
						      "rxtx5", "rxtx6",
						      "rxtx7", "dma";
					status = "disabled";
				};

				ecspi1: ecspi@02008000 {
					#address-cells = <1>;
					#size-cells = <0>;
					compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
					reg = <0x02008000 0x4000>;
					interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_ECSPI1>,
						 <&clks IMX6UL_CLK_ECSPI1>;
					clock-names = "ipg", "per";
					dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
					dma-names = "rx", "tx";
					status = "disabled";
				};

				ecspi2: ecspi@0200c000 {
					#address-cells = <1>;
					#size-cells = <0>;
					compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
					reg = <0x0200c000 0x4000>;
					interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_ECSPI2>,
						 <&clks IMX6UL_CLK_ECSPI2>;
					clock-names = "ipg", "per";
					dmas = <&sdma 5 7 1>, <&sdma 6 7 2>;
					dma-names = "rx", "tx";
					status = "disabled";
				};

				ecspi3: ecspi@02010000 {
					#address-cells = <1>;
					#size-cells = <0>;
					compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
					reg = <0x02010000 0x4000>;
					interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_ECSPI3>,
						 <&clks IMX6UL_CLK_ECSPI3>;
					clock-names = "ipg", "per";
					dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;
					dma-names = "rx", "tx";
					status = "disabled";
				};

				ecspi4: ecspi@02014000 {
					#address-cells = <1>;
					#size-cells = <0>;
					compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
					reg = <0x02014000 0x4000>;
					interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_ECSPI4>,
						 <&clks IMX6UL_CLK_ECSPI4>;
					clock-names = "ipg", "per";
					dmas = <&sdma 9 7 1>, <&sdma 10 7 2>;
					dma-names = "rx", "tx";
					status = "disabled";
				};

				uart7: serial@02018000 {
					compatible = "fsl,imx6ul-uart",
						     "fsl,imx6q-uart", "fsl,imx21-uart";
					reg = <0x02018000 0x4000>;
					interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_UART7_IPG>,
						 <&clks IMX6UL_CLK_UART7_SERIAL>;
					clock-names = "ipg", "per";
					dmas = <&sdma 43 4 0>, <&sdma 44 4 0>;
					dma-names = "rx", "tx";
					status = "disabled";
				};

				uart1: serial@02020000 {
					compatible = "fsl,imx6ul-uart",
						     "fsl,imx6q-uart", "fsl,imx21-uart";
					reg = <0x02020000 0x4000>;
					interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_UART1_IPG>,
						 <&clks IMX6UL_CLK_UART1_SERIAL>;
					clock-names = "ipg", "per";
					status = "disabled";
				};

				esai: esai@02024000 {
					compatible = "fsl,imx6ull-esai";
					reg = <0x02024000 0x4000>;
					interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_ESAI_IPG>,
						 <&clks IMX6UL_CLK_ESAI_MEM>,
						 <&clks IMX6UL_CLK_ESAI_EXTAL>,
						 <&clks IMX6UL_CLK_ESAI_IPG>,
						 <&clks IMX6UL_CLK_SPBA>;
					clock-names = "core", "mem", "extal",
						      "fsys", "dma";
					dmas = <&sdma 0 21 0>, <&sdma 47 21 0>;
					dma-names = "rx", "tx";
					dma-source = <&gpr 0 14 0 15>;
					status = "disabled";
				};

				sai1: sai@02028000 {
					compatible = "fsl,imx6ul-sai",
						     "fsl,imx6sx-sai";
					reg = <0x02028000 0x4000>;
					interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_SAI1_IPG>,
						 <&clks IMX6UL_CLK_DUMMY>,
						 <&clks IMX6UL_CLK_SAI1>,
						 <&clks 0>, <&clks 0>;
					clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
					dma-names = "rx", "tx";
					dmas = <&sdma 35 24 0>, <&sdma 36 24 0>;
					status = "disabled";
				};

				sai2: sai@0202c000 {
					compatible = "fsl,imx6ul-sai",
						     "fsl,imx6sx-sai";
					reg = <0x0202c000 0x4000>;
					interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_SAI2_IPG>,
						 <&clks IMX6UL_CLK_DUMMY>,
						 <&clks IMX6UL_CLK_SAI2>,
						 <&clks 0>, <&clks 0>;
					clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
					dma-names = "rx", "tx";
					dmas = <&sdma 37 24 0>, <&sdma 38 24 0>;
					status = "disabled";
				};

				sai3: sai@02030000 {
					compatible = "fsl,imx6ul-sai",
						     "fsl,imx6sx-sai";
					reg = <0x02030000 0x4000>;
					interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_SAI3_IPG>,
						 <&clks IMX6UL_CLK_DUMMY>,
						 <&clks IMX6UL_CLK_SAI3>,
						 <&clks 0>, <&clks 0>;
					clock-names = "bus", "mclk0", "mclk1", "mclk2", "mclk3";
					dma-names = "rx", "tx";
					dmas = <&sdma 39 24 0>, <&sdma 40 24 0>;
					status = "disabled";
				};

				asrc: asrc@02034000 {
					compatible = "fsl,imx53-asrc";
					reg = <0x02034000 0x4000>;
					interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
					clocks = <&clks IMX6UL_CLK_ASRC_IPG>,
						<&clks IMX6UL_CLK_ASRC_MEM>, <&clks 0>,
						<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
						<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
						<&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
						<&clks IMX6UL_CLK_SPDIF>, <&clks 0>, <&clks 0>,
						<&clks IMX6UL_CLK_SPBA>;
					clock-names = "mem", "ipg", "asrck_0",
						"asrck_1", "asrck_2", "asrck_3", "asrck_4",
						"asrck_5", "asrck_6", "asrck_7", "asrck_8",
						"asrck_9", "asrck_a", "asrck_b", "asrck_c",
						"asrck_d", "asrck_e", "asrck_f", "dma";
					dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
						<&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
					dma-names = "rxa", "rxb", "rxc",
						    "txa", "txb", "txc";
					fsl,asrc-rate  = <48000>;
					fsl,asrc-width = <16>;
					status = "okay";
				};
			};

			tsc: tsc@02040000 {
				compatible = "fsl,imx6ul-tsc";
				reg = <0x02040000 0x4000>, <0x0219c000 0x4000>;
				interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_IPG>,
					 <&clks IMX6UL_CLK_ADC2>;
				clock-names = "tsc", "adc";
				status = "disabled";
			};

			pwm1: pwm@02080000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x02080000 0x4000>;
				interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_PWM1>,
					 <&clks IMX6UL_CLK_PWM1>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			pwm2: pwm@02084000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x02084000 0x4000>;
				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			pwm3: pwm@02088000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x02088000 0x4000>;
				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_PWM3>,
					 <&clks IMX6UL_CLK_PWM3>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			pwm4: pwm@0208c000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x0208c000 0x4000>;
				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			flexcan1: can@02090000 {
				compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
				reg = <0x02090000 0x4000>;
				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_CAN1_IPG>,
					 <&clks IMX6UL_CLK_CAN1_SERIAL>;
				clock-names = "ipg", "per";
				stop-mode = <&gpr 0x10 1 0x10 17>;
				status = "disabled";
			};

			flexcan2: can@02094000 {
				compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
				reg = <0x02094000 0x4000>;
				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_CAN2_IPG>,
					 <&clks IMX6UL_CLK_CAN2_SERIAL>;
				clock-names = "ipg", "per";
				stop-mode = <&gpr 0x10 2 0x10 18>;
				status = "disabled";
			};

			gpt1: gpt@02098000 {
				compatible = "fsl,imx6ul-gpt", "fsl,imx31-gpt";
				reg = <0x02098000 0x4000>;
				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_GPT1_BUS>,
					 <&clks IMX6UL_CLK_GPT_3M>;
				clock-names = "ipg", "osc_per";
			};

			gpio1: gpio@0209c000 {
				compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
				reg = <0x0209c000 0x4000>;
				interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
				gpio-controller;
				#gpio-cells = <2>;
				interrupt-controller;
				#interrupt-cells = <2>;
			};

			gpio2: gpio@020a0000 {
				compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
				reg = <0x020a0000 0x4000>;
				interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
				gpio-controller;
				#gpio-cells = <2>;
				interrupt-controller;
				#interrupt-cells = <2>;
			};

			gpio3: gpio@020a4000 {
				compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
				reg = <0x020a4000 0x4000>;
				interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
				gpio-controller;
				#gpio-cells = <2>;
				interrupt-controller;
				#interrupt-cells = <2>;
			};

			gpio4: gpio@020a8000 {
				compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
				reg = <0x020a8000 0x4000>;
				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
				gpio-controller;
				#gpio-cells = <2>;
				interrupt-controller;
				#interrupt-cells = <2>;
			};

			gpio5: gpio@020ac000 {
				compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
				reg = <0x020ac000 0x4000>;
				interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
				gpio-controller;
				#gpio-cells = <2>;
				interrupt-controller;
				#interrupt-cells = <2>;
			};

			snvslp: snvs@020b0000 {
				compatible = "fsl,imx6ul-snvs";
				reg = <0x020b0000 0x4000>;
				interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
			};

			fec2: ethernet@020b4000 {
				compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
				reg = <0x020b4000 0x4000>;
				interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_ENET>,
					 <&clks IMX6UL_CLK_ENET_AHB>,
					 <&clks IMX6UL_CLK_ENET_PTP>,
					 <&clks IMX6UL_CLK_ENET2_REF_125M>,
					 <&clks IMX6UL_CLK_ENET2_REF_125M>;
				clock-names = "ipg", "ahb", "ptp",
					      "enet_clk_ref", "enet_out";
				stop-mode = <&gpr 0x10 4>;
				fsl,num-tx-queues=<1>;
				fsl,num-rx-queues=<1>;
				fsl,magic-packet;
				fsl,wakeup_irq = <0>;
				status = "disabled";
			};

			kpp: kpp@020b8000 {
				compatible = "fsl,imx6ul-kpp", "fsl,imx21-kpp";
				reg = <0x020b8000 0x4000>;
				interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>;
				status = "disabled";
			};

			wdog1: wdog@020bc000 {
				compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
				reg = <0x020bc000 0x4000>;
				interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_WDOG1>;
			};

			wdog2: wdog@020c0000 {
				compatible = "fsl,imx6ul-wdt", "fsl,imx21-wdt";
				reg = <0x020c0000 0x4000>;
				interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_WDOG2>;
				status = "disabled";
			};

			clks: ccm@020c4000 {
				compatible = "fsl,imx6ul-ccm";
				reg = <0x020c4000 0x4000>;
				interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
				#clock-cells = <1>;
				clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
				clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
			};

			anatop: anatop@020c8000 {
				compatible = "fsl,imx6ul-anatop", "fsl,imx6q-anatop",
					     "syscon", "simple-bus";
				reg = <0x020c8000 0x1000>;
				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;

				reg_3p0: regulator-3p0@120 {
					compatible = "fsl,anatop-regulator";
					regulator-name = "vdd3p0";
					regulator-min-microvolt = <2625000>;
					regulator-max-microvolt = <3400000>;
					anatop-reg-offset = <0x120>;
					anatop-vol-bit-shift = <8>;
					anatop-vol-bit-width = <5>;
					anatop-min-bit-val = <0>;
					anatop-min-voltage = <2625000>;
					anatop-max-voltage = <3400000>;
					anatop-enable-bit = <0>;
				};

				reg_arm: regulator-vddcore@140 {
					compatible = "fsl,anatop-regulator";
					regulator-name = "cpu";
					regulator-min-microvolt = <725000>;
					regulator-max-microvolt = <1450000>;
					regulator-always-on;
					anatop-reg-offset = <0x140>;
					anatop-vol-bit-shift = <0>;
					anatop-vol-bit-width = <5>;
					anatop-delay-reg-offset = <0x170>;
					anatop-delay-bit-shift = <24>;
					anatop-delay-bit-width = <2>;
					anatop-min-bit-val = <1>;
					anatop-min-voltage = <725000>;
					anatop-max-voltage = <1450000>;
				};

				reg_soc: regulator-vddsoc@140 {
					compatible = "fsl,anatop-regulator";
					regulator-name = "vddsoc";
					regulator-min-microvolt = <725000>;
					regulator-max-microvolt = <1450000>;
					regulator-always-on;
					anatop-reg-offset = <0x140>;
					anatop-vol-bit-shift = <18>;
					anatop-vol-bit-width = <5>;
					anatop-delay-reg-offset = <0x170>;
					anatop-delay-bit-shift = <28>;
					anatop-delay-bit-width = <2>;
					anatop-min-bit-val = <1>;
					anatop-min-voltage = <725000>;
					anatop-max-voltage = <1450000>;
				};
			};

			usbphy1: usbphy@020c9000 {
				compatible = "fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
				reg = <0x020c9000 0x1000>;
				interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_USBPHY1>;
				phy-3p0-supply = <&reg_3p0>;
				fsl,anatop = <&anatop>;
			};

			usbphy2: usbphy@020ca000 {
				compatible = "fsl,imx6ul-usbphy", "fsl,imx23-usbphy";
				reg = <0x020ca000 0x1000>;
				interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_USBPHY2>;
				phy-3p0-supply = <&reg_3p0>;
				fsl,anatop = <&anatop>;
			};

			tempmon: tempmon {
				compatible = "fsl,imx6ul-tempmon", "fsl,imx6sx-tempmon";
				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
				fsl,tempmon = <&anatop>;
				fsl,tempmon-data = <&ocotp>;
				clocks = <&clks IMX6UL_CLK_PLL3_USB_OTG>;
			};

			snvs: snvs@020cc000 {
				compatible = "fsl,sec-v4.0-mon", "syscon", "simple-mfd";
				reg = <0x020cc000 0x4000>;

				snvs_rtc: snvs-rtc-lp {
					compatible = "fsl,sec-v4.0-mon-rtc-lp";
					regmap = <&snvs>;
					offset = <0x34>;
					interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
				};

				snvs_poweroff: snvs-poweroff {
					compatible = "syscon-poweroff";
					regmap = <&snvs>;
					offset = <0x38>;
					mask = <0x61>;
				};

				snvs_pwrkey: snvs-powerkey {
					compatible = "fsl,sec-v4.0-pwrkey";
					regmap = <&snvs>;
					interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
					linux,keycode = <KEY_POWER>;
					wakeup;
				};
			};

			epit1: epit@020d0000 {
				reg = <0x020d0000 0x4000>;
				interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
			};

			epit2: epit@020d4000 {
				reg = <0x020d4000 0x4000>;
				interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
			};

			src: src@020d8000 {
				compatible = "fsl,imx6ul-src", "fsl,imx51-src";
				reg = <0x020d8000 0x4000>;
				interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
				#reset-cells = <1>;
			};

			gpc: gpc@020dc000 {
				compatible = "fsl,imx6ul-gpc", "fsl,imx6q-gpc";
				reg = <0x020dc000 0x4000>;
				interrupt-controller;
				#interrupt-cells = <3>;
				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
				interrupt-parent = <&intc>;
				fsl,mf-mix-wakeup-irq = <0xfc00000 0x7d00 0x0 0x1400640>;
			};

			iomuxc: iomuxc@020e0000 {
				compatible = "fsl,imx6ul-iomuxc";
				reg = <0x020e0000 0x4000>;
			};

			gpr: iomuxc-gpr@020e4000 {
				compatible = "fsl,imx6ul-iomuxc-gpr",
					"fsl,imx6q-iomuxc-gpr", "syscon";
				reg = <0x020e4000 0x4000>;
			};

			mqs: mqs {
				compatible = "fsl,imx6sx-mqs";
				gpr = <&gpr>;
				status = "disabled";
			};

			gpt2: gpt@020e8000 {
				compatible = "fsl,imx6ul-gpt", "fsl,imx31-gpt";
				reg = <0x020e8000 0x4000>;
				interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
			};

			sdma: sdma@020ec000 {
				compatible = "fsl,imx6ul-sdma", "fsl,imx35-sdma";
				reg = <0x020ec000 0x4000>;
				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_SDMA>,
					 <&clks IMX6UL_CLK_SDMA>;
				clock-names = "ipg", "ahb";
				#dma-cells = <3>;
				iram = <&ocram>;
				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx6q.bin";
			};

			pwm5: pwm@020f0000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x020f0000 0x4000>;
				interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			pwm6: pwm@020f4000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x020f4000 0x4000>;
				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			pwm7: pwm@020f8000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x020f8000 0x4000>;
				interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};

			pwm8: pwm@020fc000 {
				compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";
				reg = <0x020fc000 0x4000>;
				interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "ipg", "per";
				#pwm-cells = <2>;
			};
		};

		aips2: aips-bus@02100000 {
			compatible = "fsl,aips-bus", "simple-bus";
			#address-cells = <1>;
			#size-cells = <1>;
			reg = <0x02100000 0x100000>;
			ranges;

			usbotg1: usb@02184000 {
				compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
				reg = <0x02184000 0x200>;
				interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_USBOH3>;
				fsl,usbphy = <&usbphy1>;
				fsl,usbmisc = <&usbmisc 0>;
				fsl,anatop = <&anatop>;
				ahb-burst-config = <0x0>;
				tx-burst-size-dword = <0x10>;
				rx-burst-size-dword = <0x10>;
				status = "disabled";
			};

			usbotg2: usb@02184200 {
				compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
				reg = <0x02184200 0x200>;
				interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_USBOH3>;
				fsl,usbphy = <&usbphy2>;
				fsl,usbmisc = <&usbmisc 1>;
				ahb-burst-config = <0x0>;
				tx-burst-size-dword = <0x10>;
				rx-burst-size-dword = <0x10>;
				status = "disabled";
			};

			usbmisc: usbmisc@02184800 {
				#index-cells = <1>;
				compatible = "fsl,imx6ul-usbmisc", "fsl,imx6q-usbmisc";
				reg = <0x02184800 0x200>;
			};

			fec1: ethernet@02188000 {
				compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
				reg = <0x02188000 0x4000>;
				interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_ENET>,
					 <&clks IMX6UL_CLK_ENET_AHB>,
					 <&clks IMX6UL_CLK_ENET_PTP>,
					 <&clks IMX6UL_CLK_ENET_REF>,
					 <&clks IMX6UL_CLK_ENET_REF>;
				clock-names = "ipg", "ahb", "ptp",
					      "enet_clk_ref", "enet_out";
				stop-mode = <&gpr 0x10 3>;
				fsl,num-tx-queues=<1>;
				fsl,num-rx-queues=<1>;
				fsl,magic-packet;
				fsl,wakeup_irq = <0>;
				status = "disabled";
                        };

			usdhc1: usdhc@02190000 {
				compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";
				reg = <0x02190000 0x4000>;
				interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_USDHC1>,
					 <&clks IMX6UL_CLK_USDHC1>,
					 <&clks IMX6UL_CLK_USDHC1>;
				clock-names = "ipg", "ahb", "per";
				assigned-clocks = <&clks IMX6UL_CLK_USDHC1_SEL>, <&clks IMX6UL_CLK_USDHC1>;
				assigned-clock-parents = <&clks IMX6UL_CLK_PLL2_PFD2>;
				assigned-clock-rates = <0>, <132000000>;
				bus-width = <4>;
				fsl,tuning-step= <2>;
				status = "disabled";
			};

			usdhc2: usdhc@02194000 {
				compatible = "fsl,imx6ull-usdhc", "fsl,imx6sx-usdhc";
				reg = <0x02194000 0x4000>;
				interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_USDHC2>,
					 <&clks IMX6UL_CLK_USDHC2>,
					 <&clks IMX6UL_CLK_USDHC2>;
				clock-names = "ipg", "ahb", "per";
				assigned-clocks = <&clks IMX6UL_CLK_USDHC2_SEL>, <&clks IMX6UL_CLK_USDHC2>;
				assigned-clock-parents = <&clks IMX6UL_CLK_PLL2_PFD2>;
				assigned-clock-rates = <0>, <132000000>;
				bus-width = <4>;
				fsl,tuning-step= <2>;
				status = "disabled";
			};

			adc1: adc@02198000 {
				compatible = "fsl,imx6ul-adc", "fsl,vf610-adc";
				reg = <0x02198000 0x4000>;
				interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_ADC1>;
				num-channels = <2>;
				clock-names = "adc";
				status = "disabled";
                        };

			i2c1: i2c@021a0000 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
				reg = <0x021a0000 0x4000>;
				interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_I2C1>;
				status = "disabled";
			};

			i2c2: i2c@021a4000 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
				reg = <0x021a4000 0x4000>;
				interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_I2C2>;
				status = "disabled";
			};

			i2c3: i2c@021a8000 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
				reg = <0x021a8000 0x4000>;
				interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_I2C3>;
				status = "disabled";
			};

			romcp@021ac000 {
				compatible = "fsl,imx6ul-romcp", "syscon";
				reg = <0x021ac000 0x4000>;
			};

			mmdc: mmdc@021b0000 {
				compatible = "fsl,imx6ul-mmdc", "fsl,imx6q-mmdc";
				reg = <0x021b0000 0x4000>;
			};

			weim: weim@021b8000 {
				compatible = "fsl,imx6ul-weim", "fsl,imx6q-weim";
				reg = <0x021b8000 0x4000>;
				interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>;
			};

			ocotp: ocotp-ctrl@021bc000 {
				compatible = "fsl,imx6ull-ocotp", "syscon";
				reg = <0x021bc000 0x4000>;
				clocks = <&clks IMX6UL_CLK_OCOTP>;
			};

			csu: csu@021c0000 {
				compatible = "fsl,imx6ul-csu";
				reg = <0x021c0000 0x4000>;
				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
				status = "disabled";
			};

			csi: csi@021c4000 {
				compatible = "fsl,imx6ul-csi", "fsl,imx6s-csi";
				reg = <0x021c4000 0x4000>;
				interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>,
					<&clks IMX6UL_CLK_CSI>,
					<&clks IMX6UL_CLK_DUMMY>;
				clock-names = "disp-axi", "csi_mclk", "disp_dcic";
				status = "disabled";
			};

			lcdif: lcdif@021c8000 {
				compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
				reg = <0x021c8000 0x4000>;
				interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
					 <&clks IMX6UL_CLK_LCDIF_APB>,
					 <&clks IMX6UL_CLK_DUMMY>;
				clock-names = "pix", "axi", "disp_axi";
				status = "disabled";
			};

			pxp: pxp@021cc000 {
				compatible = "fsl,imx6ull-pxp-dma", "fsl,imx7d-pxp-dma";
				reg = <0x021cc000 0x4000>;
				interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
					<GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DUMMY>, <&clks IMX6UL_CLK_PXP>;
				clock-names = "pxp_ipg", "pxp_axi";
				status = "disabled";
			};

			qspi: qspi@021e0000 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,imx6ull-qspi", "fsl,imx6ul-qspi";
				reg = <0x021e0000 0x4000>, <0x60000000 0x10000000>;
				reg-names = "QuadSPI", "QuadSPI-memory";
				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_QSPI>,
					 <&clks IMX6UL_CLK_QSPI>;
				clock-names = "qspi_en", "qspi";
				status = "disabled";
			};

			uart2: serial@021e8000 {
				compatible = "fsl,imx6ul-uart",
					     "fsl,imx6q-uart", "fsl,imx21-uart";
				reg = <0x021e8000 0x4000>;
				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_UART2_IPG>,
					 <&clks IMX6UL_CLK_UART2_SERIAL>;
				clock-names = "ipg", "per";
				dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
				dma-names = "rx", "tx";
				status = "disabled";
			};

			uart3: serial@021ec000 {
				compatible = "fsl,imx6ul-uart",
					     "fsl,imx6q-uart", "fsl,imx21-uart";
				reg = <0x021ec000 0x4000>;
				interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_UART3_IPG>,
					 <&clks IMX6UL_CLK_UART3_SERIAL>;
				clock-names = "ipg", "per";
				dmas = <&sdma 29 4 0>, <&sdma 30 4 0>;
				dma-names = "rx", "tx";
				status = "disabled";
			};

			uart4: serial@021f0000 {
				compatible = "fsl,imx6ul-uart",
					     "fsl,imx6q-uart", "fsl,imx21-uart";
				reg = <0x021f0000 0x4000>;
				interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_UART4_IPG>,
					 <&clks IMX6UL_CLK_UART4_SERIAL>;
				clock-names = "ipg", "per";
				dmas = <&sdma 31 4 0>, <&sdma 32 4 0>;
				dma-names = "rx", "tx";
				status = "disabled";
			};

			uart5: serial@021f4000 {
				compatible = "fsl,imx6ul-uart",
					     "fsl,imx6q-uart", "fsl,imx21-uart";
				reg = <0x021f4000 0x4000>;
				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_UART5_IPG>,
					 <&clks IMX6UL_CLK_UART5_SERIAL>;
				clock-names = "ipg", "per";
				dmas = <&sdma 33 4 0>, <&sdma 34 4 0>;
				dma-names = "rx", "tx";
				status = "disabled";
			};

			i2c4: i2c@021f8000 {
				#address-cells = <1>;
				#size-cells = <0>;
				compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
				reg = <0x021f8000 0x4000>;
				interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_I2C4>;
				status = "disabled";
			};

			uart6: serial@021fc000 {
				compatible = "fsl,imx6ul-uart",
					     "fsl,imx6q-uart", "fsl,imx21-uart";
				reg = <0x021fc000 0x4000>;
				interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_UART6_IPG>,
					 <&clks IMX6UL_CLK_UART6_SERIAL>;
				clock-names = "ipg", "per";
				dmas = <&sdma 0 4 0>, <&sdma 47 4 0>;
				dma-names = "rx", "tx";
				status = "disabled";
			};
		};

		aips3: aips-bus@02200000 {
			compatible = "fsl,aips-bus", "simple-bus";
			#address-cells = <1>;
			#size-cells = <1>;
			reg = <0x02200000 0x100000>;
			ranges;

			dcp: dcp@02280000 {
				compatible = "fsl,imx6sl-dcp";
				reg = <0x02280000 0x4000>;
				interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
					     <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_DCP_CLK>;
				clock-names = "dcp";
			};

			rngb: rngb@02284000 {
				compatible = "fsl,imx6sl-rng", "fsl,imx-rng", "imx-rng";
				reg = <0x02284000 0x4000>;
				interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
				clocks =  <&clks IMX6UL_CLK_DUMMY>;
			};

			uart8: serial@02288000 {
				compatible = "fsl,imx6ul-uart",
					     "fsl,imx6q-uart", "fsl,imx21-uart";
				reg = <0x02288000 0x4000>;
				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
				clocks = <&clks IMX6UL_CLK_UART8_IPG>,
					 <&clks IMX6UL_CLK_UART8_SERIAL>;
				clock-names = "ipg", "per";
				dmas = <&sdma 45 4 0>, <&sdma 46 4 0>;
				dma-names = "rx", "tx";
				status = "disabled";
			};

			epdc: epdc@0228c000 {
				compatible = "fsl,imx7d-epdc";
				interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
				reg = <0x0228c000 0x4000>;
				clocks = <&clks IMX6UL_CLK_EPDC_ACLK>,
					 <&clks IMX6UL_CLK_EPDC_PIX>;
				clock-names = "epdc_axi", "epdc_pix";
				/* Need to fix epdc-ram */
				/* epdc-ram = <&gpr 0x4 30>; */
				status = "disabled";
			};

			iomuxc_snvs: iomuxc-snvs@02290000 {
				compatible = "fsl,imx6ull-iomuxc-snvs";
				reg = <0x02290000 0x10000>;
			};

			snvs_gpr: snvs-gpr@0x02294000 {
				compatible = "fsl, imx6ull-snvs-gpr";
				reg = <0x02294000 0x10000>;
			};
		};
	};
};

imx6ull-alientek-emmc.dts

/*
 * Copyright (C) 2016 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

/dts-v1/;

#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"

/ {
	model = "Freescale i.MX6 ULL 14x14 EVK Board";
	compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

	chosen {
		stdout-path = &uart1;
	};

	memory {
		reg = <0x80000000 0x20000000>;
	};

	reserved-memory {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;

		linux,cma {
			compatible = "shared-dma-pool";
			reusable;
			size = <0x14000000>;
			linux,cma-default;
		};
	};

	backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 5000000>;
		brightness-levels = <0 4 8 16 32 64 128 255>;
		default-brightness-level = <7>;
		status = "okay";
	};

	pxp_v4l2 {
		compatible = "fsl,imx6ul-pxp-v4l2", "fsl,imx6sx-pxp-v4l2", "fsl,imx6sl-pxp-v4l2";
		status = "okay";
	};

	regulators {
		compatible = "simple-bus";
		#address-cells = <1>;
		#size-cells = <0>;

		reg_can_3v3: regulator@0 {
			compatible = "regulator-fixed";
			reg = <0>;
			regulator-name = "can-3v3";
			regulator-min-microvolt = <3300000>;
			regulator-max-microvolt = <3300000>;
			gpios = <&gpio_spi 3 GPIO_ACTIVE_LOW>;
		};

		reg_sd1_vmmc: regulator@1 {
			compatible = "regulator-fixed";
			regulator-name = "VSD_3V3";
			regulator-min-microvolt = <3300000>;
			regulator-max-microvolt = <3300000>;
			//gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>;
			enable-active-high;
		};

		/* zuozhongkai ADC vref 3.3V */
		reg_vref_adc: regulator@2 {
			compatible = "regulator-fixed";
			regulator-name = "VREF_3V3";
			regulator-min-microvolt = <3300000>;
			regulator-max-microvolt = <3300000>;
		};

		reg_gpio_dvfs: regulator-gpio {
			compatible = "regulator-gpio";
			pinctrl-names = "default";
			pinctrl-0 = <&pinctrl_dvfs>;
			regulator-min-microvolt = <1300000>;
			regulator-max-microvolt = <1400000>;
			regulator-name = "gpio_dvfs";
			regulator-type = "voltage";
			gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;
			states = <1300000 0x1 1400000 0x0>;
		};
	};

	sound {
		compatible = "fsl,imx6ul-evk-wm8960",
			   "fsl,imx-audio-wm8960";
		model = "wm8960-audio";
		cpu-dai = <&sai2>;
		audio-codec = <&codec>;
		asrc-controller = <&asrc>;
		codec-master;
		gpr = <&gpr 4 0x100000 0x100000>;
		/*
                 * hp-det = <hp-det-pin hp-det-polarity>;
		 * hp-det-pin: JD1 JD2  or JD3
		 * hp-det-polarity = 0: hp detect high for headphone
		 * hp-det-polarity = 1: hp detect high for speaker
		 */
		hp-det = <3 0>;
		/*hp-det-gpios = <&gpio5 4 0>;
		mic-det-gpios = <&gpio5 4 0>;*/
		audio-routing =
			"Headphone Jack", "HP_L",
			"Headphone Jack", "HP_R",
			"Ext Spk", "SPK_LP",
			"Ext Spk", "SPK_LN",
			"Ext Spk", "SPK_RP",
			"Ext Spk", "SPK_RN",
			"LINPUT2", "Mic Jack",
			"LINPUT3", "Mic Jack",
			"RINPUT1", "Main MIC",
			"RINPUT2", "Main MIC",
			"Mic Jack", "MICB",
			"Main MIC", "MICB",
			"CPU-Playback", "ASRC-Playback",
			"Playback", "CPU-Playback",
			"ASRC-Capture", "CPU-Capture",
			"CPU-Capture", "Capture";
	};

	spi4 {
		compatible = "spi-gpio";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_spi4>;
		/* pinctrl-assert-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; */
		status = "okay";
		gpio-sck = <&gpio5 11 0>;
		gpio-mosi = <&gpio5 10 0>;
		/* cs-gpios = <&gpio5 7 0>;*/
		num-chipselects = <1>;
		#address-cells = <1>;
		#size-cells = <0>;

		gpio_spi: gpio_spi@0 {
			compatible = "fairchild,74hc595";
			gpio-controller;
			#gpio-cells = <2>;
			reg = <0>;
			registers-number = <1>;
			registers-default = /bits/ 8 <0x57>;
			spi-max-frequency = <100000>;
		};
	};
	
	/* zuozhongkai dts leds linux自带led驱动的设备树*/
    dtsleds {
        compatible = "gpio-leds";
 
        led0 {
            label = "red";
            gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
            linux,default-trigger = "heartbeat";
            default-state = "on";
        };
    };

	/* zuozhongkai */
	alphaled {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-led";
		status = "okay";
		reg = < 0X020C406C 0X04		/* CCM_CCGR1_BAE 			*/
				0X020E0068 0X04		/* SW_MUX_GPIO1_IO03_BASE 	*/
				0X020E02F4 0X04		/* SW_PAD_GPIO1_IO03_BASE	*/
				0X0209C000 0X04		/* GPIO1_DR_BASE 			*/
				0X0209C004 0X04>;	/* GPIO1_GDIR_BASE 			*/
	};

	gpioled {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-gpioled";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_led>;
		led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
		status = "okay";
	};

	/* liefyuan */
	/*beep {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-beep";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_beep>;
		beep-gpio = <&gpio5 1 GPIO_ACTIVE_HIGH>;
		status = "okay";
	};*/
	key {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "atkalpha-key";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_key>;
		key-gpio = <&gpio1 18 GPIO_ACTIVE_LOW>; /* KEY0 */
		interrupt-parent = <&gpio1>;
		interrupts = <18 IRQ_TYPE_EDGE_BOTH>; /* FALLING RISING */
		status = "okay";
	};

	/* zuozhongkai dts keys linux自带的key驱动设备树 */
	gpio-keys {
		compatible = "gpio-keys";
		#address-cells = <1>;
		#size-cells = <0>;
		autorepeat;
		key0 {
			label = "GPIO Key Enter";
			linux,code = <KEY_ENTER>;
			gpios = <&gpio1 18 GPIO_ACTIVE_LOW>;
		};
	};

	/* zuozhongkai sii902x reset */
	sii902x_reset: sii902x-reset {
        compatible = "gpio-reset";
        reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
    	reset-delay-us = <100000>;
        #reset-cells = <0>;
        status = "disabled";
    };
};

&cpu0 {
	arm-supply = <&reg_arm>;
	soc-supply = <&reg_soc>;
	dc-supply = <&reg_gpio_dvfs>;
};

&clks {
	assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <786432000>;
};

&csi {
	status = "okay";

	port {
		csi1_ep: endpoint {
			remote-endpoint = <&ov5640_ep>;
		};
	};
};

&fec1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet1
			&pinctrl_enet1_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy0>;
	phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
    phy-reset-duration = <200>;
	status = "okay";
};

&fec2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_enet2
				&pinctrl_enet2_reset>;
	phy-mode = "rmii";
	phy-handle = <&ethphy1>;
	phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
    phy-reset-duration = <200>;
	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy0: ethernet-phy@0 {
            compatible = "ethernet-phy-ieee802.3-c22";
            reg = <0>;
         };
 
        ethphy1: ethernet-phy@1 {
        	compatible = "ethernet-phy-ieee802.3-c22";
        	reg = <1>;
		};
	};
};

&flexcan1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexcan1>;
	xceiver-supply = <&reg_can_3v3>;
	status = "okay";
};

/*
&flexcan2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexcan2>;
	xceiver-supply = <&reg_can_3v3>;
	status = "okay";
};
*/

&gpc {
	fsl,cpu_pupscr_sw2iso = <0x1>;
	fsl,cpu_pupscr_sw = <0x0>;
	fsl,cpu_pdnscr_iso2sw = <0x1>;
	fsl,cpu_pdnscr_iso = <0x1>;
	fsl,ldo-bypass = <0>; /* DCDC, ldo-enable */
};

&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";

	ap3216c@1e {
		compatible = "alientek,ap3216c";
		reg = <0x1e>;
	};
};

&i2c2 {
	clock_frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c2>;
	status = "okay";

	codec: wm8960@1a {
		compatible = "wlf,wm8960";
		reg = <0x1a>;
		clocks = <&clks IMX6UL_CLK_SAI2>;
		clock-names = "mclk";
		wlf,shared-lrclk;
	};

	ov5640: ov5640@3c {
		compatible = "ovti,ov5640";
		reg = <0x3c>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_csi1>;
		clocks = <&clks IMX6UL_CLK_CSI>;
		clock-names = "csi_mclk";
		pwn-gpios = <&gpio_spi 6 1>;
		rst-gpios = <&gpio_spi 5 0>;
		csi_id = <0>;
		mclk = <24000000>;
		mclk_source = <0>;
		status = "okay";
		port {
			ov5640_ep: endpoint {
				remote-endpoint = <&csi1_ep>;
			};
		};
	};

	/* zuozhongkai FT5406/FT5426 */
	ft5426: ft5426@38 {
		compatible = "edt,edt-ft5426","edt,edt-ft5406";
		reg = <0x38>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_tsc
					&pinctrl_tsc_reset >; 
		interrupt-parent = <&gpio1>; 
		interrupts = <9 0>; 
		reset-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;  
		interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
		status = "okay";
	};

	gt9147:gt9147@14 {
		compatible = "goodix,gt9147", "goodix,gt9xx";
		reg = <0x14>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_tsc
					&pinctrl_tsc_reset >; 
		interrupt-parent = <&gpio1>; 
		interrupts = <9 0>; 
		reset-gpios  = <&gpio5 9 GPIO_ACTIVE_LOW>;
		interrupt-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
		status = "disable";  /* 如果需要改为okay */
	};

	/* zuozhongkai sill902x,如果需要HDMI就将status改为okay即可  */
	/*
	sii902x: sii902x@39 {
        compatible = "SiI,sii902x";
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_sii902x>;
        interrupt-parent = <&gpio1>;
        interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
		irq-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
        mode_str = "1280x720M@60";
        bits-per-pixel = <16>;
        resets = <&sii902x_reset>;
        reg = <0x39>;
        status = "disable"; 
    };*/
};

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog_1>;
	imx6ul-evk {
		pinctrl_hog_1: hoggrp-1 {
			fsl,pins = <
				MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */
				MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */
				/* MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 SD1 RESET */
				MX6UL_PAD_GPIO1_IO00__ANATOP_OTG1_ID	0x13058	/* USB_OTG1_ID */
			>;
		};
        /* zuozhongkai LED */
        pinctrl_led: ledgrp {
            fsl,pins = <
            	MX6UL_PAD_GPIO1_IO03__GPIO1_IO03        0x10B0 /* LED0 */
            >;
        };
		
		/* liefyuan beep */
		pinctrl_beep: beepgrp {
			fsl,pins =<
				MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01      0x10B0 /* beep */
			>;
		};
			
		/* zuozhongkai KEY */
		pinctrl_key: keygrp {
			fsl,pins = <
				MX6UL_PAD_UART1_CTS_B__GPIO1_IO18		0xF080	/* KEY0 */
			>;
		};		

		/* zuozhongkai ECSPI */
		pinctrl_ecspi3: icm20608 {
			fsl,pins = < 
				MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20		0x10b0	/* CS */
				MX6UL_PAD_UART2_RX_DATA__ECSPI3_SCLK	0x10b1	/* SCLK */
				MX6UL_PAD_UART2_RTS_B__ECSPI3_MISO		0x10b1	/* MISO */
				MX6UL_PAD_UART2_CTS_B__ECSPI3_MOSI		0x10b1	/* MOSI */
			>;
		};

		/* zuozhongkai HDMI RGB */
		pinctrl_hdmi_dat: hdmidatgrp {
			/* do not change the pimux vlaue on alpaha and mini board*/
            fsl,pins = <
                MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x49
                MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x49
                MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x49
                MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x49
                MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x49
                MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x49
                MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x49
                MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x49
                MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x49
                MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x49
                MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x49
                MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x49
                MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x49
                MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x49
                MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x49
                MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x51
                MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x49
                MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x49
                MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x49
                MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x49
                MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x49
                MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x49
                MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x49
                MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x49
            >;
        };

		/* zuozhongkai HDMI RGB */
        pinctrl_hdmi_ctrl: hdmictrlgrp {
            fsl,pins = <
                MX6UL_PAD_LCD_CLK__LCDIF_CLK        0x49
                MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x49
                MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x49
                MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x49
            >;
        };

		/* zuozhongkai SII902X  INT*/
        pinctrl_sii902x: hdmigrp-1 {
            fsl,pins = <
                MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x11
            >;
        };

		/* zuozhongkai PWM3 GPIO1_IO04 */
		pinctrl_pwm3: pwm3grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO04__PWM3_OUT   0x110b0
			>;
		};

		/* zuozhongkai ADC1_CH1 GPIO1_IO01 */
		pinctrl_adc1: adc1grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO01__GPIO1_IO01   0xb0
			>;
		};

		pinctrl_csi1: csi1grp {
			fsl,pins = <
				MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
				MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
				MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088
				MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088
				MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088
				MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088
				MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088
				MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088
				MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088
				MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088
				MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
				MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
			>;
		};

		pinctrl_enet1: enet1grp {
			fsl,pins = <
				MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
				MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
				MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
				MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
				MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
				MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
				MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
				MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b009
			>;
		};

		pinctrl_enet2: enet2grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
				MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
				MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
				MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
				MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
				MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
				MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
				MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
				MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
				MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b009
			>;
		};

		pinctrl_flexcan1: flexcan1grp{
			fsl,pins = <
				MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
				MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
			>;
		};

		pinctrl_flexcan2: flexcan2grp{
			fsl,pins = <
				/* MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020 */
				/* MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020 */
			>;
		};

		pinctrl_i2c1: i2c1grp {
			fsl,pins = <
				MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
				MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
			>;
		};

		pinctrl_i2c2: i2c2grp {
			fsl,pins = <
				MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
				MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
			>;
		};

		pinctrl_lcdif_dat: lcdifdatgrp {
			fsl,pins = <
				MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79
				MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79
				MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79
				MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79
				MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79
				MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79
				MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79
				MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79
				MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79
				MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79
				MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79
				MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79
				MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79
				MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79
				MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79
				MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79
				MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79
				MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79
				MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79
				MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79
				MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79
				MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79
				MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79
				MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79
			>;
		};

		pinctrl_lcdif_ctrl: lcdifctrlgrp {
			fsl,pins = <
				MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79
				MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79
				MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79
				MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79
			>;
		};

		pinctrl_pwm1: pwm1grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
			>;
		};

		pinctrl_qspi: qspigrp {
			fsl,pins = <
				MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK      0x70a1
				MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
				MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01   0x70a1
				MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02   0x70a1
				MX6UL_PAD_NAND_CLE__QSPI_A_DATA03     0x70a1
				MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B      0x70a1
			>;
		};

		pinctrl_sai2: sai2grp {
			fsl,pins = <
				MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
				MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
				MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
				MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
				MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
			>;
		};

		pinctrl_tsc: tscgrp {
			fsl,pins = <
				/* 7寸RGB屏幕,FT5426 */
				MX6UL_PAD_GPIO1_IO09__GPIO1_IO09	0xF080 		/* TSC_INT */

				/* 7寸RGB屏幕,GT9147 */
				/* MX6UL_PAD_GPIO1_IO09__GPIO1_IO09	0x10B0 	*/	/* TSC_INT */
			
			>;
		};

		pinctrl_uart1: uart1grp {
			fsl,pins = <
				MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
				MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
			>;
		};

		pinctrl_uart2: uart2grp {
			fsl,pins = <
				/* MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1 */
				/* MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1 */
				MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x1b0b1
				MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x1b0b1
			>;
		};

		pinctrl_uart2dte: uart2dtegrp {
			fsl,pins = <
				/* MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX	0x1b0b1 */
				/* MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX	0x1b0b1 */
				/* MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS	0x1b0b1 */
				/* MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS	0x1b0b1 */
			>; 
		};
	
		/* zuozhongkai */
		pinctrl_uart3: uart3grp {
			fsl,pins = <
				MX6UL_PAD_UART3_TX_DATA__UART3_DCE_TX		0X1b0b1
				MX6UL_PAD_UART3_RX_DATA__UART3_DCE_RX		0X1b0b1
			>;
		};

		pinctrl_usdhc1: usdhc1grp {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x17059
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f1
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
			>;
		};

		pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f1
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
			>;
		};

		pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f1
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
			>;
		};

		pinctrl_usdhc2: usdhc2grp {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
			>;
		};

		pinctrl_usdhc2_8bit: usdhc2grp_8bit {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
			>;
		};

		pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100b9
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170b9
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
			>;
		};

		pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100f9
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170f9
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
			>;
		};

		pinctrl_wdog: wdoggrp {
			fsl,pins = <
				MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0
			>;
		};
	};
};

&iomuxc_snvs {
	pinctrl-names = "default_snvs";
        pinctrl-0 = <&pinctrl_hog_2>;
        imx6ul-evk {

		/* zuozhongkai Touch RESET */
		pinctrl_tsc_reset: tsc_reset {
			fsl,pins = <
                        	 	MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x10B0
                        >;
        };

		/* zuozhongkai RGB RESET */
		ts_reset_hdmi_pin: ts_reset_hdmi_mux {
			fsl,pins = <
                        	 	MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09 0x49
                        >;
        };

		pinctrl_hog_2: hoggrp-2 {
                        fsl,pins = <
                                MX6ULL_PAD_SNVS_TAMPER0__GPIO5_IO00      0x80000000
                        >;
                };

		pinctrl_dvfs: dvfsgrp {
                        fsl,pins = <
                                MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03      0x79
                        >;
                };
		
		pinctrl_lcdif_reset: lcdifresetgrp {
                        fsl,pins = <
                                /* used for lcd reset */
                                /* MX6ULL_PAD_SNVS_TAMPER9__GPIO5_IO09  0x79 */
                        >;
                };

		pinctrl_spi4: spi4grp {
                        fsl,pins = <
                                MX6ULL_PAD_BOOT_MODE0__GPIO5_IO10        0x70a1
                                MX6ULL_PAD_BOOT_MODE1__GPIO5_IO11        0x70a1
                        >;
                };

        pinctrl_sai2_hp_det_b: sai2_hp_det_grp {
                        fsl,pins = <
                                MX6ULL_PAD_SNVS_TAMPER4__GPIO5_IO04   0x17059
                        >;
                };

		/*enet1 reset zuozhongkai*/
		pinctrl_enet1_reset: enet1resetgrp {
                    	fsl,pins = <
                            	/* used for enet1  reset */
                            	MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07      0x10B0      /* ENET1 RESET */
                    	>;
        		};

		/*enet2 reset zuozhongkai*/
		pinctrl_enet2_reset: enet2resetgrp {
                    	fsl,pins = <
                            	/* used for enet2  reset */
                            	MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08      0x10B0     /* ENET2 RESET */      
                    	>;
        		};
        };
};


&lcdif {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_lcdif_dat
		     &pinctrl_lcdif_ctrl>;

	display = <&display0>;
	status = "okay";

	/* 7寸1024*600 */
	display0: display {
		bits-per-pixel = <24>;
		bus-width = <24>;

		display-timings {
			native-mode = <&timing0>;
			timing0: timing0 {
			clock-frequency = <51200000>;
			hactive = <1024>;
			vactive = <600>;
			hfront-porch = <160>;
			hback-porch = <140>;
			hsync-len = <20>;
			vback-porch = <20>;
			vfront-porch = <12>;
			vsync-len = <3>;

			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <1>;
			pixelclk-active = <0>;
			};
		};
	};

	/* 4.3寸480*272 */
	/* display0: display {
		bits-per-pixel = <24>;
		bus-width = <24>;

		display-timings {
			native-mode = <&timing0>;
			timing0: timing0 {
			clock-frequency = <9000000>;
			hactive = <480>;
			vactive = <272>;
			hfront-porch = <5>;
			hback-porch = <40>;
			hsync-len = <1>;
			vback-porch = <8>;
			vfront-porch = <8>;
			vsync-len = <1>;

			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <1>;
			pixelclk-active = <0>;
			};
		};
	};*/

	/* 4.3寸800*480 */
	/* display0: display {
		bits-per-pixel = <24>;
		bus-width = <24>;

		display-timings {
			native-mode = <&timing0>;
			timing0: timing0 {
			clock-frequency = <31000000>;
			hactive = <800>;
			vactive = <480>;
			hfront-porch = <40>;
			hback-porch = <88>;
			hsync-len = <48>;
			vback-porch = <32>;
			vfront-porch = <13>;
			vsync-len = <3>;

			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <1>;
			pixelclk-active = <0>;
			};
		};
	};*/

};

&pwm1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm1>;
	status = "okay";
};

/* zuozhongkai PWM3 */
&pwm3 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm3>;
	clocks = <&clks IMX6UL_CLK_PWM3>,
			 <&clks IMX6UL_CLK_PWM3>;
	status = "disable";
};

/* zuozhongkai ADC1 */
&adc1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_adc1>;
	num-channels = <2>;
	vref-supply = <&reg_vref_adc>;
	status = "okay";
};

&pxp {
	status = "okay";
};

&qspi {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_qspi>;
	status = "okay";
	ddrsmp=<0>;

	flash0: n25q256a@0 {
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "micron,n25q256a";
		spi-max-frequency = <29000000>;
		spi-nor,ddr-quad-read-dummy = <6>;
		reg = <0>;
	};
};

&sai2 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_sai2
		     &pinctrl_sai2_hp_det_b>;

	assigned-clocks = <&clks IMX6UL_CLK_SAI2_SEL>,
			  <&clks IMX6UL_CLK_SAI2>;
	assigned-clock-parents = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
	assigned-clock-rates = <0>, <12288000>;

	status = "okay";
};

&tsc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_tsc>;
	/*xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;*/
	measure-delay-time = <0xffff>;
	pre-charge-time = <0xfff>;
	status = "disable";
};

&uart1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart1>;
	status = "okay";
};

/* zuozhongkai */
&uart3 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_uart3>;
	status = "okay";
};

&usbotg1 {
	dr_mode = "otg";
	srp-disable;
	hnp-disable;
	adp-disable;
	status = "okay";
};

&usbotg2 {
	dr_mode = "host";
	disable-over-current;
	status = "okay";
};

&usbphy1 {
	tx-d-cal = <0x5>;
};

&usbphy2 {
	tx-d-cal = <0x5>;
};

&usdhc1 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc1>;
	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
	cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
	keep-power-in-suspend;
	enable-sdio-wakeup;
	vmmc-supply = <&reg_sd1_vmmc>;
	status = "okay";
	no-1-8-v;
};

&usdhc2 {
	pinctrl-names = "default", "state_100mhz", "state_200mhz";
	pinctrl-0 = <&pinctrl_usdhc2_8bit>;
	pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
	pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
	bus-width = <8>;
	non-removable;
	status = "okay";
};

&wdog1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_wdog>;
	fsl,wdog_b;
};

/* zuozhongkai  */
&ecspi3 {
	fsl,spi-num-chipselects = <1>;
	cs-gpio = <&gpio1 20 GPIO_ACTIVE_LOW>; /* cant't use cs-gpios! */
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ecspi3>;
	status = "okay";

	spidev: icm20608@0 {
		compatible = "alientek,icm20608";
		spi-max-frequency = <8000000>;
		reg = <0>;
	};	
};
已标记关键词 清除标记
相关推荐
目录 第1章 嵌入式系统基础知识 .1 1.1 嵌入式系统概述 1 1.1.1 嵌入式系统的发展史 2 1.1.2 嵌入式系统的定义与特点 3 1.1.3 嵌入式系统的特点 4 1.2 嵌入式系统的组成 5 1.2.1 嵌入式系统的硬件架构 6 1.2.2 嵌入式操作系统 9 1.2.3 嵌入式应用软件 11 1.3 arm处理器平台介绍 12 1.3.1 arm处理器简介 12 1.3.2 arm处理器系列 13 1.3.3 arm体系结构简介 17 1.3.4 s3c2410处理器简介 18 1.4 嵌入式系统硬件平台选型 22 1.4.1 硬件平台的选择 22 1.4.2 arm处理器选型 23 1.5 嵌入式系统开发概述 25 1.5.1 嵌入式系统开发流程 25 1.5.2 嵌入式软件开发流程 26 .本章小结 31 动手练练 31 第2章 嵌入式linux c语言开发工具 32 2.1 嵌入式linux下c语言概述 32 2.1.1 c语言简史 33 2.1.2 c语言特点 33 2.1.3 嵌入式linux c语言编程环境 34 2.2 嵌入式linux编辑器vi的使用 35 2.2.1 vi的基本模式 35 2.2.2 vi的基本操作 36 2.2.3 vi的使用实例分析 40 2.3 嵌入式linux编译器gcc的使用 41 2.3.1 gcc概述 41 2.3.2 gcc编译流程分析 42 2.3.3 gcc警告提示 45 2.3.4 gcc使用库函数 47 2.3.5 gcc代码优化 49 2.4 嵌入式linux调试器gdb的使用 49 2.4.1 gdb使用实例 50 2.4.2 设置/删除断点 53 2.4.3 数据相关命令 54 2.4.4 调试运行环境相关命令 55 2.4.5 堆栈相关命令 55 2.5 make工程管理器 55 2.5.1 makefile基本结构 56 2.5.2 makefile变量 58 2.5.3 makefile规则 61 2.5.4 make使用 62 2.6 emacs综合编辑器 63 2.6.1 emacs的启动与退出 63 2.6.2 emacs的基本编辑 64 2.6.3 emacs的c模式 66 2.6.4 emacs的shell模式 69 本章小结 70 动手练练 70 第3章 构建嵌入式linux系统 71 3.1 嵌入式系统开发环境的构建 71 3.1.1 嵌入式交叉编译环境搭建 71 3.1.2 minicom和超级终端配置及使用 76 3.1.3 宿主机服务配置 83 3.2 bootloader 87 3.2.1 bootloader的概念 88 3.2.2 bootloader启动流程分析 89 3.2.3 u-boot概述 89 3.2.4 u-boot源码导读 90 3.3 编译嵌入式linux内核 91 3.4 linux内核目录结构 95 3.5 制作文件系统 95 本章小结 97 动手练练 97 第4章 嵌入式linux c语言基础——数据、表达式 98 4.1 嵌入式linux c语言概述 98 4.2 基本数据类型 100 4.2.1 整型家族 100 4.2.2 实型家族 102 4.2.3 字符型家族 103 4.2.4 枚举家族 104 4.2.5 指针家族 105 4.3 变量与常量 107 4.3.1 变量的定义 107 4.3.2 typedef 113 4.3.3 常量定义 114 4.3.4 arm-linux基本数据类型综合应用实例 115 4.4 运算符与表达式 118 4.4.1 算术运算符和表达式 119 4.4.2 赋值运算符和表达式 121 4.4.3 逗号运算符和表达式 123 4.4.4 位运算符和表达式 124 4.4.5 关系运算符和表达式 126 4.4.6 逻辑运算符和表达式 127 4.4.7 sizeof操作符 129 4.4.8 条件(?)运算符 130 4.4.9 运算符优先级总结 131 4.4.10 arm-linux运算符 综合实例 133 本章小结 137 动手练练 137 第5章 嵌入式linux c语言基础——控制语句及函数 138 5.1 嵌入式linux c语言程序结构概述 138 5.1.1 嵌入式linux c语言3种程序结构 138 5.1.2 嵌入式linux c语言基本语句 139 5.2 选择语句 142 5.2.1 if语句 142 5.2.2 
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页