在mmc.c文件中,有两个很重要的总线操作集变量,分别为:
用于可热拔插设备的mmc_ops:
static const struct mmc_bus_ops mmc_ops = { .remove = mmc_remove, .detect = mmc_detect, .suspend = NULL, .resume = NULL, .power_restore = mmc_power_restore, .alive = mmc_alive, .shutdown = mmc_shutdown, };与不可热拔插设备的: static const struct mmc_bus_ops mmc_ops_unsafe = { .remove = mmc_remove, .detect = mmc_detect, .suspend = mmc_suspend, .resume = mmc_resume, .runtime_suspend = mmc_runtime_suspend, .runtime_resume = mmc_runtime_resume, .power_restore = mmc_power_restore, .alive = mmc_alive, .shutdown = mmc_shutdown, };通过代码可以发现,mmc_ops函数指针指向的函数,在mmc_ops_unsafe变量中都存在,所以这里只分析mmc_ops_unsafe变量中的函数。一、mmc_remove
/* * Host is being removed. Free up the current card. */ static void mmc_remove(struct mmc_host *host) { BUG_ON(!host); BUG_ON(!host->card); mmc_remove_card(host->card); host->card = NULL; }注释:host被移除,释放当前卡(最后一行代码)。该函数调用了mmc_remove_card去实现释放host的功能,如下:
/* * Unregister a new MMC card with the driver model, and * (eventually) free it. */ void mmc_remove_card(struct mmc_card *card) { #ifdef CONFIG_DEBUG_FS mmc_remove_card_debugfs(card); #endif if (mmc_card_present(card)) { if (mmc_host_is_spi(card->host)) { pr_info("%s: SPI card removed\n", mmc_hostname(card->host)); } else { pr_info("%s: card %04x removed\n", mmc_hostname(card->host), card->rca); } device_del(&card->dev); } put_device(&card->dev); }该函数先判断设备是不是存在,如果存在就调用内核函数device_del将设备从系统删除,然后再调用put_device将设备的引用计数减一。mmc_remove总结:从内核删除设备,并将host从card移除。
二、mmc_detect
/* * Card detection callback from host. */ static void mmc_detect(struct mmc_host *host) { int err; BUG_ON(!host); BUG_ON(!host->card); mmc_get_card(host->card); /* * Just check if our card has been removed. */ err = _mmc_detect_card_removed(host); mmc_put_card(host->card); if (err) { mmc_remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); mmc_release_host(host); } } 注释:卡探测时host的回调函数。第11行:函数名看上去是获取一个card,实际是获取到一个host:
/* * This is a helper function, which fetches a runtime pm reference for the * card device and also claims the host. */ void mmc_get_card(struct mmc_card *card) { pm_runtime_get_sync(&card->dev); mmc_claim_host(card->host); }第11行与第18行对应。第16行:通过host判断当前卡是否被移除(1:存在,0:移除)。
mmc_detect总结:判断当前是否有设备存在,并设置对应的参数。
三、mmc_suspend
/* * Suspend callback */ static int mmc_suspend(struct mmc_host *host) { int err; err = _mmc_suspend(host, true); if (!err) { pm_runtime_disable(&host->card->dev); pm_runtime_set_suspended(&host->card->dev); } return err; }这个函数借助于 _mmc_suspend函数实现主要功能,而_mmc_suspend函数在linux关机时emmc驱动处理流程这篇文章的第十一节详细描述了。
四、mmc_resume
/* * Callback for resume. */ static int mmc_resume(struct mmc_host *host) { int err = 0; if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) { err = _mmc_resume(host); pm_runtime_set_active(&host->card->dev); pm_runtime_mark_last_busy(&host->card->dev); } pm_runtime_enable(&host->card->dev); return err; }该函数主要借助于 _mmc_resume函数实现主要功能,而_mmc_resume函数在linux关机时emmc驱动处理流程这篇文章的第九节详细描述了。五、mmc_runtime_suspend
/* * Callback for runtime_suspend. */ static int mmc_runtime_suspend(struct mmc_host *host) { int err; if (!(host->caps & MMC_CAP_AGGRESSIVE_PM)) return 0; err = _mmc_suspend(host, true); if (err) pr_err("%s: error %d doing aggessive suspend\n", mmc_hostname(host), err); return err; }注释:运行时挂载的回调函数。该函数主要借助于_mmc_suspend函数实现主要功能,而_mmc_resume函数在linux关机时emmc驱动处理流程这篇文章的第九节详细描述了。
六、mmc_runtime_resume
/* * Callback for runtime_resume. */ static int mmc_runtime_resume(struct mmc_host *host) { int err; if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME))) return 0; err = _mmc_resume(host); if (err) pr_err("%s: error %d doing aggessive resume\n", mmc_hostname(host), err); return 0; }该函数主要借助于 _mmc_resume函数实现主要功能,而_mmc_resume函数在linux关机时emmc驱动处理流程这篇文章的第九节详细描述了。七、mmc_power_restore
static int mmc_power_restore(struct mmc_host *host) { int ret; host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); mmc_claim_host(host); ret = mmc_init_card(host, host->card->ocr, host->card); mmc_release_host(host); return ret; } 第5行:关闭高速模式; 第6行和第8行:获取和释放一个host; 第7行:初始化一个card,该函数在 linux关机时emmc驱动处理流程这篇文章的第十节详细描述了。 总结:该函数用来在上电时,初始化一个设备对象。
八、mmc_alive
/* * Card detection - card is alive. */ static int mmc_alive(struct mmc_host *host) { return mmc_send_status(host->card, NULL); }注释:判断卡是不是活动状态。这里调用mmc_send_status函数判断卡是否是可用的,返回0表示可用。
九、mmc_shutdown
/* * Shutdown callback */ static int mmc_shutdown(struct mmc_host *host) { int err = 0; /* * In a specific case for poweroff notify, we need to resume the card * before we can shutdown it properly. */ if (mmc_can_poweroff_notify(host->card) && !(host->caps2 & MMC_CAP2_FULL_PWR_CYCLE)) err = _mmc_resume(host); if (!err) err = _mmc_suspend(host, false); return err; }根据函数名字知道,该函数实现了设备的关闭功能。该函数在 linux关机时emmc驱动处理流程这篇文章的第十节详细描述了,感兴趣可以跳转过去看下。 那么mmc总线ops的结构就这些内容了,以后如果用到,我们就清除它的功能了。