下面就驅動移植時需要注意的地方進行分析。
static void s3cmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
mrq所指的struct mmc_request中的值在mmc_blk_issue_rq函數中被設定:
brq.mrq.cmd = &brq.cmd;
brq.mrq.data = &brq.data;
brq.cmd.arg = req->sector << 9;
brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
brq.data.blksz = 1 << md->block_bits;
brq.data.blocks = req->nr_sectors >> (md->block_bits - 9);
brq.stop.opcode = MMC_STOP_TRANSMISSION;
brq.stop.arg = 0;
brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
...
brq.data.sg = mq->sg;
brq.data.sg_len = blk_rq_map_sg(req->q, req, brq.data.sg);//從指定的要求中獲得全部的段,然後把他們填寫到給定的表中
mmc_wait_for_req(card->host, &brq.mrq);
brq.data.sg是個struct scatterlist數組。指明了讀/寫的各個段的長度,及其位移地址 =============================================== 發現了兩篇講SD/MMC卡驅動的文章,覺得不錯,轉了過來,謝謝原作者
文一:FROM:http://blog.chinaunix.net/u2/69999/showart_734099.html
關於linux 2.6 mmc/sd驅動
linux 2.6 中的mmc/sd驅動分為以下幾方面的內容
1. sysfs 層的匯流排類型處理: 註冊一組 mmc 類型處理函數, 標誌為 "mmc"
具體在mmc_sysfs.c檔案中實現
2. mmc/sd 快裝置管理:註冊一個塊裝置和一組 mmc 匯流排類型的 driver 子函數, 實現塊裝置的隊列管理等
drivers/mmc/mmc_block.c
3. mmc/sd host管理: 實現 host 的管理
. drivers/mmc/mmc.c:主要的 MMC command 與 protocol 實作。
4. 針對特定的mcu實現一個host驅動執行個體:主要是註冊一個 host實體,中斷處理函數,io設定函數,請求處理函數等
以上1.2.3基本是不需要修改的,需要處理的就是 4.要做的工作.當有卡插入時,由4中實現的插卡中斷啟用卡初始化程式和匯流排探測函數. 由mmc匯流排探測函數會調用塊裝置的探測函數,在卡裝置探測函數中會初始化塊裝置的請求隊列和註冊一個gendisk實體(以後檔案系統會通過 gendisk實體訪問 mmc 塊裝置),同時在sysfs中建立真正的 mmc/sd 裝置.塊裝置通過具體的 host 註冊的io設定函數和請求函數與具體的host通訊.
後面的文章將具體對幾個部分進行分析
-----------------------------------------------------------------------------
文二:
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都不能通過,那這張卡恐怕就是無效卡了,初始化失敗。