? ? ? ? 本文通過(guò)為一個(gè)新machine寫一個(gè)設(shè)備樹(shù)來(lái)介紹設(shè)備樹(shù)相關(guān)的概念,以及如何來(lái)描述一個(gè)machine。
關(guān)于設(shè)備樹(shù)的技術(shù)細(xì)節(jié)描述,需要參考ePAPR文檔,ePAPR文檔中包含了大量的基礎(chǔ)語(yǔ)法之外的細(xì)節(jié),如果你需要了解更多本文之外的設(shè)備樹(shù)細(xì)節(jié),請(qǐng)參考ePAPR文檔。
基本數(shù)據(jù)格式
設(shè)備樹(shù)是一個(gè)由節(jié)點(diǎn)及屬性組成的簡(jiǎn)單樹(shù)結(jié)構(gòu)。屬性是基于key-value對(duì)的,節(jié)點(diǎn)則可以包含子節(jié)點(diǎn)以及屬性。
如,下面這個(gè)樹(shù)就是一個(gè)典型結(jié)構(gòu):
/ {
node1 {
a-string-property = "A string";
a-string-list-property = "first string", "second string";
a-byte-data-property = [0x01 0x23 0x34 0x56];
child-node1 {
first-child-property;
second-child-property = <1>;
a-string-property = "Hello, world";
};
child-node2 {
};
};
node2 {
an-empty-property;
a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
child-node1 {
};
};
};
這顆樹(shù)顯然沒(méi)什么實(shí)際用途,因?yàn)樗鼪](méi)有描述任何有意義的內(nèi)容,但是,我們通過(guò)它可以了解什么是屬性,什么是節(jié)點(diǎn)。這顆樹(shù)可以解讀如下:
一個(gè)根節(jié)點(diǎn): "/"
兩個(gè)子節(jié)點(diǎn): "node1" 和 "node2"
node1下面又有兩個(gè)子節(jié)點(diǎn):"child-node1" 和 "child-node2"
一堆的屬性分散與整顆樹(shù)的各個(gè)節(jié)點(diǎn)上
譯者注:可以這么簡(jiǎn)單理解:節(jié)點(diǎn)就是樹(shù)枝,屬性就是樹(shù)葉;樹(shù)枝上可以有再長(zhǎng)樹(shù)枝也可以長(zhǎng)樹(shù)葉,而樹(shù)葉上則不會(huì)再長(zhǎng)樹(shù)枝。
屬性是基于key-value結(jié)構(gòu)的,value可以為空或者特定格式的字符串內(nèi)容。由于數(shù)據(jù)類型并不被編碼到最終的數(shù)據(jù)結(jié)構(gòu)中,設(shè)備樹(shù)源代碼中僅能支持有限的幾種基本數(shù)據(jù)類型。
text string(以null結(jié)束),以雙引號(hào)括起來(lái),如:
string-property = "a string"
cells?是32位無(wú)符號(hào)整形數(shù),以尖括號(hào)括起來(lái),如
cell-property = <0xbeef 123 0xabcd1234>
binary data?以方括號(hào)括起來(lái),如:
binary-property = [0x01 0x23 0x45 0x67];
不同類型數(shù)據(jù)可以在同一個(gè)屬性中存在,以逗號(hào)分格,如:
mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
多個(gè)字符串組成的列表也使用逗號(hào)分格,如:
string-list = "red fish","blue fish";
基本概念
為了搞清楚設(shè)備樹(shù)該如何使用,我們將一步一步的為一個(gè)Sample Machine建立一顆設(shè)備樹(shù)。
Sample Machine
姑且想象有這么一臺(tái)機(jī)器,它由"Acme"出產(chǎn),名為"Coyote's Revenge", 配置如下:
處理器的本地內(nèi)存總線連接如下設(shè)備:串口,SPI總線控制器,I2C控制器,終端控制器以及外部總線橋
兩個(gè)串口,位于地址:0x101F1000 及 0x101F2000
GPIO控制器位于地址:0x101F3000
SPI控制器位于地址:0x10170000,在它下面連接了如下設(shè)備:
MMC卡槽,其SS腳連接了GPIO1
外部總線橋上接了如下設(shè)備:
SMC91111 以太網(wǎng)控制器,位于地址:0x10100000
I2C控制器,位于地址:0x10160000,在它下面連接了如下設(shè)備:
Maxim DS1338實(shí)時(shí)時(shí)鐘,I2C地址為0x58
64MB NOR flash 位于地址:0x30000000
初始結(jié)構(gòu)
第一步是要建立一個(gè)基本結(jié)構(gòu)來(lái)使得這顆設(shè)備樹(shù)能描述對(duì)應(yīng)的Machine
/ {
compatible = "acme,coyotes-revenge";
};
compatible這個(gè)屬性用于執(zhí)行系統(tǒng)名,通常它是以?"廠商,型號(hào)"?這樣的字符串形式存在。它能準(zhǔn)確的描述對(duì)應(yīng)的設(shè)備的特征。
CPU描述
下一部就是描述每一個(gè)CPU了。在cpus節(jié)點(diǎn)中,每個(gè)CPU就是一個(gè)子節(jié)點(diǎn)。這種情況在多核的ARM Cortex A9系統(tǒng)中很常見(jiàn)。
/ {
compatible = "acme,coyotes-revenge";
cpus {
cpu@0 {
compatible = "arm,cortex-a9";
};
cpu@1 {
compatible = "arm,cortex-a9";
};
};
};
每個(gè)cpu的子節(jié)點(diǎn)中有個(gè)compatible屬性,它描述了CPU的具體型號(hào),形式通常也是?"廠商,型號(hào)"
當(dāng)然,CPU的細(xì)節(jié)不是這么一個(gè)compatible屬性能描述清楚的,后面我們會(huì)再逐步加入。
節(jié)點(diǎn)名
有必要為節(jié)點(diǎn)的命名講幾句。每個(gè)節(jié)點(diǎn)的名字都應(yīng)該是這樣的形式:?[@]
尖括號(hào)是必須的,方括號(hào)是可選的。
是一個(gè)ASCII字符串,長(zhǎng)度不超過(guò)31個(gè)字符。通常,節(jié)點(diǎn)名都是與設(shè)備的類型有關(guān)聯(lián)的。比如,3com的以太網(wǎng)卡,通常節(jié)點(diǎn)名就叫?ethernet?而不叫?3com509
被作為節(jié)點(diǎn)名的一部分時(shí),用來(lái)描述設(shè)備的地址。通常,unit-address就是設(shè)備的寄存器地址,這個(gè)地址是被列舉在節(jié)點(diǎn)的reg屬性中的。在后文中我們會(huì)介紹reg屬性的內(nèi)容。
同級(jí)別的兄弟節(jié)點(diǎn)的節(jié)點(diǎn)名必須唯一(不可重名),但如果name一致而address不一致則是正常情況(比如,serial@101f1000 與 serial@101f2000)。
關(guān)于節(jié)點(diǎn)的命名規(guī)則細(xì)節(jié),請(qǐng)參考ePAPR文檔的2.2.1節(jié)。
設(shè)備
系統(tǒng)中的每個(gè)設(shè)備都對(duì)應(yīng)著設(shè)備樹(shù)中的一個(gè)節(jié)點(diǎn)。好了,下一步我們就是為每個(gè)設(shè)備都加上對(duì)應(yīng)的節(jié)點(diǎn)。
目前,我們僅為每個(gè)設(shè)備增加一個(gè)空節(jié)點(diǎn),待后面介紹了中斷號(hào)及地址范圍的概念后再行補(bǔ)充。
/ {
compatible = "acme,coyotes-revenge";
cpus {
cpu@0 {
compatible = "arm,cortex-a9";
};
cpu@1 {
compatible = "arm,cortex-a9";
};
};
serial@101F0000 {
compatible = "arm,pl011";
};
serial@101F2000 {
compatible = "arm,pl011";
};
gpio@101F3000 {
compatible = "arm,pl061";
};
interrupt-controller@10140000 {
compatible = "arm,pl190";
};
spi@10115000 {
compatible = "arm,pl022";
};
external-bus {
ethernet@0,0 {
compatible = "smc,smc91c111";
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
rtc@58 {
compatible = "maxim,ds1338";
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
};
};
};
上面這棵樹(shù)中,系統(tǒng)中的每個(gè)設(shè)備都被添加了一個(gè)節(jié)點(diǎn),而且節(jié)點(diǎn)的結(jié)構(gòu)真實(shí)反應(yīng)了設(shè)備是如何掛載在系統(tǒng)上的。比如,ethernet,i2c等節(jié)點(diǎn)是external-bus的子節(jié)點(diǎn),rtc設(shè)備是i2c總線下的子節(jié)點(diǎn)。通常,設(shè)備樹(shù)的結(jié)構(gòu)都是以CPU的視角來(lái)反應(yīng)出來(lái)的。
上面這棵樹(shù)還有幾點(diǎn)不足,它缺少了設(shè)備的關(guān)鍵信息。這些信息將在后文中逐步添加上去。
關(guān)于上面這顆樹(shù),我們還需要注意:
每個(gè)設(shè)備節(jié)點(diǎn)都都一個(gè)compatible屬性
flash這個(gè)節(jié)點(diǎn)的compatible屬性有兩個(gè)字串,下面一節(jié)將介紹為什么這么寫。
在前文中曾提到:節(jié)點(diǎn)名反應(yīng)的是設(shè)備類型而非設(shè)備型號(hào)。請(qǐng)參考ePAPR的2.2.2節(jié)中列出的常用節(jié)點(diǎn)名。
理解compatible屬性
每個(gè)設(shè)備節(jié)點(diǎn)都需要一個(gè)compatible屬性。compatible屬性是系統(tǒng)賴以查找對(duì)應(yīng)的設(shè)備驅(qū)動(dòng)程序的一個(gè)關(guān)鍵值,系統(tǒng)就是根據(jù)它的值來(lái)查找這個(gè)設(shè)備應(yīng)該使用哪一個(gè)驅(qū)動(dòng)的。
compatible屬性的值是一個(gè)字串表。第一個(gè)字串以"廠商,型號(hào)"的形式描述了準(zhǔn)確的設(shè)備信息。后面一個(gè)字串則表示與它兼容的其他設(shè)備。
比如,F(xiàn)reescale MPC8349有一個(gè)串口設(shè)備是由National Semiconductor ns16550寄存器接口來(lái)實(shí)現(xiàn)的。所以對(duì)MPC8349的串口設(shè)備,它的compatible屬性我們就可以這樣寫:compatible = "fsl,mpc8349-uart", "ns16550",對(duì)于這樣的情況,fsl,mpc8349-uart準(zhǔn)確描述了這個(gè)設(shè)備,而ns16550則說(shuō)明了這個(gè)設(shè)備是與National Semiconductor ns16550寄存器接口兼容的。
注:ns16550它沒(méi)有廠商名這個(gè)信息,這是由于歷史原因。但所有新創(chuàng)建的compatible屬性都應(yīng)該有廠商名這個(gè)前綴。
compatible屬性的這一特性,使得我們可以讓新設(shè)備使用系統(tǒng)中已有的舊驅(qū)動(dòng)。
警告:不要在compatible屬性中使用通配符,如 "fsl,mpc83xx-uart" 或類似的。因?yàn)?a target="_blank">半導(dǎo)體廠商會(huì)不定期的更新他們的設(shè)計(jì)這會(huì)破壞你的通配符規(guī)則。選擇具有更好兼容性的方案才是正途。
地址是怎么工作的
可尋址設(shè)備是通過(guò)使用以下屬性來(lái)將地址信息編碼到設(shè)備樹(shù)中的:
reg
#address-cells
#size-cells
可尋址設(shè)備通過(guò)reg屬性來(lái)獲取寄存器相關(guān)的地址信息列表,reg屬性的形式如下:
reg =
每一組address length對(duì)應(yīng)了設(shè)備所使用的一個(gè)地址區(qū)域。
address是一個(gè)list,其中包含一個(gè)或多個(gè)32位整數(shù),我們把它叫做 cells。同理,length也是一個(gè)list,可以是多個(gè)cell或?yàn)榭铡?/p>
由于address和length的長(zhǎng)度都是不固定的,所以有了#address-cells和#size-cells這兩個(gè)屬性。這兩個(gè)屬性被放到父節(jié)點(diǎn)中用于描述每個(gè)區(qū)域有幾個(gè)cell。簡(jiǎn)單的說(shuō),就是reg屬性需要配合父節(jié)點(diǎn)的#address-cells和#size-cells來(lái)配合使用。為了弄明白它們是怎么工作的,下面我們就來(lái)為這個(gè)設(shè)備加上地址相關(guān)的屬性,先從CPU開(kāi)始。
CPU地址
CPU節(jié)點(diǎn)的地址用法是最簡(jiǎn)單的。每個(gè)CPU被分配了唯一的ID號(hào),而且這個(gè)沒(méi)有size。
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
reg = <0>;
};
cpu@1 {
compatible = "arm,cortex-a9";
reg = <1>;
};
};
在上面的cpus節(jié)點(diǎn)中,#address-cells被設(shè)為了1,#size-cells則被設(shè)為了0,這就表示它的子節(jié)點(diǎn)中的reg屬性是一個(gè)32位整數(shù)的address,而且沒(méi)有size部分。
在上面的例子中,你可能注意到了節(jié)點(diǎn)名中的寄存器地址與reg數(shù)值一樣。
約定俗成的做法是,如果一個(gè)節(jié)點(diǎn)有reg屬性,則節(jié)點(diǎn)名中也需要包含unit-address這個(gè)部分,而unit-address的數(shù)值則是reg屬性的第一個(gè)address值。
內(nèi)存映射設(shè)備
與cpu節(jié)點(diǎn)中的這種單地址不同,內(nèi)存映射設(shè)備所分配的是一個(gè)地址范圍,而這個(gè)地址范圍則是由#size-cells和節(jié)點(diǎn)中的reg屬性的size區(qū)域來(lái)決定的。下面這個(gè)例子中,每個(gè)address是1個(gè)cell(32bit),且每個(gè)長(zhǎng)度值也是一個(gè)cell。在32位系統(tǒng)中#size-cells通常就是這樣設(shè)置為1的。而早64位系統(tǒng)中,#address-cells和#size-cells則通常設(shè)置為2。
/ {
#address-cells = <1>;
#size-cells = <1>;
...
serial@101f0000 {
compatible = "arm,pl011";
reg = <0x101f0000 0x1000 >;
};
serial@101f2000 {
compatible = "arm,pl011";
reg = <0x101f2000 0x1000 >;
};
gpio@101f3000 {
compatible = "arm,pl061";
reg = <0x101f3000 0x1000
0x101f4000 0x0010>;
};
interrupt-controller@10140000 {
compatible = "arm,pl190";
reg = <0x10140000 0x1000 >;
};
spi@10115000 {
compatible = "arm,pl022";
reg = <0x10115000 0x1000 >;
};
...
};
每個(gè)設(shè)備被分配了一個(gè)基地址以及一個(gè)size。上面的例子中,gpio設(shè)備被分配了兩個(gè)地址段: 0x101f3000~0x1013fff 以及 0x101f4000~0x101f4fff。
有些設(shè)備在系統(tǒng)總線上的地址不連續(xù)。比如,一個(gè)設(shè)備可能通過(guò)不連續(xù)的片選線連接在外部總線上。
通過(guò)在父節(jié)點(diǎn)設(shè)置合適的#address-cells和#size-cells,地址映射機(jī)制可以準(zhǔn)確的描述內(nèi)存映射關(guān)系。下面的代碼中展示了一個(gè)不同片選信息在是如何使用的。
external-bus {
#address-cells = <2>
#size-cells = <1>;
ethernet@0,0 {
compatible = "smc,smc91c111";
reg = <0 0 0x1000>;
};
i2c@1,0 {
compatible = "acme,a1234-i2c-bus";
reg = <1 0 0x1000>;
rtc@58 {
compatible = "maxim,ds1338";
};
};
flash@2,0 {
compatible = "samsung,k8f1315ebm", "cfi-flash";
reg = <2 0 0x4000000>;
};
};
上面的例子中,external-bus使用了兩個(gè)cell來(lái)描述address;一個(gè)表示片選號(hào),另一個(gè)表示與片選基地址間的偏移量。length區(qū)域則用了一個(gè)cell來(lái)描述。在這個(gè)例子中,每個(gè)reg節(jié)點(diǎn)包含3個(gè)cell,分別是:片選號(hào),偏移量,長(zhǎng)度
非內(nèi)存映射設(shè)備
還有一些設(shè)備在總線上并不是不是內(nèi)存映射型的。他們可以有地址空間,但他們沒(méi)有通過(guò)CPU直接訪問(wèn)地址空間的能力。取而代之的是他們的父設(shè)備驅(qū)動(dòng)擁有間接訪問(wèn)內(nèi)存空間的能力。
以I2C設(shè)備(不是I2C總線哦)為例子,每個(gè)設(shè)備被分配了一個(gè)地址,沒(méi)有l(wèi)ength這個(gè)字段??雌饋?lái)實(shí)際上與cpu的地址分配很相似。
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>;
};
};
Ranges(地址變換)
上文已經(jīng)討論過(guò)了我們?nèi)绾畏峙涞刂方o設(shè)備,但是這個(gè)所謂的地址僅僅是在設(shè)備節(jié)點(diǎn)中的本地地址。它無(wú)法描述該如何將這些本地的地址映射到CPU能訪問(wèn)的地址空間中。
根節(jié)點(diǎn)中一定有描述CPU的地址空間。子節(jié)點(diǎn)所用的地址空間就來(lái)自與CPU的地址空間,所以不需要進(jìn)行額外的地址映射。
如:serial@101f0000 就是直接分配的地址0x101f0000。
如果一個(gè)節(jié)點(diǎn)它不是跟節(jié)點(diǎn)下的子節(jié)點(diǎn),那么它就不能用CPU的地址空間。為了能將一個(gè)地址空間的地址映射到另一個(gè)地址空間,range屬性被創(chuàng)造出來(lái)了。
下面是在一個(gè)簡(jiǎn)單的設(shè)備樹(shù)中增加range屬性。
/ {
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屬性就定義了一個(gè)地址轉(zhuǎn)換規(guī)格。在這個(gè)表中的每個(gè)節(jié)點(diǎn)表示一個(gè)地址轉(zhuǎn)換關(guān)系。
ranges屬性中每個(gè)字段的大小取決于當(dāng)前節(jié)點(diǎn)的#address-cells,父節(jié)點(diǎn)的#address-cells以及當(dāng)前節(jié)點(diǎn)的#size-cells。
比如上面的例子中,external-bus節(jié)點(diǎn)的地址長(zhǎng)度是2,它的父節(jié)點(diǎn)的地址長(zhǎng)度是1,size長(zhǎng)度是1。所以ranges中的三個(gè)地址規(guī)則可以這樣解讀:
CS0,偏移量為0的本地地址被映射到父節(jié)點(diǎn)地址空間的 0x10100000~0x1010ffff
CS1,偏移量為1的本地地址被映射到父節(jié)點(diǎn)地址空間的 0x10160000~0x1016ffff
CS2,偏移量為0的本地地址被映射到父節(jié)點(diǎn)地址空間的 0x30000000~0x31000000
更方便的是,如果父節(jié)點(diǎn)與子節(jié)點(diǎn)的地址空間完全匹配,則子節(jié)點(diǎn)可以只定義一個(gè)空的ranges屬性。
空ranges屬性所表示的意思就是子節(jié)點(diǎn)的地址空間與父節(jié)點(diǎn)地址空間是1:1的映射關(guān)系。
你可能會(huì)問(wèn):為什么上面會(huì)寫1:1的映射關(guān)系?有些總線結(jié)構(gòu)(如PCI總線)擁有自己獨(dú)立的地址空間,但需要向操作系統(tǒng)開(kāi)放。還有些設(shè)備有DMA引擎,這就需要知道總線上的實(shí)際地址。還有些時(shí)候幾個(gè)設(shè)備因?yàn)槭褂猛瑯拥奈锢淼刂房臻g而需要組合在一起。在硬件設(shè)計(jì)以及操作系統(tǒng)的大量特性上決定了地址映射是不是1:1的映射關(guān)系。
也可能還注意到了上文中的i2c@1,0節(jié)點(diǎn)中沒(méi)有ranges屬性。原因是I2C總線不像外部總線,它的地址空間并沒(méi)有映射到CPU的地址空間中去。實(shí)際上,CPU對(duì)rtc@58的訪問(wèn)是通過(guò)i2c@1,0這個(gè)設(shè)備來(lái)間接達(dá)成的。沒(méi)有ranges屬性正表明了這個(gè)設(shè)備是不能直接訪問(wèn)除父節(jié)點(diǎn)外的任何設(shè)備的特性。
中斷是怎樣工作的
不想地址空間映射表那樣是遵循設(shè)備樹(shù)的自然結(jié)構(gòu)的(父?jìng)髯樱?,中?a target="_blank">信號(hào)可以被machine中的任何設(shè)備產(chǎn)生或終止。終端信號(hào)獨(dú)立與設(shè)備樹(shù)將各個(gè)節(jié)點(diǎn)關(guān)聯(lián)起來(lái)。描述一個(gè)中斷需要4個(gè)屬性:
interrupt-controller 這個(gè)屬性沒(méi)有值,他表示這個(gè)節(jié)點(diǎn)是一個(gè)接收中斷信號(hào)的設(shè)備
#interrupt-cells 這個(gè)屬性是一個(gè)interrupt-controller節(jié)點(diǎn)的屬性,他說(shuō)明了這個(gè) interrupt-controller的每個(gè)中斷說(shuō)明符(interrupt specifier)有幾個(gè)cells,類似#address-cells 與 #size-cells的作用
interrupt-parent 這是一個(gè)設(shè)備節(jié)點(diǎn)的屬性,用于表明當(dāng)前設(shè)備的中斷是屬于哪一個(gè)interrupt-controller的,如果沒(méi)有這個(gè)屬性,則繼承其父節(jié)點(diǎn)的interrupt-parent屬性
interrupts 這是一個(gè)設(shè)備節(jié)點(diǎn)的屬性,他是?中斷說(shuō)明符?列表,每一個(gè)?中斷說(shuō)明符?表示此設(shè)備的一個(gè)中斷信號(hào)輸出。
中斷說(shuō)明符是由一個(gè)或多個(gè)cell數(shù)據(jù)(#interrupt-cells?)來(lái)描述一個(gè)設(shè)備是與哪一個(gè)終端信號(hào)輸入設(shè)備相連接的。多數(shù)設(shè)備都只有一個(gè)中斷信號(hào)輸出,如下面的例子,但也有可能存在一個(gè)設(shè)備有多個(gè)終端信號(hào)輸出的情況。中斷說(shuō)明符的含義與具體的終端控制器(?interrupt-controller)有關(guān)。每個(gè)終端控制器都可以決定它的輸入信號(hào)的中斷說(shuō)明符有幾個(gè)cell數(shù)據(jù)。
下面的代碼中為我們的Coyote's Revenge添加了中斷連接:
/ {
compatible = "acme,coyotes-revenge";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
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>;
};
};
};
有些細(xì)節(jié)需要各位注意:
此machine僅有一個(gè)中斷控制器:interrupt-controller@10140000
標(biāo)簽"intc:"被加到了中斷控制器的節(jié)點(diǎn)上,這個(gè)標(biāo)簽在父節(jié)點(diǎn)上創(chuàng)建了一個(gè)phandle,這個(gè)phandle就是父節(jié)點(diǎn)的interrupt-parent。所以這個(gè)中斷控制器就成了系統(tǒng)所有子節(jié)點(diǎn)的默認(rèn)終端控制器,只有當(dāng)子節(jié)點(diǎn)明確的聲明了其interrupt-parent才會(huì)被覆蓋。
每個(gè)設(shè)備使用interrupt屬性來(lái)區(qū)分不同的終端輸入線。
#interrupt-cells(在interrupt-controller@10140000節(jié)點(diǎn)中)的值是2,所以,每個(gè)中斷說(shuō)明符由兩個(gè)cell數(shù)據(jù)組成。這個(gè)例子中用的是最常見(jiàn)的?中斷說(shuō)明符?形式,第一個(gè)cell表示中斷線的序號(hào),第二個(gè)cell表示終端類型的flag(表示高有效,低有效。。。),對(duì)于不同的終端控制器,需要閱讀對(duì)應(yīng)的binding document來(lái)得知其?中斷說(shuō)明符?的格式。
設(shè)備特定數(shù)據(jù)
在常用的屬性之外,我們還能為一個(gè)節(jié)點(diǎn)自行添加屬性及子節(jié)點(diǎn)。只要是系統(tǒng)需要的任何數(shù)據(jù)都能被我們按特定的規(guī)則來(lái)添加。
首先,新設(shè)備特定的屬性名需要使用?廠商前綴,這樣能避免與系統(tǒng)已有的標(biāo)準(zhǔn)屬性名稱沖突。
第二,每個(gè)屬性都應(yīng)該在某個(gè)binding文檔中有相關(guān)的說(shuō)明,這樣驅(qū)動(dòng)作者才能知道如何使用這些屬性數(shù)據(jù)。
第三,將新的binding資料在devicetree-discuss@lists.ozlabs.org中post出來(lái),大家對(duì)binding的代碼審查將能規(guī)避大部分常識(shí)性錯(cuò)誤。
特殊節(jié)點(diǎn)
aliases 節(jié)點(diǎn)
這個(gè)特殊節(jié)點(diǎn)用來(lái)引用一個(gè)長(zhǎng)路徑,比如/external-bus/ethernet@0,0,它是長(zhǎng)路徑的縮寫或叫別名。比如:
aliases {
ethernet0 = e0;
serial0 = &serial0;
};
使用別名來(lái)標(biāo)識(shí)一個(gè)設(shè)備是備受操作系統(tǒng)歡迎的做法。
chosen節(jié)點(diǎn)
chosen節(jié)點(diǎn)并不代表一個(gè)真正的設(shè)備,而是用來(lái)在Firmware與操作系統(tǒng)間傳遞數(shù)據(jù),如啟動(dòng)參數(shù)。
通常chosen節(jié)點(diǎn)在dts中被置空。
在我們這個(gè)例子中,被添加了如下的啟動(dòng)參數(shù):
chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};
?
評(píng)論