天天看點

Fuchsia MMC架構簡析

本文簡單分析下Fuchsia的MMC架構,主要是基于mmc協定的初始化流程進行說明。至于mmc架構中的SD以及SDIO協定流程本文不涉及。另外,Fuchsia塊裝置層以及檔案系統層的分析,本文也不涉及。

下表為目前rcar-M3單闆系統的“裝置樹”(為描述友善,省略了部分裝置樹節點)。

root$ dm dump

[root]

   <root> pid=2524

      [null] pid=2524 /boot/driver/builtin.so

      [zero] pid=2524 /boot/driver/builtin.so

   [misc]

      <misc> pid=2607

         [console] pid=2607 /boot/driver/console.so

         ……

   [sys]

      <sys> pid=2439 /boot/driver/platform-bus.so

         [platform] pid=2439 /boot/driver/platform-bus.so

            [rcar-m3] pid=2439 /boot/driver/rcar-m3.so

            [16:01:1] pid=2439 /boot/driver/platform-bus.so

               <16:01:1> pid=2958 /boot/driver/platform-bus.proxy.so

                  [sh_mobile_sdhi] pid=2958 /boot/driver/sh-mobile-sdhi.so

                     [sdmmc] pid=2958 /boot/driver/sdmmc.so

                        [sdmmc-mmc] pid=2958 /boot/driver/sdmmc.so

                           [block] pid=2958 /boot/driver/block.core.so

                              [part-000] pid=2958 /boot/driver/mbr.so

                                 [block] pid=2958 /boot/driver/block.core.so

                                    [fvm] pid=2958 /boot/driver/fvm.so

                                       [blobfs-p-1] pid=2958 /boot/driver/fvm.so

                                          [block] pid=2958 /boot/driver/block.core.so

                                       [minfs-p-2] pid=2958 /boot/driver/fvm.so

                                          [block] pid=2958 /boot/driver/block.core.so

[part-001]

……

            [16:01:2] pid=2439 /boot/driver/platform-bus.so

               <16:01:2> pid=3131 /boot/driver/platform-bus.proxy.so

                  [ravb-ethernet] pid=3131 /boot/driver/ethernetAVB-IF.so

                     [ethernet] pid=3131 /boot/driver/ethernet.so

         [cpu-trace] pid=2439 /boot/driver/platform-bus.so

   [test]

      <test> pid=2471

         ……

我們可以看到,這實際上是一顆“倒置”的“樹”,裝置硬體相關的資訊在上面的“樹幹”,而層層抽象的驅動則是挂在裝置下的“樹枝”和“樹葉”。以mmc塊裝置為例,其board級驅動([rcar-m3] pid=2439 /boot/driver/rcar-m3.so)裝置挂在系統的永久裝置sys的platform總線裝置下面。而board裝置下面則是挂載的emmc驅動(sh-mobile-sdhi.so)裝置。Emmc驅動裝置下面層層的挂載了系統的軟體抽象層裝置,包括mmc抽象層裝置、block塊抽象層裝置、分區裝置以及檔案系統抽象層裝置。更詳細的驅動架構DDK相關細節,請參考我的“DDK驅動架構分析”文檔。

從上面的這顆“倒置樹”可以看出mmc架構抽象層是挂載在emmc驅動([sh_mobile_sdhi] )下面的,也就是emmc驅動初始化完成并釋出裝置後,才能觸發mmc架構層驅動的初始化。如下圖所示,mmc架構層的初始化入口為SdmmcRootDevice::Bind。其在Init函數中會新啟動一個線程(SdmmcRootDevice::WorkerThread)來執行mmc協定層的probe流程。

在SdmmcRootDevice::WorkerThread流程中,首先調用emmc host驅動的reset接口,執行卡的reset初始化操作。接下來不管卡處于什麼狀态,都先發送CMD0指令,讓其進入idle态,以保證後面的初始化流程正常進行下去。接下來會依次進行SDIO、SD以及MMC子協定的probe操作,前面的probe成功,後面的就不會再執行。這裡我們選擇MMC子協定的probe流程進行展開分析。

  1. 發送CMD1指令擷取卡OCR寄存器值
  2. 設定OCR寄存器的bit30位,使能sector模式(不使能位byte模式)
  3. 發送CMD2指令擷取CID寄存器值
  4. 解析CID值,擷取mmc序列号、版本資訊等
  5. 發送CMD3指令,為卡配置設定mmc總線上的相對位址,寫入RCA寄存器。初始化時,RCA寄存器值為0,這裡如果mmc總線上隻有一個裝置,該位址将會是0001。
  6. 發送CMD9指令,擷取CSD寄存器值
  7. 解析CSD寄存器值,擷取卡容量、扇區大小等資訊
  8. 發送CMD7指令選中該卡(arg參數帶上卡位址0001)
  9. 發送CMD8指令讀取ext CSD寄存器值;該寄存器為512位元組大小,儲存了豐富的資訊,包括支援的總線位寬、高速模式、CMDQ、逾時值等等;詳情請參考emmc協定手冊
  10. 解析ext CSD寄存器值,擷取卡的相關特性支援情況
  11. 如果支援高速模式(HS、HSDDR、HS200),進行下面的初始化操作
  12. 高速模式首先需要将總線接口電平設定為1.8V(低速模式為3.3V)
  13. 然後通過CMD6和CMD13指令選擇并設定emmc支援的最大總線位寬(HS200支援4-bit和8-bit兩種總線位寬,但HS400隻支援8-bit位寬)
  14. 更進一步,如果支援高速模式中的HS200模式,進行下面的初始化操作
  15. 通過CMD6和CMD13指令設定HS200模式
  16. 切換host時鐘頻率為200MHz
  17. 執行mmc總線tuning過程(發送CMD21指令,根據host寄存器值确定需要進行的tuning次數,rcar-M3需要進行16次,然後根據結果則有選擇最佳采樣點)
  18. 再進一步,如果支援HS400模式,則進行下面的初始化操作
  19. 通過CMD6和CMD13指令,将模式切換回普通高速模式
  20. 時鐘頻率設定為52MHz(普通高速模式)
  21. 通過CMD6和CMD13指令設定總線位寬為8bit DDR(Dual Data Rate)
  22. 通過CMD6和CMD13指令切換模式為HS400
  23. 最後一步是将時鐘頻率設定為200MHz,完成HS400模式的切換

請結合下圖及具體代碼,來了解fuchsia的MMC協定架構初始化流程。

Fuchsia MMC架構簡析