Commit b9a2a0e2e9c024009010a9755d5377795f660b1a

Authored by Marek Vasut
Committed by Tom Rini
1 parent 9a878e8f17

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>

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

... ... @@ -754,7 +754,8 @@
754 754 }
755 755  
756 756 #if !CONFIG_IS_ENABLED(MMC_TINY)
757   -static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode)
  757 +static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode,
  758 + bool hsdowngrade)
758 759 {
759 760 int err;
760 761 int speed_bits;
... ... @@ -788,6 +789,20 @@
788 789 if (err)
789 790 return err;
790 791  
  792 +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
  793 + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
  794 + /*
  795 + * In case the eMMC is in HS200/HS400 mode and we are downgrading
  796 + * to HS mode, the card clock are still running much faster than
  797 + * the supported HS mode clock, so we can not reliably read out
  798 + * Extended CSD. Reconfigure the controller to run at HS mode.
  799 + */
  800 + if (hsdowngrade) {
  801 + mmc_select_mode(mmc, MMC_HS);
  802 + mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
  803 + }
  804 +#endif
  805 +
791 806 if ((mode == MMC_HS) || (mode == MMC_HS_52)) {
792 807 /* Now check to see that it worked */
793 808 err = mmc_send_ext_csd(mmc, test_csd);
... ... @@ -1849,7 +1864,7 @@
1849 1864 int err;
1850 1865  
1851 1866 /* Set timing to HS200 for tuning */
1852   - err = mmc_set_card_speed(mmc, MMC_HS_200);
  1867 + err = mmc_set_card_speed(mmc, MMC_HS_200, false);
1853 1868 if (err)
1854 1869 return err;
1855 1870  
... ... @@ -1865,7 +1880,7 @@
1865 1880 }
1866 1881  
1867 1882 /* Set back to HS */
1868   - mmc_set_card_speed(mmc, MMC_HS);
  1883 + mmc_set_card_speed(mmc, MMC_HS, false);
1869 1884 mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false);
1870 1885  
1871 1886 err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
... ... @@ -1873,7 +1888,7 @@
1873 1888 if (err)
1874 1889 return err;
1875 1890  
1876   - err = mmc_set_card_speed(mmc, MMC_HS_400);
  1891 + err = mmc_set_card_speed(mmc, MMC_HS_400, false);
1877 1892 if (err)
1878 1893 return err;
1879 1894  
... ... @@ -1920,7 +1935,19 @@
1920 1935 return -ENOTSUPP;
1921 1936 }
1922 1937  
1923   - mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
  1938 +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \
  1939 + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)
  1940 + /*
  1941 + * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode
  1942 + * before doing anything else, since a transition from either of
  1943 + * the HS200/HS400 mode directly to legacy mode is not supported.
  1944 + */
  1945 + if (mmc->selected_mode == MMC_HS_200 ||
  1946 + mmc->selected_mode == MMC_HS_400)
  1947 + mmc_set_card_speed(mmc, MMC_HS, true);
  1948 + else
  1949 +#endif
  1950 + mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE);
1924 1951  
1925 1952 for_each_mmc_mode_by_pref(card_caps, mwt) {
1926 1953 for_each_supported_width(card_caps & mwt->widths,
... ... @@ -1952,7 +1979,7 @@
1952 1979 }
1953 1980 } else {
1954 1981 /* configure the bus speed (card) */
1955   - err = mmc_set_card_speed(mmc, mwt->mode);
  1982 + err = mmc_set_card_speed(mmc, mwt->mode, false);
1956 1983 if (err)
1957 1984 goto error;
1958 1985