+#if CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+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, false);
+ 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_CMD_SEND_TUNING_BLOCK_HS200);
+ if (err) {
+ debug("tuning failed\n");
+ return err;
+ }
+
+ /* Set back to HS */
+ mmc_set_card_speed(mmc, MMC_HS, true);
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
+ EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG);
+ if (err)
+ return err;
+
+ err = mmc_set_card_speed(mmc, MMC_HS_400, false);
+ if (err)
+ return err;
+
+ mmc_select_mode(mmc, MMC_HS_400);
+ err = mmc_set_clock(mmc, mmc->tran_speed, false);
+ if (err)
+ return err;
+
+ return 0;
+}
+#else
+static int mmc_select_hs400(struct mmc *mmc)
+{
+ return -ENOTSUPP;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT)
+#if !CONFIG_IS_ENABLED(DM_MMC)
+static int mmc_set_enhanced_strobe(struct mmc *mmc)
+{
+ return -ENOTSUPP;
+}
+#endif
+static int mmc_select_hs400es(struct mmc *mmc)
+{
+ int err;
+
+ err = mmc_set_card_speed(mmc, MMC_HS, true);
+ if (err)
+ return err;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
+ EXT_CSD_BUS_WIDTH_8 | EXT_CSD_DDR_FLAG |
+ EXT_CSD_BUS_WIDTH_STROBE);
+ if (err) {
+ printf("switch to bus width for hs400 failed\n");
+ return err;
+ }
+ /* TODO: driver strength */
+ err = mmc_set_card_speed(mmc, MMC_HS_400_ES, false);
+ if (err)
+ return err;
+
+ mmc_select_mode(mmc, MMC_HS_400_ES);
+ err = mmc_set_clock(mmc, mmc->tran_speed, false);
+ if (err)
+ return err;
+
+ return mmc_set_enhanced_strobe(mmc);
+}
+#else
+static int mmc_select_hs400es(struct mmc *mmc)
+{
+ return -ENOTSUPP;
+}
+#endif
+