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