diff options
author | Jean-Jacques Hiblot | 2017-04-20 10:54:25 -0500 |
---|---|---|
committer | Jean-Jacques Hiblot | 2017-07-13 03:03:57 -0500 |
commit | 586dca26fb8865145f40c48baa33d83b950eb86a (patch) | |
tree | ec93b3d8891c7c140ff64315110a28a29f862bbf | |
parent | 91370262d74b14b41de8492f23decc0dc6076b1f (diff) | |
download | u-boot-586dca26fb8865145f40c48baa33d83b950eb86a.tar.gz u-boot-586dca26fb8865145f40c48baa33d83b950eb86a.tar.xz u-boot-586dca26fb8865145f40c48baa33d83b950eb86a.zip |
drivers: mmc: fall back to lower performance modes if HS200 or DDR52 fail during the initialization
commit e14ac74b66e3 ("drivers: mmc: fall back to lower performance modes if HS200 or DDR52 fail during the initialization") branch ti-u-boot-2017.01
If the initialization fails when trying to use HS200 or DDR52, then remove
the failing capability for the capabilities supported by the host and
restart the whole initialization process.
Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com>
-rw-r--r-- | drivers/mmc/mmc.c | 50 | ||||
-rw-r--r-- | include/mmc.h | 1 |
2 files changed, 32 insertions, 19 deletions
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 0670b16a2e..82a023190b 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -386,7 +386,7 @@ static int mmc_go_idle(struct mmc *mmc) | |||
386 | 386 | ||
387 | static int mmc_host_uhs(struct mmc *mmc) | 387 | static int mmc_host_uhs(struct mmc *mmc) |
388 | { | 388 | { |
389 | return mmc->cfg->host_caps & | 389 | return mmc->host_ok_caps & |
390 | (MMC_MODE_UHS_SDR12 | MMC_MODE_UHS_SDR25 | | 390 | (MMC_MODE_UHS_SDR12 | MMC_MODE_UHS_SDR25 | |
391 | MMC_MODE_UHS_SDR50 | MMC_MODE_UHS_SDR104 | | 391 | MMC_MODE_UHS_SDR50 | MMC_MODE_UHS_SDR104 | |
392 | MMC_MODE_UHS_DDR50); | 392 | MMC_MODE_UHS_DDR50); |
@@ -663,7 +663,7 @@ static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) | |||
663 | 663 | ||
664 | static void mmc_select_card_type(struct mmc *mmc, char card_type) | 664 | static void mmc_select_card_type(struct mmc *mmc, char card_type) |
665 | { | 665 | { |
666 | u32 caps = mmc->cfg->host_caps; | 666 | u32 caps = mmc->host_ok_caps; |
667 | uint hs_max_dtr = mmc->tran_speed; | 667 | uint hs_max_dtr = mmc->tran_speed; |
668 | 668 | ||
669 | if (caps & MMC_MODE_HS && | 669 | if (caps & MMC_MODE_HS && |
@@ -1094,7 +1094,7 @@ static int mmc_app_set_bus_width(struct mmc *mmc, int width) | |||
1094 | 1094 | ||
1095 | static void sd_update_bus_speed_mode(struct mmc *mmc) | 1095 | static void sd_update_bus_speed_mode(struct mmc *mmc) |
1096 | { | 1096 | { |
1097 | u32 caps = mmc->cfg->host_caps; | 1097 | u32 caps = mmc->host_ok_caps; |
1098 | /* | 1098 | /* |
1099 | * If the host doesn't support any of the UHS-I modes, fallback on | 1099 | * If the host doesn't support any of the UHS-I modes, fallback on |
1100 | * default speed. | 1100 | * default speed. |
@@ -1238,8 +1238,8 @@ static int mmc_sd_switch_hs(struct mmc *mmc) | |||
1238 | * This can avoid furthur problem when the card runs in different | 1238 | * This can avoid furthur problem when the card runs in different |
1239 | * mode between the host. | 1239 | * mode between the host. |
1240 | */ | 1240 | */ |
1241 | if (!((mmc->cfg->host_caps & MMC_MODE_HS_52MHz) && | 1241 | if (!((mmc->host_ok_caps & MMC_MODE_HS_52MHz) && |
1242 | (mmc->cfg->host_caps & MMC_MODE_HS))) | 1242 | (mmc->host_ok_caps & MMC_MODE_HS))) |
1243 | return -EINVAL; | 1243 | return -EINVAL; |
1244 | 1244 | ||
1245 | if (!(mmc->card_caps & MMC_MODE_HS)) | 1245 | if (!(mmc->card_caps & MMC_MODE_HS)) |
@@ -1350,7 +1350,7 @@ retry_scr: | |||
1350 | mmc->card_caps |= MMC_MODE_HS; | 1350 | mmc->card_caps |= MMC_MODE_HS; |
1351 | 1351 | ||
1352 | /* Restrict card's capabilities by what the host can do */ | 1352 | /* Restrict card's capabilities by what the host can do */ |
1353 | mmc->card_caps &= mmc->cfg->host_caps; | 1353 | mmc->card_caps &= mmc->host_ok_caps; |
1354 | 1354 | ||
1355 | if (mmc->ocr & OCR_S18R) { | 1355 | if (mmc->ocr & OCR_S18R) { |
1356 | mmc_sd_init_uhs_card(mmc); | 1356 | mmc_sd_init_uhs_card(mmc); |
@@ -1513,16 +1513,15 @@ static int mmc_select_bus_width(struct mmc *mmc) | |||
1513 | MMC_BUS_WIDTH_8, | 1513 | MMC_BUS_WIDTH_8, |
1514 | MMC_BUS_WIDTH_4, | 1514 | MMC_BUS_WIDTH_4, |
1515 | }; | 1515 | }; |
1516 | const struct mmc_config *cfg = mmc->cfg; | ||
1517 | ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); | 1516 | ALLOC_CACHE_ALIGN_BUFFER(u8, ext_csd, MMC_MAX_BLOCK_LEN); |
1518 | ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN); | 1517 | ALLOC_CACHE_ALIGN_BUFFER(u8, test_csd, MMC_MAX_BLOCK_LEN); |
1519 | unsigned idx = 0, bus_width = 0; | 1518 | unsigned idx = 0, bus_width = 0; |
1520 | int err = 0; | 1519 | int err = 0; |
1521 | 1520 | ||
1522 | if (!(cfg->host_caps & (MMC_MODE_8BIT | MMC_MODE_4BIT))) | 1521 | if (!(mmc->host_ok_caps & (MMC_MODE_8BIT | MMC_MODE_4BIT))) |
1523 | return 0; | 1522 | return 0; |
1524 | 1523 | ||
1525 | idx = (cfg->host_caps & MMC_MODE_8BIT) ? 0 : 1; | 1524 | idx = (mmc->host_ok_caps & MMC_MODE_8BIT) ? 0 : 1; |
1526 | 1525 | ||
1527 | err = mmc_send_ext_csd(mmc, ext_csd); | 1526 | err = mmc_send_ext_csd(mmc, ext_csd); |
1528 | if (err) | 1527 | if (err) |
@@ -1887,16 +1886,22 @@ static int mmc_startup(struct mmc *mmc) | |||
1887 | if (mmc->timing == MMC_TIMING_MMC_HS200) { | 1886 | if (mmc->timing == MMC_TIMING_MMC_HS200) { |
1888 | err = mmc->cfg->ops->execute_tuning(mmc, | 1887 | err = mmc->cfg->ops->execute_tuning(mmc, |
1889 | MMC_SEND_TUNING_BLOCK_HS200); | 1888 | MMC_SEND_TUNING_BLOCK_HS200); |
1890 | if (err) | 1889 | if (err) { |
1891 | return err; | 1890 | printf("Tuning failed, dropping HS200 mode.\n"); |
1891 | mmc->host_ok_caps &= ~MMC_MODE_HS200; | ||
1892 | return -EAGAIN; | ||
1893 | } | ||
1892 | } else if (mmc->timing == MMC_TIMING_MMC_HS) { | 1894 | } else if (mmc->timing == MMC_TIMING_MMC_HS) { |
1893 | err = mmc_select_bus_width(mmc); | 1895 | err = mmc_select_bus_width(mmc); |
1894 | if (err) | 1896 | if (err) |
1895 | return err; | 1897 | return err; |
1896 | 1898 | ||
1897 | err = mmc_select_hs_ddr(mmc); | 1899 | err = mmc_select_hs_ddr(mmc); |
1898 | if (err) | 1900 | if (err) { |
1899 | return err; | 1901 | printf("dropping DDR52 mode.\n"); |
1902 | mmc->host_ok_caps &= ~MMC_MODE_DDR_52MHz; | ||
1903 | return -EAGAIN; | ||
1904 | } | ||
1900 | } | 1905 | } |
1901 | } | 1906 | } |
1902 | 1907 | ||
@@ -2161,19 +2166,26 @@ static int mmc_complete_init(struct mmc *mmc) | |||
2161 | int mmc_init(struct mmc *mmc) | 2166 | int mmc_init(struct mmc *mmc) |
2162 | { | 2167 | { |
2163 | int err = 0; | 2168 | int err = 0; |
2164 | unsigned start; | 2169 | int retries = 0; |
2170 | __maybe_unused unsigned start; | ||
2165 | 2171 | ||
2166 | if (mmc->has_init) | 2172 | if (mmc->has_init) |
2167 | return 0; | 2173 | return 0; |
2168 | 2174 | ||
2175 | mmc->host_ok_caps = mmc->cfg->host_caps; | ||
2169 | start = get_timer(0); | 2176 | start = get_timer(0); |
2170 | 2177 | ||
2171 | if (!mmc->init_in_progress) | 2178 | do { |
2172 | err = mmc_start_init(mmc); | 2179 | retries++; |
2180 | if (!mmc->init_in_progress) | ||
2181 | err = mmc_start_init(mmc); | ||
2173 | 2182 | ||
2174 | if (!err) | 2183 | if (!err) |
2175 | err = mmc_complete_init(mmc); | 2184 | err = mmc_complete_init(mmc); |
2176 | debug("%s: %d, time %lu\n", __func__, err, get_timer(start)); | 2185 | } while (err == -EAGAIN); |
2186 | |||
2187 | debug("%s: %d, time %lu (retries %d)\n", __func__, err, | ||
2188 | get_timer(start), retries - 1); | ||
2177 | return err; | 2189 | return err; |
2178 | } | 2190 | } |
2179 | 2191 | ||
diff --git a/include/mmc.h b/include/mmc.h index 8cdad5a800..c7aeb74b49 100644 --- a/include/mmc.h +++ b/include/mmc.h | |||
@@ -450,6 +450,7 @@ struct mmc { | |||
450 | struct blk_desc block_dev; | 450 | struct blk_desc block_dev; |
451 | char op_cond_pending; /* 1 if we are waiting on an op_cond command */ | 451 | char op_cond_pending; /* 1 if we are waiting on an op_cond command */ |
452 | char init_in_progress; /* 1 if we have done mmc_start_init() */ | 452 | char init_in_progress; /* 1 if we have done mmc_start_init() */ |
453 | uint host_ok_caps; /* host caps that are not yet proven wrong */ | ||
453 | char preinit; /* start init as early as possible */ | 454 | char preinit; /* start init as early as possible */ |
454 | int ddr_mode; | 455 | int ddr_mode; |
455 | unsigned int sd_bus_speed; | 456 | unsigned int sd_bus_speed; |