SDIO
SDIO
1.
2.
3.
4.
5.
在
SDIO
1.
2.
CMD
3.
SDIO
CMD52
SDIO
但二者最重要的區別是,
CMD52
首先第一位爲
CMD53
CMD52
——————————————————————————————————————
瞭解了SDIO總線命令的基礎知識,下面看一個具體的基於s3c2440平臺的mmc/sd卡驅動實例,會用到sd卡的命令字,對sdio的命令字道理也是差不多的:
發現了兩篇講SD/MMC卡驅動的文章,覺得不錯,轉了過來,謝謝原作者
文一:FROM:http://blog.chinaunix.net/u2/69999/showart_734099.html
1. sysfs 層的總線類型處理: 註冊一組 mmc 類型處理函數, 標誌爲 "mmc"
2. mmc/sd 快設備管理:註冊一個塊設備和一組 mmc 總線類型的 driver 子函數, 實現塊設備的隊列管理等
drivers/mmc/mmc_block.c
3. mmc/sd host管理: 實現 host 的管理
.
4. 針對特定的mcu實現一個host驅動實例:主要是註冊一個 host實體,中斷處理函數,io設置函數,請求處理函數等
後面的文章將具體對幾個部分進行分析
-----------------------------------------------------------------------------
文二:
FROM:http://blog.chinaunix.net/u1/42456/showart_516030.html
最近要讓s3c2440在linux2.6.18上 支持4G的SD卡.
原文地址:http://linux4u.wikidot.com/mmc-controller-driver
==============================================================
linux-2.6.2x的mmc驅動與linux-2.6.1x的mmc驅動的區別
在linux-2.6.2x中,mmc驅動用到的block_device_operations結構已重新定義,請看:
linux-2.6.1x:
struct block_device_operations {
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
struct module *owner;
};
linux-2.6.2x
struct block_device_operations {
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
int (*getgeo)(struct block_device *, struct hd_geometry *);
struct module *owner;
};
注意到新版本的block驅動接口結構增加了gntgeo成員,使調用者可以直接調用此函數獲得設備的幾何結構。
工作流程:
mmc驅動主要文件包括
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/
內核啓動時,首先執行core/core.c的mmc_init,註冊mmc、sd總線,以及一個host class設備。接着執行card/block.c中,申請一個塊設備。
數據結構:
mmc總線操作相關函數,由於mmc卡支持多種總數據線,如SPI、SDIO、8LineMMC,而不同的總線的操作控制方式不盡相同,所以通過此結構與相應的總線回調函數相關聯。
//總線操作結構
struct mmc_bus_ops {
void (*remove)(struct mmc_host *);
void (*detect)(struct mmc_host *);
int (*sysfs_add)(struct mmc_host *, struct mmc_card *card);
void (*sysfs_remove)(struct mmc_host *, struct mmc_card *card);
void (*suspend)(struct mmc_host *);
void (*resume)(struct mmc_host *);
};
// mmc卡的總線操作 core/mmc.c
static const struct mmc_bus_ops mmc_ops = {
.remove = mmc_remove,
.detect = mmc_detect,
.sysfs_add = mmc_sysfs_add,
.sysfs_remove = mmc_sysfs_remove,
.suspend = mmc_suspend,
.resume = mmc_resume,
};
// sd卡的總線操作 core/sd.c
static const struct mmc_bus_ops mmc_sd_ops = {
.remove = mmc_sd_remove,
.detect = mmc_sd_detect,
.sysfs_add = mmc_sd_sysfs_add,
.sysfs_remove = mmc_sd_sysfs_remove,
.suspend = mmc_sd_suspend,
.resume = mmc_sd_resume,
};
// sdio的總線操作 core/sdio.c
static const struct mmc_bus_ops mmc_sdio_ops = {
.remove = mmc_sdio_remove,
.detect = mmc_sdio_detect,
};
關於總線操作的函數:
.detect,驅動程序經常需要調用此函數去檢測mmc卡的狀態,具體實現是發送CMD13命令,並讀迴響應,如果響應錯誤,則依次調用.remove、detach_bus來移除卡及釋放總線。
總體架構:
kernel啓動時,先後執行mmc_init()及mmc_blk_init(),以對mmc設備及mmc塊模塊進行初始化。
然後在掛載mmc設備驅動時,執行驅動程序中的xx_mmc_probe(),檢測host設備中掛載的sd設備。此時probe函數會創建一個host設備,然後開啓一個延時任務mmc_rescan()。
驅動掛載成功後,mmc_rescan()函數被執行,然後對卡進行初始化(步驟後面詳細講述)。
假如掃描到總線上掛有有效的設備,就調用相對應的函數把設備裝到系統中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()這三個函數分別是裝載sdio設備,sd卡和mmc卡的。
在 sd卡中,驅動循環發送ACMD41、CMD55給卡,讀取OCR寄存器,成功後,依次發送CMD2(讀CID)、CMD3(得到RCA)、CMD9(讀 CSD)、CMD7(選擇卡)。後面還有幾個命令分別是ACMD41&CMD51,使用CMD6切換一些功能,如切換到高速模式。
經過上述步驟,已經確定當前插入的卡是一張有效、可識別的存儲卡。然後調用mmc_add_card()把存儲卡加到系統中。正式與系統驅動連接在一起。
卡設備加到系統中後,通知mmc塊設備驅動。塊設備驅動此時調用probe函數,即mmc_blk_probe()函數,mmc_blk_probe()首先分配一個新的mmc_blk_data結構變量,然後調用mmc_init_queue,初始化blk隊列。然後建立一個線程 mmc_queue_thread()。
mmc_rescan:mmc_rescan()函數是在驅動裝載的時候,由驅動xx_mmc_probe()調用 mmc_alloc_host()時啓動的一個延時任務。 xx_mmc_probe()->mmc_alloc_host()->INIT_DELAYED_WORK(&host->detect, mmc_rescan);
當
core部分
1、取得總線
2、檢查總線操作結構指針bus_ops,如果爲空,則重新利用各總線對端口進行掃描,檢測順序依次爲:SDIO、Normal SD、MMC。當檢測到相應的卡類型後,就使用mmc_attach_bus()把相對應的總線操作與host連接起來。
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
{
...
host->bus_ops = ops;
...
}
3、初始化卡接以下流程初始化:
a、發送CMD0使卡進入IDLE狀態
b、發送CMD8,檢查卡是否SD2.0。SD1.1是不支持CMD8的,因此在SD2.0 Spec中提出了先發送CMD8,如響應爲無效命令,則卡爲SD1.1,否則就是SD2.0(請參考SD2.0 Spec)。
c、發送CMD5讀取OCR寄存器。
d、發送ACMD55、CMD41,使卡進入工作狀態。MMC卡並不支持ACMD55、CMD41,如果這步通過了,則證明這張卡是SD卡。
e、如果d步驟錯誤,則發送CMD1判斷卡是否爲MMC。SD卡不支持CMD1,而MMC卡支持,這就是SD和MMC類型的判斷依據。
f、如果ACMD41和CMD1都不能通過,那這張卡恐怕就是無效卡了,初始化失敗。