[mmc]Linux下MMC/SD/SDIO的識別與操作


轉自:http://blog.csdn.net/skdkjzz/article/details/38927943

我們知道host在掃描卡的過程中,其識別的順序為SDIO  SD MMC,並且從它的注釋可以看出,這個順序是很重要的。那這篇文章,我們就看看SDIO的識別過程,它對應的函數就是mmc_attach_sdio(host) (函數位於文件drivers/mmc/core/sdio.c), 那么同一個控制器是如何區分mmc/sd/sdio設備的,軟件會不停的輪訓設備,發不同的指令,然后不同的設備會做出不同的反應。

               這個函數大概來說做了如下的工作

               1、向卡發送CMD5命令,該命令有兩個作用:第一,通過判斷卡是否有反饋信息來判斷是否為SDIO設備(只有SDIO設備才對CMD5命令有反饋,其他卡是沒有回饋的);第二,如果是SDIO設備,就會給host反饋電壓信息,就是說告訴host,本卡所能支持的電壓是多少多少。

               2、host根據SDIO卡反饋回來的電壓要求,給其提供合適的電壓。

               3、初始化該SDIO卡

               4、注冊SDIO的各個功能模塊

               5、注冊SDIO卡

      對於以上功能的具體解釋,下面將結合程序娓娓道來

              1、CMD5命令的發送

              第789行的函數就是發送的CMD5命令,如果卡對該命令有回饋的話,err就是0,否則,err為非0,直接退出了;並且需要重點說明的一點就是,該函數的最后一個參數ocr,它是存儲反饋命令的,SDIO設備對CMD5的反饋命令為R4,下面來仔細分析一下這個R4,因為后面要用到這個R4命令。從SDIO spec文檔里面,我們能得到R4命令的格式

            

            從上圖可以看出,該命令有48位,但我們的ocr變量是32位的,那怎么存儲呢?系統就去掉原命令的開頭8位以及結尾的8位,只保留中間的32為,也就是截短后的命令格式是如下:

            

           具體各位的描述如下:

             C --   我還不知道

            Number 0f IO functions   -- 每個SDIO設備都有功能塊,這三位就記錄了該設備有多少個功能塊,最多7個

           Memory Present – 指明該設備是純粹只有功能塊的設備,還是同時包含了存儲空間,如果為0就是前者,如果是1就是后者

          Stuff Bits  -- 沒有實際用途一般為0

          I/O OCR – 該設備所能支持的電壓范圍(具體描述見sdio spec)

         2、配置電壓         

          ocr就是我們上面講的反饋命令R4(截短之后的32位),那么ocr&0x7f的意義是什么呢?從R4的格式就可以看出來,其低24位就代表了所能支持的電壓范圍,我們再來詳細的看一下這24位的OCR格式          

          現在應該可以知道ocr&0x7f的意義了吧,就是擯棄那些保留的電壓范圍。

         重點關注mmc_select_voltage         

            第1080行的相與 過程就是判斷host實際所支持的電壓與card所需要的電壓是否匹配,如果匹配,那么ocr的值就非0,否則就為0

            簡單介紹下第1082行的ffs函數,它的作用就是返回參數中第一個為1的bit的位置(ffs(0)=0,ffs(1)=1,ffs(8)=4),那么該函數用在這里的作用就是取出card需要的實際電壓是多少;

          第1090行的mmc_set_ios函數里面通過調用sdhci_set_power將host->iOS.vdd所代表的電壓寫入寄存器PWRCONn中 完成那個對電壓的重新配置(想要了解更詳細的過程,請跟蹤源代碼)

           3、初始化SDIO卡           

             第821行就是初始化SDIO卡的函數  這個函數很長,也很重要,這里筆者就不列出其程序代碼了,只是列出其中最重要的幾條:

                 1、通過函數mmc_alloc_card分配一個mmc_card的變量card

                 2、通過讀取R4命令中的bit27(也就是Memory Present)來判斷此卡是純IO卡 ,還是同時包含存儲功能。筆者使用的WIFI模塊為純IO功能,所以card->type = MMC_TYPE_SDIO(這個很重要,以后會用到) (接下來重點分析MMC_TYPE_SDIO的情況)

                3、通過發送CMD3命令獲取設備的從地址(relative addr),並且存放在變量card->rca中。筆者使用的WIFI模塊的card->rca = 1

                4、通過發送CMD7,選中相應從地址的卡

                5、通過調用函數mmc_set_clock設置卡工作的時鍾頻率

                6、通過發送CMD52命令,設置4位數據傳輸模式

           4、注冊SDIO功能模塊      

          847行的變量funcs存儲該SDIO卡所包含的IO功能塊的個數,851行到857行就是逐一初始化各個IO功能塊,下面來重點看一下該函數的內容:              

            第71行就是分配sdio_func結構體變量,該結構體存儲了功能塊的參數。

            第75行就是給功能塊編號,編號是從1到7(因為一個SDIO設備最多只有7個功能塊),存儲在變量func->num中

            第78行就是讀取SDIO卡中的FBR寄存器中關於該卡的功能類型的數據,存儲在func->class變量中(具體關於FBR寄存器內容,可以參考SDIO spec文檔)

            第82行就是讀取SDIO卡中的CIS寄存器的內容     

         上面的程序就是將功能模塊逐個的注冊進設備模型,這里想重點說明一下注冊的名稱(name),它是由三部分組成的,每部分之間用冒號隔開,(即 host的名稱:rca:功能塊編號) 。具體到筆者使用的WIFI模塊,因為其host名稱是mmc2  ,rca = 1,並且有兩個功能模塊(功能模塊編號分別是1和2),所以在/sys/bus/sdio/devices目錄下能見到如下兩個設備名

                    mmc2:0001:1

                    mmc2:0001:2

      5、注冊SDIO卡      

    上面的mmc_add_card函數就是注冊card了(這個card是在第3部分,初始化SDIO卡 里面分配和定義的)      

       第259行就是給card命名,格式為host名字:從地址,對於筆者的WIFI模塊 就是mmc2:0001

      第261到273行就是根據card->type來分辨出card的類型,給賦予相應的字符串,筆者的WIFI模塊就是"SDIO"

      第275行就是打印信息,具體不解釋 筆者的打印信息為  mmc2:new high speed SDIO card at address 0001(通常可以通過查看內核啟動信息中是否有該語句來判斷card是否被正確識別)

       第283行 就是將card注冊進Linux設備模型  注冊結果就是可以在/sys/bus/mmc/devices目錄下見到card 的名字,筆者的就是mmc2:0001  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM