Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: core: Don't do eMMC HW reset when resuming the eMMC card

In case if a pwrseq-emmc has been bound to the host, a call to
mmc_power_up() triggers an eMMC HW reset via the pwrseq_emmc's
->post_power_on() callback. This isn't really what we want, as
mmc_power_up() is called each time when resuming the card.

As a matter of fact, the current approach may also violate the eMMC spec,
as the involved delays managed in pwrseq_emmc assumes both VCC and VCCQ has
been turned on, which isn't the case for VCCQ, unless the regulator is
always on.

Fix this behaviour by aligning to the same procedure used when the mmc host
implements the ->hw_reset() callback and has the MMC_CAP_HW_RESET flag set.
In this way the eMMC HW reset is issued at card detection scan, to cope
with bogus bootloaders and in the error recovery path via the mmc specific
bus_ops->reset() callback.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>

+5 -1
+2
drivers/mmc/core/core.c
··· 2597 2597 2598 2598 static void mmc_hw_reset_for_init(struct mmc_host *host) 2599 2599 { 2600 + mmc_pwrseq_reset(host); 2601 + 2600 2602 if (!(host->caps & MMC_CAP_HW_RESET) || !host->ops->hw_reset) 2601 2603 return; 2602 2604 host->ops->hw_reset(host);
+2
drivers/mmc/core/mmc.c
··· 27 27 #include "mmc_ops.h" 28 28 #include "quirks.h" 29 29 #include "sd_ops.h" 30 + #include "pwrseq.h" 30 31 31 32 #define DEFAULT_CMD6_TIMEOUT_MS 500 32 33 ··· 2128 2127 } else { 2129 2128 /* Do a brute force power cycle */ 2130 2129 mmc_power_cycle(host, card->ocr); 2130 + mmc_pwrseq_reset(host); 2131 2131 } 2132 2132 return mmc_init_card(host, card->ocr, card); 2133 2133 }
+1 -1
drivers/mmc/core/pwrseq_emmc.c
··· 56 56 } 57 57 58 58 static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = { 59 - .post_power_on = mmc_pwrseq_emmc_reset, 59 + .reset = mmc_pwrseq_emmc_reset, 60 60 }; 61 61 62 62 static int mmc_pwrseq_emmc_probe(struct platform_device *pdev)