Commit 4c95f3389019ae1cf87f78057d4f8071c43e20c3

Authored by Marek Vasut
Committed by Haibo Chen
1 parent 128b1aaf8d

mmc: Add support for downgrading HS200/HS400 to HS mode

The mmc_select_mode_and_width() function can be called while the card
is in HS200/HS400 mode and can be used to downgrade the card to lower
mode, e.g. HS. This is used for example by mmc_boot_part_access_chk()
which cannot access the card in HS200/HS400 mode and which is in turn
called by saveenv if env is in the MMC.

In such case, forcing the card clock to legacy frequency cannot work.
Instead, the card must be switched to HS mode first, from which it can
then be reprogrammed as needed.

However, this procedure needs additional code changes, since the current
implementation checks whether the card correctly switched to HS mode in
mmc_set_card_speed(). The check only expects that the card will be going
to HS mode from lower modes, not from higher modes, hence add a parameter
which indicates that the HS200/HS400 to HS downgrade is happening. This
makes the code send the switch command first, reconfigure the controller
next and finally perform the EXT_CSD readback check. The last two steps
cannot be done in reverse order as the card is already in HS mode when
the clock are being switched on the controller side.

Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
Cc: Jaehoon Chung <jh80.chung@samsung.com>
(cherry picked from commit 523f613609545252f08f01f346ba4b0403f78b7c)
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>

Showing 1 changed file with 33 additions and 6 deletions Side-by-side Diff

... ... @@ -777,7 +777,8 @@
777 777  
778 778 }
779 779  
780   -static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
  780 +static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
  781 + bool hsdowngrade)
781 782 {
782 783 int err;
783 784 int speed_bits;
... ... @@ -816,6 +817,20 @@
816 817 if (err)
817 818 return err;
818 819  
  820 +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
  821 + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
  822 + /*
  823 + * In case the eMMC is in HS200/HS400 mode and we are downgrading
  824 + * to HS mode, the card clock are still running much faster than
  825 + * the supported HS mode clock, so we can not reliably read out
  826 + * Extended CSD. Reconfigure the controller to run at HS mode.
  827 + */
  828 + if (hsdowngrade) {
  829 + mmc_select_mode(mmc, MMC_HS);
  830 + mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
  831 + }
  832 +#endif
  833 +
819 834 if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
820 835 /* Now check to see that it worked */
821 836 err = mmc_send_ext_csd(mmc, test_csd);
... ... @@ -1881,7 +1896,7 @@
1881 1896 int err;
1882 1897  
1883 1898 /* Set timing to HS200 for tuning */
1884   - err = mmc_set_card_speed(mmc, MMC_HS_200);
  1899 + err = mmc_set_card_speed(mmc, MMC_HS_200, false);
1885 1900 if (err)
1886 1901 return err;
1887 1902  
... ... @@ -1897,7 +1912,7 @@
1897 1912 }
1898 1913  
1899 1914 /* Set back to HS */
1900   - mmc_set_card_speed(mmc, MMC_HS);
  1915 + mmc_set_card_speed(mmc, MMC_HS, false);
1901 1916 mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
1902 1917  
1903 1918 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
... ... @@ -1905,7 +1920,7 @@
1905 1920 if (err)
1906 1921 return err;
1907 1922  
1908   - err = mmc_set_card_speed(mmc, MMC_HS_400);
  1923 + err = mmc_set_card_speed(mmc, MMC_HS_400, false);
1909 1924 if (err)
1910 1925 return err;
1911 1926  
... ... @@ -1935,7 +1950,7 @@
1935 1950 {
1936 1951 int err;
1937 1952  
1938   - err = mmc_set_card_speed(mmc, MMC_HS);
  1953 + err = mmc_set_card_speed(mmc, MMC_HS, false);
1939 1954 if (err)
1940 1955 return err;
1941 1956  
... ... @@ -2001,6 +2016,18 @@
2001 2016 return -ENOTSUPP;
2002 2017 }
2003 2018  
  2019 +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
  2020 + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
  2021 + /*
  2022 + * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
  2023 + * before doing anything else, since a transition from either of
  2024 + * the HS200/HS400 mode directly to legacy mode is not supported.
  2025 + */
  2026 + if (mmc->selected_mode == MMC_HS_200 ||
  2027 + mmc->selected_mode == MMC_HS_400)
  2028 + mmc_set_card_speed(mmc, MMC_HS, true);
  2029 + else
  2030 +#endif
2004 2031 mmc_set_clock(mmc, mmc->legacy_speed, false);
2005 2032  
2006 2033 for_each_mmc_mode_by_pref(card_caps, mwt) {
... ... @@ -2035,7 +2062,7 @@
2035 2062 goto error;
2036 2063 } else {
2037 2064 /* configure the bus speed (card) */
2038   - err = mmc_set_card_speed(mmc, mwt->mode);
  2065 + err = mmc_set_card_speed(mmc, mwt->mode, false);
2039 2066 if (err)
2040 2067 goto error;
2041 2068