标签:
现在EMMC盛行,分析总结还是很有必要的。以下以全志a64为实例切入主题。
这里a64有三个sdc0~2,硬件上sdc2是连接EMMC,这里只分析sdc2的代码。
初始化的代码在linux-3.10/drivers/mmc/host/sunxi-mmc.c
以下忽略部分冗余代码:
1 static const struct of_device_id sunxi_mmc_of_match[] = { 2 ...... 3 ...... 4 { .compatible = "allwinner,sun50i-sdmmc2", }, 5 ...... 6 ...... 7 }; 8 MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match); 9 10 static struct platform_driver sunxi_mmc_driver = { 11 .driver = { 12 .name = "sunxi-mmc", 13 .of_match_table = of_match_ptr(sunxi_mmc_of_match), 14 .pm = sunxi_mmc_pm_ops, 15 }, 16 .probe = sunxi_mmc_probe, 17 .remove = sunxi_mmc_remove, 18 .shutdown = sunxi_shutdown_mmc, 19 }; 20 module_platform_driver(sunxi_mmc_driver);
设备树会初始化deivce,这里有driver,下面直接进sunxi_mmc_probe分析。
以下忽略部分冗余代码:
1 static int sunxi_mmc_probe(struct platform_device *pdev) 2 { 3 struct sunxi_mmc_host *host; //全志a64主控硬件相关 4 struct mmc_host *mmc; //emmc架构相关 5 int ret; 6 7 dev_info(&pdev->dev,"%s\n",DRIVER_VERSION); 8 9 mmc = mmc_alloc_host(sizeof(struct sunxi_mmc_host), &pdev->dev); //初始化mmc_host,后面会分析 10 11 host = mmc_priv(mmc); //host = mmc->private; 12 host->mmc = mmc; //sunxi_mmc_host和mmc_host建立纽带 13 14 //配置硬件相关,如时钟,sdc控制寄存器,IO复用,中断,电源控制 15 ret = sunxi_mmc_resource_request(host, pdev); 16 17 //初始化dma #define 4*PAGE_SIZE 18 host->dma_mask = DMA_BIT_MASK(32); 19 pdev->dev.dma_mask = &host->dma_mask; 20 pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 21 host->sg_cpu = dma_alloc_coherent(&pdev->dev, SUNXI_REQ_PAGE_SIZE, 22 &host->sg_dma, GFP_KERNEL); 23 24 mmc->ops = &sunxi_mmc_ops; 25 mmc->max_blk_count = 8192; 26 mmc->max_blk_size = 4096; 27 mmc->max_segs = SUNXI_REQ_PAGE_SIZE / sizeof(struct sunxi_idma_des); 28 mmc->max_seg_size = (1 << host->idma_des_size_bits); 29 mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; 30 /* 400kHz ~ 50MHz */ 31 mmc->f_min = 400000; 32 mmc->f_max = 50000000; 33 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | MMC_CAP_ERASE 34 | MMC_CAP_WAIT_WHILE_BUSY; 35 //mmc->caps2 |= MMC_CAP2_HS400_1_8V; 36 37 38 mmc_of_parse(mmc); //解析设备树相关的信息 39 40 ret = mmc_add_host(mmc); //重点,真正初始化emmc并启动,后面会分析 41 42 ret = mmc_create_sys_fs(host,pdev); 43 44 dev_info(&pdev->dev, "base:0x%p irq:%u\n", host->reg_base, host->irq); 45 platform_set_drvdata(pdev, mmc); 46 return 0; 47 }
到此probe结束,有两个比较关键的函数mmc_alloc_host和mmc_add_host,真正启动emmc的操作都在这里
mmc_alloc_host和mmc_add_host的代码在linux-3.10/drivers/mmc/core/host.c
以下忽略部分冗余代码:
1 struct mmc_host *mmc_alloc_host(int extra, struct device *dev) 2 { 3 int err; 4 struct mmc_host *host; 5 6 host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL); 7 8 /* scanning will be enabled when we‘re ready */ 9 host->rescan_disable = 1; 10 idr_preload(GFP_KERNEL); 11 12 err = idr_alloc(&mmc_host_idr, host, 0, 0, GFP_NOWAIT); 13 if (err >= 0) 14 host->index = err; //通过整数id管理地址,具体细节本人不太清楚 15 16 idr_preload_end(); 17 18 dev_set_name(&host->class_dev, "mmc%d", host->index); 19 20 host->parent = dev; 21 host->class_dev.parent = dev; 22 host->class_dev.class = &mmc_host_class; 23 device_initialize(&host->class_dev); 24 25 mmc_host_clk_init(host); //这里初始化框架相关的clock,不涉及硬件 26 27 host->slot.cd_irq = -EINVAL; 28 29 init_waitqueue_head(&host->wq); 30 wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND, //初始化唤醒内核的锁 31 kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host))); 32 INIT_DELAYED_WORK(&host->detect, mmc_rescan); //重要,初始化检查card的队列 33 34 host->pm_notify.notifier_call = mmc_pm_notify; 35 /* 36 * By default, hosts do not support SGIO or large requests. 37 * They have to set these according to their abilities. 38 */ 39 host->max_segs = 1; 40 host->max_seg_size = PAGE_CACHE_SIZE; //#define PAGE_CACHE_SIZE 1UL << 16 41 42 host->max_req_size = PAGE_CACHE_SIZE; 43 host->max_blk_size = 512; 44 host->max_blk_count = PAGE_CACHE_SIZE / 512; 45 46 return host; 47 } 48 49 int mmc_add_host(struct mmc_host *host) 50 { 51 int err; 52 53 err = device_add(&host->class_dev); 54 55 led_trigger_register_simple(dev_name(&host->class_dev), &host->led); //;类似硬盘的LED闪烁 56 57 #ifdef CONFIG_DEBUG_FS 58 mmc_add_host_debugfs(host); //debug用 59 #endif 60 mmc_host_clk_sysfs_init(host); 61 62 mmc_start_host(host); //重要,真正操作都在这里 63 64 return 0; 65 }
mmc_start_host的代码在linux-3.10/drivers/mmc/core/core.c
以下忽略部分冗余代码:
void mmc_start_host(struct mmc_host *host) { host->f_init = max(freqs[0], host->f_min); //初始时钟 host->rescan_disable = 0; //开启rescan mmc_power_up(host); mmc_detect_change(host, 0); } static void mmc_power_up(struct mmc_host *host) { int bit; if (host->ios.power_mode == MMC_POWER_ON) //已经启动 return; mmc_host_clk_hold(host); //没有定义CONFIG_MMC_CLKGATE 所有gateclock相关都是空操作 /* If ocr is set, we use it */ if (host->ocr) //ocr是电源配置,在sunxi_mmc_resource_request已经设置好 bit = ffs(host->ocr) - 1; else bit = fls(host->ocr_avail) - 1; //io bus设置 host->ios.vdd = bit; if (mmc_host_is_spi(host)) host->ios.chip_select = MMC_CS_HIGH; else host->ios.chip_select = MMC_CS_DONTCARE; host->ios.bus_mode = MMC_BUSMODE_PUSHPULL; host->ios.power_mode = MMC_POWER_UP; //上电状态 host->ios.bus_width = MMC_BUS_WIDTH_1; host->ios.timing = MMC_TIMING_LEGACY; mmc_set_ios(host); //一开始用单线模式初始化,最终调用sunxi_mmc_set_ios,设置线宽,总线,时序 /* Set signal voltage to 3.3V */ __mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330); //最终调用sunxi_mmc_signal_voltage_switch /* * This delay should be sufficient to allow the power supply * to reach the minimum voltage. */ mmc_delay(10); host->ios.clock = host->f_init; host->ios.power_mode = MMC_POWER_ON; //工作状态 mmc_set_ios(host); /* * This delay must be at least 74 clock sizes, or 1 ms, or the * time required to reach a stable voltage. */ mmc_delay(10); mmc_host_clk_release(host); //没有定义CONFIG_MMC_CLKGATE 所有gateclock相关都是空操作 } void mmc_detect_change(struct mmc_host *host, unsigned long delay) { host->detect_change = 1; //wake_lock(&host->detect_wake_lock); if(!(host->caps&MMC_CAP_NEEDS_POLL)) wake_lock(&host->detect_wake_lock); //唤醒内核 mmc_schedule_delayed_work(&host->detect, delay); //主动执行队列mmc_rescan }
初始化emmc的程序已经完成,如果是sd卡,会中断或者查询方法调用检测sd卡的程序。
mmc_set_ios这个函数很重要,改变emmc的配置都在这里,会调用硬件底层相关函数。
emmc直接主动调用mmc_rescan。
以下忽略部分冗余和大量无关的逻辑判断的代码:
1 void mmc_rescan(struct work_struct *work) 2 { 3 struct mmc_host *host = container_of(work, struct mmc_host, detect.work); 4 int i; 5 bool extend_wakelock = false; 6 bool present = false; 7 8 if (host->rescan_disable) //rescan_disable = 0 9 return; 10 11 /* If there is a non-removable card registered, only scan once */ 12 if ((host->caps & MMC_CAP_NONREMOVABLE) && host->rescan_entered){ 13 wake_unlock(&host->detect_wake_lock); 14 return; 15 } 16 17 host->rescan_entered = 1; 18 19 host->detect_change = 0; 20 21 22 mmc_claim_host(host); 23 for (i = 0; i < ARRAY_SIZE(freqs); i++) { 24 if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) { 25 extend_wakelock = true; //mmc_rescan_try_freq真正的初始化 26 present = true; 27 break; //初始化成功立刻跳出 28 } 29 if (freqs[i] <= host->f_min) 30 break; 31 } 32 mmc_release_host(host); 33 34 if (extend_wakelock) 35 wake_lock_timeout(&host->detect_wake_lock, HZ / 2); 36 else 37 wake_unlock(&host->detect_wake_lock); 38 }
核心函数是mmc_rescan_try_freq,里面做了什么?
1 static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) 2 { 3 host->f_init = freq; 4 5 mmc_power_up(host); 6 7 /* 8 * Some eMMCs (with VCCQ always on) may not be reset after power up, so 9 * do a hardware reset if possible. 10 */ 11 mmc_hw_reset_for_init(host); //硬件复位,调用mmc_host_ops.hw_reset = sunxi_mmc_hw_reset 12 13 mmc_go_idle(host); //使mmc空闲 14 15 mmc_send_if_cond(host, host->ocr_avail); 16 17 /* Order‘s important: probe SDIO, then SD, then MMC */ 18 if (!mmc_attach_sdio(host)) //不是sdio,不会响应对应命令 19 return 0; 20 if (!mmc_attach_sd(host)) //不是sd,不会响应对应命令 21 return 0; 22 if (!mmc_attach_mmc(host)) //zho真正attach对应的emmc 23 return 0; 24 25 mmc_power_off(host); 26 return -EIO; 27 }
mmc_attach_mmc的代码在linux-3.10/drivers/mmc/core/mmc.c
以下忽略部分冗余和大量无关的逻辑判断的代码:
1 int mmc_attach_mmc(struct mmc_host *host) 2 { 3 int err; 4 u32 ocr; 5 6 mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); //bus开漏 7 8 err = mmc_send_op_cond(host, 0, &ocr); //配置ocr电源状态 9 10 mmc_attach_bus_ops(host); //设置bus_ops,mmc_bus_ops = mmc_ops_unsafe 11 12 13 host->ocr = mmc_select_voltage(host, ocr); 14 15 /* 16 * Detect and init the card. 17 */ 18 err = mmc_init_card(host, host->ocr, NULL); 19 20 mmc_release_host(host); 21 err = mmc_add_card(host->card); 22 mmc_claim_host(host); 23 return 0; 24 25 } 26 27 static int mmc_init_card(struct mmc_host *host, u32 ocr, 28 struct mmc_card *oldcard) 29 { 30 struct mmc_card *card; 31 int err, ddr = 0; 32 u32 cid[4]; 33 unsigned int max_dtr; 34 u32 rocr; 35 u8 *ext_csd = NULL; 36 37 38 mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN); 39 40 /* 41 * Since we‘re changing the OCR value, we seem to 42 * need to tell some cards to go back to the idle 43 * state. We wait 1ms to give cards time to 44 * respond. 45 * mmc_go_idle is needed for eMMC that are asleep 46 */ 47 mmc_go_idle(host); 48 49 /* The extra bit indicates that we support high capacity */ 50 err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr); //识别大容量 51 52 /* 53 * Fetch CID from card. 54 */ 55 err = mmc_all_send_cid(host, cid); //识别card id 56 57 /* 58 * Allocate card structure. 59 */ 60 card = mmc_alloc_card(host, &mmc_type); //重要,后续分析 61 62 63 card->type = MMC_TYPE_MMC; 64 card->rca = 1; 65 memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); 66 67 /* 68 * For native busses: set card RCA and quit open drain mode. 69 */ 70 71 err = mmc_set_relative_addr(card); 72 73 mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); 74 75 /* 76 * Fetch CSD from card. 77 */ 78 err = mmc_send_csd(card, card->raw_csd); 79 80 err = mmc_decode_csd(card); 81 82 err = mmc_decode_cid(card); 83 84 /* 85 * Select card, as all following commands rely on that. 86 */ 87 88 err = mmc_select_card(card); 89 90 /* 91 * Fetch and process extended CSD. 92 */ 93 94 err = mmc_get_ext_csd(card, &ext_csd); 95 96 err = mmc_read_ext_csd(card, ext_csd); 97 98 /* If doing byte addressing, check if required to do sector 99 * addressing. Handle the case of <2GB cards needing sector 100 * addressing. See section 8.1 JEDEC Standard JED84-A441; 101 * ocr register has bit 30 set for sector addressing. 102 */ 103 if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30))) 104 mmc_card_set_blockaddr(card); 105 106 /* Erase size depends on CSD and Extended CSD */ 107 mmc_set_erase_size(card); 108 109 /* 110 * Activate high speed (if supported) 111 */ 112 if (card->ext_csd.hs_max_dtr != 0) { 113 err = 0; 114 if (card->ext_csd.hs_max_dtr > 52000000 && 115 host->caps2 & MMC_CAP2_HS200) 116 err = mmc_select_hs200(card); 117 else if (host->caps & MMC_CAP_MMC_HIGHSPEED) 118 //err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 119 // EXT_CSD_HS_TIMING, 1, 120 // card->ext_csd.generic_cmd6_time); 121 err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 122 EXT_CSD_HS_TIMING, 1, 123 card->ext_csd.generic_cmd6_time, 124 true, true, true); 125 126 if (card->ext_csd.hs_max_dtr > 52000000 && 127 host->caps2 & MMC_CAP2_HS200) { 128 mmc_card_set_hs200(card); 129 mmc_set_timing(card->host, 130 MMC_TIMING_MMC_HS200); 131 } else { 132 mmc_card_set_highspeed(card); 133 mmc_set_timing(card->host, MMC_TIMING_MMC_HS); 134 } 135 } 136 137 /* 138 * Compute bus speed. 139 */ 140 max_dtr = (unsigned int)-1; 141 142 if (mmc_card_highspeed(card) || (mmc_card_hs200(card)|| mmc_card_hs400(card))) { 143 if (max_dtr > card->ext_csd.hs_max_dtr) 144 max_dtr = card->ext_csd.hs_max_dtr; 145 if (mmc_card_highspeed(card) && (max_dtr > 52000000)) 146 max_dtr = 52000000; 147 } else if (max_dtr > card->csd.max_dtr) { 148 max_dtr = card->csd.max_dtr; 149 } 150 151 mmc_set_clock(host, max_dtr); 152 //mmc_set_ios(host)一开始用单线模式初始化,最终调用sunxi_mmc_set_ios 153 //设置线宽,总线,时序 154 155 /* 156 * Indicate HS200 SDR mode (if supported). 157 */ 158 if (mmc_card_hs200(card)) { 159 u32 ext_csd_bits; 160 u32 bus_width = card->host->ios.bus_width; 161 162 163 if(host->caps2 & MMC_CAP2_HS400){ 164 //pr_info("************%s: %s,%d************\n", 165 // mmc_hostname(card->host),__FUNCTION__,__LINE__); 166 err = mmc_select_hs400(card); 167 } 168 169 170 if(mmc_card_hs400(card)){ 171 ext_csd_bits = EXT_CSD_DDR_BUS_WIDTH_8; 172 err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); //配置mmc电源 173 }else{ 174 ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ? 175 EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; 176 err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); 177 } 178 } 179 180 /* 181 * Enable HPI feature (if supported) 182 */ 183 if (card->ext_csd.hpi) { 184 err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, 185 EXT_CSD_HPI_MGMT, 1, 186 card->ext_csd.generic_cmd6_time); 187 188 189 card->ext_csd.hpi_en = 1; 190 } 191 192 host->card = card; 193 194 mmc_free_ext_csd(ext_csd); 195 return 0; 196 }
调用完mmc_attach_mmc,card和host已经准备就绪,怎么通知drv呢?当然需要device!
剩下mmc_alloc_card和mmc_add_card没有分析完,代码都在linux-3.10/drivers/mmc/core/bus.c
以下忽略部分冗余代码:
1 struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type) 2 { 3 struct mmc_card *card; 4 5 card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL); 6 if (!card) 7 return ERR_PTR(-ENOMEM); 8 9 card->host = host; 10 11 device_initialize(&card->dev); 12 13 card->dev.parent = mmc_classdev(host); 14 card->dev.bus = &mmc_bus_type; //dev.bus,device_attach优先选择bus->probe 15 card->dev.release = mmc_release_card; 16 card->dev.type = type; 17 18 return card; 19 } 20 21 /* 22 * This currently matches any MMC driver to any MMC card - drivers 23 * themselves make the decision whether to drive this card in their 24 * probe method. 25 */ 26 static int mmc_bus_match(struct device *dev, struct device_driver *drv) 27 { 28 return 1; //只要在这个总线就匹配成功 29 } 30 31 static int mmc_bus_probe(struct device *dev) 32 { 33 struct mmc_driver *drv = to_mmc_driver(dev->driver); 34 struct mmc_card *card = mmc_dev_to_card(dev); 35 36 return drv->probe(card); 37 } 38 39 static struct bus_type mmc_bus_type = { 40 .name = "mmc", 41 .dev_attrs = mmc_dev_attrs, 42 .match = mmc_bus_match, 43 .uevent = mmc_bus_uevent, 44 .probe = mmc_bus_probe, 45 .remove = mmc_bus_remove, 46 .pm = &mmc_bus_pm_ops, 47 }; 48 49 int mmc_register_bus(void) //在linux-3.10/drivers/mmc/core/core.c里subsys_initcall(mmc_init)被调用 50 { 51 return bus_register(&mmc_bus_type); 52 } 53 54 int mmc_add_card(struct mmc_card *card) 55 { 56 int ret; 57 const char *type; 58 const char *uhs_bus_speed_mode = ""; 59 static const char *const uhs_speeds[] = { 60 [UHS_SDR12_BUS_SPEED] = "SDR12 ", 61 [UHS_SDR25_BUS_SPEED] = "SDR25 ", 62 [UHS_SDR50_BUS_SPEED] = "SDR50 ", 63 [UHS_SDR104_BUS_SPEED] = "SDR104 ", 64 [UHS_DDR50_BUS_SPEED] = "DDR50 ", 65 }; 66 67 dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); 68 69 switch (card->type) { 70 case MMC_TYPE_MMC: 71 type = "MMC"; 72 break; 73 .... 74 .... 75 default: 76 type = "?"; 77 break; 78 } 79 80 if (mmc_sd_card_uhs(card) && 81 (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds))) 82 uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed]; 83 84 85 pr_info("%s: new %s%s%s%s%s card at address %04x\n", 86 mmc_hostname(card->host), 87 mmc_card_uhs(card) ? "ultra high speed " : 88 (mmc_card_highspeed(card) ? "high speed " : ""), 89 mmc_card_hs400(card) ? "HS400 " : 90 (mmc_card_hs200(card) ? "HS200 " : ""), 91 mmc_card_ddr_mode(card) ? "DDR " : "", 92 uhs_bus_speed_mode, type, card->rca); 93 94 mmc_init_context_info(card->host); //emmc队列等信息(block设备会用到) 95 96 ret = device_add(&card->dev); //等待driver 97 98 mmc_card_set_present(card); 99 100 return 0; 101 } 102 103 /** 104 * mmc_register_driver - register a media driver 105 * @drv: MMC media driver 106 */ 107 int mmc_register_driver(struct mmc_driver *drv) 108 { 109 drv->drv.bus = &mmc_bus_type; 110 return driver_register(&drv->drv); 111 }
现在device这边已经准备就绪,就差某个drv调用mmc_register_driver进行match,最后调用某个drv->probe。
其实在linux-3.10/drivers/mmc/card/block.c就调用了mmc_register_driver。
以下忽略部分冗余代码:
1 static struct mmc_driver mmc_driver = { 2 .drv = { 3 .name = "mmcblk", 4 }, 5 .probe = mmc_blk_probe, 6 .remove = mmc_blk_remove, 7 .suspend = mmc_blk_suspend, 8 .resume = mmc_blk_resume, 9 }; 10 11 static int __init mmc_blk_init(void) 12 { 13 int res; 14 15 max_devices = 256 / perdev_minors; //perdev_minors = 8 16 17 res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); //注册块设备 18 19 res = mmc_register_driver(&mmc_driver); //我们要找的目标函数 20 21 return 0; 22 } 23 24 static void __exit mmc_blk_exit(void) 25 { 26 mmc_unregister_driver(&mmc_driver); 27 unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); 28 } 29 30 module_init(mmc_blk_init); 31 module_exit(mmc_blk_exit); 32 33 static int mmc_blk_probe(struct mmc_card *card) 34 { 35 struct mmc_blk_data *md, *part_md; 36 char cap_str[10]; 37 38 md = mmc_blk_alloc(card); 39 40 string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, 41 cap_str, sizeof(cap_str)); 42 pr_info("%s: %s %s %s %s\n", 43 md->disk->disk_name, mmc_card_id(card), mmc_cardrd_name(card), 44 cap_str, md->read_only ? "(ro)" : ""); 45 46 if (mmc_blk_alloc_parts(card, md)) 47 goto out; 48 49 mmc_set_drvdata(card, md); 50 mmc_fixup_device(card, blk_fixups); 51 52 mmc_add_disk(md); 53 54 list_for_each_entry(part_md, &md->part, part) { 55 mmc_add_disk(part_md); 56 57 } 58 return 0; 59 }
这里暂时没时间分析block.c里面的函数了,是比较复杂。
总结emmc初始化流程:
sunxi_mmc_probe---->mmc_alloc_host---->mmc_add_host---->mmc_start_host---->mmc_rescan---->mmc_rescan_try_freq
---->mmc_attach_mmc---->mmc_init_card---->mmc_alloc_card---->mmc_add_card + mmc_blk_init---->mmc_blk_probe......
标签:
原文地址:http://www.cnblogs.com/kevinhwang/p/5835520.html