When the mmc_start_host is invoked to enable a EMMC host
void Mmc_start_host (struct mmc_host *host)
{
Host->f_init = Max (freqs[0], host->f_min);
host->rescan_disable = 0;
Host->ios.power_mode = mmc_power_undefined;
MMC_GPIOD_REQUEST_CD_IRQ (host);
_mmc_detect_change (host, 0, false);
}
In Mmc_start_host, _mmc_detect_change is used to start the scan connected to the MMC on this host device
static void _mmc_detect_change (struct mmc_host *host, unsigned long delay,
BOOL CD_IRQ)
{
/*
* If The device is configured as wakeup, we prevent a new sleep for
* 5 s to give provision for user spaces to consume the event.
*/
if (CD_IRQ &&! ( Host->caps & Mmc_cap_needs_poll) &&
Device_can_wakeup (Mmc_dev (host))
Pm_wakeup_event (Mmc_dev (host), 5000);
Host->detect_change = 1;
Mmc_schedule_delayed_work (&host->detect, delay);
}
Place Host->detect_change, and call Mmc_schedule_delayed_work to scan device
static int mmc_schedule_delayed_work (struct delayed_work *work,
unsigned long delay)
{
Return Queue_delayed_work (SYSTEM_FREEZABLE_WQ, work, delay);
}
But this host->detect this work corresponding Func is assigned in the following way
The assignment in Mmc_alloc_host is as follows:
Init_delayed_work (&host->detect, Mmc_rescan);
So when you call Mmc_schedule_delayed_work, you call the Mmc_rescan
The most wanted in Mmc_rescan is as follows:
for (i = 0; i < array_size (freqs); i++) {
if (!mmc_rescan_try_freq (host, Max (freqs[i), host->f_min))
Break
if (Freqs[i] <= host->f_min)
Break
}
static const unsigned freqs[] = {400000, 300000, 200000, 100000};
Can see each host up to scan four times, find device on the current FREQS exit
static int mmc_rescan_try_freq (struct mmc_host *host, unsigned freq)
{
Host->f_init = freq;
/*
* Some Emmcs (with VCCQ-always on)
* Do a hardware reset if possible.
*/
Mmc_hw_reset_for_init (host);
/*
* Sdio_reset sends CMD52 to reset card. Since We do not know
* If the is being re-initialized, just send it. CMD52
* should be ignored by SD/EMMC cards.
* Skip it if we already know that we did not support SDIO commands
*/
if (!) ( HOST->CAPS2 & Mmc_cap2_no_sdio))
Sdio_reset (host);
Mmc_go_idle (host);
if (!) ( HOST->CAPS2 & MMC_CAP2_NO_SD))
Mmc_send_if_cond (host, host->ocr_avail);
/* order ' s important:probe SDIO, then SD, then MMC * *
if (!) ( HOST->CAPS2 & Mmc_cap2_no_sdio))
if (!mmc_attach_sdio (host))
return 0;
if (!) ( HOST->CAPS2 & MMC_CAP2_NO_SD))
if (!MMC_ATTACH_SD (host))
return 0;
if (!) ( HOST->CAPS2 & Mmc_cap2_no_mmc))
if (!MMC_ATTACH_MMC (host))
return 0;
Mmc_power_off (host);
Return-eio;
}
Can see from the Mmc_rescan_try_freq, eMMC host can hang three kinds of equipment, these three kinds of sets can only hang one can not coexist, and have a certain priority
Where priority is: Mmc->sd->sdio
Take Mmc_attach_sdio->mmc_add_card as an example to print the following log
[11.565233] mmc_host Mmc2:bus speed (slot 0) = 25000000Hz (slot req 2500000)
+ + Setting up Mdev
[11.587289] mmc2:queuing unknown CIS tuple 0x91 (3 bytes)
[11.599206] mmc2:new SDIO card at address 0001
In Mmc_rescan_try_freq, HOST->CAPS2 & Mmc_cap2_no_sdio are used to determine whether there is a SDIO, that is, if you do not add this mmc_of_parse in flag the default call MMC_ Attach_sdio. The Mmc_of_parse is the DTS corresponding to the parse host, which means that in DTS, if there is no
if (Of_property_read_bool (NP, "No-sdio"))
HOST->CAPS2 |= Mmc_cap2_no_sdio;
Call Mmc_attach_sdio on the default
int mmc_of_parse (struct mmc_host *host)
{
if (Of_property_read_bool (NP, "DISABLE-WP"))
HOST->CAPS2 |= Mmc_cap2_no_write_protect;
* * The comment on CD inversion above * *
if (ro_cap_invert ^ ro_gpio_invert)
HOST->CAPS2 |= Mmc_cap2_ro_active_high;
if (Of_property_read_bool (NP, "Cap-sd-highspeed"))
Host->caps |= Mmc_cap_sd_highspeed;
if (Of_property_read_bool (NP, "Cap-mmc-highspeed"))
Host->caps |= Mmc_cap_mmc_highspeed;
if (Of_property_read_bool (NP, "Sd-uhs-sdr12"))
Host->caps |= Mmc_cap_uhs_sdr12;
if (Of_property_read_bool (NP, "Sd-uhs-sdr25"))
Host->caps |= Mmc_cap_uhs_sdr25;
if (Of_property_read_bool (NP, "Sd-uhs-sdr50"))
Host->caps |= Mmc_cap_uhs_sdr50;
if (Of_property_read_bool (NP, "sd-uhs-sdr104"))
Host->caps |= mmc_cap_uhs_sdr104;
if (Of_property_read_bool (NP, "Sd-uhs-ddr50"))
Host->caps |= Mmc_cap_uhs_ddr50;
if (Of_property_read_bool (NP, "Cap-power-off-card"))
Host->caps |= Mmc_cap_power_off_card;
if (Of_property_read_bool (NP, "Cap-mmc-hw-reset"))
Host->caps |= Mmc_cap_hw_reset;
if (Of_property_read_bool (NP, "CAP-SDIO-IRQ"))
Host->caps |= Mmc_cap_sdio_irq;
if (Of_property_read_bool (NP, "Full-pwr-cycle"))
HOST->CAPS2 |= mmc_cap2_full_pwr_cycle;
if (Of_property_read_bool (NP, "Keep-power-in-suspend"))
Host->pm_caps |= Mmc_pm_keep_power;
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.