Linux设备树翻译计划
生活随笔
收集整理的這篇文章主要介紹了
Linux设备树翻译计划
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文翻譯自Device Tree Usage主頁:
http://devicetree.org/Device_Tree_Usage 此譯文為本人原創(chuàng),若要轉(zhuǎn)載請(qǐng)注明!
Linux device tree的背景(引用自宋寶華博客): ? ? ? ? Linus Torvalds在2011年3月17日的ARM Linux郵件列表宣稱“this whole ARM thing is a f*cking pain in the ass”,引發(fā)ARM Linux社區(qū)的地震,隨后ARM社區(qū)進(jìn)行了一系列的重大修正。在過去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥著大量的垃圾代碼,相當(dāng)多數(shù)的代碼只是在描述板級(jí)細(xì)節(jié),而這些板級(jí)細(xì)節(jié)對(duì)于內(nèi)核來講,不過是垃圾,如板上的platform設(shè)備、resource、i2c_board_info、spi_board_info以及各種硬件的platform_data。讀者有興趣可以統(tǒng)計(jì)下常見的s3c2410、s3c6410等板級(jí)目錄,代碼量在數(shù)萬行。 ? ? ? ? 社區(qū)必須改變這種局面,于是PowerPC等其他體系架構(gòu)下已經(jīng)使用的Flattened Device Tree(FDT)進(jìn)入ARM社區(qū)的視野。Device Tree是一種描述硬件的數(shù)據(jù)結(jié)構(gòu),它起源于 OpenFirmware (OF)。在Linux 2.6中,ARM架構(gòu)的板極硬件細(xì)節(jié)過多地被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx,采用Device Tree后,許多硬件的細(xì)節(jié)可以直接透過它傳遞給Linux,而不再需要在kernel中進(jìn)行大量的冗余編碼。
設(shè)備樹使用 ________________________________________________ 本頁演示怎樣為一個(gè)新的機(jī)器編寫設(shè)備樹。這主要為了給出設(shè)備樹的整體概念以及他們是怎樣被用來描述機(jī)器的。 如果需要設(shè)備樹數(shù)據(jù)格式的完整描述,請(qǐng)參考ePAPR規(guī)范。本本主頁只是講述了一些基本主題,而ePAPR規(guī)范講述了很多這些主題的細(xì)節(jié),對(duì)于本頁中沒有講述的高級(jí)用法,請(qǐng)參考ePAPR。 基本數(shù)據(jù)格式 ________________________________________________ 設(shè)備樹是具有簡(jiǎn)單樹形結(jié)構(gòu)的節(jié)點(diǎn)和屬性。屬性是成對(duì)的鍵值,節(jié)點(diǎn)可能包含屬性和子節(jié)點(diǎn)。舉個(gè)例子來說,下面是一個(gè)簡(jiǎn)單的.dts格式的樹: / {? ? 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 {? ? ? ? };? ? };}; 這棵樹很明顯是沒用的,因?yàn)樗鼪]用描述任何東西,但是它確實(shí)展示出了節(jié)點(diǎn)屬性。即:
基本概念 ________________________________________________ 為了理解怎樣使用設(shè)備樹,我們從一個(gè)樣品機(jī)開始并且搭建設(shè)備樹來一步步描述它 樣品機(jī) 考慮下面的假想機(jī)器(粗略地基于ARM Versatile),"Acme"制造,命名 “Coyote's Revenge":
(接下來的內(nèi)容大部分為PCI設(shè)備相關(guān),不太常用,由于本人精力有限,留著以后再翻譯了)
參考鏈接: http://blog.csdn.net/21cnbao/article/details/8457546
Linux device tree的背景(引用自宋寶華博客): ? ? ? ? Linus Torvalds在2011年3月17日的ARM Linux郵件列表宣稱“this whole ARM thing is a f*cking pain in the ass”,引發(fā)ARM Linux社區(qū)的地震,隨后ARM社區(qū)進(jìn)行了一系列的重大修正。在過去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥著大量的垃圾代碼,相當(dāng)多數(shù)的代碼只是在描述板級(jí)細(xì)節(jié),而這些板級(jí)細(xì)節(jié)對(duì)于內(nèi)核來講,不過是垃圾,如板上的platform設(shè)備、resource、i2c_board_info、spi_board_info以及各種硬件的platform_data。讀者有興趣可以統(tǒng)計(jì)下常見的s3c2410、s3c6410等板級(jí)目錄,代碼量在數(shù)萬行。 ? ? ? ? 社區(qū)必須改變這種局面,于是PowerPC等其他體系架構(gòu)下已經(jīng)使用的Flattened Device Tree(FDT)進(jìn)入ARM社區(qū)的視野。Device Tree是一種描述硬件的數(shù)據(jù)結(jié)構(gòu),它起源于 OpenFirmware (OF)。在Linux 2.6中,ARM架構(gòu)的板極硬件細(xì)節(jié)過多地被硬編碼在arch/arm/plat-xxx和arch/arm/mach-xxx,采用Device Tree后,許多硬件的細(xì)節(jié)可以直接透過它傳遞給Linux,而不再需要在kernel中進(jìn)行大量的冗余編碼。
設(shè)備樹使用 ________________________________________________ 本頁演示怎樣為一個(gè)新的機(jī)器編寫設(shè)備樹。這主要為了給出設(shè)備樹的整體概念以及他們是怎樣被用來描述機(jī)器的。 如果需要設(shè)備樹數(shù)據(jù)格式的完整描述,請(qǐng)參考ePAPR規(guī)范。本本主頁只是講述了一些基本主題,而ePAPR規(guī)范講述了很多這些主題的細(xì)節(jié),對(duì)于本頁中沒有講述的高級(jí)用法,請(qǐng)參考ePAPR。 基本數(shù)據(jù)格式 ________________________________________________ 設(shè)備樹是具有簡(jiǎn)單樹形結(jié)構(gòu)的節(jié)點(diǎn)和屬性。屬性是成對(duì)的鍵值,節(jié)點(diǎn)可能包含屬性和子節(jié)點(diǎn)。舉個(gè)例子來說,下面是一個(gè)簡(jiǎn)單的.dts格式的樹: / {? ? 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 {? ? ? ? };? ? };}; 這棵樹很明顯是沒用的,因?yàn)樗鼪]用描述任何東西,但是它確實(shí)展示出了節(jié)點(diǎn)屬性。即:
- 單個(gè)根節(jié)點(diǎn):"/"
- 一對(duì)子節(jié)點(diǎn):"node1", "node2"
- 一對(duì)node1的子節(jié)點(diǎn):"child-node1", "child-node2"
- 樹上散布的一堆屬性
- 文本字符串(以null作為終止)以雙引號(hào)的形式表示:
- string-property = "a string'
- 'Cells'是32位無符號(hào)整數(shù),并且使用尖括號(hào)分隔:
- cell-property = <0xbeef 123 0xabcd1234>
- 二進(jìn)制數(shù)據(jù)使用方括號(hào)分隔:
- binary-perperty = [0x01 0x23 0x45 0x67]
- 不同表示類型的數(shù)據(jù)可以通過逗號(hào)級(jí)聯(lián)在一起:
- mixed-perperty = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
- 逗號(hào)也可以用來創(chuàng)建字符串列表:
- string-list = "red fish", "blue fish";
基本概念 ________________________________________________ 為了理解怎樣使用設(shè)備樹,我們從一個(gè)樣品機(jī)開始并且搭建設(shè)備樹來一步步描述它 樣品機(jī) 考慮下面的假想機(jī)器(粗略地基于ARM Versatile),"Acme"制造,命名 “Coyote's Revenge":
- 32位 ARM CPU單核
- PLB粘附在內(nèi)存映射串口上,spi總線控制器,i2c控制器,中斷控制器以及外部總線橋
- 256MB SDRAM基址從0開始
- 2個(gè)串口,基址從0x101F1000,0X101F2000開始
- GPIO控制器,基址從0x101F3000開始
- SPI控制器,基址從0x10170000并且總線上掛載著下列設(shè)備:
- MMC卡槽并且SS引腳連接在GPIO #1上
- 外部總線橋并且總線上掛載著下列設(shè)備:
- SMC SMC91111以太網(wǎng)設(shè)備連接在基址從0x10100000開始的外部總線上
- i2c控制器,基址從0x10160000開始并且總線上掛載著如下設(shè)備:
- Maxim DS1338實(shí)時(shí)時(shí)鐘。該器件響應(yīng)0x58的從機(jī)地址。
- 64MB NOR flash,基址從0x30000000開始
- 每一個(gè)設(shè)備節(jié)點(diǎn)都有一個(gè)compatible屬性
- flash節(jié)點(diǎn)的compatible屬性中有兩個(gè)字符串。閱讀下一部分來了解為什么會(huì)這樣。
- 之前提到過,節(jié)點(diǎn)的名字反映了設(shè)備的類型,而不是特定的型號(hào)。情況ePAPR規(guī)范的2.2.2部分,規(guī)范中提到了一系列已經(jīng)定義好了隨處可能用到的通用節(jié)點(diǎn)名字
- reg
- #address-cells
- #size-cells
? ? cpus {? ? ? ? #address-cells = <1>;? ? ? ? #size-cells = <0>;? ? ? ? cpu@0 {? ? ? ? ? ? compatible = "arm,cortex-a9";? ? ? ? ? ? reg = <0>;? ? ? ? };? ? ? ? cpu@1 {? ? ? ? ? ? compatible = "arm,cortex-a9";? ? ? ? ? ? reg = <1>;? ? ? ? };? ? }; cpu節(jié)點(diǎn)中,#address-cells被設(shè)置為1,#size-cells被設(shè)置為0.這意味著子節(jié)點(diǎn)的reg值是代表地址且沒有size域的單個(gè)32位無符號(hào)整數(shù)。在這個(gè)例子中,2個(gè)cpu被賦予了地址0和1。cpu節(jié)點(diǎn)的#size-cells是0,因?yàn)閏pu僅僅被賦予了單個(gè)地址。 你能注意到reg值匹配節(jié)點(diǎn)名字中的值。按照慣例,如果一個(gè)節(jié)點(diǎn)具有reg屬性,這個(gè)節(jié)點(diǎn)必須包含單元地址,也就是reg屬性中的第一個(gè)地址值。 內(nèi)存映射設(shè)備 不同于cpu節(jié)點(diǎn)中找到的單地址值,內(nèi)存映射設(shè)備被分配了它會(huì)響應(yīng)的一個(gè)地址范圍。#size-cells用來說明每一個(gè)子節(jié)點(diǎn)中的reg元組有多長。接下來的例子中,每一個(gè)地址值都是一個(gè)單元的(32位),每一個(gè)長度值也是一個(gè)單元,即典型的32位系統(tǒng)。64位系統(tǒng)可以把#address-cells和#size-cells賦值為2從而在設(shè)備設(shè)備樹中得到64位尋址。 / {? ? #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è)基地址,以及它被分配的區(qū)域的尺寸。本例中的GPIO設(shè)備地址被分配了兩個(gè)地址范圍:0x101f3000...0x101f3fff 和0x101f4000..0x101f400f。 有一些設(shè)備掛載在具有不同尋址策略的總線上。舉個(gè)例子來說,一個(gè)設(shè)備可以被連接到具有獨(dú)立片選信號(hào)的外部總線上。因?yàn)槊恳粋€(gè)父節(jié)點(diǎn)定義了它子節(jié)點(diǎn)的尋址域,所以我們可以從最佳描述系統(tǒng)的角度來選擇地址映射方案。下面的代碼顯示了連接到外部總線上的設(shè)備的地址分配情況,并且這些外部總線具有編碼如地址的片選數(shù)字。 ? ? 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>;? ? ? ? };? ? }; 外部總線使用了2個(gè)單元的地址值。一個(gè)是片選數(shù)字,另一個(gè)是片選基地址的偏移。長度域仍舊是單個(gè)單元,因?yàn)橹挥械刂返钠撇糠中枰粋€(gè)范圍。因此在本例中,每一個(gè)reg入口都包含了3個(gè)單元:片選數(shù)字,偏移以及長度。 因?yàn)榈刂酚虮话诠?jié)點(diǎn)以及它的子節(jié)點(diǎn)中,所以父節(jié)點(diǎn)可以自由定義任何總線上可行的尋址方案。直接父節(jié)點(diǎn)之外的節(jié)點(diǎn)通常不需要考慮本地尋址域,并且為了從一個(gè)域到另一個(gè)域,地址必須被映射。 非內(nèi)存映射設(shè)備 其他設(shè)備并沒有內(nèi)存映射在處理器總線上。它們可以有尋址范圍,但是它們并不能直接被CPU訪問。相反,父節(jié)點(diǎn)設(shè)備的驅(qū)動(dòng)會(huì)代表CPU間接地訪問。 現(xiàn)在來看i2c設(shè)備的例子,每一個(gè)設(shè)備被分配了一個(gè)地址,但是它沒有關(guān)聯(lián)的長度或者范圍。這看上去與CPU地址分配時(shí)一樣的。 ? ? ? ? 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>;? ? ? ? ? ? };? ? ? ? }; 范圍(地址轉(zhuǎn)換) 我們已經(jīng)討論過了怎樣為設(shè)備分配地址,但是這里的這些地址只是本地的設(shè)備節(jié)點(diǎn)地址。它缺并沒有描述怎樣從那些地址映射到CPU可以使用的地址。 根節(jié)點(diǎn)總是描述從CPU的視角看到的地址空間。根節(jié)點(diǎn)的子節(jié)點(diǎn)已經(jīng)使用了CPU的地址域,是、因此不需要任何顯示地映射。舉個(gè)例子來說,serial@101f0000設(shè)備是直接被分配了0x101f0000地址。 那些不是根節(jié)點(diǎn)的直接子節(jié)點(diǎn)的節(jié)點(diǎn)不能使用CPU的地址域。為了得到一個(gè)內(nèi)存映射的地址,設(shè)備樹必須制定如何從一個(gè)域地址轉(zhuǎn)換到另一個(gè)域。ranges屬性就是用于這個(gè)目的的。 這里是添加了ranges屬性的設(shè)備樹例子。 / {? ? 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是地址轉(zhuǎn)換清單。ranges表中的每一個(gè)條目是包含子節(jié)點(diǎn)地址,父節(jié)點(diǎn)地址以及子節(jié)點(diǎn)地址空間區(qū)域大小的元組。每一個(gè)域的大小分別由子節(jié)點(diǎn)的#address-cells值,父節(jié)點(diǎn)的#address-cells值以及子節(jié)點(diǎn)的#size-cells值決定。對(duì)于本例子中的外部總線,子節(jié)點(diǎn)地址是2個(gè)單元,父節(jié)點(diǎn)地址是1個(gè)單元,大小也是一個(gè)單元的。三個(gè)ranges是這樣被轉(zhuǎn)換的:
- 從片選0處偏移0開始的地方被映射到地址范圍0x10100000...0x1010ffff
- 從片選1處偏移0開始的地方被映射到地址范圍0x10160000...0x1016ffff
- 從片選2處偏移0開始的地方被映射到地址范圍0x30000000...0x10000000
- interrupt-controller ?—— ?一個(gè)空的屬性聲明接收中斷信號(hào)的設(shè)備為節(jié)點(diǎn)
- #interrupt-cells ?—— 這是中斷控制器節(jié)點(diǎn)的屬性。它表明這個(gè)中斷控制器的中斷描述符符中有多少單元。(類似于#adderss-cells以及#size-cells)
- interrupt-parent —— 包含phandle的設(shè)備節(jié)點(diǎn)的一個(gè)屬性,這個(gè)phandle指向它所連接到的中斷控制器
- interrupts —— 包含中斷描述符列表的設(shè)備節(jié)點(diǎn)的一個(gè)屬性,每一個(gè)設(shè)備上的中斷輸出信號(hào)都有一個(gè)
- 這個(gè)機(jī)器只有一個(gè)中斷控制器,interrupt-controller@10140000
- 標(biāo)簽'intc:'已經(jīng)被添加到中斷控制器節(jié)點(diǎn),并且標(biāo)簽被用來分配指向根節(jié)點(diǎn)的interrupt-parent屬性的phandle。這個(gè)interrupt-parent值變成了系統(tǒng)的默認(rèn)值,因?yàn)樗械淖庸?jié)點(diǎn)都繼承了它,除非它被顯示地覆蓋。
- 每一個(gè)設(shè)備都使用一個(gè)interrupt屬性來制定一個(gè)不同的中斷輸入信號(hào)。
- #interrupt-cells是2,因此每一個(gè)中斷描述符有2個(gè)單元。這個(gè)例子采用了使用了常見的模式,用第一個(gè)單元來編碼中斷線號(hào),用第二個(gè)單元來編碼標(biāo)志,比如高有效還是低有效又或者是邊緣觸發(fā)還是電平觸發(fā)。對(duì)于任何給定的中斷控制器,請(qǐng)參考控制器綁定文檔來了解描述符是怎樣編碼的。
(接下來的內(nèi)容大部分為PCI設(shè)備相關(guān),不太常用,由于本人精力有限,留著以后再翻譯了)
參考鏈接: http://blog.csdn.net/21cnbao/article/details/8457546
總結(jié)
以上是生活随笔為你收集整理的Linux设备树翻译计划的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每个银行信用卡初始交易密码是什么
- 下一篇: linux网络设备—mdio总线