From: Kaustabh Chakraborty Date: Fri, 17 Oct 2025 15:24:13 +0000 (+0530) Subject: mmc: exynos_dw_mmc: add support for SD UHS mode X-Git-Tag: v2026.01-rc2~55^2~11 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bc707c576c4c926a98e57030861af4c8d1596862;p=pandora-u-boot.git mmc: exynos_dw_mmc: add support for SD UHS mode SD UHS mode is already supported by the Exynos DW-MMC driver in mainline Linux. Using that as reference, add support in the U-Boot driver. The maximum frequency was capped to 200000000, increase it to 208000000, which is the required frequency for UHS_SDR104, which has the highest frequency of all UHS modes. Moreover, add UHS_CAPS to host capailities. These changes allow both host and card to recognize support for all UHS modes. SDR104, SDR50, and DDR50 have their own CLKSEL timing values, which requires the CIU div value to be set in bits 18:16. Move the function exynos_dwmci_clksel() below exynos_dwmmc_get_ciu_div() so that the latter is accessible from the former, and add cases for said timing modes. Signed-off-by: Kaustabh Chakraborty Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 66d2b8bdafd..7e7b472411c 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -18,7 +18,7 @@ #include #define DWMMC_MAX_CH_NUM 4 -#define DWMMC_MAX_FREQ 200000000 +#define DWMMC_MAX_FREQ 208000000 #define DWMMC_MIN_FREQ 400000 #define DWMMC_MMC0_SDR_TIMING_VAL 0x03030001 #define DWMMC_MMC2_SDR_TIMING_VAL 0x03020001 @@ -126,22 +126,6 @@ static int exynos_dwmmc_set_sclk(struct dwmci_host *host, unsigned long rate) return 0; } -/* Configure CLKSEL register with chosen timing values */ -static int exynos_dwmci_clksel(struct dwmci_host *host) -{ - struct dwmci_exynos_priv_data *priv = exynos_dwmmc_get_priv(host); - u32 timing; - - if (host->mmc->selected_mode == MMC_DDR_52) - timing = priv->ddr_timing; - else - timing = priv->sdr_timing; - - dwmci_writel(host, priv->chip->clksel, timing); - - return 0; -} - /** * exynos_dwmmc_get_ciu_div - Get internal clock divider value * @host: MMC controller object @@ -165,6 +149,33 @@ static u8 exynos_dwmmc_get_ciu_div(struct dwmci_host *host) & DWMCI_DIVRATIO_MASK) + 1; } +/* Configure CLKSEL register with chosen timing values */ +static int exynos_dwmci_clksel(struct dwmci_host *host) +{ + struct dwmci_exynos_priv_data *priv = exynos_dwmmc_get_priv(host); + u8 clk_div = exynos_dwmmc_get_ciu_div(host) - 1; + u32 timing; + + switch (host->mmc->selected_mode) { + case MMC_DDR_52: + timing = priv->ddr_timing; + break; + case UHS_SDR104: + case UHS_SDR50: + timing = (priv->sdr_timing & 0xfff8ffff) | (clk_div << 16); + break; + case UHS_DDR50: + timing = (priv->ddr_timing & 0xfff8ffff) | (clk_div << 16); + break; + default: + timing = priv->sdr_timing; + } + + dwmci_writel(host, priv->chip->clksel, timing); + + return 0; +} + static unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq) { unsigned long sclk; @@ -393,7 +404,8 @@ static int exynos_dwmmc_probe(struct udevice *dev) host->name = dev->name; host->board_init = exynos_dwmci_board_init; - host->caps = MMC_MODE_DDR_52MHz | MMC_MODE_HS200 | MMC_MODE_HS400; + host->caps = MMC_MODE_DDR_52MHz | MMC_MODE_HS200 | MMC_MODE_HS400 | + UHS_CAPS; host->clksel = exynos_dwmci_clksel; host->get_mmc_clk = exynos_dwmci_get_clk;