5、地址转换 前面描述了如何给设备分配地址,但目前来说这些地址还只是设备节点的本地地址,最终要将这些地址映射成 CPU 可使用的地址 根节点始终描述的是 CPU 视角的地址空间。根节点的子节点已经使用的是 CPU 的地址域,所以它们不需要任何直接映射。例如,serial@101f0000 设备就是直接分配的 0x101f0000 地址。 那些非根节点直接子节点的节点就没有使用 CPU 地址域。为了得到一个内存映射地址,设备树必须指定从一个域到另一个域地址转换地方法,而 ranges 属性就为此而生。 下面就是一个添加了 ranges 属性的示例设备树。 / { compatible = "acme,coyotes-revenge"; #address-cells = <1>; #size-cells = <1>; ... external-bus { #address-cells = <2> #size-cells = <1>; ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash ethernet@0,0 { compatible = "smc,smc91c111"; reg = <0 0 0x1000>; }; i2c@1,0 { compatible = "acme,a1234-i2c-bus"; #address-cells = <1>; #size-cells = <0>; reg = <1 0 0x1000>; rtc@58 { compatible = "maxim,ds1338"; reg = <58>; }; }; flash@2,0 { compatible = "samsung,k8f1315ebm", "cfi-flash"; reg = <2 0 0x4000000>; }; }; }; 那么这三个 ranges 被翻译为: 从片选 0 开始的偏移量 0 被映射为地址范围: 0x10100000..0x1010ffff 从片选 0 开始的偏移量 1 被映射为地址范围: 0x10160000..0x1016ffff 从片选 0 开始的偏移量 2 被映射为地址范围: 0x30000000..0x10000000 另外,如果父地址空间和子地址空间是相同的,那么该节点可以添加一个空的 range 属性。一个空的 range 属性意味着子地址将被 1:1 映射到父地址空间。 8、添加中断 与遵循树的自然结构而进行的地址转换不同,机器上的任何设备都可以发起和终止中断信号。另外地址的编址也不同于中断信号,前者是设备树的自然表示,而后者者表现为独立于设备树结构的节点之间的链接。描述中断连接需要四个属性: ■ interrupt-controller -一个空的属性定义该节点作为一个接收中断信号的设备。 ■ #interrupt-cells - 这是一个中断控制器节点的属性。它声明了该中断控制器的中断指示符中 cell 的个数(类似于 #address-cells 和 #size-cells)。 ■ interrupt-parent -这是一个设备节点的属性,包含一个指向该设备连接的中断控制器的 phandle。那些没有 interrupt-parent 的节点则从它们的父节点中继承该属性。 ■ interrupts - 一个设备节点属性,包含一个中断指示符的列表,对应于该设备上的每个中断输出信号。 中断指示符是一个或多个 cell 的数据(由 #interrupt-cells 指定),这些数据指定了该设备连接至哪些输入中断。在以下的例子中,大部分设备都只有一个输出中断,但也有可能在一个设备上有多个输出中断。一个中断指示符的意义完全取决于与中断控制器设备的 binding。每个中断控制器可以决定使用几个 cell 来唯一的定义一个输入中断。 / { compatible = "acme,coyotes-revenge"; #address-cells = <1>; #size-cells = <1>; interrupt-parent = <&intc>; cpus { #address-cells = <1>; #size-cells = <0>; compatible = "arm,cortex-a9"; reg = <0>; }; compatible = "arm,cortex-a9"; reg = <1>; }; }; serial@101f0000 { compatible = "arm,pl011"; reg = <0x101f0000 0x1000 >; interrupts = < 1 0 >; }; serial@101f2000 { compatible = "arm,pl011"; reg = <0x101f2000 0x1000 >; interrupts = < 2 0 >; }; gpio@101f3000 { compatible = "arm,pl061"; reg = <0x101f3000 0x1000 0x101f4000 0x0010>; interrupts = < 3 0 >; }; intc: interrupt-controller@10140000 { compatible = "arm,pl190"; reg = <0x10140000 0x1000 >; interrupt-controller; #interrupt-cells = <2>; }; spi@10115000 { compatible = "arm,pl022"; reg = <0x10115000 0x1000 >; interrupts = < 4 0 >; }; external-bus { #address-cells = <2> #size-cells = <1>; ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash ethernet@0,0 { compatible = "smc,smc91c111"; reg = <0 0 0x1000>; interrupts = < 5 2 >; }; i2c@1,0 { compatible = "acme,a1234-i2c-bus"; #address-cells = <1>; #size-cells = <0>; reg = <1 0 0x1000>; interrupts = < 6 2 >; rtc@58 { compatible = "maxim,ds1338"; reg = <58>; interrupts = < 7 3 >; }; }; flash@2,0 { compatible = "samsung,k8f1315ebm", "cfi-flash"; reg = <2 0 0x4000000>; }; }; }; 需要注意的事情: ■ 这个机器只有一个中断控制器:interrupt-controller@10140000。 ■ 中断控制器节点上添加了‘inc:’标签,该标签用于给根节点的 interrupt-parent 属性分配一个 phandle。这个 interrupt-parent 将成为本系统的默认值,因为所有的子节点都将继承它,除非显示覆写这个属性。 ■每个设备使用 interrupts 属性来不同的中断输入线。 ■ #interrupt-cells 是 2,所以每个中断指示符都有 2 个 cell。本例使用一种通用的模式,也就是用第一个 cell 来编码中断线号;然后用第二个 cell 编码标志位,比如高电平/低电平有效,或者边缘/水平触发。对于任何给定的中断控制器,请参考该控制器的 binding 文档以了解指示符如何编码。 经过上面几步后,一个较为完整的设备树文件就形成了,当然这个设备树文件只是作为一个实验,让我们在熟悉一遍关于设备树的知识,对于不同平台的设备,设备树文件会有所不同,需要根据具体的soc平台手册具体修改。
|