思想是很有帮助的。mmc分为控制器和mmc卡,所以也有两个驱动
1. core文件夹的core.c先创建一个工作队列,再注册总线和类。
点击(此处)折叠或打开
- 
				static int __init mmc_init(void)
 
- 
				{
 
- int ret;
- 
				    workqueue = alloc_ordered_workqueue("kmmcd", 0);
 
- 
				    if (!workqueue)
 
- return -ENOMEM;
- 
				    ret = mmc_register_bus();
 
- 
				    if (ret)
 
- goto destroy_workqueue;
- 
				    ret = mmc_register_host_class();
 
- 
				    if (ret)
 
- goto unregister_bus;
- 
				    ret = sdio_register_bus();
 
- 
				    if (ret)
 
- goto unregister_host_class;
- return 0;
- 
				unregister_host_class:
 
- 
				    mmc_unregister_host_class();
 
- 
				unregister_bus:
 
- 
				    mmc_unregister_bus();
 
- 
				destroy_workqueue:
 
- destroy_workqueue(workqueue);
- 
				    return ret;
 
- }
点击(此处)折叠或打开
- 
				static int __init mmc_blk_init(void)
 
- 
				{
 
- 
				    int res;
 
- 
				
 
- 
				    if (perdev_minors != CONFIG_MMC_BLOCK_MINORS)
 
- 
				        pr_info("mmcblk: using %d minors per device\n", perdev_minors);
 
- 
				
 
- 
				    max_devices = 256 / perdev_minors;
 
- 
				
 
- 
				    res = register_blkdev(MMC_BLOCK_MAJOR, "mmc");
 
- 
				    if (res)
 
- 
				        goto out;
 
- 
				
 
- 
				    res = mmc_register_driver(&mmc_driver);
 
- 
				    if (res)
 
- 
				        goto out2;
 
- 
				
 
- 
				    return 0;
 
- 
				 out2:
 
- 
				    unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
 
- 
				 out:
 
- 
				    return res;
 
- }
点击(此处)折叠或打开
- static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
点击(此处)折叠或打开
- 
				struct sdhci_s3c {
 
- 
				    struct sdhci_host    *host;    //新创建的host控制器
 
- 
				    struct platform_device    *pdev;
 
- 
				    struct resource        *ioarea;
 
- 
				    struct s3c_sdhci_platdata *pdata;
 
- 
				    unsigned int        cur_clk;
 
- 
				    int            ext_cd_irq;
 
- 
				    int            ext_cd_gpio;
 
- 
				
 
- 
				    struct clk        *clk_io;
 
- 
				    struct clk        *clk_bus[MAX_BUS_CLK];
 
- };
其实sdhci_alloc_host分配了sdhci_host和mmc_host两个结构体,并将sdhci_host的mmc成员指向mmc_host。
点击(此处)折叠或打开
- 
				host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
 点击(此处)折叠或打开 - 
								host->ioaddr = ioremap_nocache(res->start, resource_size(res));
 
- 
								if (!host->ioaddr) {
 
- 
								dev_err(dev, "failed to map registers\n");
 
- 
								ret = -ENXIO;
 
- 
								goto err_req_regs;
 
- 
								}
 
- 
								/* Ensure we have minimal gpio selected CMD/CLK/Detect */
 
- 
								if (pdata->cfg_gpio)
 
- 
								pdata->cfg_gpio(pdev, pdata->max_width);
 
- 
								
 
- 
								host->hw_name = "samsung-hsmmc";
 
- 
								host->ops = &sdhci_s3c_ops;
 
- 
								host->quirks = 0;
 
- host->irq = irq;
 
 
- 
								host->ioaddr = ioremap_nocache(res->start, resource_size(res));
7. 总结:
其实这个host设备和字符驱动中的cdev作用差不多,仅用platform_driver与设备匹配后再在cdev的fops中做真正的硬件工作。
所以这个添加的host也是做真正的工作:探测到mmc卡并初始化一个card结构体挂载到总线上。总线用最前面的块设备驱动来匹配,
最终肯定是用一个块设备来表示卡。那么块设备驱动中的函数是怎样调用到这个控制器host的函数呢?
很简单,仅需要用一个指针指向host就可以了。
还有,在platform_driver的probe中添加到内核的控制器设备host添加到哪里了?它又是如何完成上面的探测工作呢?
由下面,host仅需要探测卡和发送数据命令即可,工作简单,所以就放在/sys/class/mmc/下的mmc0文件。而不需要把控制器也
挂载到总线上,因为它不需要什么驱动,不像I2C控制器也挂载在总线上并要驱动。
探测工作主要依靠工作队列,中断,定时器来完成的,不需要深究。
点击(此处)折叠或打开
- 
				/**
 
- 
				 *    mmc_add_host - initialise host hardware
 
- 
				 *    @host: mmc host
 
- 
				 *
 
- 
				 *    Register the host with the driver model. The host must be
 
- 
				 *    prepared to start servicing requests before this function
 
- 
				 *    completes.
 
- 
				 */
 
- 
				int mmc_add_host(struct mmc_host *host)
 
- 
				{
 
- 
				    int err;
 
- 
				
 
- 
				    WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
 
- 
				        !host->ops->enable_sdio_irq);
 
- 
				
 
- 
				    err = device_add(&host->class_dev);
 
- 
				    if (err)
 
- 
				        return err;
 
- 
				
 
- 
				    led_trigger_register_simple(dev_name(&host->class_dev), &host->led);
 
- 
				
 
- 
				#ifdef CONFIG_DEBUG_FS
 
- 
				    mmc_add_host_debugfs(host);
 
- 
				#endif
 
- 
				
 
- 
				    mmc_start_host(host);
 
- 
				    register_pm_notifier(&host->pm_notify);
 
- 
				
 
- 
				    return 0;
 
- }
