diff options
| author | Tom Rini <[email protected]> | 2025-11-07 08:26:10 -0600 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2025-11-07 08:26:10 -0600 |
| commit | b660df558545b42f7257899807b83cfc620b2983 (patch) | |
| tree | bca942b3912681010f038bf154d154482d6be4e5 | |
| parent | fdf36c2e9ad4f770ee951398a86bd55404d9b7ec (diff) | |
| parent | 0408ae531fe8ad01b9b788181fc5b91e0a527b42 (diff) | |
Merge tag 'mmc-master-2025-11-07' of https://source.denx.de/u-boot/custodians/u-boot-mmc
CI: https://source.denx.de/u-boot/custodians/u-boot-mmc/-/pipelines/28218
- Disabling FMP on Exynos850 to make eMMC functional when U-Boot is
executed during USB boot
- Drop extra included errno.h
| -rw-r--r-- | arch/arm/mach-exynos/include/mach/dwmmc.h | 6 | ||||
| -rw-r--r-- | common/spl/spl_mmc.c | 1 | ||||
| -rw-r--r-- | drivers/mmc/dw_mmc.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/exynos_dw_mmc.c | 78 | ||||
| -rw-r--r-- | include/dwmmc.h | 3 |
5 files changed, 65 insertions, 29 deletions
diff --git a/arch/arm/mach-exynos/include/mach/dwmmc.h b/arch/arm/mach-exynos/include/mach/dwmmc.h index 75d84988b7d..4432deedef7 100644 --- a/arch/arm/mach-exynos/include/mach/dwmmc.h +++ b/arch/arm/mach-exynos/include/mach/dwmmc.h @@ -17,10 +17,16 @@ /* Protector Register */ #define DWMCI_EMMCP_BASE 0x1000 +#define EMMCP_MPSECURITY (DWMCI_EMMCP_BASE + 0x0010) #define EMMCP_MPSBEGIN0 (DWMCI_EMMCP_BASE + 0x0200) #define EMMCP_SEND0 (DWMCI_EMMCP_BASE + 0x0204) #define EMMCP_CTRL0 (DWMCI_EMMCP_BASE + 0x020c) +/* EMMCP_MPSECURITY bits */ +#define MPSECURITY_FMP_ON BIT(29) +#define MPSECURITY_MMC_SFR_PROT_ON BIT(28) + +/* EMMCP_CTRL0 bits */ #define MPSCTRL_SECURE_READ_BIT BIT(7) #define MPSCTRL_SECURE_WRITE_BIT BIT(6) #define MPSCTRL_NON_SECURE_READ_BIT BIT(5) diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 0a00d295575..d8ce3a84614 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -12,7 +12,6 @@ #include <spl_load.h> #include <linux/compiler.h> #include <errno.h> -#include <errno.h> #include <mmc.h> #include <image.h> #include <imx_container.h> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index f3c0cc5cd8e..d9c05b223d5 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -490,8 +490,8 @@ static int dwmci_send_cmd_common(struct dwmci_host *host, struct mmc_cmd *cmd, } #ifdef CONFIG_DM_MMC -int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, - struct mmc_data *data) +static int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) { struct mmc *mmc = mmc_get_mmc_dev(dev); #else @@ -597,7 +597,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) } #ifdef CONFIG_DM_MMC -int dwmci_set_ios(struct udevice *dev) +static int dwmci_set_ios(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); #else diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index b230e9dbbf8..7ccd113bd79 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -26,12 +26,25 @@ #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 /* CLKSEL register defines */ -#define CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) -#define CLKSEL_UP_SAMPLE(x, y) (((x) & ~CLKSEL_CCLK_SAMPLE(7)) |\ +#define CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) +#define CLKSEL_UP_SAMPLE(x, y) (((x) & ~CLKSEL_CCLK_SAMPLE(7)) | \ CLKSEL_CCLK_SAMPLE(y)) -/* Quirks */ +/** + * DOC: Quirk flags for different Exynos DW MMC blocks + * + * %DWMCI_QUIRK_DISABLE_SMU: DW MMC block has Security Management Unit (SMU) + * which has to be configured in non-encryption mode during driver's init. + * + * %DWMCI_QUIRK_DISABLE_FMP: DW MMC block has Flash Memory Protector (FMP) which + * has to be disabled during driver's init. This flag disables FMP encryption + * and lets external non-secure main CPUs access the SFR (peripheral memory + * region, i.e. registers) in MMC core. Although it's usually done by early + * bootloaders (before U-Boot), in some cases like during USB boot the FMP might + * be left unconfigured. + */ #define DWMCI_QUIRK_DISABLE_SMU BIT(0) +#define DWMCI_QUIRK_DISABLE_FMP BIT(1) #ifdef CONFIG_DM_MMC #include <dm.h> @@ -183,9 +196,11 @@ static unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq) int err; /* Should be double rate for DDR or HS mode */ - if ((host->mmc->selected_mode == MMC_DDR_52 && host->mmc->bus_width == 8) || - host->mmc->selected_mode == MMC_HS_400) + if ((host->mmc->selected_mode == MMC_DDR_52 && + host->mmc->bus_width == 8) || + host->mmc->selected_mode == MMC_HS_400) { freq *= 2; + } clk_div = exynos_dwmmc_get_ciu_div(host); err = exynos_dwmmc_set_sclk(host, freq * clk_div); @@ -218,6 +233,18 @@ static void exynos_dwmci_board_init(struct dwmci_host *host) MPSCTRL_NON_SECURE_WRITE_BIT | MPSCTRL_VALID); } + if (priv->chip->quirks & DWMCI_QUIRK_DISABLE_FMP) { + u32 reg; + + reg = dwmci_readl(host, EMMCP_MPSECURITY); + if (reg & MPSECURITY_FMP_ON || + reg & MPSECURITY_MMC_SFR_PROT_ON) { + reg &= ~MPSECURITY_FMP_ON; + reg &= ~MPSECURITY_MMC_SFR_PROT_ON; + dwmci_writel(host, EMMCP_MPSECURITY, reg); + } + } + if (priv->sdr_timing) exynos_dwmci_clksel(host); } @@ -302,7 +329,7 @@ static int exynos_dwmmc_of_to_plat(struct udevice *dev) #if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int exynos_dwmmc_get_best_clksmpl(u8 candidates) { - u8 i; + int i; for (i = 0; i < 8; i++) { candidates = (candidates >> 1) | (candidates << 7); /* ror */ @@ -317,8 +344,8 @@ static int exynos_dwmmc_get_best_clksmpl(u8 candidates) } /* - * If no valid clock sample values are found, use the first - * canditate bit for clock sample value. + * If no valid clock sample values are found, use the first candidate + * bit for clock sample value. */ for (i = 0; i < 8; i++) { candidates = (candidates >> 1) | (candidates << 7); /* ror */ @@ -344,7 +371,7 @@ static int exynos_dwmmc_execute_tuning(struct udevice *dev, u32 opcode) do { dwmci_writel(host, DWMCI_TMOUT, ~0); - /* move to the next clksmpl */ + /* Move to the next clksmpl */ smpl = (clksel + 1) & 0x7; clksel = CLKSEL_UP_SAMPLE(clksel, smpl); dwmci_writel(host, priv->chip->clksel, clksel); @@ -360,12 +387,13 @@ static int exynos_dwmmc_execute_tuning(struct udevice *dev, u32 opcode) return ret; } - dwmci_writel(host, priv->chip->clksel, - CLKSEL_UP_SAMPLE(clksel, ret)); + dwmci_writel(host, priv->chip->clksel, CLKSEL_UP_SAMPLE(clksel, ret)); return 0; } -#endif +#endif /* CONFIG_MMC_SUPPORTS_TUNING */ + +struct dm_mmc_ops exynos_dwmmc_ops; static int exynos_dwmmc_probe(struct udevice *dev) { @@ -376,6 +404,12 @@ static int exynos_dwmmc_probe(struct udevice *dev) unsigned long freq; int err; + /* Extend generic 'dm_dwmci_ops' with .execute_tuning implementation */ + memcpy(&exynos_dwmmc_ops, &dm_dwmci_ops, sizeof(struct dm_mmc_ops)); +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) + exynos_dwmmc_ops.execute_tuning = exynos_dwmmc_execute_tuning; +#endif + #ifndef CONFIG_CPU_V7A err = clk_get_by_index(dev, 1, &priv->clk); /* ciu */ if (err) @@ -388,7 +422,7 @@ static int exynos_dwmmc_probe(struct udevice *dev) flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; err = exynos_pinmux_config(host->dev_id, flag); if (err) { - printf("DWMMC%d not configure\n", host->dev_index); + printf("DWMMC%d not configured\n", host->dev_index); return err; } #endif @@ -454,6 +488,11 @@ static const struct exynos_dwmmc_variant exynos7_smu_drv_data = { .quirks = DWMCI_QUIRK_DISABLE_SMU, }; +static const struct exynos_dwmmc_variant exynos850_drv_data = { + .clksel = DWMCI_CLKSEL64, + .quirks = DWMCI_QUIRK_DISABLE_SMU | DWMCI_QUIRK_DISABLE_FMP, +}; + static const struct udevice_id exynos_dwmmc_ids[] = { { .compatible = "samsung,exynos4412-dw-mshc", @@ -476,18 +515,13 @@ static const struct udevice_id exynos_dwmmc_ids[] = { }, { .compatible = "samsung,exynos7870-dw-mshc-smu", .data = (ulong)&exynos7_smu_drv_data, + }, { + .compatible = "samsung,exynos850-dw-mshc-smu", + .data = (ulong)&exynos850_drv_data, }, { } }; -struct dm_mmc_ops exynos_dwmmc_ops = { - .send_cmd = dwmci_send_cmd, - .set_ios = dwmci_set_ios, -#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) - .execute_tuning = exynos_dwmmc_execute_tuning, -#endif -}; - U_BOOT_DRIVER(exynos_dwmmc_drv) = { .name = "exynos_dwmmc", .id = UCLASS_MMC, @@ -499,4 +533,4 @@ U_BOOT_DRIVER(exynos_dwmmc_drv) = { .priv_auto = sizeof(struct dwmci_exynos_priv_data), .plat_auto = sizeof(struct exynos_mmc_plat), }; -#endif +#endif /* CONFIG_DM_MMC */ diff --git a/include/dwmmc.h b/include/dwmmc.h index 47e3220985e..7e1a6646518 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -338,9 +338,6 @@ int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk); #ifdef CONFIG_DM_MMC /* Export the operations to drivers */ int dwmci_probe(struct udevice *dev); -int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, - struct mmc_data *data); -int dwmci_set_ios(struct udevice *dev); extern const struct dm_mmc_ops dm_dwmci_ops; #endif |
