When we are writing MMC host driver, it is inevitable to call Mmc_alloc_host this kernel interface, it not only for the host application allocated memory, and will do some initialization, now posted code:
struct mmc_host *mmc_alloc_host (int extra, struct device *dev) {... host = Kzalloc (sizeof (struct mmc_host) + extra, Gfp_kernel);
Application allocation memory if (!host) return NULL;
Spin_lock (&mmc_host_lock);
Err = Idr_get_new (&MMC_HOST_IDR, Host, &host->index);
Spin_unlock (&mmc_host_lock);
if (err) goto free;
Dev_set_name (&host->class_dev, "mmc%d", Host->index);
host->parent = Dev;
host->class_dev.parent = Dev;
Host->class_dev.class = &mmc_host_class;
Device_initialize (&host->class_dev);
Mmc_host_clk_init (host);
Spin_lock_init (&host->lock);
Init_waitqueue_head (&HOST->WQ); Wake_lock_init (&host->detect_wake_lock, Wake_lock_suspend, kasprintf (Gfp_kernel, "%s_detect", Mmc_hostname (
Host))); Init_delayed_work (&host->detect, Mmc_rescan);
Initializes the delay work, which is to detect the insertion of mmc/sd/sdio work.
#ifdef config_pm host->pm_notify.notifier_call = mmc_pm_notify; #endif/* By default, hosts does not support Sgio or Large requests.
* They have to set this according to their abilities.
* * Host->max_segs = 1;
Host->max_seg_size = page_cache_size;
Host->max_req_size = page_cache_size;
Host->max_blk_size = 512;
Host->max_blk_count = page_cache_size/512;
return host;
Free:kfree (host);
return NULL;
}
Then when we initialize the MMC host, we need to call Mmc_add_host to register the MMC host with the kernel
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);
Registration device 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_host_clk_sysfs_init (host); Mmc_start_host (host); Open host, let's take a look at what the behavior of this function really is if (!
Host->pm_flags & Mmc_pm_ignore_pm_notify)) Register_pm_notifier (&host->pm_notify);
return 0; Mmc_start_host (host) posted the following code: void Mmc_start_host (struct mmc_host *host) {Mmc_power_off (host); "Void Mmc_power_off (str
UCT mmc_host *host) {int err = 0;
Mmc_host_clk_hold (host); Host->ios.clock = 0;//Clock frequency set to 0 HOST->IOS.VDD = 0;//because it is just registered host, the host voltage is set to 0 first .../* Reset OCR mask to is T He highest possible voltage supported for * This MMC host.
This value is used at the next power up. * * HOST->OCR = 1 << (FLS (Host->ocr_avail)-1);
if (!MMC_HOST_IS_SPI (host)) {host->ios.bus_mode = Mmc_busmode_opendrain;
Host->ios.chip_select = Mmc_cs_dontcare; Host->ios.power_mode = mmc_power_off;//Power off mode host->ios.bus_width = Mmc_bus_width_1;//data bus width is set to 1bit HOST-&G
t;ios.timing = mmc_timing_legacy;
Mmc_set_ios (host);//calls the callback function implemented by the MMC host. * * Some configurations, such as the 802.11 SDIO card in the OLPC * XO-1.5, require a short delay after Poweroff befo
Re the card * Can is successfully turned on again.
* * Mmc_delay (1);
Mmc_host_clk_release (host);
} "Mmc_detect_change (host, 0);
"Void Mmc_detect_change (struct mmc_host *host, unsigned long delay) {#ifdef config_mmc_debug unsigned long flags;
Spin_lock_irqsave (&host->lock, flags);
WARN_ON (host->removed);
Spin_unlock_irqrestore (&host->lock, flags);
#endif host->detect_change = 1;
Wake_lock (&host->detect_wake_lock); Mmc_schedule_delayed_work (&host->deteCT, delay); Submit schedule delay work, the delay is 0 good, this means that will immediately call the Mmc_scan function, start probing the SD card, or Mmc/sdio card.
For some Sdio function card, not pluggable, this is the detection Sdio function card start point.
} 】 }