
On 05/13/2017 03:16 AM, Jean-Jacques Hiblot wrote:
Boot partitions do not support HS200. Changing to a lower performance mode is required to access them. mmc_select_mode_and_width() and sd_select_mode_and_width() are modified to make it easier to call them outside of the initialization context.
This patch should be important to support the HS200 mode on u-boot.. So i need to test this..more detail..
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
drivers/mmc/mmc.c | 66 +++++++++++++++++++++++++++++++++++++++++-------------- include/mmc.h | 1 + 2 files changed, 50 insertions(+), 17 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 074d286..c7dda64 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -32,6 +32,7 @@ static const unsigned int sd_au_size[] = { static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage); static void mmc_power_cycle(struct mmc *mmc); static int mmc_card_busy(struct mmc *mmc); +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps);
#if CONFIG_IS_ENABLED(MMC_TINY) static struct mmc mmc_static; @@ -788,10 +789,38 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return 0; }
+static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num) +{
- int forbiden = 0;
forbiden? typo?
- bool change = false;
- if (part_num & PART_ACCESS_MASK)
forbiden = MMC_CAP(MMC_HS_200);
- if (MMC_CAP(mmc->selected_mode) & forbiden) {
debug("selected mode (%s) is forbiden for part %d\n",
mmc_mode_name(mmc->selected_mode), part_num);
change = true;
- } else if (mmc->selected_mode != mmc->best_mode) {
debug("selected mode is not optimal\n");
change = true;
- }
- if (change)
return mmc_select_mode_and_width(mmc,
mmc->card_caps & ~forbiden);
- return 0;
+}
int mmc_switch_part(struct mmc *mmc, unsigned int part_num) { int ret;
- ret = mmc_boot_part_access_chk(mmc, part_num);
- if (ret)
return ret;
- ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, (mmc->part_config & ~PART_ACCESS_MASK) | (part_num & PART_ACCESS_MASK));
@@ -1438,7 +1467,7 @@ static const struct mode_width_tuning sd_modes_by_pref[] = { mwt++) \ if (caps & MMC_CAP(mwt->mode))
-static int sd_select_mode_and_width(struct mmc *mmc) +static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) { int err; uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; @@ -1447,11 +1476,8 @@ static int sd_select_mode_and_width(struct mmc *mmc) uint caps;
- err = sd_get_capabilities(mmc);
- if (err)
/* Restrict card's capabilities by what the host can do */return err;
- caps = mmc->card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
caps = card_caps & (mmc->cfg->host_caps | MMC_MODE_1BIT);
if (!uhs_en) caps &= ~UHS_CAPS;
@@ -1582,18 +1608,14 @@ static const struct ext_csd_bus_width { ecbv++) \ if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap))
-static int mmc_select_mode_and_width(struct mmc *mmc) +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) { int err; const struct mode_width_tuning *mwt; const struct ext_csd_bus_width *ecbw;
- err = mmc_get_capabilities(mmc);
- if (err)
return err;
- /* Restrict card's capabilities by what the host can do */
- mmc->card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
card_caps &= (mmc->cfg->host_caps | MMC_MODE_1BIT);
/* Only version 4 of MMC supports wider bus widths */ if (mmc->version < MMC_VERSION_4)
@@ -1605,8 +1627,10 @@ static int mmc_select_mode_and_width(struct mmc *mmc) return -ENOTSUPP; }
- for_each_mmc_mode_by_pref(mmc->card_caps, mwt) {
for_each_supported_width(mmc->card_caps & mwt->widths,
- mmc_set_clock(mmc, mmc->legacy_speed, false);
- for_each_mmc_mode_by_pref(card_caps, mwt) {
for_each_supported_width(card_caps & mwt->widths, mmc_is_mode_ddr(mwt->mode), ecbw) { debug("trying mode %s width %d (at %d MHz)\n", mmc_mode_name(mwt->mode),
@@ -1999,14 +2023,22 @@ static int mmc_startup(struct mmc *mmc) if (err) return err;
- if (IS_SD(mmc))
err = sd_select_mode_and_width(mmc);
- else
err = mmc_select_mode_and_width(mmc);
if (IS_SD(mmc)) {
err = sd_get_capabilities(mmc);
if (err)
return err;
err = sd_select_mode_and_width(mmc, mmc->card_caps);
} else {
err = mmc_get_capabilities(mmc);
if (err)
return err;
mmc_select_mode_and_width(mmc, mmc->card_caps);
}
if (err) return err;
mmc->best_mode = mmc->selected_mode;
/* Fix the block length for DDR mode */ if (mmc->ddr_mode) {
diff --git a/include/mmc.h b/include/mmc.h index 775c47e..921a7ff 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -573,6 +573,7 @@ struct mmc { #endif u8 *ext_csd; enum bus_mode selected_mode;
- enum bus_mode best_mode;
};
struct mmc_hwpart_conf {