Hi Alexandru,

> Sent: mercredi 9 septembre 2020 23:54
> To: uboot-st...@st-md-mailman.stormreply.com
> Cc: Alexandru Gagniuc <mr.nuke...@gmail.com>; Patrick DELAUNAY
> <patrick.delau...@st.com>; Patrice CHOTARD <patrice.chot...@st.com>; Peng
> Fan <peng....@nxp.com>; u-boot@lists.denx.de
> Subject: [PATCH] mmc: stm32_sdmmc2: Use mmc_of_parse() to read host
> capabilities
> Importance: High
> 
> mmc_of_parse() can populate the 'f_max' and 'host_caps' fields of struct
> mmc_config from devicetree.
> The same logic is duplicated in stm32_sdmmc2_probe(). Use mmc_of_parse(),
> which is more generic.
> 
> Signed-off-by: Alexandru Gagniuc <mr.nuke...@gmail.com>
> ---

Thanks for the patch, I miss the addition of this new API.

>  drivers/mmc/stm32_sdmmc2.c | 18 ++----------------
>  1 file changed, 2 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index
> 6d50356217..77871d5afc 100644
> --- a/drivers/mmc/stm32_sdmmc2.c
> +++ b/drivers/mmc/stm32_sdmmc2.c
> @@ -676,27 +676,13 @@ static int stm32_sdmmc2_probe(struct udevice *dev)
>                            GPIOD_IS_IN);
> 
>       cfg->f_min = 400000;
> -     cfg->f_max = dev_read_u32_default(dev, "max-frequency", 52000000);
>       cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 |
> MMC_VDD_165_195;
>       cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
>       cfg->name = "STM32 SD/MMC";
> 
>       cfg->host_caps = 0;
> -     if (cfg->f_max > 25000000)
> -             cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
> -
> -     switch (dev_read_u32_default(dev, "bus-width", 1)) {
> -     case 8:
> -             cfg->host_caps |= MMC_MODE_8BIT;
> -             /* fall through */
> -     case 4:
> -             cfg->host_caps |= MMC_MODE_4BIT;
> -             break;
> -     case 1:
> -             break;
> -     default:
> -             pr_err("invalid \"bus-width\" property, force to 1\n");
> -     }
> +     cfg->f_max = 52000000;
> +     mmc_of_parse(dev, cfg);

Result of mmc_of_parse is not tested ?

I proposed:

+       ret = mmc_of_parse(dev, cfg);
+       if (ret)
+               return ret;

> 
>       upriv->mmc = &plat->mmc;
> 
> --
> 2.25.4

I test this patch with a trace in stm32_sdmmc2_probe on STM32MP157C-EV1

Before the patch :
cfg->host_caps = 0x2000000e (SD card)
cfg->host_caps = 0x6000000e (eMMC)

After the patch:
cfg->host_caps = 0x300001e6 (SD card)
cfg->host_caps = 0x70004006 (eMMC)


I see 2 problem here :

1/ MMC_MODE_HS_52MHz = MMC_CAP(MMC_HS_52) is removed
    and the eMMC on EV1 use only at 26MHz instead 52MHz before the patch

        Mode: MMC High Speed (52MHz)
        =>
        Mode: MMC High Speed (26MHz)

The "cap-mmc-highspeed" is used in Linux for MMC HS at 26MHz or 52MHz

./Documentation/devicetree/bindings/mmc/mmc-controller.yaml:122: 
cap-mmc-highspeed:
    $ref: /schemas/types.yaml#/definitions/flag
    description:
      MMC high-speed timing is supported.

And in Linux mmc/core/mmc.c
        static void mmc_select_card_type(struct mmc_card *card)
        {
        .....

        if (caps & MMC_CAP_MMC_HIGHSPEED &&
            card_type & EXT_CSD_CARD_TYPE_HS_26) {
                hs_max_dtr = MMC_HIGH_26_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS_26;
        }

        if (caps & MMC_CAP_MMC_HIGHSPEED &&
            card_type & EXT_CSD_CARD_TYPE_HS_52) {
                hs_max_dtr = MMC_HIGH_52_MAX_DTR;
                avail_type |= EXT_CSD_CARD_TYPE_HS_52;
        }
        ....

include/linux/mmc/mmc.h:347:
        #define EXT_CSD_CARD_TYPE_HS_26 (1<<0)  /* Card can run at 26MHz */
        #define EXT_CSD_CARD_TYPE_HS_52 (1<<1)  /* Card can run at 52MHz */

I think that it is a issue U-Boot, in mmc uclass in mmc_of_parse():

        if (dev_read_bool(dev, "cap-mmc-highspeed"))
-               cfg->host_caps |= MMC_CAP(MMC_HS);
+               cfg->host_caps |= MMC_CAP(MMC_HS) | MMC_CAP(MMC_HS_52);

In U-Boot this capability is splitted in 2 bits = one for 26MHz one for 52MHz
And  for card side it is managed on card side by mmc_get_capabilities()

include/mmc.h:254:
        #define EXT_CSD_CARD_TYPE_26    (1 << 0)        /* Card can run at 
26MHz */
        #define EXT_CSD_CARD_TYPE_52    (1 << 1)        /* Card can run at 
52MHz */

A other solution is to only impact the sdmmc driver..... 
and to activate 52MHZ mode support is frequency is >= 26MHz

        cfg->f_max = 52000000;
        ret = mmc_of_parse(dev, cfg);
        if (ret)
                return ret;

        if ((cfg->host_caps & MMC_HS) && 
            cfg->f_max > 26000000)
                cfg->host_caps |= MMC_HS_52;

but I prefer the previous generic solution in u-class.


2) some host caps can be added in device tree (they are supported by SOC and by 
Linux driver)
    but they are not supported by U-Boot driver, for example:

#define MMC_MODE_DDR_52MHz      MMC_CAP(MMC_DDR_52)
#define MMC_MODE_HS200          MMC_CAP(MMC_HS_200)
#define MMC_MODE_HS400          MMC_CAP(MMC_HS_400)
#define MMC_MODE_HS400_ES       MMC_CAP(MMC_HS_400_ES)

MMC_CAP(UHS_SDR12)
MMC_CAP(UHS_SDR25) 
MMC_CAP(UHS_SDR50)
MMC_CAP(UHS_SDR104)
MMC_CAP(UHS_DDR50)

I afraid (I don't sure) that this added caps change the mmc core behavior in 
U-Boot =
U-Boot try to select  the high speed mode even if not supported by driver....

The host_caps bitfield should be limited by the supported features in the 
driver  (or remove the unsupported features)

#define SDMMC_SUPPORTED_CAPS (MMC_MODE_1BIT | MMC_MODE_4BIT | MMC_MODE_8BIT | 
MMC_CAP_CD_ACTIVE_HIGH | MMC_CAP_NEEDS_POLL |  MMC_CAP_NONREMOVABLE | 
MMC_MODE_HS | MMC_MODE_HS_52MHz)
or
#define SDMMC_UNSUPPORTED_CAPS (MMC_MODE_DDR_52MHz | MMC_MODE_HS200 | 
MMC_MODE_HS400 | MMC_MODE_HS400_ES | UHS_CAPS)
 
        cfg->f_max = 52000000;
        ret = mmc_of_parse(dev, cfg);
        if (ret)
                return ret;

        cfg->host_caps &= SDMMC_SUPPORTED_CAPS;
or 
        cfg->host_caps |= ~SDMMC_UNSUPPORTED_CAPS;


Best Regards

Patrick

Reply via email to