mmc: tmio: Make DMA transfer end bit configurable
[oweals/u-boot.git] / drivers / mmc / mmc.c
index f5c821e308cba8331a8109a3e109cbf79c8ebfb9..84d157ff4033518f98073ed9d5f094bf85ce1811 100644 (file)
@@ -754,7 +754,8 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
 }
 
 #if !CONFIG_IS_ENABLED(MMC_TINY)
-static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
+static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
+                             bool hsdowngrade)
 {
        int err;
        int speed_bits;
@@ -788,6 +789,20 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
        if (err)
                return err;
 
+#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+       /*
+        * In case the eMMC is in HS200/HS400 mode and we are downgrading
+        * to HS mode, the card clock are still running much faster than
+        * the supported HS mode clock, so we can not reliably read out
+        * Extended CSD. Reconfigure the controller to run at HS mode.
+        */
+       if (hsdowngrade) {
+               mmc_select_mode(mmc, MMC_HS);
+               mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
+       }
+#endif
+
        if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
                /* Now check to see that it worked */
                err = mmc_send_ext_csd(mmc, test_csd);
@@ -1849,7 +1864,7 @@ 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);
+       err = mmc_set_card_speed(mmc, MMC_HS_200, false);
        if (err)
                return err;
 
@@ -1865,7 +1880,7 @@ static int mmc_select_hs400(struct mmc *mmc)
        }
 
        /* Set back to HS */
-       mmc_set_card_speed(mmc, MMC_HS);
+       mmc_set_card_speed(mmc, MMC_HS, false);
        mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
 
        err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
@@ -1873,7 +1888,7 @@ static int mmc_select_hs400(struct mmc *mmc)
        if (err)
                return err;
 
-       err = mmc_set_card_speed(mmc, MMC_HS_400);
+       err = mmc_set_card_speed(mmc, MMC_HS_400, false);
        if (err)
                return err;
 
@@ -1920,7 +1935,19 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
                return -ENOTSUPP;
        }
 
-       mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
+#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
+    CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
+       /*
+        * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
+        * before doing anything else, since a transition from either of
+        * the HS200/HS400 mode directly to legacy mode is not supported.
+        */
+       if (mmc->selected_mode == MMC_HS_200 ||
+           mmc->selected_mode == MMC_HS_400)
+               mmc_set_card_speed(mmc, MMC_HS, true);
+       else
+#endif
+               mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
 
        for_each_mmc_mode_by_pref(card_caps, mwt) {
                for_each_supported_width(card_caps & mwt->widths,
@@ -1952,7 +1979,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
                                }
                        } else {
                                /* configure the bus speed (card) */
-                               err = mmc_set_card_speed(mmc, mwt->mode);
+                               err = mmc_set_card_speed(mmc, mwt->mode, false);
                                if (err)
                                        goto error;
 
@@ -2449,6 +2476,10 @@ static int mmc_startup(struct mmc *mmc)
        bdesc->revision[0] = 0;
 #endif
 
+#if !defined(CONFIG_DM_MMC) && (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBDISK_SUPPORT))
+       part_init(bdesc);
+#endif
+
        return 0;
 }