日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux加载DTS设备节点的过程(以高通8974平台为例)

發布時間:2025/4/16 linux 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux加载DTS设备节点的过程(以高通8974平台为例) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

DTS是Device Tree Source的縮寫,用來描述設備的硬件細節。在過去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥著大量的垃圾代碼,相當多數的代碼只是在描述板級細節,而這些板級細節對于內核來講,不過是垃圾,如板上的platform設備、resource、i2c_board_info、spi_board_info以及各種硬件的platform_data。為了去掉這些垃圾代碼,Linux采用DTS這種新的數據結構來描述硬件設備。采用Device Tree后,許多硬件的細節可以直接透過它傳遞給Linux,而不再需要在kernel中進行大量的冗余編碼。

? ? ? ?有關DTS的語法格式,網上有很多資料,這里我就不再贅述了。本文主要講Linux是怎樣加載DTS設備節點的流程。下面以高通QCT8974平臺(Linux內核)為例進行講解:

(1)使用DTS注冊平臺總線的過程

? ? ? ?在講注冊過程之前,我們先看看DTS是怎樣描述平臺總線結構的,以i2c總線為例:

[c]?view plaincopyprint?
  • /?{??
  • ????model?=?"Qualcomm?MSM?8974";??
  • ????compatible?=?"qcom,msm8974";??
  • ????interrupt-parent?=?<&intc>;??
  • ??
  • ????aliases?{??
  • ????????spi0?=?&spi_0;??
  • ????????spi7?=?&spi_7;??
  • ????????sdhc1?=?&sdhc_1;?/*?SDC1?eMMC?slot?*/??
  • ????????sdhc2?=?&sdhc_2;?/*?SDC2?SD?card?slot?*/??
  • ????????sdhc3?=?&sdhc_3;?/*?SDC3?SDIO?slot?*/??
  • ????????sdhc4?=?&sdhc_4;?/*?SDC4?SDIO?slot?*/??
  • ????};??
  • ??
  • ????memory?{??
  • ??
  • ????????secure_mem:?secure_region?{??
  • ????????????linux,contiguous-region;??
  • ????????????reg?=?<0?0x7800000="">;??
  • ????????????label?=?"secure_mem";??
  • ????????};??
  • ??
  • ????????adsp_mem:?adsp_region?{??
  • ????????????linux,contiguous-region;??
  • ????????????reg?=?<0?0x2000000="">;??
  • ????????????label?=?"adsp_mem";??
  • ????????};??
  • ????};??
  • ??
  • ????intc:?interrupt-controller@F9000000?{??
  • ????????compatible?=?"qcom,msm-qgic2";??
  • ????????interrupt-controller;??
  • ????????#interrupt-cells?=?<3>;??
  • ????????reg?=?<0xf9000000?0x1000="">,??
  • ??????????????<0xf9002000?0x1000="">;??
  • ????};??
  • ??
  • ????msmgpio:?gpio@fd510000?{??
  • ????????compatible?=?"qcom,msm-gpio";??
  • ????????gpio-controller;??
  • ????????#gpio-cells?=?<2>;??
  • ????????interrupt-controller;??
  • ????????#interrupt-cells?=?<2>;??
  • ????????reg?=?<0xfd510000?0x4000="">;??
  • ????????ngpio?=?<146>;??
  • ????????interrupts?=?<0?208=""?0="">;??
  • ????????qcom,direct-connect-irqs?=?<8>;??
  • ????};??
  • ??
  • ????wcd9xxx_intc:?wcd9xxx-irq?{??
  • ????????compatible?=?"qcom,wcd9xxx-irq";??
  • ????????interrupt-controller;??
  • ????????#interrupt-cells?=?<1>;??
  • ????????interrupt-parent?=?<&msmgpio>;??
  • ????????interrupts?=?<72?0="">;??
  • ????????interrupt-names?=?"cdc-int";??
  • ????};??
  • ??
  • ????timer?{??
  • ????????compatible?=?"arm,armv7-timer";??
  • ????????interrupts?=?<1?2=""?0=""?1=""?3=""?0="">;??
  • ????????clock-frequency?=?<19200000>;??
  • ????};??
  • ??
  • ????i2c_0:?i2c@f9967000?{?/*?BLSP#11?*/??
  • ????????cell-index?=?<0>;??
  • ????????compatible?=?"qcom,i2c-qup";??
  • ????????reg?=?<0xf9967000?0x1000="">;??
  • ????????#address-cells?=?<1>;??
  • ????????#size-cells?=?<0>;??
  • ????????reg-names?=?"qup_phys_addr";??
  • ????????interrupts?=?<0?105=""?0="">;??
  • ????????interrupt-names?=?"qup_err_intr";??
  • ????????qcom,i2c-bus-freq?=?<100000>;??
  • ????????qcom,i2c-src-freq?=?<50000000>;??
  • ????};??
  • ??
  • ????i2c_2:?i2c@f9924000?{??
  • ????????cell-index?=?<2>;??
  • ????????compatible?=?"qcom,i2c-qup";??
  • ????????reg?=?<0xf9924000?0x1000="">;??
  • ????????#address-cells?=?<1>;??
  • ????????#size-cells?=?<0>;??
  • ????????reg-names?=?"qup_phys_addr";??
  • ????????interrupts?=?<0?96=""?0="">;??
  • ????????interrupt-names?=?"qup_err_intr";??
  • ????????qcom,i2c-bus-freq?=?<100000>;??
  • ????????qcom,i2c-src-freq?=?<50000000>;??
  • ????};??
  • ??
  • ????spi_0:?spi@f9923000?{??
  • ????????compatible?=?"qcom,spi-qup-v2";??
  • ????????reg?=?<0xf9923000?0x1000="">;??
  • ????????interrupts?=?<0?95=""?0="">;??
  • ????????spi-max-frequency?=?<19200000>;??
  • ????????#address-cells?=?<1>;??
  • ????????#size-cells?=?<0>;??
  • ????????gpios?=?<&msmgpio?3?0>,?/*?CLK??*/??
  • ????????????<&msmgpio?1?0>,?/*?MISO?*/??
  • ????????????<&msmgpio?0?0>;?/*?MOSI?*/??
  • ????????cs-gpios?=?<&msmgpio?9?0>;??
  • ????};??
  • ??
  • };??

  • 從上面可知,系統平臺上掛載了很多總線,如i2c、spi、uart等等,每一個總線分別被描述為一個節點。Linux在啟動后,到C入口時,會執行以下操作,加載系統平臺上的總線和設備:

    start_kernel() --> setup_arch() --> unflatten_device_tree()?

    unflatten_device_tree()的代碼如下:

    [c]?view plaincopyprint?
  • void?__init?unflatten_device_tree(void)??
  • {??
  • ????__unflatten_device_tree(initial_boot_params,?&allnodes,??
  • ????????????????early_init_dt_alloc_memory_arch);??
  • ??
  • ????/*?Get?pointer?to?"/chosen"?and?"/aliasas"?nodes?for?use?everywhere?*/??
  • ????of_alias_scan(early_init_dt_alloc_memory_arch);??
  • }??
  • ?在執行完unflatten_device_tree()后,DTS節點信息被解析出來,保存到allnodes鏈表中,allnodes會在后面被用到。

    隨后,當系統啟動到board文件時,會調用.init_machine,高通8974平臺對應的是msm8974_init()。接著調用of_platform_populate(....)接口,加載平臺總線和平臺設備。至此,系統平臺上的所有已配置的總線和設備將被注冊到系統中。注意:不是dtsi文件中所有的節點都會被注冊,在注冊總線和設備時,會對dts節點的狀態作一個判斷,如果節點里面的status屬性沒有被定義,或者status屬性被定義了并且值被設為“ok”或者“okay”,其他情況則不被注冊到系統中。


    (2)使用DTS注冊總線設備的過程

    ? ? ? ?上面講了Linux怎樣使用DTS注冊平臺總線和平臺設備到系統中,那么其他設備,例如i2c、spi設備是怎樣注冊到系統中的呢?下面我們就以i2c設備為例,講解Linux怎樣注冊i2c設備到系統中。

    ?以高通8974平臺為例,在注冊i2c總線時,會調用到qup_i2c_probe()接口,該接口用于申請總線資源和添加i2c適配器。在成功添加i2c適配器后,會調用of_i2c_register_devices()接口。此接口會解析i2c總線節點的子節點(掛載在該總線上的i2c設備節點),獲取i2c設備的地址、中斷號等硬件信息。然后調用request_module()加載設備對應的驅動文件,調用i2c_new_device(),生成i2c設備。此時設備和驅動都已加載,于是drvier里面的probe方法將被調用。后面流程就和之前一樣了。


    ? ? ? ?簡而言之,Linux采用DTS描述設備硬件信息后,省去了大量板文件垃圾信息。Linux在開機啟動階段,會解析DTS文件,保存到全局鏈表allnodes中,在掉用.init_machine時,會跟據allnodes中的信息注冊平臺總線和設備。值得注意的是,加載流程并不是按找從樹根到樹葉的方式遞歸注冊,而是只注冊根節點下的第一級子節點,第二級及之后的子節點暫不注冊。Linux系統下的設備大多都是掛載在平臺總線下的,因此在平臺總線被注冊后,會根據allnodes節點的樹結構,去尋找該總線的子節點,所有的子節點將被作為設備注冊到該總線上。

    總結

    以上是生活随笔為你收集整理的Linux加载DTS设备节点的过程(以高通8974平台为例)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。