看mmc之前先看看mmc在Linux中的位置
图片来自:http://free-electrons.com/doc/block_drivers.pdf
从上图可以看出,MMC与SCSI,IDE一样都属于block driver
上面这张图清晰的描述了mmc subsystem的结构,接下来我们分开来看
drivers/mmc/host/ 下面存放mmc host driver, 这些driver完成芯片的初始化之后会调用mmc_add_host向mmc core层注册这个host.
mmc_add_host (core/host.c)
mmc_start_host (core/core.c)
mmc_detect_change (core/core.c)
mmc_rescan (core/core.c)
mmc_rescan_try_freq (core/core.c)
mmc_attach_sd (core/sd.c): starting point for SD card init
mmc_sd_init_card (core/sd.c)
mmc_alloc_card (core/bus.c)
mmc_add_card (core/bus.c)
device_add
这个调用关系中,主要是mmc_alloc_card和mmc_add_card
320 /*
321 * Allocate and initialise a new MMC card structure.
322 */
323 struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
324 {
325 struct mmc_card *card;
326
327 card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
328 if (!card)
329 return ERR_PTR(-ENOMEM);
330
331 card->host = host;
332
333 device_initialize(&card->dev);
334
335 card->dev.parent = mmc_classdev(host);
336 card->dev.bus = &mmc_bus_type;
337 card->dev.release = mmc_release_card;
338 card->dev.type = type;
339
340 spin_lock_init(&card->bkops_info.bkops_stats.lock);
341 spin_lock_init(&card->wr_pack_stats.lock);
342
343 return card;
344 }
263 static struct bus_type mmc_bus_type = {
264 .name = "mmc",
265 .dev_attrs = mmc_dev_attrs,
266 .match = mmc_bus_match,
267 .uevent = mmc_bus_uevent,
268 .probe = mmc_bus_probe,
269 .remove = mmc_bus_remove,
270 .shutdown = mmc_bus_shutdown,
271 .pm = &mmc_bus_pm_ops,
272 };这样当mmc_add_card调用device_add的时候,根据linux device driver模型,会自动去找bus上对应的driver。
那首先会调用match去判断是否匹配
60 static int mmc_bus_match(struct device *dev, struct device_driver *drv)
61 {
62 return 1;
63 }108 static int mmc_bus_probe(struct device *dev)
109 {
110 struct mmc_driver *drv = to_mmc_driver(dev->driver);
111 struct mmc_card *card = mmc_dev_to_card(dev);
112
113 return drv->probe(card);
114 }
这个driver在mmc/card/block.c中注册,到这里,上图中host和core基本介绍完了
3597 static struct mmc_driver mmc_driver = {
3598 .drv = {
3599 .name = "mmcblk",
3600 },
3601 .probe = mmc_blk_probe,
3602 .remove = mmc_blk_remove,
3603 .suspend = mmc_blk_suspend,
3604 .resume = mmc_blk_resume,
3605 .shutdown = mmc_blk_shutdown,
3606 };
3607
3608 static int __init mmc_blk_init(void)
3609 {
3610 int res;
3611
3612 if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
3613 pr_info("mmcblk: using %d minors per device\n", perdev_minors);
3614
3615 max_devices = 256 / perdev_minors;
3616
3617 res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
3618 if (res)
3619 goto out;
3620
3621 res = mmc_register_driver(&mmc_driver);
3622 if (res)
3623 goto out2;
3624
3625 return 0;
3626 out2:
3627 unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
3628 out:
3629 return res;
3630 }
288 int mmc_register_driver(struct mmc_driver *drv)
289 {
290 drv->drv.bus = &mmc_bus_type;
291 return driver_register(&drv->drv);
292 }
mmc_blk_probe
原文:http://blog.csdn.net/successcw/article/details/19913691