case MMC_HS_200:
speed_bits = EXT_CSD_TIMING_HS200;
break;
+ case MMC_HS_400:
+ speed_bits = EXT_CSD_TIMING_HS400;
+ break;
+ case MMC_HS_400_ES:
+ speed_bits = EXT_CSD_TIMING_HS400;
+ break;
case MMC_LEGACY:
speed_bits = EXT_CSD_TIMING_LEGACY;
break;
.mode = MMC_HS_400_ES,
.widths = MMC_MODE_8BIT,
},
+ {
+ .mode = MMC_HS_400,
+ .widths = MMC_MODE_8BIT,
+ .tuning = MMC_SEND_TUNING_BLOCK_HS200
+ },
{
.mode = MMC_HS_200,
.widths = MMC_MODE_8BIT | MMC_MODE_4BIT,
return 0;
}
+static int mmc_select_hs400(struct mmc *mmc)
+{
+ int err;
+
+ /* Set timing to HS200 for tuning */
+ err = mmc_set_card_speed(mmc, MMC_HS_200);
+ if (err)
+ return err;
+
+ /* configure the bus mode (host) */
+ mmc_select_mode(mmc, MMC_HS_200);
+ mmc_set_clock(mmc, mmc->tran_speed, false);
+
+ /* execute tuning if needed */
+ err = mmc_execute_tuning(mmc, MMC_SEND_TUNING_BLOCK_HS200);
+ if (err) {
+ debug("tuning failed\n");
+ return err;
+ }
+
+ /* Set back to HS */
+ mmc_set_card_speed(mmc, MMC_HS);
+ mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR);
+ if (err)
+ return err;
+
+ err = mmc_set_card_speed(mmc, MMC_HS_400);
+ if (err)
+ return err;
+
+ mmc_select_mode(mmc, MMC_HS_400);
+ mmc_set_clock(mmc, mmc->tran_speed, false);
+
+ return 0;
+}
+
static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
{
int err;
goto error;
mmc_set_bus_width(mmc, bus_width(ecbw->cap));
- if (mwt->mode == MMC_HS_400_ES) {
+ if (mwt->mode == MMC_HS_400) {
+ err = mmc_select_hs400(mmc);
+ if (err)
+ goto error;
+ } else if (mwt->mode == MMC_HS_400_ES) {
err = mmc_select_hs400es(mmc);
if (err)
goto error;