From 6dcf1c28dd4344e73fb3108c037b5b9093852328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 29 Apr 2022 20:27:34 +0200 Subject: [PATCH 1/5] mmc: fsl_esdhc: Fix 'Internal clock never stabilised.' error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only newer eSDHC controllers set PRSSTAT_SDSTB flag. So do not wait until flag PRSSTAT_SDSTB is set on old pre-2.2 controllers. Instead sleep for fixed amount of time like it was before commit 6f883e501b65 ("mmc: fsl_esdhc: Add emmc hs200 support"). This change fixes error 'Internal clock never stabilised.' which is printed on P2020 board at every access to SD card. Fixes: 6f883e501b65 ("mmc: fsl_esdhc: Add emmc hs200 support") Signed-off-by: Pali Rohár Reviewed-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/mmc/fsl_esdhc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index b49a7b425b..ca5a87969f 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -504,6 +504,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) u32 time_out; u32 value; uint clk; + u32 hostver; if (clock < mmc->cfg->f_min) clock = mmc->cfg->f_min; @@ -544,6 +545,14 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); + /* Only newer eSDHC controllers set PRSSTAT_SDSTB flag */ + hostver = esdhc_read32(&priv->esdhc_regs->hostver); + if (HOSTVER_VENDOR(hostver) <= VENDOR_V_22) { + udelay(10000); + esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); + return; + } + time_out = 20; value = PRSSTAT_SDSTB; while (!(esdhc_read32(®s->prsstat) & value)) { @@ -563,6 +572,7 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) struct fsl_esdhc *regs = priv->esdhc_regs; u32 value; u32 time_out; + u32 hostver; value = esdhc_read32(®s->sysctl); @@ -573,6 +583,13 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) esdhc_write32(®s->sysctl, value); + /* Only newer eSDHC controllers set PRSSTAT_SDSTB flag */ + hostver = esdhc_read32(&priv->esdhc_regs->hostver); + if (HOSTVER_VENDOR(hostver) <= VENDOR_V_22) { + udelay(10000); + return; + } + time_out = 20; value = PRSSTAT_SDSTB; while (!(esdhc_read32(®s->prsstat) & value)) { From 3363a73ddfcda752256b8c06ffde75f6b8d5b819 Mon Sep 17 00:00:00 2001 From: Jim Liu Date: Tue, 24 May 2022 16:55:33 +0800 Subject: [PATCH 2/5] mmc: nuvoton: Add NPCM7xx mmc driver Add Nuvoton BMC NPCM750 mmc control driver. Signed-off-by: Jim Liu Reviewed-by: Jaehoon Chung --- drivers/mmc/Kconfig | 12 ++++++ drivers/mmc/Makefile | 1 + drivers/mmc/npcm_sdhci.c | 86 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 drivers/mmc/npcm_sdhci.c diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 95d63b6226..c5e1a1b098 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -618,6 +618,18 @@ config MMC_SDHCI_MV If unsure, say N. +config MMC_SDHCI_NPCM + bool "SDHCI support on Nuvoton NPCM device" + depends on MMC_SDHCI + depends on DM_MMC + help + This selects the Secure Digital Host Controller Interface (SDHCI) + on Nuvoton NPCM device. + + If you have a controller with this interface, say Y here. + + If unsure, say N. + config MMC_SDHCI_PIC32 bool "Microchip PIC32 on-chip SDHCI support" depends on DM_MMC && MACH_PIC32 diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 7c4243289c..5d5104bbf1 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_MMC_SDHCI_IPROC) += iproc_sdhci.o obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o obj-$(CONFIG_MMC_SDHCI_MSM) += msm_sdhci.o obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o +obj-$(CONFIG_MMC_SDHCI_NPCM) += npcm_sdhci.o obj-$(CONFIG_MMC_SDHCI_PIC32) += pic32_sdhci.o obj-$(CONFIG_MMC_SDHCI_ROCKCHIP) += rockchip_sdhci.o obj-$(CONFIG_MMC_SDHCI_S5P) += s5p_sdhci.o diff --git a/drivers/mmc/npcm_sdhci.c b/drivers/mmc/npcm_sdhci.c new file mode 100644 index 0000000000..7eb17cce0b --- /dev/null +++ b/drivers/mmc/npcm_sdhci.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2022 Nuvoton Technology Corp. + */ + +#include +#include +#include +#include +#include + +#define NPCM_SDHC_MIN_FREQ 400000 + +struct npcm_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static int npcm_sdhci_probe(struct udevice *dev) +{ + struct npcm_sdhci_plat *plat = dev_get_plat(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct sdhci_host *host = dev_get_priv(dev); + struct udevice *vqmmc_supply; + int vqmmc_uv, ret; + struct clk clk; + + host->name = dev->name; + host->ioaddr = dev_read_addr_ptr(dev); + host->max_clk = dev_read_u32_default(dev, "clock-frequency", 0); + + ret = clk_get_by_index(dev, 0, &clk); + if (!ret && host->max_clk) { + ret = clk_set_rate(&clk, host->max_clk); + if (ret < 0) + return ret; + } + + if (IS_ENABLED(CONFIG_DM_REGULATOR)) { + device_get_supply_regulator(dev, "vqmmc-supply", &vqmmc_supply); + vqmmc_uv = dev_read_u32_default(dev, "vqmmc-microvolt", 0); + /* Set IO voltage */ + if (vqmmc_supply && vqmmc_uv) + regulator_set_value(vqmmc_supply, vqmmc_uv); + } + + host->index = dev_read_u32_default(dev, "index", 0); + ret = mmc_of_parse(dev, &plat->cfg); + if (ret) + return ret; + + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, NPCM_SDHC_MIN_FREQ); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static int npcm_sdhci_bind(struct udevice *dev) +{ + struct npcm_sdhci_plat *plat = dev_get_plat(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id npcm_mmc_ids[] = { + { .compatible = "nuvoton,npcm750-sdhci" }, + { .compatible = "nuvoton,npcm845-sdhci" }, + { } +}; + +U_BOOT_DRIVER(npcm_sdhci_drv) = { + .name = "npcm_sdhci", + .id = UCLASS_MMC, + .of_match = npcm_mmc_ids, + .ops = &sdhci_ops, + .bind = npcm_sdhci_bind, + .probe = npcm_sdhci_probe, + .priv_auto = sizeof(struct sdhci_host), + .plat_auto = sizeof(struct npcm_sdhci_plat), +}; From 19a29ff362d4cc9e7f420021de57e3193812d4c6 Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Mon, 25 Apr 2022 21:59:02 +0800 Subject: [PATCH 3/5] drivers: mmc: write protect single boot area Add features to write protect single boot area rather than all boot areas. Signed-off-by: Ying-Chun Liu (PaulLiu) Cc: Peng Fan Cc: Jaehoon Chung --- drivers/mmc/mmc.c | 27 +++++++++++++++++++++++++++ include/mmc.h | 16 ++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 12d29da528..8efee9977e 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -863,6 +863,33 @@ int mmc_boot_wp(struct mmc *mmc) return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, 1); } +int mmc_boot_wp_single_partition(struct mmc *mmc, int partition) +{ + u8 value; + int ret; + + value = EXT_CSD_BOOT_WP_B_PWR_WP_EN; + + if (partition == 0) { + value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL; + ret = mmc_switch(mmc, + EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BOOT_WP, + value); + } else if (partition == 1) { + value |= EXT_CSD_BOOT_WP_B_SEC_WP_SEL; + value |= EXT_CSD_BOOT_WP_B_PWR_WP_SEC_SEL; + ret = mmc_switch(mmc, + EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BOOT_WP, + value); + } else { + ret = mmc_boot_wp(mmc); + } + + return ret; +} + #if !CONFIG_IS_ENABLED(MMC_TINY) static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode, bool hsdowngrade) diff --git a/include/mmc.h b/include/mmc.h index 073b01f82b..f519d86972 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -308,6 +308,10 @@ static inline bool mmc_is_tuning_cmd(uint cmdidx) #define EXT_CSD_HS_CTRL_REL (1 << 0) /* host controlled WR_REL_SET */ +#define EXT_CSD_BOOT_WP_B_SEC_WP_SEL (0x80) /* enable partition selector */ +#define EXT_CSD_BOOT_WP_B_PWR_WP_SEC_SEL (0x02) /* partition selector to protect */ +#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01) /* power-on write-protect */ + #define EXT_CSD_WR_DATA_REL_USR (1 << 0) /* user data area WR_REL */ #define EXT_CSD_WR_DATA_REL_GP(x) (1 << ((x)+1)) /* GP part (x+1) WR_REL */ @@ -991,6 +995,18 @@ int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd); */ int mmc_boot_wp(struct mmc *mmc); +/** + * mmc_boot_wp_single_partition() - set write protection to a boot partition. + * + * This function sets a single boot partition to protect and leave the + * other partition writable. + * + * @param mmc the mmc device. + * @param partition 0 - first boot partition, 1 - second boot partition. + * @return 0 for success + */ +int mmc_boot_wp_single_partition(struct mmc *mmc, int partition); + static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) { return data->flags & MMC_DATA_WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE; From 233662411d12109cdc8957de6e85fb30fe2d42b8 Mon Sep 17 00:00:00 2001 From: "Ying-Chun Liu (PaulLiu)" Date: Mon, 25 Apr 2022 21:59:03 +0800 Subject: [PATCH 4/5] cmd: mmc: allow to write protect single boot partition add arguments for mmc wp to assign which boot partition to protect. Signed-off-by: Ying-Chun Liu (PaulLiu) Cc: Peng Fan Cc: Jaehoon Chung --- cmd/mmc.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index 63bf69b0bd..f7b02b3149 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -1048,6 +1048,7 @@ static int do_mmc_boot_wp(struct cmd_tbl *cmdtp, int flag, { int err; struct mmc *mmc; + int part; mmc = init_mmc_device(curr_device, false); if (!mmc) @@ -1056,7 +1057,14 @@ static int do_mmc_boot_wp(struct cmd_tbl *cmdtp, int flag, printf("It is not an eMMC device\n"); return CMD_RET_FAILURE; } - err = mmc_boot_wp(mmc); + + if (argc == 2) { + part = dectoul(argv[1], NULL); + err = mmc_boot_wp_single_partition(mmc, part); + } else { + err = mmc_boot_wp(mmc); + } + if (err) return CMD_RET_FAILURE; printf("boot areas protected\n"); @@ -1066,7 +1074,7 @@ static int do_mmc_boot_wp(struct cmd_tbl *cmdtp, int flag, static struct cmd_tbl cmd_mmc[] = { U_BOOT_CMD_MKENT(info, 1, 0, do_mmcinfo, "", ""), U_BOOT_CMD_MKENT(read, 4, 1, do_mmc_read, "", ""), - U_BOOT_CMD_MKENT(wp, 1, 0, do_mmc_boot_wp, "", ""), + U_BOOT_CMD_MKENT(wp, 2, 0, do_mmc_boot_wp, "", ""), #if CONFIG_IS_ENABLED(MMC_WRITE) U_BOOT_CMD_MKENT(write, 4, 0, do_mmc_write, "", ""), U_BOOT_CMD_MKENT(erase, 3, 0, do_mmc_erase, "", ""), @@ -1140,7 +1148,11 @@ U_BOOT_CMD( " [MMC_LEGACY, MMC_HS, SD_HS, MMC_HS_52, MMC_DDR_52, UHS_SDR12, UHS_SDR25,\n" " UHS_SDR50, UHS_DDR50, UHS_SDR104, MMC_HS_200, MMC_HS_400, MMC_HS_400_ES]\n" "mmc list - lists available devices\n" - "mmc wp - power on write protect boot partitions\n" + "mmc wp [PART] - power on write protect boot partitions\n" + " arguments:\n" + " PART - [0|1]\n" + " : 0 - first boot partition, 1 - second boot partition\n" + " if not assigned, write protect all boot partitions\n" #if CONFIG_IS_ENABLED(MMC_HW_PARTITIONING) "mmc hwpartition - does hardware partitioning\n" " arguments (sizes in 512-byte blocks):\n" From 2785fc4868db1f2643ffd2b989c88cde9dcced4c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 12 Jun 2022 12:53:48 +0000 Subject: [PATCH 5/5] mmc: pci_mmc.c should build with ACPIGEN=n sandbox_defconfig builds the PCI MMC driver. It should be possible to build the sandbox without ACPI support. ACPI support in the PCI MMC driver is only needed when creating an ACPI table. Fix building with ACPIGEN=n. Fixes: dba7ee419d9d ("acpi: mmc: Generate ACPI info for the PCI SD Card") Signed-off-by: Heinrich Schuchardt --- drivers/mmc/pci_mmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index cba2ea8cf3..9fb7044029 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -86,6 +86,7 @@ static int pci_mmc_bind(struct udevice *dev) return sdhci_bind(dev, &plat->mmc, &plat->cfg); } +__maybe_unused static int pci_mmc_acpi_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) { @@ -138,7 +139,9 @@ static int pci_mmc_acpi_fill_ssdt(const struct udevice *dev, } struct acpi_ops pci_mmc_acpi_ops = { +#ifdef CONFIG_ACPIGEN .fill_ssdt = pci_mmc_acpi_fill_ssdt, +#endif }; static const struct udevice_id pci_mmc_match[] = {