linux字符设备驱动开发之设备树(1)

本文章参考正点原子相关教程,仅学习使用

为什么使用设备树?

linux内核3.x以前,采用板级信息描述设备,由于芯片发展速度快,造成linux内的板级信息太多,使系统太臃肿.所以采用设备树来简化表达.

文件目录: 内核源码位置/arch/arm/boot/dts

linux字符设备驱动开发之设备树(1)_第1张图片

2.文件后缀

设备树文件扩展名(.dts),一个soc可以定制出很多板子,板子的通用信息通过后缀(.dtsi)文件描述.
一般地,(.dts)描述板级信息(开发板有那些设备),(.dtsi)表示SOC级信息(几个CPU,主频等等).

dtb:dts编译后的二进制文件.
dtc:编译工具
编译dts文件---->cd linux源目录 ----> make dtbs

3. DTS语法

小型设备树
dtsi: soc内部外部信息,cpu架构,主频,外设寄存器等等.

/ {

	aliases {
		can0 = &flexcan1;
		...
	};
	
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 */
			...
			};
	};

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";
			clocks = <&clks IMX6UL_CLK_PLL2_PFD2>, <&clks IMX6UL_CLK_PLL2_198M>,
			...
	};

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";
		};
		.....	
}
语法 解释
/ { } 根节点
aliases 别名,定义别名方便访问节点
nodename@unit addr 节点名@外设基地址
cpu0: cpu@0 标签与节点名用:隔开
compatible 兼容属性, 查找linux是否存在该兼容驱动
model 描述设备模块信息
status 设备状态信息
address-cells 决定子节点reg属性地址属性所占的字长(32)
size-cells 决定子节点reg属性长度属性所占的字长(32)
reg ,一般表示某个寄存器地址范围信息, address :起始地址,length:地址长度
range 地址映射转换表,可以为空,也可以按照格式表示.若表示为空,说明子地址空间和父地址空间完全相同,不需要地址转换.
name 记录节点名字,新版本已抛弃使用,老版本中存在

根节点的compatible

// /linux内核源码位置/arch/arm/boot/dts/imx6ull-9x9-evk.dts

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

// fsl,imx6ull-9x9-evk:使用的硬件设备
// fsl,imx6ull:设备使用的SOC
//系统检测是否支持该设备,支持则启动linux内核.

向节点添加,修改内容
通常不能在dtsi文件内添加子节点信息,这个导致所有板都必须支持该子节点.一般地,在特定板(dts)文件内添加子节点.

// 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";
			};
			...
};

// imx6ull-14x14-evk.dts
&i2c1 {
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_i2c1>;
	status = "okay";
	
	// 子节点
	mag3110@0e {
		compatible = "fsl,mag3110";
		reg = <0x0e>;
		position = <2>;
	};
	
	// 子节点
	ap3216c@1e {
		compatible = "ap3216c";
		reg = <0x1e>;
	};
};

你可能感兴趣的:(linux驱动开发学习)