日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux SD卡驱动开发(六) —— SD卡启动过程总体分析

發(fā)布時間:2023/12/9 linux 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux SD卡驱动开发(六) —— SD卡启动过程总体分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、工作流程

mmc驅動主要文件包括

drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/

內核啟動時,首先執(zhí)行core/core.c的mmc_init,注冊mmc、sd總線,以及一個host class設備。接著執(zhí)行card/block.c中,申請一個塊設備

二、數(shù)據(jù)結構:

這里涉及三種總線

[cpp]?view plaincopy
  • 1.?platform?bus?//MMC?host?controller?作為一種?platform?device,?它是需要注冊到?platform?bus上?的????
  • driver/base/platform.c????
  • struct?bus_type?platform_bus_type?=?{????
  • ????.name????????=?"platform",????
  • ????.dev_attrs????=?platform_dev_attrs,????
  • ????.match????????=?platform_match,????
  • ????.uevent????????=?platform_uevent,????
  • ????.pm????????=?&platform_dev_pm_ops,????
  • };????
  • ????
  • 2.?mmc?bus?type??//在mmc_init()中被創(chuàng)建的.通過調用?mmc_register_bus()?來注冊?MMC?總線????
  • drivers\mmc\core\bus.c????
  • static?struct?bus_type?mmc_bus_type?=?{????
  • ????.name????????=?"mmc",????
  • ????.dev_attrs????=?mmc_dev_attrs,????
  • ????.match????????=?mmc_bus_match,????
  • ????.uevent????????=?mmc_bus_uevent,????
  • ????.probe????????=?mmc_bus_probe,????
  • ????.remove????????=?mmc_bus_remove,????
  • ????.shutdown????????=?mmc_bus_shutdown,????
  • ????.pm????????=?&mmc_bus_pm_ops,????
  • };????
  • ????
  • 3.?sdio?bus?type????//在mmc_init()中被創(chuàng)建的.通過調用sdio_register_bus()?來注冊?SDIO?總線????
  • drivers\mmc\core\sdio_bus.c????
  • static?struct?bus_type?sdio_bus_type?=?{????
  • ????.name????????=?"sdio",????
  • ????.dev_attrs????=?sdio_dev_attrs,????
  • ????.match????????=?sdio_bus_match,????
  • ????.uevent????????=?sdio_bus_uevent,????
  • ????.probe????????=?sdio_bus_probe,????
  • ????.remove????????=?sdio_bus_remove,????
  • ????.pm????????=?SDIO_PM_OPS_PTR,????
  • };????
  • ? ? ?其中mmc總線操作相關函數(shù),由于mmc卡支持多種總數(shù)據(jù)線,如SPI、SDIO、8LineMMC而不同的總線的操作控制方式不盡相同,所以通過此結構與相應的總線回調函數(shù)相關聯(lián)。 [cpp]?view plaincopy
  • //總線操作結構??
  • 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,??
  • };??
  • 關于總線操作的函數(shù):

    .detect,驅動程序經(jīng)常需要調用此函數(shù)去檢測mmc卡的狀態(tài),具體實現(xiàn)是發(fā)送CMD13命令,并讀回響應,如果響應錯誤,則依次調用.remove、detach_bus來移除卡及釋放總線。


    三、總體架構

    1、kernel啟動時,先后執(zhí)行mmc_init()及mmc_blk_init(),以對mmc設備及mmc塊模塊進行初始化

    [cpp]?view plaincopy
  • mmc/core/core.c????
  • static?int?__init?mmc_init(void)????
  • ????workqueue?=?alloc_ordered_workqueue("kmmcd",?0);//建立了一個工作隊列workqueue,這個工作隊列的作用主要是用來支持熱插拔????
  • ????ret?=?mmc_register_bus();//注冊一個mmc總線????
  • ????ret?=?mmc_register_host_class();//注冊了一個?mmc_host?類????
  • ????ret?=?sdio_register_bus();//注冊了一個?sdio_bus_type????
  • ????????
  • *******?????
  • mmc/card/block.c????
  • static?int?__init?mmc_blk_init(void)????
  • ????res?=?register_blkdev(MMC_BLOCK_MAJOR,?"mmc");//注冊一個塊設備????
  • ????res?=?mmc_register_driver(&mmc_driver);//注冊一個mmc設備驅動????
  • ????
  • static?struct?mmc_driver?mmc_driver?=????
  • ????.probe??????=?mmc_blk_probe,????
  • ????????
  • static?int?mmc_blk_probe(struct?mmc_card?*card)????
  • ????mmc_set_bus_resume_policy(card->host,?1);//*host?該指針指向一個mmc主機實例,塊設備中的讀寫操作就是調用這個mmc主機的操作函數(shù)host->ops->request來實現(xiàn)對實際硬件的操作。????
  • 2、core部分會做兩件事

    a --?取得總線

    b --?檢查總線操作結構指針bus_ops,如果為空,則重新利用各總線對端口進行掃描,檢測順序依次為:SDIO、Normal SD、MMC。當檢測到相應的卡類型后,就使用mmc_attach_bus()把相對應的總線操作與host連接起來

    [cpp]?view plaincopy
  • void?mmc_attach_bus(struct?mmc_host?*host,?const?struct?mmc_bus_ops?*ops)??
  • {??
  • ????...??
  • ????host->bus_ops?=?ops;??
  • ????...??
  • }??
  • 3、然后在掛載mmc設備驅動時,執(zhí)行驅動程序中的xx_mmc_probe(),檢測host設備中掛載的sd設備

    [cpp]?view plaincopy
  • kernel\arch\arm\configs\msm9625_defconfig????
  • CONFIG_MMC_MSM=y????
  • ????
  • kernel\drivers\mmc\host\Makefile????
  • obj-$(CONFIG_MMC_MSM)????????+=?msm_sdcc.o????????
  • ????
  • msm_sdcc.c?(drivers\mmc\host)????
  • //系統(tǒng)初始化時掃描?platform?總線上是否有名為該SD主控制器名字"msm_sdcc"的設備,如果有,?驅動程序將主控制器掛載到?platform?總線上,并注冊該驅動程序????
  • static?int?__init?msmsdcc_init(void)????
  • ????platform_driver_register(&msmsdcc_driver);????//注冊?platform?driver????
  • ????????
  • static?struct?platform_driver?msmsdcc_driver?=?{????
  • ????.probe????????=?msmsdcc_probe,????
  • ????.remove????????=?msmsdcc_remove,????
  • ????.driver????????=?{????
  • ????????.name????=?"msm_sdcc",????
  • ????????.pm????=?&msmsdcc_dev_pm_ops,????
  • ????????.of_match_table?=?msmsdcc_dt_match,????
  • ????},????
  • };????????
  • ????????
  • //整個設備驅動的?probe()函數(shù),其本質就是是為設備建立起數(shù)據(jù)結構并對其賦初值????
  • //msmsdcc_probe?所有賦值中,我們重點關注從?platform_device?*pdev里得到的數(shù)據(jù),即設備樹里的數(shù)據(jù)????
  • //platform_device?*pdev是在系統(tǒng)初始化的時候掃描?platform?總線發(fā)現(xiàn)SD主控制器后所得到的數(shù)據(jù)????
  • static?int?msmsdcc_probe(struct?platform_device?*pdev)????????
  • {????????
  • ????//初始化設備的數(shù)據(jù)結構????
  • ????if?(pdev->dev.of_node)?{????
  • ????plat?=?msmsdcc_populate_pdata(&pdev->dev);????????//獲取設備樹信息????
  • ????of_property_read_u32((&pdev->dev)->of_node,"cell-index",?&pdev->id);????
  • ????}?else?{????
  • ????????plat?=?pdev->dev.platform_data;????
  • ????}????
  • ????//為主設備控制器建立數(shù)據(jù)結構,建立kobject,并初始化等待隊列,工作隊列,以及一些控制器的配置????
  • ????mmc?=?mmc_alloc_host(sizeof(struct?msmsdcc_host),?&pdev->dev);????????????----?1????
  • ????//實現(xiàn)設備驅動的功能函數(shù),如mmc->ops?=?&pxamci_ops;????
  • ????mmc->ops?=?&msmsdcc_ops;????
  • ????//申請中斷函數(shù)?request_irq()????
  • ????ret?=?request_irq(core_irqres->start,?msmsdcc_irq,?IRQF_SHARED,DRIVER_NAME?"?(cmd)",?host);????
  • ????//注冊設備,即注冊kobject,建立sys文件,發(fā)送uevent等????
  • ????mmc_add_host(mmc);????????????????????????????????????????????????????????----?2????
  • ????//其他需求,如在/proc/driver下建立用戶交互文件等????
  • ????ret?=?device_create_file(&pdev->dev,?&host->auto_cmd21_attr);????
  • }????????
  • 4、此時probe函數(shù)會創(chuàng)建一個host設備,然后開啟一個延時任務mmc_rescan()

    [cpp]?view plaincopy
  • 1:??????
  • core/host.c?????
  • //重要函數(shù)mmc_alloc_host?,?用于分配mmc_host結構體指針的內存空間大小????
  • struct?mmc_host?*mmc_alloc_host(int?extra,?struct?device?*dev)----創(chuàng)建一個?mmc_host?和?mmc_spi_host?,且mmc_host的最后一個成員指針private指向mmc_spi_host????
  • ????//建立數(shù)據(jù)結構????
  • ????struct?mmc_host?*host;??????
  • ????host?=?kzalloc(sizeof(struct?mmc_host)?+?extra,?GFP_KERNEL);????
  • ????//建立kobject????
  • ????host->parent?=?dev;????
  • ????host->class_dev.parent?=?dev;????
  • ????host->class_dev.class?=?&mmc_host_class;????
  • ????device_initialize(&host->class_dev);????
  • ????//初始化等待隊列,工作隊列????
  • ????init_waitqueue_head(&host->wq);????
  • ????INIT_DELAYED_WORK(&host->detect,?mmc_rescan);????//建立了一個工作隊列任務?structdelayed_work?detect。工作隊列任務執(zhí)行的函數(shù)為mmc_rescan????
  • ????//配置控制器????
  • ????host->max_segs?=?1;????
  • ????host->max_seg_size?=?PAGE_CACHE_SIZE;????
  • ????return?host;????
  • 5、驅動掛載成功后,mmc_rescan()函數(shù)被執(zhí)行,然后對卡進行初始化(步驟后面詳細講述)

    [cpp]?view plaincopy
  • core/core.c????
  • //mmc_rescan?函數(shù)是需要重點關注的,因為SD卡協(xié)議中的檢測,以及卡識別等都是在此函數(shù)中實現(xiàn)????
  • void?mmc_rescan(struct?work_struct?*work)????
  • ????if?(host->bus_ops?&&?host->bus_ops->detect?&&?!host->bus_dead?&&?!(host->caps?&?MMC_CAP_NONREMOVABLE))????//存在熱插拔卡,不包括emmc,調用探測函數(shù)????
  • ????host->bus_ops->detect(host);????
  • ????mmc_bus_put(host);????//減少引用技術,就釋放????
  • ????mmc_bus_get(host);????//增加bus引用計數(shù)????
  • ????if?(host->bus_ops?!=?NULL)?{????
  • ????????mmc_bus_put(host);????//如果卡仍然存在,減少引用計數(shù),不必探測了????
  • ????????goto?out;????
  • ????}????
  • ????if?(host->ops->get_cd?&&?host->ops->get_cd(host)?==?0)??//有卡,退出????
  • ????goto?out;????
  • ????mmc_claim_host(host);???????????????????//用于檢測host是否被占用,占用則退出,否則標記成占用????
  • ????????
  • ????if?(!mmc_rescan_try_freq(host,?host->f_min))????
  • 初始化卡接以下流程初始化:

    a、發(fā)送CMD0使卡進入IDLE狀態(tài)
    b、發(fā)送CMD8,檢查卡是否SD2.0。SD1.1是不支持CMD8的,因此在SD2.0 Spec中提出了先發(fā)送CMD8,如響應為無效命令,則卡為SD1.1,否則就是SD2.0(請參考SD2.0 Spec)。
    c、發(fā)送CMD5讀取OCR寄存器。
    d、發(fā)送ACMD55、CMD41,使卡進入工作狀態(tài)。MMC卡并不支持ACMD55、CMD41,如果這步通過了,則證明這張卡是SD卡。
    e、如果d步驟錯誤,則發(fā)送CMD1判斷卡是否為MMC。SD卡不支持CMD1,而MMC卡支持,這就是SD和MMC類型的判斷依據(jù)。
    f、如果ACMD41和CMD1都不能通過,那這張卡恐怕就是無效卡了,初始化失敗。

    ? ? ??假如掃描到總線上掛有有效的設備,就調用相對應的函數(shù)把設備裝到系統(tǒng)中,mmc_attach_sdio()、mmc_attach_sd()、mmc_attach_mmc()這三個函數(shù)分別是裝載sdio設備,sd卡和mmc卡的。

    ? ? ?在 sd卡中,驅動循環(huán)發(fā)送ACMD41、CMD55給卡,讀取OCR寄存器,成功后,依次發(fā)送CMD2(讀CID)、CMD3(得到RCA)、CMD9(讀 CSD)、CMD7(選擇卡)。后面還有幾個命令分別是ACMD41&CMD51,使用CMD6切換一些功能,如切換到高速模式。

    ? ? ?經(jīng)過上述步驟,已經(jīng)確定當前插入的卡是一張有效、可識別的存儲卡。然后調用mmc_add_card()把存儲卡加到系統(tǒng)中。正式與系統(tǒng)驅動連接在一起

    [cpp]?view plaincopy
  • static?int?mmc_rescan_try_freq(struct?mmc_host?*host,?unsigned?freq)????
  • ????host->f_init?=?freq;?????????????????//設置某一個時鐘頻率????
  • ????mmc_power_up(host);?????????????????????//與?mmc_power_off?類似,不過設置了啟動時需要的?ios????
  • ????mmc_go_idle(host);??????????----1a??????//CMD0?,SD卡從?inactive?到?idle????????????
  • ????mmc_send_if_cond(host,?host->ocr_avail);//檢測SD卡是否支持SD2.0?????????
  • ????if?(!mmc_attach_sd(host))???----1b??????//然后對mmc或者sd發(fā)送一些命令進行探測,這里以?sd?為例????
  • ????
  • 1a:????
  • int?mmc_go_idle(struct?mmc_host?*host)??????
  • ????struct?mmc_command?cmd?=?{0};????
  • ????cmd.opcode?=?MMC_GO_IDLE_STATE;?//即CMD0????
  • ????cmd.arg?=?0;????????????????????//此命令無參數(shù)????
  • ????err?=?mmc_wait_for_cmd(host,?&cmd,?0)????
  • ????????
  • int?mmc_wait_for_cmd(struct?mmc_host?*host,?struct?mmc_command?*cmd,?int?retries)????
  • ????memset(cmd->resp,?0,?sizeof(cmd->resp));??//調用了?mmc_start_request,?????
  • ????cmd->retries?=?retries;????
  • ????mrq.cmd?=?cmd;??????????????????????????????????
  • ????mmc_wait_for_req(host,?&mrq);????
  • ????????
  • void?mmc_wait_for_req(struct?mmc_host?*host,?struct?mmc_request?*mrq)???----重要函數(shù)????
  • ????__mmc_start_req(host,?mrq);????
  • ????
  • static?int?__mmc_start_req(struct?mmc_host?*host,?struct?mmc_request?*mrq)????
  • ????mmc_start_request(host,?mrq);????
  • ????????????
  • static?void?mmc_start_request(struct?mmc_host?*host,?struct?mmc_request?*mrq)????
  • ????host->ops->request(host,?mrq);????//即?msmsdcc_request,?MMC?核心與核HOST?層握手了????
  • ????
  • ????????
  • 1b:?????
  • core/mmc.c????
  • int?mmc_attach_sd(struct?mmc_host?*host)????????????????????//完成匹配,和初始化卡的功能????
  • ????err?=?mmc_send_app_op_cond(host,?0,?&ocr);??????----1b1?//檢測是否是支持SD卡????
  • ????host->ocr?=?mmc_select_voltage(host,?ocr);???????????????//設置MMC電壓????
  • ????err?=?mmc_init_card(host,?host->ocr,?NULL);??????????????//對mmc卡進行初始化,主要是讀取mmc卡里的一些寄存器信息,且對這些寄存器的值進行設置????
  • ????err?=?mmc_sd_init_card(host,?host->ocr,?NULL);???----1b2????
  • ????err?=?mmc_add_card(host->card);??????????????????----1b3?//調用?mmc_add_card?來把?mmc_card?掛載到?mmc_bus_type?總線去????
  • ????????
  • ????????
  • 1b1:????
  • int?mmc_send_app_op_cond(struct?mmc_host?*host,?u32?ocr,?u32?*rocr)????
  • ????cmd.opcode?=?SD_APP_OP_COND;????//ACMD41,獲取?SDcard?的允許電壓范圍值,保存在?ocr?中.?所有發(fā)送它之前需要發(fā)送?CMD_55?命令。執(zhí)行完后?card?狀態(tài)變?yōu)?READY????
  • ????
  • ????????
  • ????????
  • 1b2:????
  • static?int?mmc_sd_init_card(struct?mmc_host?*host,?u32?ocr,struct?mmc_card?*oldcard)????
  • ????err?=?mmc_sd_get_cid(host,?ocr,?cid,?&rocr);????????//發(fā)送?CMD2?,獲取卡的身份信息,進入到身份狀態(tài)????
  • ????card?=?mmc_alloc_card(host,?&sd_type);??????????????//分配一張?SD?類型的?card?結構????
  • ????err?=?mmc_send_relative_addr(host,?&card->rca);??????//獲取卡的相對地址,注意一前卡和主機通信都采用默認地址,現(xiàn)在有了自己的地址了,進入到?stand_by?狀態(tài)????
  • ????err?=?mmc_sd_get_csd(host,?card);?----mmc_send_csd(card,?card->raw_csd);//CMD9,?獲取?CSD?寄存器的信息,包括?block?長度,卡容量等信息????
  • ????err?=?mmc_select_card(card);????????????????????????//發(fā)送?CMD7,?選中目前?RADD?地址上的卡,任何時候總線上只有一張卡被選中,進入了傳輸狀態(tài)?????
  • ????err?=?mmc_sd_setup_card(host,?card,?oldcard?!=?NULL);???????
  • ????
  • int?mmc_sd_setup_card(struct?mmc_host?*host,?struct?mmc_card?*card,bool?reinit)????
  • ????mmc_app_send_scr(card,?card->raw_scr);???//發(fā)送命令?ACMD51?獲取?SRC?寄存器的內容,進入到?SENDING-DATA?狀態(tài)????
  • ????if?(host->ops->get_ro(host)?>?0?)??????//?get_ro(host)?即是?msmsdcc_get_ro?????
  • ????????mmc_card_set_readonly(card);????????//是否寫保護,如果是的,將?card?狀態(tài)設置為只讀狀態(tài)????
  • ????????
  • 1b3:????
  • core/bus.c????
  • int?mmc_add_card(struct?mmc_card?*card)?????//??/sys/devices/msm_sdcc.2/mmc_host/mmc0????
  • ????ret?=?device_add(&card->dev);????
  • ????
  • drivers/base/core.c????
  • int?device_add(struct?device?*dev)????
  • ????dev_set_name(dev,?"%s%u",?dev->bus->dev_name,?dev->id);?//????
  • ????bus_probe_device(dev);????
  • ????
  • void?bus_probe_device(struct?device?*dev)????
  • ????????if?(bus->p->drivers_autoprobe)?????
  • ????????ret?=?device_attach(dev);???????????//這樣,在總線?mmc_bus_type?中就有了?mmc?設備?mmc_card?了????????
  • ????????
  • ????????
  • ***********?????
  • 2:????
  • //完成kobject的注冊,并調用?mmc_rescan,目的在于在系統(tǒng)初始化的時候就掃描SD總線查看是否存在SD卡????
  • int?mmc_add_host(struct?mmc_host?*host)????
  • ????err?=?device_add(&host->class_dev);//將設備注冊進linux設備模型,最終的結果就是在?sys/bus/platform/devices?目錄下能見到?mmc?設備節(jié)點????
  • ????mmc_start_host(host);????
  • ????????
  • ????????
  • void?mmc_start_host(struct?mmc_host?*host)??????
  • ????mmc_power_off(host);????????????????----2a????
  • ????mmc_detect_change(host,?0);?????????----2b????
  • ????
  • 2a:????
  • void?mmc_power_off(struct?mmc_host?*host)???????
  • ????host->ios.power_mode?=?MMC_POWER_OFF;????//對?ios?進行了設置????
  • ????...????
  • ????mmc_set_ios(host);????
  • ????
  • void?mmc_set_ios(struct?mmc_host?*host)????
  • ????host->ops->set_ios(host,?ios);????????????//?set_ios?實際上就是?mmc_host_ops?的?.set_ios??=?msmsdcc_set_ios,????
  • ????
  • 2b:????
  • void?mmc_detect_change(struct?mmc_host?*host,?unsigned?long?delay)????
  • ????????mmc_schedule_delayed_work(&host->detect,?delay);?//實際上就是調用我們前面說的延時函數(shù)?mmc_rescan????
  • 6、卡設備加到系統(tǒng)中后,通知mmc塊設備驅動。塊設備驅動此時調用probe函數(shù),即mmc_blk_probe()函數(shù),mmc_blk_probe()首 先分配一個新的mmc_blk_data結構變量,然后調用mmc_init_queue,初始化blk隊列。然后建立一個線程 mmc_queue_thread()


    7、然后就可以進行傳輸命令和數(shù)據(jù)了

    [cpp]?view plaincopy
  • struct?mmc_host_ops?{???????????
  • ????//用于SD卡命令的傳輸,比如發(fā)送和接收命令,CMD0,CMD8,ACMD41諸如此類的都是在這個函數(shù)去實現(xiàn)????
  • ????void????(*request)(struct?mmc_host?*host,?struct?mmc_request?*req);????
  • ????
  • }????
  • ????
  • static?const?struct?mmc_host_ops?msmsdcc_ops?=?{????
  • ????.enable?????=?msmsdcc_enable,????
  • ????.disable????=?msmsdcc_disable,????
  • ????.pre_req????????=?msmsdcc_pre_req,????
  • ????.post_req???????=?msmsdcc_post_req,????
  • ????.request????=?msmsdcc_request,????
  • ????.set_ios????=?msmsdcc_set_ios,????
  • ????.get_ro?????=?msmsdcc_get_ro,????
  • ????.enable_sdio_irq?=?msmsdcc_enable_sdio_irq,????
  • ????.start_signal_voltage_switch?=?msmsdcc_switch_io_voltage,????
  • ????.execute_tuning?=?msmsdcc_execute_tuning,????
  • ????.hw_reset?=?msmsdcc_hw_reset,????
  • ????.stop_request?=?msmsdcc_stop_request,????
  • ????.get_xfer_remain?=?msmsdcc_get_xfer_remain,????
  • ????.notify_load?=?msmsdcc_notify_load,????
  • };????
  • ????
  • /*這個函數(shù)實現(xiàn)了命令和數(shù)據(jù)的發(fā)送和接收,??
  • 當?CORE?部分需要發(fā)送命令或者傳輸數(shù)據(jù)時,都會調用這個函數(shù),并傳遞?mrq?請求*/????
  • static?void?msmsdcc_request(struct?mmc_host?*mmc,?struct?mmc_request?*mrq)????
  • ????mmc_request_done(mmc,?mrq);?????????????//?如果卡不存在,就終止請求????
  • ????msmsdcc_request_start(host,?mrq);???????????
  • ????
  • static?void?msmsdcc_request_start?(struct?msmsdcc_host?*host,?struct?mmc_request?*mrq)????
  • ????if?((mrq->data->flags?&?MMC_DATA_READ)?||host->curr.use_wr_data_pend)??????//判斷發(fā)送數(shù)據(jù)還是命令????
  • ????????msmsdcc_start_data(host,?mrq->data,mrq->sbc???mrq->sbc?:?mrq->cmd,0);???//發(fā)送數(shù)據(jù)????
  • ????else????
  • ????????msmsdcc_start_command(host,mrq->sbc???mrq->sbc?:?mrq->cmd,0);??????????//發(fā)送命令????
  • ????
  • ????
  • static?void?msmsdcc_start_data(struct?msmsdcc_host?*host,?struct?mmc_data?*data,struct?mmc_command?*cmd,?u32?c)????
  • ????//對某些?寄存器進行設置,?使能某些中斷,?如?pio_irqmask????
  • ????...????
  • ????if?(is_dma_mode(host)?&&?(datactrl?&?MCI_DPSM_DMAENABLE))???//采用?DMA?進行數(shù)據(jù)傳輸還是采用?FIFO?進行數(shù)據(jù)傳輸????
  • ????????msmsdcc_start_command_deferred(host,?cmd,?&c);??????????//啟動了數(shù)據(jù)傳輸模式????
  • ????else????????
  • ????????msmsdcc_start_command(host,?cmd,?c)????
  • ????
  • static?void?msmsdcc_start_command(struct?msmsdcc_host?*host,?struct?mmc_command?*cmd,?u32?c)????
  • {????
  • ????msmsdcc_start_command_deferred(host,?cmd,?&c);????
  • ????msmsdcc_start_command_exec(host,?cmd->arg,?c);????
  • }????
  • ????
  • static?void?msmsdcc_start_command_deferred(struct?msmsdcc_host?*host,struct?mmc_command?*cmd,?u32?*c)????
  • ????cmd->opcode?----對應SD卡命令?,如?CMD0:復位SD?卡?
  • 總結

    以上是生活随笔為你收集整理的Linux SD卡驱动开发(六) —— SD卡启动过程总体分析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。