Linux-Kernel-DT(Device-Tree)_第1頁(yè)
Linux-Kernel-DT(Device-Tree)_第2頁(yè)
Linux-Kernel-DT(Device-Tree)_第3頁(yè)
Linux-Kernel-DT(Device-Tree)_第4頁(yè)
Linux-Kernel-DT(Device-Tree)_第5頁(yè)
已閱讀5頁(yè),還剩12頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Linux Kernel DT(Device Tree) 之前在使用的3.0.8版本內(nèi)核還沒有使用上DT,而最近在研發(fā)使用的3.10.37版本內(nèi)核已使用上了DT,瞬間感覺自己的知識(shí)體系更新慢了,查了資料發(fā)現(xiàn)3.x版本的內(nèi)核已經(jīng)支持DT了,為何ARM也要使用上DT呢? 在舊版本的ARM Linux內(nèi)核里,我們習(xí)慣上會(huì)去arch/arm/mach-XXX/目錄下進(jìn)行一些板載級(jí)設(shè)備配置,尤其在board-YYY.c文件里使用platform_add_devices()等函數(shù)去注冊(cè)一堆硬件設(shè)備以及板級(jí)初始化操作,還有如下宏:MACHINE_START(project name, board name) .boot_params = PLAT_PHYS_OFFSET + 0x800, .fixup = XXX_fixup, .reserve = &XXX_reserve, .map_io = XXX_map_io, .init_irq = XXX_init_irq, .timer = &XXX_timer, .init_machine = XXX_init,MACHINE_END 其中的XXX_init函數(shù)里就會(huì)調(diào)用platform_add_devices()。 以及arch/arm/plat-XXX目錄下也有一堆平臺(tái)級(jí)的操作,一般在進(jìn)行移植工作的時(shí)候,就是修改了上面的board-YYY.c文件,調(diào)試好了各種Clock之后,剩下的就是設(shè)備驅(qū)動(dòng)程序了。這些處理往往在所有ARM平臺(tái)里有很多的相同操作和共同定義,而這些往往存在了大量的重復(fù)編碼工作,故而Linux內(nèi)核的開發(fā)人員和ARM的相關(guān)人員引入了DT來改善該問題,相關(guān)的歷史有如下引用內(nèi)容: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)行大量的冗余編碼。Device Tree 由一系列被命名的結(jié)點(diǎn)(node)和屬性(property)組成,而結(jié)點(diǎn)本身可包含子結(jié)點(diǎn)。所謂屬性,其實(shí)就是成對(duì)出現(xiàn)的name 和value。在Device Tree 中,可描述的信息包括(原先這些信息大多被hard code 到kernel 中): CPU 的數(shù)量和類別 內(nèi)存基地址和大小 總線和橋 外設(shè)連接 中斷控制器和中斷使用情況 GPIO 控制器和GPIO 使用情況 Clock 控制器和Clock 使用情況它基本上就是畫一棵電路板上CPU、總線、設(shè)備組成的樹,Bootloader 會(huì)將這棵樹傳遞給內(nèi)核,然后內(nèi)核可以識(shí)別這棵樹,并根據(jù)它展開出Linux 內(nèi)核中的platform_device、i2c_client、spi_device 等設(shè)備,而這些設(shè)備用到的內(nèi)存、IRQ 等資源,也被傳遞給了內(nèi)核,內(nèi)核會(huì)將這些資源綁定給展開的相應(yīng)的設(shè)備。 了解完相關(guān)歷史后,我們接下來分如下幾個(gè)方面了解ARM Linux中的DT:1 使用和不使用DT對(duì)bootloader和kernel的影響2 關(guān)于DT3 kernel中的DT 一.使用和不使用DT對(duì)bootloader和kernel的影響1.不使用DT 不使用DT時(shí),kernel包含了硬件的完整描述信息,bootloader加載單獨(dú)的一個(gè)二進(jìn)制文件(kernel鏡像文件uImage或zImage)并執(zhí)行它,bootloader通過寄存器r2傳遞ATAGS(為一些附加信息,如RAM大小和地址、cmdline等)給kernel,通過寄存器r1傳遞一個(gè)機(jī)器類型(machine type,用于告訴內(nèi)核將啟動(dòng)哪一款板卡)整數(shù)給kernel。有如下映射: 這時(shí)候,在U-boot命令行里執(zhí)行bootm 命令可以啟動(dòng)kernel。2.使用DT 使用DT時(shí),kernel包含的硬件完整打樁信息被提取為一個(gè)二進(jìn)制文件DTB(device tree blob)文件,bootloader則需要加載kernel鏡像(uImage或zImage)以及DTB(arch/arm/boot/dts/目錄下的DTS文件通過DTC編譯成DTB文件),bootloader通過寄存器r2傳遞DTB文件(該文件也包含了RAM信息、cmdline等信息)所在地址給kernel,而原先傳遞板卡類型整數(shù)的r1則不需要再關(guān)注了,相應(yīng)的映射如下: 這時(shí)候,在U-boot里使用命令bootm - 來啟動(dòng)kernel。3.bootloader對(duì)DT的支持 Uboot的主線代碼從v1.1.3開始就支持DT了,其對(duì)ARM的支持和kernel對(duì)Device Tree的支持是同期完成的,在Uboot中需要在config文件中加入#define CONFIG_OF_LIBFDT配置項(xiàng)即可,當(dāng)我們將DTB文件在Uboot里加載到內(nèi)存中后,通過fdt addr 0xnnnnnnnn命令來設(shè)置DTB文件對(duì)應(yīng)地址,這樣就可以使用fdt resize、fdt print等命令對(duì)DTB文件進(jìn)行操作了。對(duì)于ARM,使用bootz kernel_addr initrd_addr dtb_addr命令來啟動(dòng)kernel,dtb_addr作為bootz或bootm最后一個(gè)參數(shù),第一個(gè)參數(shù)為內(nèi)核鏡像的地址,第二個(gè)參數(shù)為initrd的地址,如不存在,使用-代替(看完這句話,一的2中的命令就能理解了)。4.kernel的DT兼容引導(dǎo)模式 在實(shí)際情況下,存在部分平臺(tái)過舊,方案廠無法提供新版的bootloader,而原有的bootloader不支持DT時(shí),還好kernel有兼容機(jī)制: 當(dāng)設(shè)置CONFIG_ARM_APPENDED_DTB為y時(shí),它表示我們使用kernel時(shí),需要在kernel鏡像后面查找DTB信息(即kernel鏡像后緊挨著DTB),而Makefile也沒有相應(yīng)的規(guī)則去生成相應(yīng)格式的kernel鏡像,此時(shí),我們需要執(zhí)行如下命令手動(dòng)制作相應(yīng)的鏡像: cat arch/arm/boot/zImage arch/arm/boot/dts/myboard.dtb my-zImage mkimage . d my-zImage my-uImage 而當(dāng)設(shè)置CONFIG_ARM_ATAG_DTB_COMPAT為y時(shí),它表示kernel將從bootloader獲取到ATAGS信息,并更新DT文件使用這些信息。二.關(guān)于DT 首先,先看下一個(gè)基本的DT語(yǔ)法格式圖示: 上圖中所保存成的一個(gè).dts文件并不會(huì)有實(shí)質(zhì)的功能,僅僅是一個(gè)Device Tree源文件結(jié)構(gòu)的呈現(xiàn),由圖可見,一個(gè).dts文件包含一個(gè)root結(jié)點(diǎn)/,root結(jié)點(diǎn)下面有一系列子結(jié)點(diǎn),上圖中有node0和node1,其中node0下面還有兩個(gè)子結(jié)點(diǎn)child-node0和child-node1,node1下面有child-node0子結(jié)點(diǎn),而結(jié)點(diǎn)中又有一系列的屬性,如屬性來空:an-empty-property,為字符串:a-string-property,為字符串?dāng)?shù)組:a-string-list-property,為二進(jìn)制:a-byte-data-property,為Cells(由u32整數(shù)組成):a-cell-property、second-child-property,為引用:a-reference-to-something。還有別名node1,實(shí)際上是node1結(jié)點(diǎn),如果引用時(shí),則需要完整路徑/node1,而使用別名可以省掉這絕對(duì)路徑的一長(zhǎng)串字符。 接下來,拿一個(gè)實(shí)例來說明下一個(gè)平臺(tái)于DTS的配置: 假如我們有如下配置的一臺(tái)機(jī)器: 1個(gè)雙核ARM Cortex-A9 32位處理器 ARM的local bus上的內(nèi)在映射區(qū)域分布如下控制器: 2個(gè)串口(分別位于0x101F1000和0x101F2000) GPIO控制器(0x101F3000) SPI控制器(0x10170000) 中斷控制器(0x10160000) 一個(gè)external bus橋,橋上連接如下設(shè)備: SMC SMC91111 Ethernet(0x10100000) I2C控制器(0x10160000),上面接了如下設(shè)備: Maxim DS1338 RTC(I2C地址0x58) 64MB Nor Flash(0x30000000) 上述配置對(duì)應(yīng)的.dts文件內(nèi)容如下: / compatible = acme,coyotes-revenge; #address-cells = ; #size-cells = ; interrupt-parent = ; cpus #address-cells = ; #size-cells = ; cpu0 compatible = arm,cortex-a9; reg = ; ; cpu1 compatible = arm,cortex-a9; reg = ; ; ; serial101f0000 compatible = arm,pl011; reg = ; interrupts = ; ; serial101f2000 compatible = arm,pl011; reg = ; interrupts = ; ; gpio101f3000 compatible = arm,pl061; reg = ; interrupts = ; ; intc: interrupt-controller10140000 compatible = arm,pl190; reg = ; interrupt-controller; #interrupt-cells = ; ; spi10115000 compatible = arm,pl022; reg = ; interrupts = ; ; external-bus #address-cells = #size-cells = ; ranges = ; / Chipselect 3, NOR Flash ethernet0,0 compatible = smc,smc91c111; reg = ; interrupts = ; ; i2c1,0 compatible = acme,a1234-i2c-bus; #address-cells = ; #size-cells = ; reg = ; interrupts = ; rtc58 compatible = maxim,ds1338; reg = ; interrupts = ; ; ; flash2,0 compatible = samsung,k8f1315ebm, cfi-flash; reg = ; ; ; ; 上面的.dts文件中,root結(jié)點(diǎn)/的compatible屬性(compatible = acme,coyotes-revenge;)定義了系統(tǒng)的名字,其組織形式為:,。Linux kernel通過root結(jié)點(diǎn)的該屬性就可以判斷需要啟動(dòng)的是什么machine。 在.dts文件中的每個(gè)設(shè)備,都有一個(gè)compatible屬性,用于驅(qū)動(dòng)與設(shè)備間的綁定。compatible屬性是一個(gè)字符串列表,該列表第一個(gè)字符串表示了結(jié)點(diǎn)所代表的確切設(shè)備,其后的字符串代表可兼容的設(shè)備,在上面的.dts文件中有如下內(nèi)容: flash2,0 compatible = samsung,k8f1315ebm, cfi-flash; reg = ; ; 其中,compatible屬性的第一個(gè)字符串samsung,k8f1315ebm表示了該配置項(xiàng)是對(duì)samsung的k8f1315ebm這款Nor Flash的支持,第二個(gè)字符串cfi-flash表示可被兼容的設(shè)備型號(hào)(省略了廠商信息,表示可用的范圍更廣)。 接下來root結(jié)點(diǎn)/的cpus子結(jié)點(diǎn)下包含了2個(gè)cpu子結(jié)點(diǎn),描述了該machine上的雙核CPU,并且這兩個(gè)子結(jié)點(diǎn)的compatible屬性都為arm,cortex-a9。注意這兩個(gè)子結(jié)點(diǎn)的命名都遵循的組織形式為:,其中中的內(nèi)容是必選項(xiàng),而中的則為可選項(xiàng)。name是一個(gè)ASCII字符串,用于描述結(jié)點(diǎn)對(duì)應(yīng)的設(shè)備類型,如3com Ethernet PHY對(duì)應(yīng)的結(jié)點(diǎn)name為ethernet,而不是3com509。如果一結(jié)點(diǎn)描述的設(shè)備有地址,則應(yīng)給出相應(yīng)的unit-address。多個(gè)相同類型的設(shè)備結(jié)點(diǎn)的name可以一樣,只需相應(yīng)的unit-address不同即可,如上述.dts文件中所示。設(shè)備的unit-address地址通常也在其對(duì)應(yīng)結(jié)點(diǎn)的reg屬性中給出。 可尋址的設(shè)備使用reg、#address-cells、#size-cells三屬性來確定其在DT中的編址信息,其中reg的組織形式為:reg=,這里每一組address length表明了該設(shè)備使用的一個(gè)地址范圍。address和length字段是可變長(zhǎng)的,address為1個(gè)或多個(gè)cell(32位的整形),而length則為cell列表或空,父結(jié)點(diǎn)的#address-cells和#size-cells決定了子結(jié)點(diǎn)的reg屬性的address和length字段的長(zhǎng)度。在上面的.dts中,root結(jié)點(diǎn)的#address-cells=;和#size-cells=;決定了serial、gpio、spi等結(jié)點(diǎn)的address和length字段的長(zhǎng)度都為1。cpus結(jié)點(diǎn)的#address-cells=;和#size-cells=;決定了2個(gè)cpu子結(jié)點(diǎn)的address長(zhǎng)度為1,而length為空,即2個(gè)cpu的reg分別為reg=;和reg=;。external-bus結(jié)點(diǎn)的#address-cells=;和#size-cells=;決定了其子結(jié)點(diǎn)ethernet、i2c、flash的reg字段為reg=;、reg=;和reg=;,這三個(gè)reg的第一個(gè)值分別為0、1、2,是對(duì)應(yīng)的片選,第二個(gè)值都為0,表示相應(yīng)片選的基地址,第三個(gè)值分別為0x1000、0x1000、0x4000000為length。特別要注意的是i2c結(jié)點(diǎn)中定義的#address-cells=;和#size-cells=;作用到相應(yīng)總結(jié)上的RTC設(shè)備的address字段則為0x58,是該設(shè)備的i2c地址。 對(duì)于root結(jié)點(diǎn)的子結(jié)點(diǎn),其address區(qū)域直接位于CPU的memory區(qū)域,均為CPU的視圖范圍,但是,經(jīng)過總線橋后的address一般需要進(jìn)行轉(zhuǎn)換才能被CPU的memory區(qū)域映射到,從上面的.dts文件中可看到,external-bus的ranges屬性定義了經(jīng)過external-bus橋后的地址范圍如何映射到CPU的memory區(qū)域,如下所示: ranges = ; / Chipselect 3, NOR Flash ranges是地址轉(zhuǎn)換表,其中第個(gè)項(xiàng)目是一個(gè)子地址、父地址及其空間大小的映射。映射表中的子地址、父地址分別采用子地址空間的#address-cells和父地址空間的#address-cells大小。對(duì)于這兒的ranges,子地址空間的#address-cells為2,父地址空間的#address-cells為1,故而0 0 0x10100000 0x10000的前兩項(xiàng)(cell)為external-bus片選0上偏移0,第3項(xiàng)為external-bus片選0上偏移0的地址空間被映射到CPU的0x10100000位置上,第4項(xiàng)為映射的大小為0x10000。后面的兩組片選同樣理解。 對(duì)于中斷控制器,DT提供了如下屬性: interrupt-controller這個(gè)屬性為空,中斷控制器使用該屬性表明身份; #interrupt-cells和#address-cells和#size-cells相似,表明使用該中斷控制器的設(shè)備的interrupts屬性的cell大??; interrupt-parent設(shè)備結(jié)點(diǎn)通過它來指定其所依附的中斷控制器的phandle,當(dāng)結(jié)點(diǎn)沒指定interrupt-parent時(shí),則從父結(jié)點(diǎn)繼續(xù)。上面的.dts中,root結(jié)點(diǎn)指定了interrupt-parent=;其對(duì)應(yīng)于intc:interrupt-controller10140000,而root結(jié)點(diǎn)的子結(jié)點(diǎn)沒有指定interrupt-parent,故而都繼續(xù)了intc,即位于0x10140000的中斷控制器。 interrupts用到了中斷的設(shè)備結(jié)點(diǎn)通過它來指定中斷號(hào)、觸發(fā)方式等,具體該屬性含有多少個(gè)cell,由其所依附的中斷控制器結(jié)點(diǎn)的#interrupt-cells屬性決定,而具體每個(gè)cell的含義,一般由驅(qū)動(dòng)的實(shí)現(xiàn)決定,其會(huì)在DT的binding文檔中說明,如ARM GIC中斷控制器,#interrupt-cells為3,3個(gè)cell的具體含義可查閱Documentation/devicetree/bindings/arm/gic.txt文件,有如下說明: The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI interrupts. The 2nd cell contains the interrupt number for the interrupt type. SPI interrupts are in the range 0-987. PPI interrupts are in the range 0-15. The 3rd cell is the flags, encoded as follows: bits3:0 trigger type and level flags. 1 = low-to-high edge triggered 2 = high-to-low edge triggered 4 = active high level-sensitive 8 = active low level-sensitive bits15:8 PPI interrupt cpu mask. Each bit corresponds to each of the 8 possible cpus attached to the GIC. A bit set to 1 indicated the interrupt is wired to that CPU. Only valid for PPI interrupts. 還需注意的是,一個(gè)設(shè)備可能使用多個(gè)中斷號(hào)。對(duì)于ARM GIC來說,若某設(shè)備使用SPI的168、169兩個(gè)中斷,并且都是高電平觸發(fā),那么該設(shè)備結(jié)點(diǎn)的interrupts屬性可定義為:interrupts=,;。除了中斷外,ARM Linux中clock、GPIO、pinmux都可通過.dts來描述,而pinmux/pinctl與對(duì)應(yīng)的平臺(tái)關(guān)系較大。三.kernel中的DT1.DTB、DTS和DTC 在ARM Linux Kernel中,所有的DTS(Device Tree Source)文件存放在arch/arm/boot/dts目錄下,該目錄下后綴為.dts的文件為板級(jí)定義,而.dtsi為SOC級(jí)定義,是被包含的文件,在.dts文件中會(huì)使用/include/ XXX.dtsi或#include XXX.dtsi這樣的語(yǔ)句放在文件最開始位置,將相關(guān)文件包含進(jìn)來。既然.dts可以包含.dtsi,如果碰到兩文件中有定義了同一結(jié)點(diǎn),那么會(huì)合并兩文件中的所有屬性,而當(dāng)為同一屬性時(shí),則以.dts文件中的為準(zhǔn),有如下例圖所示: 對(duì)于DTC(Device Tree Compiler)會(huì)將.dts文件編譯為.dtb文件,該工具的源碼在scripts/dtc目錄下,在該目錄下的Makefile文件中有hostprogs-y := dtc一句,確保在編譯時(shí)會(huì)將該dtc編譯為主機(jī)工具。 對(duì)于DTB(Device Tree Blob)文件由DTC編譯生成,是在bootloader中被加載和在kernel引導(dǎo)時(shí)被解析的二進(jìn)制文件。2.kernel對(duì)DT支持做的改變 使用DT后,以往所使用的大量板級(jí)信息都不再需要的,例如在arch/arm/plat-xxx和arch/arm/mach-xxx曾經(jīng)經(jīng)常實(shí)施的操作: a.注冊(cè)platform_device、綁定resource,即內(nèi)存和IRQ等板級(jí)信息 使用DT后,形如 static struct resource xxx_resources = 0 = .start = , .end = , .flags = IORESOURCE_MEM, , 1 = .start = , .end = , .flags = IORESOURCE_IRQ, , ; static struct platform_device xxx_device = .name = xxx, .id = -1, .dev = .platform_data = &xxx_data, , .resource = xxx_resources, .num_resources = ARRAY_SIZE(xxx_resources), ; 之類的platform_device代碼都不再需要了,其中platform_device 會(huì)由kernel自動(dòng)展開,其中這些resource來自.dts的設(shè)備結(jié)點(diǎn)reg、interruptes屬性。 比較典型的,大多數(shù)總結(jié)與“simple_bus”都兼容,而在SoC對(duì)應(yīng)machine的.init_machine成員函數(shù)中,調(diào)用of_platform_bus_probe(NULL, xxx_of_bus_ids, NULL);來展開所有的platform_device。例如,有XXX SoC,在arch/arm/mach-xxx/的板級(jí)文件中有如下的展開.dts中設(shè)備結(jié)點(diǎn)對(duì)就的platform_device: static struct of_device_id xxx_of_bus_ids _initdata = .compatible = simple-bus, , , ; void _init xxx_mach_init(void) of_platform_bus_probe(NULL, xxx_of_bus_ids, NULL); #ifdef CONFIG_ARCH_XXX DT_MACHINE_START(XXX_DT, Generic XXX (Flattened Device Tree) .init_machine = xxx_mach_init, MACHINE_END #endif b.注冊(cè)i2c_board_info,指定IRQ等板級(jí)信息 形如: static struct i2c_board_info _initdata afeb9260_i2c_devices = I2C_BOARD_INFO(tlv320aic23, 0x1a), , I2C_BOARD_INFO(fm3130, 0x68), , I2C_BOARD_INFO(24c64, 0x50), , ; 之類的代碼,現(xiàn)在也不需要了,只需要將tlv320aic23、fm3130和24c64之類的設(shè)備結(jié)點(diǎn)填充到相應(yīng)的I2C Controller結(jié)點(diǎn)的子結(jié)點(diǎn)中,如上面的.dts中所示。DT的I2C Client會(huì)通過I2C Host驅(qū)動(dòng)的probe()函數(shù)中調(diào)用of_i2c_register_devices(&i2c_dev-adapter);被自動(dòng)展開使用。 c.注冊(cè)spi_board_info,指定IRQ等板級(jí)信息 形如: static struct spi_board_info afeb9260_spi_devices = /* DataFlash chip */ .modalias = mtd_dataflash, .chip_select = 1, .max_speed_hz = 15 * 1000 * 1000, .bus_num = 0, , ; 之類的代碼也不再需要了,只需將mtd_dataflash之類結(jié)點(diǎn)作為SPI控制器的子結(jié)點(diǎn)即可,SPI Host驅(qū)動(dòng)的probe函數(shù)通過spi_register_master()注冊(cè)master的時(shí)候,會(huì)自動(dòng)展開其slave。 d.指定電路板的machine及相關(guān)callback 以前,ARM Linux 針對(duì)不同的電路板會(huì)建立由MACHINE_START 和MACHINE_END 包圍起來的針對(duì)這個(gè)machine 的一系列callback,如: MACHINE_START(VEXPRESS, ARM-Versatile Express) .atag_offset = 0x100, .smp = smp_ops(vexpress_smp_ops), .map_io = v2m_map_io, .init_early = v2m_init_early, .init_irq = v2m_init_irq, .timer = &v2m_timer, .handle_irq = gic_handle_irq, .init_machine = v2m_init, .restart = vexpress_restart, MACHINE_END Uboot在啟動(dòng)kernel時(shí)會(huì)將MACHINE_ID放在r1中,Linux Kernel啟動(dòng)時(shí)會(huì)匹配傳過來的MACHINE_ID,將該值與MACHINE_START處聲明的MACHINE_ID比對(duì),如匹配則會(huì)執(zhí)行相應(yīng)machine的一系列初始化函數(shù)。 使用DT后,MACHINE_START變?yōu)镈T_MACHINE_START,其中多了一個(gè).dt_compat成員,用于指定該machine與.dts中root結(jié)點(diǎn)compatible屬性兼容關(guān)系。一旦bootloader傳遞給kernel的DTB中root結(jié)點(diǎn)compatible屬性出現(xiàn)在某machine的.dt_compat表中,則匹配上了,從而執(zhí)行相應(yīng)的初始化函數(shù)。如: static const char * const v2m_dt_match _initconst = arm,vexpress, xen,xenvm, NULL, ; DT_MACHINE_START(VEXPRESS_DT, ARM-Versatile Express) .dt_compat = v2m_dt_match, .smp = smp_ops(vexpress_smp_ops), .map_io = v2m_dt_map_io, .init_early = v2m_dt_init_early, .init_irq = v2m_dt_init_irq, .timer = &v2m_dt_timer, .init_machine = v2m_dt_init, .handle_irq = gic_handle_irq, .restart = vexpress_restart, MACHINE_END Linux中倡導(dǎo)對(duì)多個(gè)SoC、多個(gè)電路板的通用DT machine,即一個(gè)DT machine的.dt_compat表含有多個(gè)電路板.dts文件的root結(jié)點(diǎn)compatible屬性字符串,之后,如果不同的電路板的初始化序列不一樣時(shí),可通過of_machine_is_compatible() API來判斷。例如arch/arm/mach-exynos/mach-exynos5-dt.c 的EXYNOS5_DT machine 同時(shí)兼容samsung,exynos5250和samsung,exynos5440: static char const *exynos5_dt_compat _initdata = samsung,exynos5250, samsung,exynos5440, NULL ; DT_MACHINE_START(EXYNOS5_DT, SAMSUNG EXYNOS5 (Flattened Device Tree) /* Maintainer: Kukjin Kim */ .init_irq = exynos5_init_irq, .smp = smp_ops(exynos_smp_ops), .map_io = exynos5_dt_map_io, .handle_irq = gic_handle_irq, .init_machine = exynos5_dt_machine_init, .init_late = exynos_init_late, .timer = &exynos4_timer, .dt_compat = exynos5_dt_compat, .restart = exynos5_restart, .reserve = exynos5_reserve, MACHINE_END 其.init_machine成員函數(shù)中有針對(duì)不同machine進(jìn)行分支處理: static void _init exynos5_dt_machine_init(void) if (of_machine_is_compatible(samsung,exynos5250) of_platform_populate(NULL, of_default_bus_match_table, exynos5250_auxdata_lookup, NULL); else if (of_machine_is_compatible(samsung,exynos5440) of_platform_populate(NULL, of_default_bus_match_table, exynos5440_auxdata_lookup, NULL); 使用DT后,驅(qū)動(dòng)需要與.dts中描述的設(shè)備結(jié)點(diǎn)匹配,才會(huì)引發(fā)驅(qū)動(dòng)的probe()函數(shù)執(zhí)行。對(duì)于platform_driver,需要添加一個(gè)OF匹配表,如上面的.dts文件的acme,a1234-i2c-bus兼容I2C 控制器結(jié)點(diǎn)的OF 匹配表為: static const struct of_device_id a1234_i2c_of_match = .compatible = acme,a1234-i2c-bus , , , ; MODULE_DEVICE_TABLE(of, a1234_i

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論