On 09/21/2017 11:30 PM, Jean-Jacques Hiblot wrote: > HS200 only supports 1.2v and 1.8v signal voltages. DDR52 supports 3.3v/1.8v > or 1.2v signal voltages. > Select the lowest voltage available when using those modes. > > Signed-off-by: Jean-Jacques Hiblot <jjhib...@ti.com> > --- > drivers/mmc/mmc.c | 68 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++- > include/mmc.h | 20 +++++++++++++--- > 2 files changed, 84 insertions(+), 4 deletions(-) > > diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c > index 6d1bf94..2d447dd 100644 > --- a/drivers/mmc/mmc.c > +++ b/drivers/mmc/mmc.c > @@ -767,6 +767,7 @@ static int mmc_get_capabilities(struct mmc *mmc) > mmc->card_caps |= MMC_MODE_4BIT | MMC_MODE_8BIT; > > cardtype = ext_csd[EXT_CSD_CARD_TYPE] & 0x3f; > + mmc->cardtype = cardtype; > > if (cardtype & (EXT_CSD_CARD_TYPE_HS200_1_2V | > EXT_CSD_CARD_TYPE_HS200_1_8V)) { > @@ -1441,10 +1442,30 @@ struct mode_width_tuning { > uint tuning; > }; > > +int mmc_voltage_to_mv(enum mmc_voltage voltage) > +{ > + switch (voltage) { > + case MMC_SIGNAL_VOLTAGE_000: return 0; > + case MMC_SIGNAL_VOLTAGE_330: return 3300; > + case MMC_SIGNAL_VOLTAGE_180: return 1800; > + case MMC_SIGNAL_VOLTAGE_120: return 1200;
Plz, change line. case xxx: return xxx; > + } > + return -EINVAL; > +} > + > static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage) > { > + int err; Initialized err = 0 > + > + if (mmc->signal_voltage == signal_voltage) > + return 0; return err; or use return ret? > + > mmc->signal_voltage = signal_voltage; > - return mmc_set_ios(mmc); > + err = mmc_set_ios(mmc); > + if (err) > + debug("unable to set voltage (err %d)\n", err); > + > + return err; > } > > static const struct mode_width_tuning sd_modes_by_pref[] = { > @@ -1584,6 +1605,43 @@ static int mmc_read_and_compare_ext_csd(struct mmc > *mmc) > return -EBADMSG; > } > > +static int mmc_set_lowest_voltage(struct mmc *mmc, enum bus_mode mode, > + uint32_t allowed_mask) > +{ > + u32 card_mask = 0; > + > + switch (mode) { > + case MMC_HS_200: > + if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_8V) > + card_mask |= MMC_SIGNAL_VOLTAGE_180; > + if (mmc->cardtype & EXT_CSD_CARD_TYPE_HS200_1_2V) > + card_mask |= MMC_SIGNAL_VOLTAGE_120; > + break; > + case MMC_DDR_52: > + if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_8V) > + card_mask |= MMC_SIGNAL_VOLTAGE_330 | > + MMC_SIGNAL_VOLTAGE_180; > + if (mmc->cardtype & EXT_CSD_CARD_TYPE_DDR_1_2V) > + card_mask |= MMC_SIGNAL_VOLTAGE_120; > + break; > + default: > + card_mask |= MMC_SIGNAL_VOLTAGE_330; > + break; > + } > + > + while (card_mask & allowed_mask) { > + enum mmc_voltage best_match; > + > + best_match = 1 << (ffs(card_mask & allowed_mask) - 1); > + if (!mmc_set_signal_voltage(mmc, best_match)) > + return 0; Just return 0? > + > + allowed_mask &= ~best_match; > + } > + > + return -ENOTSUPP; > +} > + > static const struct mode_width_tuning mmc_modes_by_pref[] = { > { > .mode = MMC_HS_200, > @@ -1655,10 +1713,17 @@ static int mmc_select_mode_and_width(struct mmc *mmc, > uint card_caps) > for_each_mmc_mode_by_pref(card_caps, mwt) { > for_each_supported_width(card_caps & mwt->widths, > mmc_is_mode_ddr(mwt->mode), ecbw) { > + enum mmc_voltage old_voltage; > debug("trying mode %s width %d (at %d MHz)\n", > mmc_mode_name(mwt->mode), > bus_width(ecbw->cap), > mmc_mode2freq(mmc, mwt->mode) / 1000000); > + old_voltage = mmc->signal_voltage; > + err = mmc_set_lowest_voltage(mmc, mwt->mode, > + MMC_ALL_SIGNAL_VOLTAGE); > + if (err) > + continue; > + > /* configure the bus width (card + host) */ > err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, > EXT_CSD_BUS_WIDTH, > @@ -1702,6 +1767,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, > uint card_caps) > if (!err) > return 0; > error: > + mmc_set_signal_voltage(mmc, old_voltage); doesn't need to check the return value? > /* if an error occured, revert to a safer bus mode */ > mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, > EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_1); > diff --git a/include/mmc.h b/include/mmc.h > index a9ebc88..c11f698 100644 > --- a/include/mmc.h > +++ b/include/mmc.h > @@ -311,11 +311,15 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) > > enum mmc_voltage { > MMC_SIGNAL_VOLTAGE_000 = 0, > - MMC_SIGNAL_VOLTAGE_120, > - MMC_SIGNAL_VOLTAGE_180, > - MMC_SIGNAL_VOLTAGE_330 > + MMC_SIGNAL_VOLTAGE_120 = 1, > + MMC_SIGNAL_VOLTAGE_180 = 2, > + MMC_SIGNAL_VOLTAGE_330 = 4, > }; > > +#define MMC_ALL_SIGNAL_VOLTAGE (MMC_SIGNAL_VOLTAGE_120 |\ > + MMC_SIGNAL_VOLTAGE_180 |\ > + MMC_SIGNAL_VOLTAGE_330) > + > /* Maximum block size for MMC */ > #define MMC_MAX_BLOCK_LEN 512 > > @@ -588,6 +592,8 @@ struct mmc { > #endif > #endif > u8 *ext_csd; > + u32 cardtype; /* cardtype read from the MMC */ > + enum mmc_voltage current_voltage; > enum bus_mode selected_mode; /* mode currently used */ > enum bus_mode best_mode; /* best mode is the supported mode with the > * highest bandwidth. It may not always be the > @@ -647,6 +653,14 @@ int mmc_init(struct mmc *mmc); > int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size); > > /** > + * mmc_voltage_to_mv() - Convert a mmc_voltage in mV > + * > + * @voltage: The mmc_voltage to convert > + * @return the value in mV if OK, -EINVAL on error (invalid mmc_voltage > value) > + */ > +int mmc_voltage_to_mv(enum mmc_voltage voltage); > + > +/** > * mmc_set_clock() - change the bus clock > * @mmc: MMC struct > * @clock: bus frequency in Hz > _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot