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

mmc: core: Don't try UHS-I mode if 4-bit mode isn't supported

Per SD specification physical layer v4.0, section 3.9.4, it
says "UHS-I supports only 4-bit mode. Host shall select 4-bit
mode by ACMD6. However mmc_sd_init_uhs_card() still go ahead
to initialize the cards anyway, whether card or host won't
support 4-bit mode.

This breaks the platforms which could support UHS-I mode but on
some certain boards only support 1-bit mode with a UHS-I card inserted,
as all the tuning process is broken due to this. Alternatively, we
should check the return value from mmc_set_bus_width() to see if host
could finish the request to switch the bus width on its side. But that
needs more thing to do than this patch that just bails out early to try
high speed mode if 4-bit mode isn't available for whatever reason. And
this patch could also fix the same problem for sdio since R4_18V_PRESENT
won't be set for ocr when mmc_sdio_init_card() finds mmc_host_uhs()
is false.

Note that this patch doesn't keep the checking of card->scr.sda_spec3
and comparing card->scr.bus_widths with SD_SCR_BUS_WIDTH_4 within
mmc_sd_init_uhs_card() since if the sd cards response with SD_ROCR_S18A,
it definitely supports UHS-I mode, which implicitly means these checkings
are always true.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>

authored by

Shawn Lin and committed by
Ulf Hansson
d6743a8a 812dd020

+7 -12
+2 -1
drivers/mmc/core/host.h
··· 56 56 return host->caps & 57 57 (MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | 58 58 MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | 59 - MMC_CAP_UHS_DDR50); 59 + MMC_CAP_UHS_DDR50) && 60 + host->caps & MMC_CAP_4_BIT_DATA; 60 61 } 61 62 62 63 static inline bool mmc_card_hs200(struct mmc_card *card)
+5 -11
drivers/mmc/core/sd.c
··· 582 582 int err; 583 583 u8 *status; 584 584 585 - if (!card->scr.sda_spec3) 586 - return 0; 587 - 588 585 if (!(card->csd.cmdclass & CCC_SWITCH)) 589 586 return 0; 590 587 ··· 590 593 return -ENOMEM; 591 594 592 595 /* Set 4-bit bus width */ 593 - if ((card->host->caps & MMC_CAP_4_BIT_DATA) && 594 - (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { 595 - err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); 596 - if (err) 597 - goto out; 596 + err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); 597 + if (err) 598 + goto out; 598 599 599 - mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); 600 - } 600 + mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4); 601 601 602 602 /* 603 603 * Select the bus speed mode depending on host ··· 1027 1033 } 1028 1034 1029 1035 /* Initialization sequence for UHS-I cards */ 1030 - if (rocr & SD_ROCR_S18A) { 1036 + if (rocr & SD_ROCR_S18A && mmc_host_uhs(host)) { 1031 1037 err = mmc_sd_init_uhs_card(card); 1032 1038 if (err) 1033 1039 goto free_card;