范围(地址转换)
我们已经讨论过如何向设备分配地址,但此时这些地址只是本地设备节点,还没有说明如何从那些地址里映射到cpu可以使用的地址。
根节点经常描述地址空间的CPU视图。根节点的子节点已经使用了CPU的address domain,所以不需要任何明确的映射。例如,serial@101f0000设备被直接分配了地址0x101f0000。
根节点的非直接子节点是无法使用CPU的address domain的。为了在deivce tree获取内存映射地址必须指定如何从一个域名将地址转换到另一个。Ranges属性就用于此目的。
以下是添加了ranges属性的device tree示例。
/ {
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是一个地址转换列表。每个输入ranges表格的是包含子地址的元组,母地址和子地址空间的范围大小。每个字段的大小都由获取的子地址的#address-cells值,母地址的#address-cell值和子地址的#size-cells值而定。以外部总线为例,子地址是2 cells,母地址是1 cell,大小也为1 cell。转换三个ranges:
Offset 0 from chip select 0 被映射到address range 0x10100000..0x1010ffff
Offset 0 from chip select 1被映射到address range 0x10160000..0x1016ffff
Offset 0 from chip select 2被映射到 address range 0x30000000..0x10000000
轮流的,如果母地址或子地址空间是唯一的,那么一个节点可以添加一个空ranges属性。一个空ranges属性的出现表示位于子地址空间的地址被1:1的映射到母地址空间。
你也许要问为什么当地址可以被1:1映射的时候还要使用地址转换。一些总线(如PCI)拥有完全不同的地址空间,而这些地址空间细节需要出现在操作系统。其它则拥有DMA驱动程序,这些程序需要在总线了解真正的地址。有时设备需要被集合,因为他们都分享相同的软件可编程物理地址映射。
你需要注意的是在i2c@1,0节点中没有ranges属性。原因是与外部总线不同,i2c总线的设备在cpu地址域名没有内存映射。而是cpu通过i2c@1,0设备间接访问rtc@58设备。缺少ranges属性意味着一个人设备除了线设备之外,不允许任何设备进行直接访问。
如何中断运行
与遵循自然树结构的地址范围转换不同,中断信号可以源自于或终止于一个机器的任何设备。与树结构中自然传递的设备地址不同,中断信号只在树结构中的独立节点间传递。四个属笥用于描述中断联接:
Interrupt-controller-一个空属性表明一个节点作为一个接收中断信号的设备
#interrupt-cell-这是中断控制器节点的一个属性。它代表此中断控制器的interrupt specifier有多少cells。
Interrupts-包括interrupt specifier列表设备的一个属性,设备上每个中断输出信号都有一个。
一个interrupt specifier数据的是一个或多个cell,此数据表示此设备附属于哪个中断输入。大多数设备只有一个单独的中断输出,如下面示例,但设备上也可能有多个中断输出。一个中断说明符表达的意思完全取决于与中断控制器设备的捆绑。每个中断控制器都可以决定唯一识别中断输入的所需的cell量。
以下代码向我们Coyote’s Revenge样机添加了中断连接:
/ {
compatible = "acme,coyotes-revenge";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = ;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
};
cpu@1 {
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。
“intc:”标签被添加到了中断控制器节点,并且用于向根节点的interrupt-parent属性分配一个phandle。此interrupt-parent值成了系统的默认值。
每个设备都使用一个中断属性来指定一个不同的输入线
#interrupt-cell是2,所以每个中断说明符拥有2个cell。
欢迎大家提出自己的想法和意见,可以以回复的形式提出,或者加入我的QQ群大家一起交流,互相学习。
名 称:openwrt开发
群 号: 79612872