[U-Boot] [PATCH v3 0/4] mmc: fixes for HS200/UHS core support

This series applies on top of "[PATCH v2 00/26] mmc: Add support for HS200 and UHS modes"
It fixes a bug with old SD and MMC cards that support only the legacy mode. It also addresses the comments made on the mailing list: * dump card and host capabilities in debug mode * use 1-bit if the DTS property 'bus-width' is not present. * recognize the "mmc-ddr-1_2v" and "mmc-hs200-1_2v" DTS properties * convert mmc_of_parse to livetree
Tested on DRA7, DRA72 and AM335x
changes since v2: * use the device-oriented helpers like dev_read_u32_default() instead of using the livetree API * Dump the host and card capabilities only in when debug is enabled. Also dump the capabilities when 'mmc info' is executed if the verbose option is enabled
changes since v1: * convert mmc_of_parse to livetree * squashed all changes to mmc_of_parse in a single patch
Jean-Jacques Hiblot (4): dm: mmc: update mmc_of_parse() mmc: dump card and host capabilities if debug is enabled mmc: Fixed a problem with old sd or mmc that do not support High speed mmc: all hosts support 1-bit bus width and legacy timings
cmd/mmc.c | 4 ++++ drivers/mmc/mmc-uclass.c | 36 ++++++++++++++++++++---------------- drivers/mmc/mmc.c | 24 +++++++++++++++++++----- include/mmc.h | 11 ++++++++++- 4 files changed, 53 insertions(+), 22 deletions(-)

* convert to livetree API * don't fail because of an invalid bus-width, instead default to 1-bit. * recognize 1.2v DDR and 1.2v HS200 flags
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com ---
changes since v2: * use the wrappers like dev_read_u32_default() to access the DTS instead of using the livetree API.
drivers/mmc/mmc-uclass.c | 36 ++++++++++++++++++++---------------- include/mmc.h | 11 ++++++++++- 2 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index e30cde7..bfda942 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -10,7 +10,6 @@ #include <dm.h> #include <dm/device-internal.h> #include <dm/lists.h> -#include <dm/root.h> #include "mmc_private.h"
DECLARE_GLOBAL_DATA_PTR; @@ -120,11 +119,11 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode) return dm_mmc_execute_tuning(mmc->dev, opcode); }
-int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg) +int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg) { int val;
- val = fdtdec_get_int(fdt, node, "bus-width", 1); + val = dev_read_u32_default(dev, "bus-width", 1);
switch (val) { case 0x8: @@ -137,30 +136,35 @@ int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg) cfg->host_caps |= MMC_MODE_1BIT; break; default: - printf("error: %s invalid bus-width property %d\n", - fdt_get_name(fdt, node, NULL), val); - return -ENOENT; + debug("warning: %s invalid bus-width property. using 1-bit\n", + dev_read_name(dev)); + cfg->host_caps |= MMC_MODE_1BIT; + break; }
- cfg->f_max = fdtdec_get_int(fdt, node, "max-frequency", 52000000); + cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000);
- if (fdtdec_get_bool(fdt, node, "cap-sd-highspeed")) + if (dev_read_bool(dev, "cap-sd-highspeed")) cfg->host_caps |= MMC_CAP(SD_HS); - if (fdtdec_get_bool(fdt, node, "cap-mmc-highspeed")) + if (dev_read_bool(dev, "cap-mmc-highspeed")) cfg->host_caps |= MMC_CAP(MMC_HS); - if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr12")) + if (dev_read_bool(dev, "sd-uhs-sdr12")) cfg->host_caps |= MMC_CAP(UHS_SDR12); - if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr25")) + if (dev_read_bool(dev, "sd-uhs-sdr25")) cfg->host_caps |= MMC_CAP(UHS_SDR25); - if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr50")) + if (dev_read_bool(dev, "sd-uhs-sdr50")) cfg->host_caps |= MMC_CAP(UHS_SDR50); - if (fdtdec_get_bool(fdt, node, "sd-uhs-sdr104")) + if (dev_read_bool(dev, "sd-uhs-sdr104")) cfg->host_caps |= MMC_CAP(UHS_SDR104); - if (fdtdec_get_bool(fdt, node, "sd-uhs-ddr50")) + if (dev_read_bool(dev, "sd-uhs-ddr50")) cfg->host_caps |= MMC_CAP(UHS_DDR50); - if (fdtdec_get_bool(fdt, node, "mmc-ddr-1_8v")) + if (dev_read_bool(dev, "mmc-ddr-1_8v")) cfg->host_caps |= MMC_CAP(MMC_DDR_52); - if (fdtdec_get_bool(fdt, node, "mmc-hs200-1_8v")) + if (dev_read_bool(dev, "mmc-ddr-1_2v")) + cfg->host_caps |= MMC_CAP(MMC_DDR_52); + if (dev_read_bool(dev, "mmc-hs200-1_8v")) + cfg->host_caps |= MMC_CAP(MMC_HS_200); + if (dev_read_bool(dev, "mmc-hs200-1_2v")) cfg->host_caps |= MMC_CAP(MMC_HS_200);
return 0; diff --git a/include/mmc.h b/include/mmc.h index 6230a32..e3f777f 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -651,7 +651,16 @@ int mmc_unbind(struct udevice *dev); int mmc_initialize(bd_t *bis); int mmc_init(struct mmc *mmc); int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error); -int mmc_of_parse(const void *fdt, int node, struct mmc_config *cfg); + +/** + * mmc_of_parse() - Parse the device tree to get the capabilities of the host + * + * @dev: MMC device + * @cfg: MMC configuration + * @return 0 if OK, -ve on error + */ +int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg); + int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
/**

On 28 November 2017 at 03:26, Jean-Jacques Hiblot jjhiblot@ti.com wrote:
- convert to livetree API
- don't fail because of an invalid bus-width, instead default to 1-bit.
- recognize 1.2v DDR and 1.2v HS200 flags
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com
changes since v2:
- use the wrappers like dev_read_u32_default() to access the DTS instead of using the livetree API.
drivers/mmc/mmc-uclass.c | 36 ++++++++++++++++++++---------------- include/mmc.h | 11 ++++++++++- 2 files changed, 30 insertions(+), 17 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

This is a useful information while debugging the initialization process or performance issues. Also dump this information with the other mmc info if the verbose option is selected
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com --- changes since v2: * dump the capabilities during the initialization only when debug is enabled * dump teh capabilities in print_mmcinfo() if the MMC_VERBOSE option is enabled (it's enabled by default).
cmd/mmc.c | 4 ++++ drivers/mmc/mmc.c | 9 +++++++++ 2 files changed, 13 insertions(+)
diff --git a/cmd/mmc.c b/cmd/mmc.c index 6d48ecb..25795e0 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -24,7 +24,11 @@ static void print_mmcinfo(struct mmc *mmc) (mmc->cid[1] >> 8) & 0xff, mmc->cid[1] & 0xff);
printf("Bus Speed: %d\n", mmc->clock); +#if CONFIG_IS_ENABLED(MMC_VERBOSE) printf("Mode : %s\n", mmc_mode_name(mmc->selected_mode)); + mmc_dump_capabilities("card capabilities", mmc->card_caps); + mmc_dump_capabilities("host capabilities", mmc->host_caps); +#endif printf("Rd Block Len: %d\n", mmc->read_bl_len);
printf("%s version %d.%d", IS_SD(mmc) ? "SD" : "MMC", diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ab2483e..9b5c982 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1582,6 +1582,10 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) bool uhs_en = (mmc->ocr & OCR_S18R) ? true : false; uint caps;
+#ifdef DEBUG + mmc_dump_capabilities("sd card", card_caps); + mmc_dump_capabilities("host", mmc->host_caps | MMC_MODE_1BIT); +#endif
/* Restrict card's capabilities by what the host can do */ caps = card_caps & (mmc->host_caps | MMC_MODE_1BIT); @@ -1764,6 +1768,11 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) const struct mode_width_tuning *mwt; const struct ext_csd_bus_width *ecbw;
+#ifdef DEBUG + mmc_dump_capabilities("mmc", card_caps); + mmc_dump_capabilities("host", mmc->host_caps | MMC_MODE_1BIT); +#endif + /* Restrict card's capabilities by what the host can do */ card_caps &= (mmc->host_caps | MMC_MODE_1BIT);

