LINUX MMC 子系統分析(六)MMC card添加流程分析

原文再續,書接上回。本文我們進行mmc子系統中mmc card的添加與刪除流程。針對iic設備、spi設備、rtc設備等非熱插拔設備而言,我們一般在板級文件或者設備樹中定義外設信息,完成外設的註冊;但針對mmc card而言,其屬於熱插拔設備,不需要在板級文件或設備樹中進行外設的註冊,而由mmc子系統通過mmc card的rescan機制,實現mmc card的自動檢測及註冊機制。本篇主要即用來介紹mmc card的檢測流程及mmc card的註冊及註銷機制。主要分為如下兩部分:

一、mmc card rescan機制

二、mmc card探測及移除


一、Mmc card rescan機制

我們知道mmc card是依附於mmc controller的,因此mmc card rescan機制主要是基於mmc host進行設計的;該rescan機制主要是通過工作隊列實現的,如下圖為該機制的實現流程,主要說明如下:

  1. Mmc host子系統提供了延遲隊列機制,在執行mmc_alloc_host、mmc_add_host後,則完成了mmc card rescan延遲工作隊列及其處理接口的創建等操作;
  2. 若要觸發mmc card rescan(即調度工作隊列),則調用mmc_detect_change接口,即可觸發mmc card rescan(即完成mmc_host->detect隊列的調度);
  3. 延遲隊列的處理函數為mmc_rescan,該函數實現mmc card的添加與移除操作。


LINUX MMC 子系統分析(六)MMC card添加流程分析

Mmc card rescan的幾種方式

在上一小節的介紹中,延遲工作隊列的創建及處理函數的註冊操作由mmc host子模塊完成(mmc_alloc_host/mmc_add),無需驅動開發者關心;而延遲工作隊列的調度則需要具體的mmc host驅動進行實現。而mmc card rescan的方式有如下幾種:

  1. Mmc card是不可移除的(如emmc),則在mmc host初始化時設置mmc host為nonremovable(僅在mmc_add_host時,調用mmc_detect_change完成一次mmc rescan,此後不再執行mmc rescan操作);
  2. Mmc host支持mmc card detect功能(通過提供mmc detect中斷,進行mmc card detect),此種情況在mmc card detect中斷對應的中斷處理接口中,調用mmc_detect_change接口,對延遲工作隊列進行調度,從而調用接口mmc_rescan,完成一次mmc card的rescan;
  3. Mmc host不支持mmc card detect功能,針對此情形,可以設置mmc host為poll模式。針對此種模式,在mmc_add_host執行一次mmc rescan時,在mmc rescan的最後會執行延遲1s調度該延遲工作隊列,從而完成每秒執行一次mmc rescan操作。

以上即為mmc card rescan的幾種模式,在進行mmc host驅動開發時,可以根據自己驅動的情形,選擇相應的處理方式進行驅動開發。


二、mmc card探測及移除

mmc card的探測及移除由mmc_rescan完成(而mmc_rescan接口則由上述一中的mmc_detect_change調度),下面我們分析mmc_rescan,來說明mmc card的探測及移除

mmc_rescan接口分析

mmc_rescan接口實現mmc card rescan的操作,該接口的處理流程圖如下:

  1. 若mmc host不支持mmc card的移除操作,則做相應的判斷(非第一次執行,則直接退出);
  2. 針對已註冊的mmc card,則執行一次detect(host->bus_ops->detect),移除已經離線的mmc card(這會觸發mmc_card的release操作,即調用device_unregister將該mmc_card從mmc_bus上移除,這會觸發mmc_card的release操作,即調用device_unregister將該mmc_card從mmc_bus上移除,而這即觸發mmc_driver與mmc_card的解綁流程(詳見上一篇分析文章),從而調用mmc_driver->remove接口,即將已註冊的mmc block device進行註銷。);
  3. 若mmc host支持get_cd接口,則調用其get_cd接口針對cd引腳值,判斷mmc card是否在線;
  4. 針對每一個頻率(400khz、300khz、200khz、100khz(若host->f_min大於400khz,則以host->f_min進行探測)),調用mmc_rescan_try_freq進行mmc card rescan操作。


LINUX MMC 子系統分析(六)MMC card添加流程分析

mmc_rescan_try_freq接口

該接口的處理流程如上圖所示,該接口實現的功能如下:

  1. 設置mmc host的總線帶寬、總線模式(pushpull),並設置mmc host(從powerup->poweron);
  2. 若mmc host支持hw_reset,執行hw_reset;
  3. 向mmc card 發送MMC_GO_IDLE_STATE命令(讓mmc卡進入idle狀態,該命令為broadcast commnad without response);
  4. 執行mmc 設備的探測:
    1. 針對sdio 設備,則調用mmc_attach_sdio執行sdio設備的探測;
    2. 針對sd設備,則調用mmc_attach_sd執行sd設備的探測;
    3. 針對mmc設備,則調用mmc_attach_mmc執行mmc設備的探測

mmc_attach_sdio、mmc_attach_sd、mmc_attach_mmc則為具體設備的探測及綁定流程。下面我們以sd card為主,進行sd card探測及綁定流程說明:

mmc_attach_sd接口分析

mmc_attach_sd接口的主要處理流程如下圖所示,其實現的主要功能如下:

  1. 發送send_op_cond(該指令為broadcast command with response);若沒有響應,則說明card不在線,程序返回;
  2. 若card回覆,則說明card在線,則調用mmc_sd_attach_bus_ops,設置mmc_host->bus_ops為mmc_sd_ops_unsafe/mmc_sd_ops;
  3. 調用mmc_sd_init_card,獲取mmc card的csd、cid,並創建mmc_card,並對mmc card進行初始化(如是否只讀等信息);
  4. 調用mmc_add_card,將該mmc_card註冊至mmc_bus中,該接口會調用device_register將mmc_card註冊至mmc_bus上,而這即觸發mmc_driver與mmc_card的綁定流程(詳見上一篇分析文章),從而調用mmc_driver->probe接口,即執行mmc block device的註冊操作。


LINUX MMC 子系統分析(六)MMC card添加流程分析

以上即為本篇的主要內容,主要介紹了mmc card的rescan機制以及mmc card的探測及移除流程。

本篇亦為mmc子系統的最後一篇文章,針對mmc 子系統而言,涉及總線-設備-驅動模型、塊設備模型,實現了mmc card、mmc host、mmc driver的抽象。而針對mmc 子系統而言,其實現了mmc driver的實現、mmc block device的實現、mmc card的rescan機制,而驅動工程師只需要實現mmc host驅動即可,無需關注mmc driver、mmc block device實現以及mmc card的註冊。


分享到:


相關文章: