Commit 01298da31d92ecc46cf9130d8cff68bc51698197
mmc: Change mode when switching to a boot partition
Boot partitions do not support HS200. Changing to a lower performance mode is required to access them. mmc_select_mode_and_width() and sd_select_mode_and_width() are modified to make it easier to call them outside of the initialization context. Signed-off-by: Jean-Jacques Hiblot <jjhiblot@ti.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Showing 2 changed files with 55 additions and 18 deletions Side-by-side Diff
... | ... | @@ -32,6 +32,7 @@ |
32 | 32 | |
33 | 33 | static int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage); |
34 | 34 | static int mmc_power_cycle(struct mmc *mmc); |
35 | +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps); | |
35 | 36 | |
36 | 37 | #if CONFIG_IS_ENABLED(MMC_TINY) |
37 | 38 | static struct mmc mmc_static; |
38 | 39 | |
... | ... | @@ -792,10 +793,38 @@ |
792 | 793 | return 0; |
793 | 794 | } |
794 | 795 | |
796 | +static int mmc_boot_part_access_chk(struct mmc *mmc, unsigned int part_num) | |
797 | +{ | |
798 | + int forbidden = 0; | |
799 | + bool change = false; | |
800 | + | |
801 | + if (part_num & PART_ACCESS_MASK) | |
802 | + forbidden = MMC_CAP(MMC_HS_200); | |
803 | + | |
804 | + if (MMC_CAP(mmc->selected_mode) & forbidden) { | |
805 | + debug("selected mode (%s) is forbidden for part %d\n", | |
806 | + mmc_mode_name(mmc->selected_mode), part_num); | |
807 | + change = true; | |
808 | + } else if (mmc->selected_mode != mmc->best_mode) { | |
809 | + debug("selected mode is not optimal\n"); | |
810 | + change = true; | |
811 | + } | |
812 | + | |
813 | + if (change) | |
814 | + return mmc_select_mode_and_width(mmc, | |
815 | + mmc->card_caps & ~forbidden); | |
816 | + | |
817 | + return 0; | |
818 | +} | |
819 | + | |
795 | 820 | int mmc_switch_part(struct mmc *mmc, unsigned int part_num) |
796 | 821 | { |
797 | 822 | int ret; |
798 | 823 | |
824 | + ret = mmc_boot_part_access_chk(mmc, part_num); | |
825 | + if (ret) | |
826 | + return ret; | |
827 | + | |
799 | 828 | ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, |
800 | 829 | (mmc->part_config & ~PART_ACCESS_MASK) |
801 | 830 | | (part_num & PART_ACCESS_MASK)); |
... | ... | @@ -1438,7 +1467,7 @@ |
1438 | 1467 | mwt++) \ |
1439 | 1468 | if (caps & MMC_CAP(mwt->mode)) |
1440 | 1469 | |
1441 | -static int sd_select_mode_and_width(struct mmc *mmc) | |
1470 | +static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) | |
1442 | 1471 | { |
1443 | 1472 | int err; |
1444 | 1473 | uint widths[] = {MMC_MODE_4BIT, MMC_MODE_1BIT}; |
1445 | 1474 | |
... | ... | @@ -1447,11 +1476,8 @@ |
1447 | 1476 | uint caps; |
1448 | 1477 | |
1449 | 1478 | |
1450 | - err = sd_get_capabilities(mmc); | |
1451 | - if (err) | |
1452 | - return err; | |
1453 | 1479 | /* Restrict card's capabilities by what the host can do */ |
1454 | - caps = mmc->card_caps & (mmc->host_caps | MMC_MODE_1BIT); | |
1480 | + caps = card_caps & (mmc->host_caps | MMC_MODE_1BIT); | |
1455 | 1481 | |
1456 | 1482 | if (!uhs_en) |
1457 | 1483 | caps &= ~UHS_CAPS; |
1458 | 1484 | |
1459 | 1485 | |
... | ... | @@ -1588,18 +1614,14 @@ |
1588 | 1614 | ecbv++) \ |
1589 | 1615 | if ((ddr == ecbv->is_ddr) && (caps & ecbv->cap)) |
1590 | 1616 | |
1591 | -static int mmc_select_mode_and_width(struct mmc *mmc) | |
1617 | +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) | |
1592 | 1618 | { |
1593 | 1619 | int err; |
1594 | 1620 | const struct mode_width_tuning *mwt; |
1595 | 1621 | const struct ext_csd_bus_width *ecbw; |
1596 | 1622 | |
1597 | - err = mmc_get_capabilities(mmc); | |
1598 | - if (err) | |
1599 | - return err; | |
1600 | - | |
1601 | 1623 | /* Restrict card's capabilities by what the host can do */ |
1602 | - mmc->card_caps &= (mmc->host_caps | MMC_MODE_1BIT); | |
1624 | + card_caps &= (mmc->host_caps | MMC_MODE_1BIT); | |
1603 | 1625 | |
1604 | 1626 | /* Only version 4 of MMC supports wider bus widths */ |
1605 | 1627 | if (mmc->version < MMC_VERSION_4) |
... | ... | @@ -1610,8 +1632,10 @@ |
1610 | 1632 | return -ENOTSUPP; |
1611 | 1633 | } |
1612 | 1634 | |
1613 | - for_each_mmc_mode_by_pref(mmc->card_caps, mwt) { | |
1614 | - for_each_supported_width(mmc->card_caps & mwt->widths, | |
1635 | + mmc_set_clock(mmc, mmc->legacy_speed, false); | |
1636 | + | |
1637 | + for_each_mmc_mode_by_pref(card_caps, mwt) { | |
1638 | + for_each_supported_width(card_caps & mwt->widths, | |
1615 | 1639 | mmc_is_mode_ddr(mwt->mode), ecbw) { |
1616 | 1640 | debug("trying mode %s width %d (at %d MHz)\n", |
1617 | 1641 | mmc_mode_name(mwt->mode), |
1618 | 1642 | |
... | ... | @@ -2006,14 +2030,22 @@ |
2006 | 2030 | if (err) |
2007 | 2031 | return err; |
2008 | 2032 | |
2009 | - if (IS_SD(mmc)) | |
2010 | - err = sd_select_mode_and_width(mmc); | |
2011 | - else | |
2012 | - err = mmc_select_mode_and_width(mmc); | |
2033 | + if (IS_SD(mmc)) { | |
2034 | + err = sd_get_capabilities(mmc); | |
2035 | + if (err) | |
2036 | + return err; | |
2037 | + err = sd_select_mode_and_width(mmc, mmc->card_caps); | |
2038 | + } else { | |
2039 | + err = mmc_get_capabilities(mmc); | |
2040 | + if (err) | |
2041 | + return err; | |
2042 | + mmc_select_mode_and_width(mmc, mmc->card_caps); | |
2043 | + } | |
2013 | 2044 | |
2014 | 2045 | if (err) |
2015 | 2046 | return err; |
2016 | 2047 | |
2048 | + mmc->best_mode = mmc->selected_mode; | |
2017 | 2049 | |
2018 | 2050 | /* Fix the block length for DDR mode */ |
2019 | 2051 | if (mmc->ddr_mode) { |
... | ... | @@ -585,7 +585,12 @@ |
585 | 585 | #endif |
586 | 586 | #endif |
587 | 587 | u8 *ext_csd; |
588 | - enum bus_mode selected_mode; | |
588 | + enum bus_mode selected_mode; /* mode currently used */ | |
589 | + enum bus_mode best_mode; /* best mode is the supported mode with the | |
590 | + * highest bandwidth. It may not always be the | |
591 | + * operating mode due to limitations when | |
592 | + * accessing the boot partitions | |
593 | + */ | |
589 | 594 | }; |
590 | 595 | |
591 | 596 | struct mmc_hwpart_conf { |
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50
-
mentioned in commit 8adf50