As the legacy modes were not added to the list of supported modes, old cards that do not support other modes could not be used.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Lukasz Majewski lukma@denx.de Reviewed-by: Simon Glass sjg@chromium.org --- no change since v1
drivers/mmc/mmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 9b5c982..c1f8851 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -818,7 +818,7 @@ static int mmc_get_capabilities(struct mmc *mmc) u8 *ext_csd = mmc->ext_csd; char cardtype;
- mmc->card_caps = MMC_MODE_1BIT; + mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(MMC_LEGACY);
if (mmc_host_is_spi(mmc)) return 0; @@ -1171,7 +1171,7 @@ static int sd_get_capabilities(struct mmc *mmc) int timeout; u32 sd3_bus_mode;
- mmc->card_caps = MMC_MODE_1BIT; + mmc->card_caps = MMC_MODE_1BIT | MMC_CAP(SD_LEGACY);
if (mmc_host_is_spi(mmc)) return 0;

Make sure that those basic capabilities are advertised by the host.
Signed-off-by: Jean-Jacques Hiblot jjhiblot@ti.com Reviewed-by: Lukasz Majewski lukma@denx.de Reviewed-by: Simon Glass sjg@chromium.org --- no change since v1
drivers/mmc/mmc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index c1f8851..0ebcc45 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1584,11 +1584,11 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps)
#ifdef DEBUG mmc_dump_capabilities("sd card", card_caps); - mmc_dump_capabilities("host", mmc->host_caps | MMC_MODE_1BIT); + mmc_dump_capabilities("host", mmc->host_caps); #endif
/* Restrict card's capabilities by what the host can do */ - caps = card_caps & (mmc->host_caps | MMC_MODE_1BIT); + caps = card_caps & mmc->host_caps;
if (!uhs_en) caps &= ~UHS_CAPS; @@ -1770,11 +1770,11 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps)
#ifdef DEBUG mmc_dump_capabilities("mmc", card_caps); - mmc_dump_capabilities("host", mmc->host_caps | MMC_MODE_1BIT); + mmc_dump_capabilities("host", mmc->host_caps); #endif
/* Restrict card's capabilities by what the host can do */ - card_caps &= (mmc->host_caps | MMC_MODE_1BIT); + card_caps &= mmc->host_caps;
/* Only version 4 of MMC supports wider bus widths */ if (mmc->version < MMC_VERSION_4) @@ -2389,7 +2389,12 @@ int mmc_start_init(struct mmc *mmc) bool uhs_en = supports_uhs(mmc->cfg->host_caps); int err;
- mmc->host_caps = mmc->cfg->host_caps; + /* + * all hosts are capable of 1 bit bus-width and able to use the legacy + * timings. + */ + mmc->host_caps = mmc->cfg->host_caps | MMC_CAP(SD_LEGACY) | + MMC_CAP(MMC_LEGACY) | MMC_MODE_1BIT;
/* we pretend there's no card when init is NULL */ no_card = mmc_getcd(mmc) == 0;
participants (2)
-
Jean-Jacques Hiblot
-
Simon Glass