diff options
Diffstat (limited to 'drivers/mmc')
67 files changed, 616 insertions, 300 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index cef05790dd9..d0944793c92 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -20,11 +20,19 @@ config MMC_WRITE config MMC_PWRSEQ bool "HW reset support for eMMC" - depends on PWRSEQ + depends on PWRSEQ && DM_GPIO help - Ths select Hardware reset support aka pwrseq-emmc for eMMC + This select Hardware reset support aka pwrseq-emmc for eMMC devices. +config SPL_MMC_PWRSEQ + bool "HW reset support for eMMC in SPL" + depends on SPL_PWRSEQ && SPL_DM_GPIO + default y if MMC_PWRSEQ + help + This select Hardware reset support aka pwrseq-emmc for eMMC + devices in SPL. + config MMC_BROKEN_CD bool "Poll for broken card detection case" help @@ -79,11 +87,12 @@ config MMC_SPI_CRC_ON config ARM_PL180_MMCI bool "ARM AMBA Multimedia Card Interface and compatible support" + depends on DM_MMC help This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card Interface (PL180, PL181 and compatible) support. If you have an ARM(R) platform with a Multimedia Card slot, - say Y or M here. + say Y here. config MMC_QUIRKS bool "Enable quirks" @@ -138,9 +147,16 @@ config SPL_MMC_IO_VOLTAGE support. For eMMC this not mandatory, but not enabling this option may prevent the driver of using the faster modes. +config MMC_SUPPORTS_TUNING + bool + +config SPL_MMC_SUPPORTS_TUNING + bool + config MMC_UHS_SUPPORT bool "enable UHS support" depends on MMC_IO_VOLTAGE + select MMC_SUPPORTS_TUNING help The Ultra High Speed (UHS) bus is available on some SDHC and SDXC cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus @@ -149,6 +165,7 @@ config MMC_UHS_SUPPORT config SPL_MMC_UHS_SUPPORT bool "enable UHS support in SPL" depends on SPL_MMC_IO_VOLTAGE + select SPL_MMC_SUPPORTS_TUNING help The Ultra High Speed (UHS) bus is available on some SDHC and SDXC cards. The IO voltage must be switchable from 3.3v to 1.8v. The bus @@ -184,6 +201,7 @@ config SPL_MMC_HS400_SUPPORT config MMC_HS200_SUPPORT bool "enable HS200 support" + select MMC_SUPPORTS_TUNING help The HS200 mode is support by some eMMC. The bus frequency is up to 200MHz. This mode requires tuning the IO. @@ -191,6 +209,7 @@ config MMC_HS200_SUPPORT config SPL_MMC_HS200_SUPPORT bool "enable HS200 support in SPL" depends on SPL_MMC + select SPL_MMC_SUPPORTS_TUNING help The HS200 mode is support by some eMMC. The bus frequency is up to 200MHz. This mode requires tuning the IO. @@ -338,6 +357,7 @@ config MMC_OCTEONTX bool "Marvell Octeon Multimedia Card Interface support" depends on (ARCH_OCTEON || ARCH_OCTEONTX || ARCH_OCTEONTX2) depends on DM_MMC + select MMC_SUPPORTS_TUNING if ARCH_OCTEONTX2 help This selects the Octeon Multimedia card Interface. If you have an OcteonTX/TX2 or MIPS Octeon board with a @@ -495,6 +515,24 @@ config SPL_MMC_SDHCI_ADMA This enables support for the ADMA (Advanced DMA) defined in the SD Host Controller Standard Specification Version 3.00 in SPL. +config MMC_SDHCI_ADMA_FORCE_32BIT + bool "Force 32 bit mode for ADMA on 64 bit platforms" + help + This forces SDHCI ADMA to be built for 32 bit descriptors, even + on a 64 bit platform where they would otherwise be assumed to + be 64 bits. This is necessary for certain hardware platforms + that are 64-bit but include only 32-bit support within the selected + SD host controller IP. + +config MMC_SDHCI_ADMA_64BIT + bool "Use SHDCI ADMA with 64 bit descriptors" + depends on !MMC_SDHCI_ADMA_FORCE_32BIT + default y if DMA_ADDR_T_64BIT + help + This selects 64 bit descriptors for SDHCI ADMA. It is enabled by + default on 64 bit systems, but can be disabled if one of these + systems includes 32-bit ADMA. + config FIXED_SDHCI_ALIGNED_BUFFER hex "SDRAM address for fixed buffer" depends on SPL && MVEBU_SPL_BOOT_DEVICE_MMC @@ -568,6 +606,19 @@ config MMC_SDHCI_CADENCE If unsure, say N. +config MMC_SDHCI_CV1800B + bool "SDHCI support for the CV1800B SD/SDIO/eMMC controller" + depends on BLK && DM_MMC + depends on MMC_SDHCI + depends on OF_CONTROL + help + This selects the CV1800B SD/SDIO/eMMC driver. + + If you have a controller with this interface, + say Y here. + + If unsure, say N. + config MMC_SDHCI_AM654 bool "SDHCI Controller on TI's Am654 devices" depends on ARCH_K3 @@ -586,7 +637,7 @@ config MMC_SDHCI_IPROC This selects the iProc SD/MMC controller. If you have a Broadcom IPROC platform with SD or MMC devices, - say Y or M here. + say Y here. If unsure, say N. @@ -597,7 +648,7 @@ config MMC_SDHCI_F_SDH30 help This selects the Secure Digital Host Controller Interface (SDHCI) Needed by some Fujitsu/Socionext SoC for MMC / SD / SDIO support. - If you have a controller with this interface, say Y or M here. + If you have a controller with this interface, say Y here. If unsure, say N. config MMC_SDHCI_KONA @@ -791,7 +842,7 @@ config STM32_SDMMC2 help This selects support for the SD/MMC controller on STM32H7 SoCs. If you have a board based on such a SoC and with a SD/MMC slot, - say Y or M here. + say Y here. config FTSDC010 bool "Ftsdc010 SD/MMC controller Support" @@ -811,7 +862,7 @@ config MMC_MTK depends on OF_CONTROL help This selects the MediaTek(R) Secure digital and Multimedia card Interface. - If you have a machine with a integrated SD/MMC card reader, say Y or M here. + If you have a machine with a integrated SD/MMC card reader, say Y here. This is needed if support for any SD/SDIO/MMC devices is required. If unsure, say N. diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index e9cf1fcc640..72c3fb66ce0 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += mmc_bootdev.o endif obj-$(CONFIG_$(SPL_TPL_)MMC_WRITE) += mmc_write.o -obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o +obj-$(CONFIG_$(SPL_)MMC_PWRSEQ) += mmc-pwrseq.o obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o ifndef CONFIG_$(SPL_)BLK @@ -60,6 +60,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o +obj-$(CONFIG_MMC_SDHCI_CV1800B) += cv1800b_sdhci.o obj-$(CONFIG_MMC_SDHCI_AM654) += am654_sdhci.o obj-$(CONFIG_MMC_SDHCI_IPROC) += iproc_sdhci.o obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index 05595bdac39..48fac7a11b4 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -6,7 +6,6 @@ */ #include <clk.h> -#include <common.h> #include <dm.h> #include <malloc.h> #include <mmc.h> @@ -85,6 +84,8 @@ #define AM654_SDHCI_MIN_FREQ 400000 #define CLOCK_TOO_SLOW_HZ 50000000 +#define ENABLE 0x1 + struct am654_sdhci_plat { struct mmc_config cfg; struct mmc mmc; @@ -92,11 +93,13 @@ struct am654_sdhci_plat { bool non_removable; u32 otap_del_sel[MMC_MODES_END]; u32 itap_del_sel[MMC_MODES_END]; + u32 itap_del_ena[MMC_MODES_END]; u32 trm_icp; u32 drv_strength; u32 strb_sel; u32 clkbuf_sel; u32 flags; + bool dll_enable; #define DLL_PRESENT BIT(0) #define IOMUX_PRESENT BIT(1) #define FREQSEL_2_BIT BIT(2) @@ -110,6 +113,12 @@ struct timing_data { u32 capability; }; +struct window { + u8 start; + u8 end; + u8 length; +}; + static const struct timing_data td[] = { [MMC_LEGACY] = {"ti,otap-del-sel-legacy", "ti,itap-del-sel-legacy", @@ -216,8 +225,10 @@ static int am654_sdhci_setup_dll(struct am654_sdhci_plat *plat, } static void am654_sdhci_write_itapdly(struct am654_sdhci_plat *plat, - u32 itapdly) + u32 itapdly, u32 enable) { + regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK, + enable << ITAPDLYENA_SHIFT); /* Set ITAPCHGWIN before writing to ITAPDLY */ regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 1 << ITAPCHGWIN_SHIFT); @@ -235,7 +246,8 @@ static void am654_sdhci_setup_delay_chain(struct am654_sdhci_plat *plat, mask = SELDLYTXCLK_MASK | SELDLYRXCLK_MASK; regmap_update_bits(plat->base, PHY_CTRL5, mask, val); - am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode]); + am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode], + plat->itap_del_ena[mode]); } static int am654_sdhci_set_ios_post(struct sdhci_host *host) @@ -276,12 +288,22 @@ static int am654_sdhci_set_ios_post(struct sdhci_host *host) regmap_update_bits(plat->base, PHY_CTRL4, mask, val); - if (mode > UHS_SDR25 && speed >= CLOCK_TOO_SLOW_HZ) { + if ((mode > UHS_SDR25 || mode == MMC_DDR_52) && speed >= CLOCK_TOO_SLOW_HZ) { ret = am654_sdhci_setup_dll(plat, speed); if (ret) return ret; + + plat->dll_enable = true; + if (mode == MMC_HS_400) { + plat->itap_del_ena[mode] = ENABLE; + plat->itap_del_sel[mode] = plat->itap_del_sel[mode - 1]; + } + + am654_sdhci_write_itapdly(plat, plat->itap_del_sel[mode], + plat->itap_del_ena[mode]); } else { am654_sdhci_setup_delay_chain(plat, mode); + plat->dll_enable = false; } regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK, @@ -374,46 +396,110 @@ static void am654_sdhci_write_b(struct sdhci_host *host, u8 val, int reg) writeb(val, host->ioaddr + reg); } -#ifdef MMC_SUPPORTS_TUNING -#define ITAP_MAX 32 +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) +#define ITAPDLY_LENGTH 32 +#define ITAPDLY_LAST_INDEX (ITAPDLY_LENGTH - 1) + +static u32 am654_sdhci_calculate_itap(struct udevice *dev, struct window + *fail_window, u8 num_fails, bool circular_buffer) +{ + u8 itap = 0, start_fail = 0, end_fail = 0, pass_length = 0; + u8 first_fail_start = 0, last_fail_end = 0; + struct window pass_window = {0, 0, 0}; + int prev_fail_end = -1; + u8 i; + + if (!num_fails) + return ITAPDLY_LAST_INDEX >> 1; + + if (fail_window->length == ITAPDLY_LENGTH) { + dev_err(dev, "No passing ITAPDLY, return 0\n"); + return 0; + } + + first_fail_start = fail_window->start; + last_fail_end = fail_window[num_fails - 1].end; + + for (i = 0; i < num_fails; i++) { + start_fail = fail_window[i].start; + end_fail = fail_window[i].end; + pass_length = start_fail - (prev_fail_end + 1); + + if (pass_length > pass_window.length) { + pass_window.start = prev_fail_end + 1; + pass_window.length = pass_length; + } + prev_fail_end = end_fail; + } + + if (!circular_buffer) + pass_length = ITAPDLY_LAST_INDEX - last_fail_end; + else + pass_length = ITAPDLY_LAST_INDEX - last_fail_end + first_fail_start; + + if (pass_length > pass_window.length) { + pass_window.start = last_fail_end + 1; + pass_window.length = pass_length; + } + + if (!circular_buffer) + itap = pass_window.start + (pass_window.length >> 1); + else + itap = (pass_window.start + (pass_window.length >> 1)) % ITAPDLY_LENGTH; + + return (itap > ITAPDLY_LAST_INDEX) ? ITAPDLY_LAST_INDEX >> 1 : itap; +} + static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) { struct udevice *dev = mmc->dev; struct am654_sdhci_plat *plat = dev_get_plat(dev); - int cur_val, prev_val = 1, fail_len = 0, pass_window = 0, pass_len; - u32 itap; + struct window fail_window[ITAPDLY_LENGTH]; + int mode = mmc->selected_mode; + u8 curr_pass, itap; + u8 fail_index = 0; + u8 prev_pass = 1; + + memset(fail_window, 0, sizeof(fail_window)); /* Enable ITAPDLY */ - regmap_update_bits(plat->base, PHY_CTRL4, ITAPDLYENA_MASK, - 1 << ITAPDLYENA_SHIFT); + plat->itap_del_ena[mode] = ENABLE; - for (itap = 0; itap < ITAP_MAX; itap++) { - am654_sdhci_write_itapdly(plat, itap); + for (itap = 0; itap < ITAPDLY_LENGTH; itap++) { + am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]); - cur_val = !mmc_send_tuning(mmc, opcode, NULL); - if (cur_val && !prev_val) - pass_window = itap; + curr_pass = !mmc_send_tuning(mmc, opcode); - if (!cur_val) - fail_len++; + if (!curr_pass && prev_pass) + fail_window[fail_index].start = itap; - prev_val = cur_val; + if (!curr_pass) { + fail_window[fail_index].end = itap; + fail_window[fail_index].length++; + } + + if (curr_pass && !prev_pass) + fail_index++; + + prev_pass = curr_pass; } - /* - * Having determined the length of the failing window and start of - * the passing window calculate the length of the passing window and - * set the final value halfway through it considering the range as a - * circular buffer - */ - pass_len = ITAP_MAX - fail_len; - itap = (pass_window + (pass_len >> 1)) % ITAP_MAX; - am654_sdhci_write_itapdly(plat, itap); + + if (fail_window[fail_index].length != 0) + fail_index++; + + itap = am654_sdhci_calculate_itap(dev, fail_window, fail_index, + plat->dll_enable); + + /* Save ITAPDLY */ + plat->itap_del_sel[mode] = itap; + + am654_sdhci_write_itapdly(plat, itap, plat->itap_del_ena[mode]); return 0; } #endif const struct sdhci_ops am654_sdhci_ops = { -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .platform_execute_tuning = am654_sdhci_execute_tuning, #endif .deferred_probe = am654_sdhci_deferred_probe, @@ -442,12 +528,29 @@ static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host) { struct udevice *dev = host->mmc->dev; struct am654_sdhci_plat *plat = dev_get_plat(dev); - u32 otap_del_sel, mask, val; + int mode = host->mmc->selected_mode; + u32 otap_del_sel; + u32 itap_del_ena; + u32 itap_del_sel; + u32 mask, val; + + otap_del_sel = plat->otap_del_sel[mode]; - otap_del_sel = plat->otap_del_sel[host->mmc->selected_mode]; mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK; - val = (1 << OTAPDLYENA_SHIFT) | (otap_del_sel << OTAPDLYSEL_SHIFT); + val = (1 << OTAPDLYENA_SHIFT) | + (otap_del_sel << OTAPDLYSEL_SHIFT); + + itap_del_ena = plat->itap_del_ena[mode]; + itap_del_sel = plat->itap_del_sel[mode]; + + mask |= ITAPDLYENA_MASK | ITAPDLYSEL_MASK; + val |= (itap_del_ena << ITAPDLYENA_SHIFT) | + (itap_del_sel << ITAPDLYSEL_SHIFT); + + regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, + 1 << ITAPCHGWIN_SHIFT); regmap_update_bits(plat->base, PHY_CTRL4, mask, val); + regmap_update_bits(plat->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0); regmap_update_bits(plat->base, PHY_CTRL5, CLKBUFSEL_MASK, plat->clkbuf_sel); @@ -456,7 +559,7 @@ static int j721e_4bit_sdhci_set_ios_post(struct sdhci_host *host) } const struct sdhci_ops j721e_4bit_sdhci_ops = { -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .platform_execute_tuning = am654_sdhci_execute_tuning, #endif .deferred_probe = am654_sdhci_deferred_probe, @@ -501,7 +604,7 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev, * Remove the corresponding capability if an otap-del-sel * value is not found */ - for (i = MMC_HS; i <= MMC_HS_400; i++) { + for (i = MMC_LEGACY; i <= MMC_HS_400; i++) { ret = dev_read_u32(dev, td[i].otap_binding, &plat->otap_del_sel[i]); if (ret) { @@ -513,9 +616,13 @@ static int sdhci_am654_get_otap_delay(struct udevice *dev, cfg->host_caps &= ~td[i].capability; } - if (td[i].itap_binding) - dev_read_u32(dev, td[i].itap_binding, - &plat->itap_del_sel[i]); + if (td[i].itap_binding) { + ret = dev_read_u32(dev, td[i].itap_binding, + &plat->itap_del_sel[i]); + + if (!ret) + plat->itap_del_ena[i] = ENABLE; + } } return 0; diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 5cf5502ed54..f00b0ff0dc9 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -11,13 +11,13 @@ /* #define DEBUG */ -#include "common.h" #include <clk.h> #include <errno.h> #include <log.h> #include <malloc.h> #include <mmc.h> #include <dm/device_compat.h> +#include <dm.h> #include <asm/io.h> #include <asm-generic/gpio.h> @@ -25,8 +25,6 @@ #include "arm_pl180_mmci.h" #include <linux/delay.h> -#ifdef CONFIG_DM_MMC -#include <dm.h> #define MMC_CLOCK_MAX 48000000 #define MMC_CLOCK_MIN 400000 @@ -34,7 +32,6 @@ struct arm_pl180_mmc_plat { struct mmc_config cfg; struct mmc mmc; }; -#endif static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd) { @@ -231,6 +228,7 @@ static int do_data_transfer(struct mmc *dev, u32 blksz = 0; u32 data_ctrl = 0; u32 data_len = (u32) (data->blocks * data->blocksize); + assert(data_len < U16_MAX); /* should be ensured by arm_pl180_get_b_max */ if (!host->version2) { blksz = (ffs(data->blocksize) - 1); @@ -358,65 +356,14 @@ static int host_set_ios(struct mmc *dev) return 0; } -#ifndef CONFIG_DM_MMC -/* MMC uses open drain drivers in the enumeration phase */ -static int mmc_host_reset(struct mmc *dev) -{ - struct pl180_mmc_host *host = dev->priv; - - writel(host->pwr_init, &host->base->power); - - return 0; -} - -static const struct mmc_ops arm_pl180_mmci_ops = { - .send_cmd = host_request, - .set_ios = host_set_ios, - .init = mmc_host_reset, -}; - -/* - * mmc_host_init - initialize the mmc controller. - * Set initial clock and power for mmc slot. - * Initialize mmc struct and register with mmc framework. - */ - -int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc) +static int arm_pl180_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt) { - u32 sdi_u32; - - writel(host->pwr_init, &host->base->power); - writel(host->clkdiv_init, &host->base->clock); - udelay(CLK_CHANGE_DELAY); - - /* Disable mmc interrupts */ - sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; - writel(sdi_u32, &host->base->mask0); - - host->cfg.name = host->name; - host->cfg.ops = &arm_pl180_mmci_ops; - - /* TODO remove the duplicates */ - host->cfg.host_caps = host->caps; - host->cfg.voltages = host->voltages; - host->cfg.f_min = host->clock_min; - host->cfg.f_max = host->clock_max; - if (host->b_max != 0) - host->cfg.b_max = host->b_max; - else - host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - - *mmc = mmc_create(&host->cfg, host); - if (!*mmc) - return -1; - debug("registered mmc interface number is:%d\n", - (*mmc)->block_dev.devnum); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct mmc *mmc = upriv->mmc; - return 0; + return U16_MAX / mmc->read_bl_len; } -#endif -#ifdef CONFIG_DM_MMC static void arm_pl180_mmc_init(struct pl180_mmc_host *host) { u32 sdi_u32; @@ -477,7 +424,7 @@ static int arm_pl180_mmc_probe(struct udevice *dev) host->version2 = true; break; default: - host->version2 = true; + host->version2 = false; /* ARM variant */ } gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN); @@ -531,6 +478,7 @@ static const struct dm_mmc_ops arm_pl180_dm_mmc_ops = { .send_cmd = dm_host_request, .set_ios = dm_host_set_ios, .get_cd = dm_mmc_getcd, + .get_b_max = arm_pl180_get_b_max, }; static int arm_pl180_mmc_of_to_plat(struct udevice *dev) @@ -561,4 +509,3 @@ U_BOOT_DRIVER(arm_pl180_mmc) = { .priv_auto = sizeof(struct pl180_mmc_host), .plat_auto = sizeof(struct arm_pl180_mmc_plat), }; -#endif diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c index c9626c6beb8..87a6f66ebb3 100644 --- a/drivers/mmc/aspeed_sdhci.c +++ b/drivers/mmc/aspeed_sdhci.c @@ -4,7 +4,6 @@ * Eddie James <eajames@linux.ibm.com> */ -#include <common.h> #include <clk.h> #include <dm.h> #include <malloc.h> diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index d92bad97b71..0b265196f02 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -4,7 +4,6 @@ * Wenyou.Yang <wenyou.yang@atmel.com> */ -#include <common.h> #include <clk.h> #include <dm.h> #include <malloc.h> diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 5e48394fd0f..598a51d914a 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -36,7 +36,6 @@ * Inspired by sdhci-pci.c, by Pierre Ossman */ -#include <common.h> #include <dm.h> #include <log.h> #include <malloc.h> diff --git a/drivers/mmc/bcm2835_sdhost.c b/drivers/mmc/bcm2835_sdhost.c index 5c23c03d10d..720127468d3 100644 --- a/drivers/mmc/bcm2835_sdhost.c +++ b/drivers/mmc/bcm2835_sdhost.c @@ -30,7 +30,6 @@ * sdhci.c and sdhci-pci.c by Pierre Ossman */ #include <clk.h> -#include <common.h> #include <dm.h> #include <mmc.h> #include <asm/arch/msg.h> diff --git a/drivers/mmc/bcmstb_sdhci.c b/drivers/mmc/bcmstb_sdhci.c index 49846adcf54..7bddbebb162 100644 --- a/drivers/mmc/bcmstb_sdhci.c +++ b/drivers/mmc/bcmstb_sdhci.c @@ -6,7 +6,6 @@ * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org> */ -#include <common.h> #include <dm.h> #include <mach/sdhci.h> #include <malloc.h> diff --git a/drivers/mmc/ca_dw_mmc.c b/drivers/mmc/ca_dw_mmc.c index a17ed8c11cb..54a2ba4795e 100644 --- a/drivers/mmc/ca_dw_mmc.c +++ b/drivers/mmc/ca_dw_mmc.c @@ -4,7 +4,6 @@ * Arthur Li <arthur.li@cortina-access.com> */ -#include <common.h> #include <dwmmc.h> #include <fdtdec.h> #include <asm/global_data.h> diff --git a/drivers/mmc/cv1800b_sdhci.c b/drivers/mmc/cv1800b_sdhci.c new file mode 100644 index 00000000000..4e75051c317 --- /dev/null +++ b/drivers/mmc/cv1800b_sdhci.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +#include <dm.h> +#include <mmc.h> +#include <sdhci.h> +#include <linux/delay.h> + +#define SDHCI_PHY_TX_RX_DLY 0x240 +#define MMC_MAX_CLOCK 375000000 +#define TUNE_MAX_PHCODE 128 + +#define PHY_TX_SRC_INVERT BIT(8) + +struct cv1800b_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static void cv1800b_set_tap_delay(struct sdhci_host *host, u16 tap) +{ + sdhci_writel(host, PHY_TX_SRC_INVERT | tap << 16, SDHCI_PHY_TX_RX_DLY); +} + +static void cv1800b_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); + while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) + udelay(10); +} + +static int cv1800b_execute_tuning(struct mmc *mmc, u8 opcode) +{ + struct sdhci_host *host = dev_get_priv(mmc->dev); + + u16 tap; + + int current_size = 0; + int max_size = 0; + int max_window = 0; + + for (tap = 0; tap < TUNE_MAX_PHCODE; tap++) { + cv1800b_set_tap_delay(host, tap); + + if (mmc_send_tuning(host->mmc, opcode)) { + current_size = 0; + } else { + current_size++; + if (current_size > max_size) { + max_size = current_size; + max_window = tap; + } + } + } + + cv1800b_sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + cv1800b_set_tap_delay(host, max_window - max_size / 2); + + return 0; +} + +const struct sdhci_ops cv1800b_sdhci_sd_ops = { + .platform_execute_tuning = cv1800b_execute_tuning, +}; + +static int cv1800b_sdhci_bind(struct udevice *dev) +{ + struct cv1800b_sdhci_plat *plat = dev_get_plat(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static int cv1800b_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct cv1800b_sdhci_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + int ret; + + host->name = dev->name; + host->ioaddr = devfdt_get_addr_ptr(dev); + + upriv->mmc = &plat->mmc; + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + host->ops = &cv1800b_sdhci_sd_ops; + host->max_clk = MMC_MAX_CLOCK; + + ret = mmc_of_parse(dev, &plat->cfg); + if (ret) + return ret; + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, 200000); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static const struct udevice_id cv1800b_sdhci_match[] = { + { .compatible = "sophgo,cv1800b-dwcmshc" }, + { } +}; + +U_BOOT_DRIVER(cv1800b_sdhci) = { + .name = "sdhci-cv1800b", + .id = UCLASS_MMC, + .of_match = cv1800b_sdhci_match, + .bind = cv1800b_sdhci_bind, + .probe = cv1800b_sdhci_probe, + .priv_auto = sizeof(struct sdhci_host), + .plat_auto = sizeof(struct cv1800b_sdhci_plat), + .ops = &sdhci_ops, +}; diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c index 3a3d23aec00..5107fcd8362 100644 --- a/drivers/mmc/davinci_mmc.c +++ b/drivers/mmc/davinci_mmc.c @@ -6,7 +6,6 @@ */ #include <config.h> -#include <common.h> #include <dm.h> #include <errno.h> #include <mmc.h> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 400066fa99a..e6107c770fe 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -6,7 +6,6 @@ */ #include <bouncebuf.h> -#include <common.h> #include <cpu_func.h> #include <errno.h> #include <log.h> @@ -262,8 +261,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { if (get_timer(start) > timeout) { - debug("%s: Timeout on data busy\n", __func__); - return -ETIMEDOUT; + debug("%s: Timeout on data busy, continue anyway\n", __func__); + break; } } diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 2f849c43b12..a51f762988d 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -4,7 +4,6 @@ * Jaehoon Chung <jh80.chung@samsung.com> */ -#include <common.h> #include <dwmmc.h> #include <fdtdec.h> #include <asm/global_data.h> diff --git a/drivers/mmc/f_sdh30.c b/drivers/mmc/f_sdh30.c index 3d587a464d5..f47cf848521 100644 --- a/drivers/mmc/f_sdh30.c +++ b/drivers/mmc/f_sdh30.c @@ -5,7 +5,6 @@ * Copyright 2021 Socionext, Inc. */ -#include <common.h> #include <clk.h> #include <dm.h> #include <malloc.h> diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index d5066666698..0c66980b621 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -10,7 +10,6 @@ */ #include <config.h> -#include <common.h> #include <command.h> #include <cpu_func.h> #include <errno.h> @@ -252,7 +251,7 @@ static void esdhc_setup_dma(struct fsl_esdhc_priv *priv, struct mmc_data *data) priv->adma_desc_table) { debug("Using ADMA2\n"); /* prefer ADMA2 if it is available */ - sdhci_prepare_adma_table(priv->adma_desc_table, data, + sdhci_prepare_adma_table(NULL, priv->adma_desc_table, data, priv->dma_addr); adma_addr = virt_to_phys(priv->adma_desc_table); @@ -1102,7 +1101,7 @@ static int fsl_esdhc_reinit(struct udevice *dev) return esdhc_init_common(priv, &plat->mmc); } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) { struct fsl_esdhc_plat *plat = dev_get_plat(dev); @@ -1123,7 +1122,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) esdhc_write32(®s->irqstaten, IRQSTATEN_BRR); for (i = 0; i < MAX_TUNING_LOOP; i++) { - mmc_send_tuning(mmc, opcode, NULL); + mmc_send_tuning(mmc, opcode); mdelay(1); val = esdhc_read32(®s->autoc12err); @@ -1175,7 +1174,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = { .get_cd = fsl_esdhc_get_cd, .send_cmd = fsl_esdhc_send_cmd, .set_ios = fsl_esdhc_set_ios, -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .execute_tuning = fsl_esdhc_execute_tuning, #endif .reinit = fsl_esdhc_reinit, diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 7c39c86c5e9..a9b8d7dd67f 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -11,7 +11,6 @@ */ #include <config.h> -#include <common.h> #include <command.h> #include <clk.h> #include <cpu_func.h> @@ -635,7 +634,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) priv->clock = clock; } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int esdhc_change_pinstate(struct udevice *dev) { struct fsl_esdhc_priv *priv = dev_get_priv(dev); @@ -882,7 +881,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) esdhc_write32(®s->mixctrl, val); /* We are using STD tuning, no need to check return value */ - mmc_send_tuning(mmc, opcode, NULL); + mmc_send_tuning(mmc, opcode); ctrl = esdhc_read32(®s->autoc12err); if ((!(ctrl & MIX_CTRL_EXE_TUNE)) && @@ -913,7 +912,7 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) int ret __maybe_unused; u32 clock; -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) /* * call esdhc_set_timing() before update the clock rate, * This is because current we support DDR and SDR mode, @@ -951,7 +950,7 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) /* * For HS400/HS400ES mode, make sure set the strobe dll in the * target clock rate. So call esdhc_set_strobe_dll() after the @@ -1618,7 +1617,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = { .get_cd = fsl_esdhc_get_cd, .send_cmd = fsl_esdhc_send_cmd, .set_ios = fsl_esdhc_set_ios, -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .execute_tuning = fsl_esdhc_execute_tuning, #endif #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) diff --git a/drivers/mmc/fsl_esdhc_spl.c b/drivers/mmc/fsl_esdhc_spl.c index 6d7c0cff22a..1a11258be4d 100644 --- a/drivers/mmc/fsl_esdhc_spl.c +++ b/drivers/mmc/fsl_esdhc_spl.c @@ -3,7 +3,7 @@ * Copyright 2013 Freescale Semiconductor, Inc. */ -#include <common.h> +#include <config.h> #include <cpu_func.h> #include <hang.h> #include <mmc.h> diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c index cabb747fbbd..11e44264e47 100644 --- a/drivers/mmc/ftsdc010_mci.c +++ b/drivers/mmc/ftsdc010_mci.c @@ -9,7 +9,6 @@ * Author: Rick Chen (rick@andestech.com) */ -#include <common.h> #include <clk.h> #include <log.h> #include <malloc.h> diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index 3ee99558f6f..6a531fa0961 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -8,7 +8,7 @@ * Copyright (C) 2004-2006 Atmel Corporation */ -#include <common.h> +#include <config.h> #include <clk.h> #include <display_options.h> #include <dm.h> diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c index 71962cd47e0..c68a9157bfc 100644 --- a/drivers/mmc/hi6220_dw_mmc.c +++ b/drivers/mmc/hi6220_dw_mmc.c @@ -4,16 +4,24 @@ * peter.griffin <peter.griffin@linaro.org> */ -#include <common.h> +#include <clk.h> #include <dm.h> #include <dwmmc.h> #include <errno.h> #include <fdtdec.h> #include <malloc.h> +#include <reset.h> #include <asm/global_data.h> +#include <dm/device_compat.h> DECLARE_GLOBAL_DATA_PTR; +enum hi6220_dwmmc_clk_type { + HI6220_DWMMC_CLK_BIU, + HI6220_DWMMC_CLK_CIU, + HI6220_DWMMC_CLK_CNT, +}; + struct hi6220_dwmmc_plat { struct mmc_config cfg; struct mmc mmc; @@ -21,18 +29,43 @@ struct hi6220_dwmmc_plat { struct hi6220_dwmmc_priv_data { struct dwmci_host host; + struct clk *clks[HI6220_DWMMC_CLK_CNT]; + struct reset_ctl_bulk rsts; }; struct hisi_mmc_data { unsigned int clock; bool use_fifo; + u32 fifoth_val; }; static int hi6220_dwmmc_of_to_plat(struct udevice *dev) { struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; + int ret; + if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) { + priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu"); + if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) { + ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]); + dev_err(dev, "Failed to get BIU clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu"); + if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) { + ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]); + dev_err(dev, "Failed to get CIU clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + ret = reset_get_bulk(dev, &priv->rsts); + if (ret) { + dev_err(dev, "Failed to get resets(ret = %d)", ret); + return log_msg_ret("rst", ret); + } + } host->name = dev->name; host->ioaddr = dev_read_addr_ptr(dev); host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), @@ -56,16 +89,43 @@ static int hi6220_dwmmc_probe(struct udevice *dev) struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; struct hisi_mmc_data *mmc_data; + int ret; mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev); - /* Use default bus speed due to absence of clk driver */ host->bus_hz = mmc_data->clock; + if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) { + ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]); + if (ret) { + dev_err(dev, "Failed to enable biu clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]); + if (ret) { + dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + ret = reset_deassert_bulk(&priv->rsts); + if (ret) { + dev_err(dev, "Failed to deassert resets(ret = %d).\n", ret); + return log_msg_ret("rst", ret); + } + + host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]); + if (host->bus_hz <= 0) { + dev_err(dev, "Failed to get ciu clock rate(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + } + dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz); dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000); host->mmc = &plat->mmc; host->fifo_mode = mmc_data->use_fifo; + host->fifoth_val = mmc_data->fifoth_val; host->mmc->priv = &priv->host; upriv->mmc = host->mmc; host->mmc->dev = dev; @@ -95,13 +155,20 @@ static const struct hisi_mmc_data hi6220_mmc_data = { .use_fifo = false, }; +static const struct hisi_mmc_data hi3798mv2x_mmc_data = { + .clock = 50000000, + .use_fifo = false, + // FIFO depth is 256 + .fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80), +}; + static const struct udevice_id hi6220_dwmmc_ids[] = { { .compatible = "hisilicon,hi6220-dw-mshc", .data = (ulong)&hi6220_mmc_data }, { .compatible = "hisilicon,hi3798cv200-dw-mshc", .data = (ulong)&hi6220_mmc_data }, { .compatible = "hisilicon,hi3798mv200-dw-mshc", - .data = (ulong)&hi6220_mmc_data }, + .data = (ulong)&hi3798mv2x_mmc_data }, { .compatible = "hisilicon,hi3660-dw-mshc", .data = (ulong)&hi3660_mmc_data }, { } diff --git a/drivers/mmc/iproc_sdhci.c b/drivers/mmc/iproc_sdhci.c index 11d86ad658f..7ab74ff117a 100644 --- a/drivers/mmc/iproc_sdhci.c +++ b/drivers/mmc/iproc_sdhci.c @@ -4,7 +4,6 @@ * */ -#include <common.h> #include <dm.h> #include <errno.h> #include <malloc.h> diff --git a/drivers/mmc/jz_mmc.c b/drivers/mmc/jz_mmc.c index 61e48ee0f62..fc10bb256a4 100644 --- a/drivers/mmc/jz_mmc.c +++ b/drivers/mmc/jz_mmc.c @@ -6,7 +6,6 @@ * Author: Paul Burton <paul.burton@imgtec.com> */ -#include <common.h> #include <malloc.h> #include <mmc.h> #include <asm/global_data.h> diff --git a/drivers/mmc/kona_sdhci.c b/drivers/mmc/kona_sdhci.c index 2bbe673b912..83f14122632 100644 --- a/drivers/mmc/kona_sdhci.c +++ b/drivers/mmc/kona_sdhci.c @@ -3,7 +3,6 @@ * Copyright 2013 Broadcom Corporation. */ -#include <common.h> #include <malloc.h> #include <sdhci.h> #include <linux/delay.h> diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c index fcf4f03d1e2..5852b24c6d2 100644 --- a/drivers/mmc/meson_gx_mmc.c +++ b/drivers/mmc/meson_gx_mmc.c @@ -3,7 +3,6 @@ * (C) Copyright 2016 Carlo Caione <carlo@caione.org> */ -#include <common.h> #include <clk.h> #include <cpu_func.h> #include <dm.h> @@ -288,7 +287,7 @@ static int meson_mmc_probe(struct udevice *dev) mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE); -#ifdef CONFIG_MMC_PWRSEQ +#if CONFIG_IS_ENABLED(MMC_PWRSEQ) /* Enable power if needed */ ret = mmc_pwrseq_get_power(dev, cfg); if (!ret) { diff --git a/drivers/mmc/mmc-pwrseq.c b/drivers/mmc/mmc-pwrseq.c index 2539f61323d..a1c9624a222 100644 --- a/drivers/mmc/mmc-pwrseq.c +++ b/drivers/mmc/mmc-pwrseq.c @@ -4,7 +4,6 @@ * Jaehoon Chung <jh80.chung@samsung.com> */ -#include <common.h> #include <dm.h> #include <mmc.h> #include <pwrseq.h> diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 328456831dd..da6a39b7d99 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -7,7 +7,6 @@ #define LOG_CATEGORY UCLASS_MMC -#include <common.h> #include <bootdev.h> #include <log.h> #include <mmc.h> @@ -112,7 +111,7 @@ int mmc_getcd(struct mmc *mmc) return dm_mmc_get_cd(mmc->dev); } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int dm_mmc_execute_tuning(struct udevice *dev, uint opcode) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -124,7 +123,13 @@ static int dm_mmc_execute_tuning(struct udevice *dev, uint opcode) int mmc_execute_tuning(struct mmc *mmc, uint opcode) { - return dm_mmc_execute_tuning(mmc->dev, opcode); + int ret; + + mmc->tuning = true; + ret = dm_mmc_execute_tuning(mmc->dev, opcode); + mmc->tuning = false; + + return ret; } #endif @@ -251,11 +256,14 @@ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg) if (dev_read_bool(dev, "mmc-hs200-1_2v")) cfg->host_caps |= MMC_CAP(MMC_HS_200); if (dev_read_bool(dev, "mmc-hs400-1_8v")) - cfg->host_caps |= MMC_CAP(MMC_HS_400); + cfg->host_caps |= MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_200); if (dev_read_bool(dev, "mmc-hs400-1_2v")) - cfg->host_caps |= MMC_CAP(MMC_HS_400); + cfg->host_caps |= MMC_CAP(MMC_HS_400) | MMC_CAP(MMC_HS_200); if (dev_read_bool(dev, "mmc-hs400-enhanced-strobe")) cfg->host_caps |= MMC_CAP(MMC_HS_400_ES); + if (dev_read_bool(dev, "no-mmc-hs400")) + cfg->host_caps &= ~(MMC_CAP(MMC_HS_400) | + MMC_CAP(MMC_HS_400_ES)); if (dev_read_bool(dev, "non-removable")) { cfg->host_caps |= MMC_CAP_NONREMOVABLE; @@ -494,10 +502,7 @@ static int mmc_blk_probe(struct udevice *dev) if (ret) { debug("Probing %s failed (err=%d)\n", dev->name, ret); - if (CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)) - mmc_deinit(mmc); + mmc_deinit(mmc); return ret; } @@ -505,9 +510,6 @@ static int mmc_blk_probe(struct udevice *dev) return 0; } -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) static int mmc_blk_remove(struct udevice *dev) { struct udevice *mmc_dev = dev_get_parent(dev); @@ -516,7 +518,6 @@ static int mmc_blk_remove(struct udevice *dev) return mmc_deinit(mmc); } -#endif static const struct blk_ops mmc_blk_ops = { .read = mmc_bread, @@ -532,12 +533,8 @@ U_BOOT_DRIVER(mmc_blk) = { .id = UCLASS_BLK, .ops = &mmc_blk_ops, .probe = mmc_blk_probe, -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) .remove = mmc_blk_remove, .flags = DM_FLAG_OS_PREPARE, -#endif }; #endif /* CONFIG_BLK */ diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d96db7a0f83..b18dc331f78 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -8,7 +8,6 @@ */ #include <config.h> -#include <common.h> #include <blk.h> #include <command.h> #include <dm.h> @@ -17,6 +16,7 @@ #include <errno.h> #include <mmc.h> #include <part.h> +#include <time.h> #include <linux/bitops.h> #include <linux/delay.h> #include <linux/printk.h> @@ -24,6 +24,7 @@ #include <malloc.h> #include <memalign.h> #include <linux/list.h> +#include <linux/printk.h> #include <div64.h> #include "mmc_private.h" @@ -329,7 +330,7 @@ int mmc_set_blocklen(struct mmc *mmc, int len) MMC_QUIRK_RETRY_SET_BLOCKLEN, 4); } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static const u8 tuning_blk_pattern_4bit[] = { 0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc, 0xc3, 0x3c, 0xcc, 0xff, 0xfe, 0xff, 0xfe, 0xef, @@ -360,7 +361,7 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; -int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error) +int mmc_send_tuning(struct mmc *mmc, u32 opcode) { struct mmc_cmd cmd; struct mmc_data data; @@ -1570,13 +1571,20 @@ static int sd_read_ssr(struct mmc *mmc) return 0; } #endif -/* frequency bases */ -/* divided by 10 to be nice to platforms without floating point */ +/* + * TRAN_SPEED bits 0:2 encode the frequency unit: + * 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, values 4 - 7 are reserved. + * The values in fbase[] are divided by 10 to avoid floats in multiplier[]. + */ static const int fbase[] = { 10000, 100000, 1000000, 10000000, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ }; /* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice @@ -1614,7 +1622,7 @@ static inline int bus_width(uint cap) } #if !CONFIG_IS_ENABLED(DM_MMC) -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int mmc_execute_tuning(struct mmc *mmc, uint opcode) { return -ENOTSUPP; @@ -1695,7 +1703,7 @@ void mmc_dump_capabilities(const char *text, uint caps) struct mode_width_tuning { enum bus_mode mode; uint widths; -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) uint tuning; #endif }; @@ -1736,7 +1744,7 @@ static inline int mmc_set_signal_voltage(struct mmc *mmc, uint signal_voltage) #if !CONFIG_IS_ENABLED(MMC_TINY) static const struct mode_width_tuning sd_modes_by_pref[] = { #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) { .mode = UHS_SDR104, .widths = MMC_MODE_4BIT | MMC_MODE_1BIT, @@ -1839,7 +1847,7 @@ static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) /* execute tuning if needed */ if (mwt->tuning && !mmc_host_is_spi(mmc)) { err = mmc_execute_tuning(mmc, @@ -2027,9 +2035,9 @@ static int mmc_select_hs400(struct mmc *mmc) mmc_set_clock(mmc, mmc->tran_speed, false); /* execute tuning if needed */ - mmc->hs400_tuning = 1; + mmc->hs400_tuning = true; err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200); - mmc->hs400_tuning = 0; + mmc->hs400_tuning = false; if (err) { debug("tuning failed\n"); return err; @@ -2217,7 +2225,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) mmc_select_mode(mmc, mwt->mode); mmc_set_clock(mmc, mmc->tran_speed, MMC_CLK_ENABLE); -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) /* execute tuning if needed */ if (mwt->tuning) { @@ -2250,6 +2258,16 @@ error: return -ENOTSUPP; } +#else +static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) +{ + return 0; +}; + +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) +{ + return 0; +}; #endif #if CONFIG_IS_ENABLED(MMC_TINY) @@ -2560,6 +2578,8 @@ static int mmc_startup(struct mmc *mmc) mult = multipliers[((cmd.response[0] >> 3) & 0xf)]; mmc->legacy_speed = freq * mult; + if (!mmc->legacy_speed) + log_debug("TRAN_SPEED: reserved value"); mmc_select_mode(mmc, MMC_LEGACY); mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1); @@ -3010,13 +3030,15 @@ int mmc_init(struct mmc *mmc) return err; } -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) int mmc_deinit(struct mmc *mmc) { u32 caps_filtered; + if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) && + !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) && + !CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)) + return 0; + if (!mmc->has_init) return 0; @@ -3034,7 +3056,6 @@ int mmc_deinit(struct mmc *mmc) return mmc_select_mode_and_width(mmc, caps_filtered); } } -#endif int mmc_set_dsr(struct mmc *mmc, u16 val) { diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c index 0a74b1fb776..367c957b518 100644 --- a/drivers/mmc/mmc_boot.c +++ b/drivers/mmc/mmc_boot.c @@ -4,7 +4,6 @@ * Written by Amar <amarendra.xt@samsung.com> */ -#include <common.h> #include <log.h> #include <mmc.h> #include "mmc_private.h" diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c index 55ecead2ddf..5a1688b75d0 100644 --- a/drivers/mmc/mmc_bootdev.c +++ b/drivers/mmc/mmc_bootdev.c @@ -6,7 +6,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <bootdev.h> #include <dm.h> #include <mmc.h> diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c index a101ee43fde..a87d2276c1b 100644 --- a/drivers/mmc/mmc_legacy.c +++ b/drivers/mmc/mmc_legacy.c @@ -5,7 +5,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <log.h> #include <malloc.h> #include <mmc.h> diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c index bcea800e5f6..675e642efd0 100644 --- a/drivers/mmc/mmc_spi.c +++ b/drivers/mmc/mmc_spi.c @@ -6,7 +6,6 @@ * * Licensed under the GPL-2 or later. */ -#include <common.h> #include <errno.h> #include <log.h> #include <malloc.h> diff --git a/drivers/mmc/mmc_write.c b/drivers/mmc/mmc_write.c index a6f93380dd0..c023d15e52a 100644 --- a/drivers/mmc/mmc_write.c +++ b/drivers/mmc/mmc_write.c @@ -7,7 +7,6 @@ */ #include <config.h> -#include <common.h> #include <blk.h> #include <dm.h> #include <part.h> diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 059cb3da77c..4ce0de6c47d 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -7,7 +7,6 @@ * Based on Linux driver */ -#include <common.h> #include <clk.h> #include <dm.h> #include <malloc.h> @@ -33,9 +32,6 @@ #define SDCC_MCI_STATUS2_MCI_ACT 0x1 #define SDCC_MCI_HC_MODE 0x78 -/* Non standard (?) SDHCI register */ -#define SDHCI_VENDOR_SPEC_CAPABILITIES0 0x11c - struct msm_sdhc_plat { struct mmc_config cfg; struct mmc mmc; @@ -49,6 +45,8 @@ struct msm_sdhc { struct msm_sdhc_variant_info { bool mci_removed; + + u32 core_vendor_spec_capabilities0; }; DECLARE_GLOBAL_DATA_PTR; @@ -63,7 +61,7 @@ static int msm_sdc_clk_init(struct udevice *dev) ret = ofnode_read_u32(node, "clock-frequency", (uint *)(&clk_rate)); if (ret) - clk_rate = 400000; + clk_rate = 201500000; ret = clk_get_bulk(dev, &prv->clks); if (ret) { @@ -174,6 +172,8 @@ static int msm_sdc_probe(struct udevice *dev) core_minor = core_version & SDCC_VERSION_MINOR_MASK; + log_debug("SDCC version %d.%d\n", core_major, core_minor); + /* * Support for some capabilities is not advertised by newer * controller versions and must be explicitly enabled. @@ -181,7 +181,7 @@ static int msm_sdc_probe(struct udevice *dev) if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) { caps = readl(host->ioaddr + SDHCI_CAPABILITIES); caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT; - writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0); + writel(caps, host->ioaddr + var_info->core_vendor_spec_capabilities0); } ret = mmc_of_parse(dev, &plat->cfg); @@ -207,7 +207,7 @@ static int msm_sdc_remove(struct udevice *dev) var_info = (void *)dev_get_driver_data(dev); /* Disable host-controller mode */ - if (!var_info->mci_removed) + if (!var_info->mci_removed && priv->base) writel(0, priv->base + SDCC_MCI_HC_MODE); clk_release_bulk(&priv->clks); @@ -217,21 +217,31 @@ static int msm_sdc_remove(struct udevice *dev) static int msm_of_to_plat(struct udevice *dev) { - struct udevice *parent = dev->parent; struct msm_sdhc *priv = dev_get_priv(dev); + const struct msm_sdhc_variant_info *var_info; struct sdhci_host *host = &priv->host; - int node = dev_of_offset(dev); + int ret; + + var_info = (void*)dev_get_driver_data(dev); host->name = strdup(dev->name); host->ioaddr = dev_read_addr_ptr(dev); - host->bus_width = fdtdec_get_int(gd->fdt_blob, node, "bus-width", 4); - host->index = fdtdec_get_uint(gd->fdt_blob, node, "index", 0); - priv->base = (void *)fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - dev_of_offset(parent), node, "reg", 1, NULL, false); - if (priv->base == (void *)FDT_ADDR_T_NONE || - host->ioaddr == (void *)FDT_ADDR_T_NONE) + ret = dev_read_u32(dev, "bus-width", &host->bus_width); + if (ret) + host->bus_width = 4; + ret = dev_read_u32(dev, "index", &host->index); + if (ret) + host->index = 0; + priv->base = dev_read_addr_index_ptr(dev, 1); + + if (!host->ioaddr) return -EINVAL; + if (!var_info->mci_removed && !priv->base) { + printf("msm_sdhci: MCI base address not found\n"); + return -EINVAL; + } + return 0; } @@ -244,10 +254,14 @@ static int msm_sdc_bind(struct udevice *dev) static const struct msm_sdhc_variant_info msm_sdhc_mci_var = { .mci_removed = false, + + .core_vendor_spec_capabilities0 = 0x11c, }; static const struct msm_sdhc_variant_info msm_sdhc_v5_var = { .mci_removed = true, + + .core_vendor_spec_capabilities0 = 0x21c, }; static const struct udevice_id msm_mmc_ids[] = { diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 5a0c61daed5..3a9258255a7 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -7,7 +7,6 @@ */ #include <clk.h> -#include <common.h> #include <dm.h> #include <mmc.h> #include <errno.h> @@ -1011,7 +1010,7 @@ static int msdc_ops_get_wp(struct udevice *dev) #endif } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static u32 test_delay_bit(u32 delay, u32 bit) { bit %= PAD_DELAY_MAX; @@ -1131,7 +1130,7 @@ static int hs400_tune_response(struct udevice *dev, u32 opcode) i << PAD_CMD_TUNE_RX_DLY3_S); for (j = 0; j < 3; j++) { - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) { cmd_delay |= (1 << i); } else { @@ -1181,7 +1180,7 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode) i << MSDC_PAD_TUNE_CMDRDLY_S); for (j = 0; j < 3; j++) { - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) { rise_delay |= (1 << i); } else { @@ -1203,7 +1202,7 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode) i << MSDC_PAD_TUNE_CMDRDLY_S); for (j = 0; j < 3; j++) { - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) { fall_delay |= (1 << i); } else { @@ -1238,7 +1237,7 @@ skip_fall: clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M, i << MSDC_PAD_TUNE_CMDRRDLY_S); - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) internal_delay |= (1 << i); } @@ -1264,7 +1263,6 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0, }; u8 final_delay, final_maxlen; void __iomem *tune_reg = &host->base->pad_tune; - int cmd_err; int i, ret; if (host->dev_comp->pad_tune0) @@ -1277,10 +1275,10 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, i << MSDC_PAD_TUNE_DATRRDLY_S); - ret = mmc_send_tuning(mmc, opcode, &cmd_err); + ret = mmc_send_tuning(mmc, opcode); if (!ret) { rise_delay |= (1 << i); - } else if (cmd_err) { + } else { /* in this case, retune response is needed */ ret = msdc_tune_response(dev, opcode); if (ret) @@ -1300,10 +1298,10 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, i << MSDC_PAD_TUNE_DATRRDLY_S); - ret = mmc_send_tuning(mmc, opcode, &cmd_err); + ret = mmc_send_tuning(mmc, opcode); if (!ret) { fall_delay |= (1 << i); - } else if (cmd_err) { + } else { /* in this case, retune response is needed */ ret = msdc_tune_response(dev, opcode); if (ret) @@ -1362,7 +1360,7 @@ static int msdc_tune_together(struct udevice *dev, u32 opcode) for (i = 0; i < PAD_DELAY_MAX; i++) { msdc_set_cmd_delay(host, i); msdc_set_data_delay(host, i); - ret = mmc_send_tuning(mmc, opcode, NULL); + ret = mmc_send_tuning(mmc, opcode); if (!ret) rise_delay |= (1 << i); } @@ -1378,7 +1376,7 @@ static int msdc_tune_together(struct udevice *dev, u32 opcode) for (i = 0; i < PAD_DELAY_MAX; i++) { msdc_set_cmd_delay(host, i); msdc_set_data_delay(host, i); - ret = mmc_send_tuning(mmc, opcode, NULL); + ret = mmc_send_tuning(mmc, opcode); if (!ret) fall_delay |= (1 << i); } @@ -1761,7 +1759,7 @@ static const struct dm_mmc_ops msdc_ops = { .set_ios = msdc_ops_set_ios, .get_cd = msdc_ops_get_cd, .get_wp = msdc_ops_get_wp, -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .execute_tuning = msdc_execute_tuning, #endif .wait_dat0 = msdc_ops_wait_dat0, diff --git a/drivers/mmc/mv_sdhci.c b/drivers/mmc/mv_sdhci.c index dbdd671c88b..2da5334c21f 100644 --- a/drivers/mmc/mv_sdhci.c +++ b/drivers/mmc/mv_sdhci.c @@ -3,7 +3,6 @@ * Marvell SD Host Controller Interface */ -#include <common.h> #include <dm.h> #include <malloc.h> #include <sdhci.h> diff --git a/drivers/mmc/mvebu_mmc.c b/drivers/mmc/mvebu_mmc.c index fea55c61ed7..5af1953cd14 100644 --- a/drivers/mmc/mvebu_mmc.c +++ b/drivers/mmc/mvebu_mmc.c @@ -7,7 +7,6 @@ * Written-by: Maen Suleiman, Gerald Kerma */ -#include <common.h> #include <errno.h> #include <log.h> #include <malloc.h> diff --git a/drivers/mmc/mxcmmc.c b/drivers/mmc/mxcmmc.c index 0057273a2a7..1acea6f820b 100644 --- a/drivers/mmc/mxcmmc.c +++ b/drivers/mmc/mxcmmc.c @@ -17,7 +17,6 @@ */ #include <config.h> -#include <common.h> #include <command.h> #include <mmc.h> #include <part.h> diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 35a8e21058e..95390a5be7e 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -20,7 +20,6 @@ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net */ -#include <common.h> #include <log.h> #include <malloc.h> #include <mmc.h> diff --git a/drivers/mmc/nexell_dw_mmc.c b/drivers/mmc/nexell_dw_mmc.c index 2723e4887cf..2e1ce54c7d5 100644 --- a/drivers/mmc/nexell_dw_mmc.c +++ b/drivers/mmc/nexell_dw_mmc.c @@ -6,7 +6,6 @@ * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net> */ -#include <common.h> #include <dm.h> #include <dt-structs.h> #include <dwmmc.h> diff --git a/drivers/mmc/npcm_sdhci.c b/drivers/mmc/npcm_sdhci.c index d63521d6855..dff4732ea06 100644 --- a/drivers/mmc/npcm_sdhci.c +++ b/drivers/mmc/npcm_sdhci.c @@ -3,7 +3,6 @@ * Copyright (c) 2022 Nuvoton Technology Corp. */ -#include <common.h> #include <dm.h> #include <sdhci.h> #include <clk.h> diff --git a/drivers/mmc/octeontx_hsmmc.c b/drivers/mmc/octeontx_hsmmc.c index 4ee62df9d40..3b5e1221732 100644 --- a/drivers/mmc/octeontx_hsmmc.c +++ b/drivers/mmc/octeontx_hsmmc.c @@ -794,7 +794,7 @@ octeontx_mmc_get_cr_mods(struct mmc *mmc, const struct mmc_cmd *cmd, u8 desired_ctype = 0; if (IS_MMC(mmc)) { -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) if (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200) { if (cmd->resp_type == MMC_RSP_R1) cr.rtype_xor = 1; @@ -1631,7 +1631,7 @@ static int octeontx_mmc_dev_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, return octeontx_mmc_send_cmd(dev_to_mmc(dev), cmd, data); } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int octeontx_mmc_test_cmd(struct mmc *mmc, u32 opcode, int *statp) { struct mmc_cmd cmd; @@ -1653,6 +1653,12 @@ static int octeontx_mmc_test_cmd(struct mmc *mmc, u32 opcode, int *statp) return err; } +static int octeontx_mmc_send_tuning(struct mmc *mmc, u32 opcode, int *error) +{ + *error = 0; + return mmc_send_tuning(mmc, opcode); +} + static int octeontx_mmc_test_get_ext_csd(struct mmc *mmc, u32 opcode, int *statp) { @@ -2006,7 +2012,7 @@ struct adj adj[] = { { "CMD_IN", 48, octeontx_mmc_test_cmd, MMC_CMD_SEND_STATUS, false, false, false, 2, }, /* { "CMD_OUT", 32, octeontx_mmc_test_cmd, MMC_CMD_SEND_STATUS, },*/ - { "DATA_IN(HS200)", 16, mmc_send_tuning, + { "DATA_IN(HS200)", 16, octeontx_mmc_send_tuning, MMC_CMD_SEND_TUNING_BLOCK_HS200, false, true, false, 2, }, { "DATA_IN", 16, octeontx_mmc_test_get_ext_csd, 0, false, false, true, 2, }, @@ -2415,12 +2421,12 @@ static int octeontx_mmc_execute_tuning(struct udevice *dev, u32 opcode) return 0; } -#else /* MMC_SUPPORTS_TUNING */ +#else /* CONFIG_MMC_SUPPORTS_TUNING */ static void octeontx_mmc_set_emm_timing(struct mmc *mmc, union mio_emm_timing emm_timing) { } -#endif /* MMC_SUPPORTS_TUNING */ +#endif /* CONFIG_MMC_SUPPORTS_TUNING */ /** * Calculate the clock period with rounding up @@ -2567,7 +2573,7 @@ static int octeontx_mmc_set_ios(struct udevice *dev) err = octeontx_mmc_configure_delay(mmc); -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) if (!err && mmc->selected_mode == MMC_HS_400 && !slot->hs400_tuned) { debug("%s: Tuning HS400 mode\n", __func__); err = octeontx_tune_hs400(mmc); @@ -3770,7 +3776,7 @@ static const struct dm_mmc_ops octeontx_hsmmc_ops = { .set_ios = octeontx_mmc_set_ios, .get_cd = octeontx_mmc_get_cd, .get_wp = octeontx_mmc_get_wp, -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .execute_tuning = octeontx_mmc_execute_tuning, #endif }; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index a2595d19e7f..2b7f9fc9a20 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -23,7 +23,6 @@ */ #include <config.h> -#include <common.h> #include <cpu_func.h> #include <log.h> #include <malloc.h> @@ -577,7 +576,7 @@ static uint32_t omap_hsmmc_set_capabilities(struct mmc *mmc) return val; } -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static void omap_hsmmc_disable_tuning(struct mmc *mmc) { struct hsmmc *mmc_base; @@ -666,7 +665,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) while (phase_delay <= MAX_PHASE_DELAY) { omap_hsmmc_set_dll(mmc, phase_delay); - cur_match = !mmc_send_tuning(mmc, opcode, NULL); + cur_match = !mmc_send_tuning(mmc, opcode); if (cur_match) { if (prev_match) { @@ -731,7 +730,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) */ for (i = 3; i <= 10; i++) { omap_hsmmc_set_dll(mmc, phase_delay + i); - if (mmc_send_tuning(mmc, opcode, NULL)) { + if (mmc_send_tuning(mmc, opcode)) { if (temperature < 10000) phase_delay += i + 6; else if (temperature < 20000) @@ -749,7 +748,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) for (i = 2; i >= -10; i--) { omap_hsmmc_set_dll(mmc, phase_delay + i); - if (mmc_send_tuning(mmc, opcode, NULL)) { + if (mmc_send_tuning(mmc, opcode)) { if (temperature < 10000) phase_delay += i + 12; else if (temperature < 20000) @@ -1518,7 +1517,7 @@ static const struct dm_mmc_ops omap_hsmmc_ops = { .get_cd = omap_hsmmc_getcd, .get_wp = omap_hsmmc_getwp, #endif -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .execute_tuning = omap_hsmmc_execute_tuning, #endif .wait_dat0 = omap_hsmmc_wait_dat0, diff --git a/drivers/mmc/owl_mmc.c b/drivers/mmc/owl_mmc.c index e84171a661a..bd4906f58e7 100644 --- a/drivers/mmc/owl_mmc.c +++ b/drivers/mmc/owl_mmc.c @@ -11,7 +11,6 @@ * channel, and those special bits used in this driver is picked from vendor * source exclusively for MMC/SD. */ -#include <common.h> #include <clk.h> #include <cpu_func.h> #include <dm.h> diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 4d163ccba04..d446c55f72b 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -4,7 +4,6 @@ * Copyright (C) 2014, Bin Meng <bmeng.cn@gmail.com> */ -#include <common.h> #include <dm.h> #include <errno.h> #include <log.h> diff --git a/drivers/mmc/piton_mmc.c b/drivers/mmc/piton_mmc.c index a330bbf8cbe..fed1f841608 100644 --- a/drivers/mmc/piton_mmc.c +++ b/drivers/mmc/piton_mmc.c @@ -11,7 +11,6 @@ #include <asm/gpio.h> #include <asm/io.h> -#include <common.h> #include <div64.h> #include <dm.h> #include <errno.h> diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 20b1e9277eb..23db2a75c44 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -568,8 +568,8 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) struct mmc *mmc = upriv->mmc; unsigned int tap_num; unsigned int taps = 0; - int i, ret = 0; - u32 caps; + int i, ret = 0, sret; + u32 caps, reg; /* Only supported on Renesas RCar */ if (!(priv->caps & TMIO_SD_CAP_RCAR_UHS)) @@ -605,15 +605,15 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) caps = priv->caps; priv->caps &= ~TMIO_SD_CAP_DMA_INTERNAL; - ret = mmc_send_tuning(mmc, opcode, NULL); + ret = mmc_send_tuning(mmc, opcode); priv->caps = caps; if (ret == 0) taps |= BIT(i); - ret = renesas_sdhi_compare_scc_data(priv); - if (ret == 0) + reg = renesas_sdhi_compare_scc_data(priv); + if (reg == 0) priv->smpcmp |= BIT(i); mdelay(1); @@ -624,9 +624,9 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) * eMMC. */ if (ret && (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200)) { - ret = mmc_send_stop_transmission(mmc, false); - if (ret < 0) - dev_dbg(dev, "Tuning abort fail (%d)\n", ret); + sret = mmc_send_stop_transmission(mmc, false); + if (sret < 0) + dev_dbg(dev, "Tuning abort fail (%d)\n", sret); } } @@ -798,9 +798,12 @@ static int renesas_sdhi_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct tmio_sd_priv *priv = dev_get_priv(dev); + struct mmc *mmc = upriv->mmc; - renesas_sdhi_check_scc_error(dev); + if (!mmc->tuning) + renesas_sdhi_check_scc_error(dev); if (cmd->cmdidx == MMC_CMD_SEND_STATUS) renesas_sdhi_adjust_hs400_mode_enable(priv); diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index 72c820ee633..1a10b7057a4 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -3,7 +3,6 @@ * Copyright (c) 2013 Google, Inc */ -#include <common.h> #include <clk.h> #include <dm.h> #include <dt-structs.h> @@ -145,7 +144,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev) host->fifo_mode = priv->fifo_mode; -#ifdef CONFIG_MMC_PWRSEQ +#if CONFIG_IS_ENABLED(MMC_PWRSEQ) /* Enable power if needed */ ret = mmc_pwrseq_get_power(dev, &plat->cfg); if (!ret) { diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 706fb123579..35667b86b50 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -5,7 +5,6 @@ * Rockchip SD Host Controller Interface */ -#include <common.h> #include <clk.h> #include <dm.h> #include <dm/ofnode.h> @@ -391,6 +390,8 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { struct mmc *mmc = host->mmc; + struct rockchip_sdhc_plat *plat = dev_get_plat(mmc->dev); + struct mmc_config *cfg = &plat->cfg; u32 reg; reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); @@ -437,6 +438,20 @@ static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) sdhci_writew(host, reg, DWCMSHC_EMMC_EMMC_CTRL); + /* + * Reading more than 4 blocks with a single CMD18 command in PIO mode + * triggers Data End Bit Error using a slower mode than HS200. Limit to + * reading max 4 blocks in one command when using PIO mode. + */ + if (!(host->flags & USE_DMA)) { + if (mmc->selected_mode == MMC_HS_200 || + mmc->selected_mode == MMC_HS_400 || + mmc->selected_mode == MMC_HS_400_ES) + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + else + cfg->b_max = 4; + } + return 0; } @@ -598,16 +613,6 @@ static int rockchip_sdhci_probe(struct udevice *dev) dev_read_bool(dev, "u-boot,spl-fifo-mode")) host->flags &= ~USE_DMA; - /* - * Reading more than 4 blocks with a single CMD18 command in PIO mode - * triggers Data End Bit Error on RK3568 and RK3588. Limit to reading - * max 4 blocks in one command when using PIO mode. - */ - if (!(host->flags & USE_DMA) && - (device_is_compatible(dev, "rockchip,rk3568-dwcmshc") || - device_is_compatible(dev, "rockchip,rk3588-dwcmshc"))) - cfg->b_max = 4; - return sdhci_probe(dev); } diff --git a/drivers/mmc/rpmb.c b/drivers/mmc/rpmb.c index b68d98573c9..0658ce22cf1 100644 --- a/drivers/mmc/rpmb.c +++ b/drivers/mmc/rpmb.c @@ -8,7 +8,6 @@ */ #include <config.h> -#include <common.h> #include <log.h> #include <memalign.h> #include <mmc.h> diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 3b74feae68c..80dbb38c9b3 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -4,7 +4,6 @@ * Jaehoon Chung <jh80.chung@samsung.com> */ -#include <common.h> #include <dm.h> #include <log.h> #include <malloc.h> diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 0ba7940a4db..a24520f2e78 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -4,7 +4,6 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <common.h> #include <dm.h> #include <errno.h> #include <fdtdec.h> diff --git a/drivers/mmc/sdhci-adma.c b/drivers/mmc/sdhci-adma.c index 8213223d3f9..fdb189d71a6 100644 --- a/drivers/mmc/sdhci-adma.c +++ b/drivers/mmc/sdhci-adma.c @@ -3,15 +3,15 @@ * SDHCI ADMA2 helper functions. */ -#include <common.h> #include <cpu_func.h> #include <sdhci.h> #include <malloc.h> #include <asm/cache.h> -static void sdhci_adma_desc(struct sdhci_adma_desc *desc, - dma_addr_t addr, u16 len, bool end) +void sdhci_adma_write_desc(struct sdhci_host *host, void **next_desc, + dma_addr_t addr, int len, bool end) { + struct sdhci_adma_desc *desc = *next_desc; u8 attr; attr = ADMA_DESC_ATTR_VALID | ADMA_DESC_TRANSFER_DATA; @@ -19,17 +19,30 @@ static void sdhci_adma_desc(struct sdhci_adma_desc *desc, attr |= ADMA_DESC_ATTR_END; desc->attr = attr; - desc->len = len; + desc->len = len & 0xffff; desc->reserved = 0; desc->addr_lo = lower_32_bits(addr); -#ifdef CONFIG_DMA_ADDR_T_64BIT +#ifdef CONFIG_MMC_SDHCI_ADMA_64BIT desc->addr_hi = upper_32_bits(addr); #endif + + *next_desc += ADMA_DESC_LEN; +} + +static inline void __sdhci_adma_write_desc(struct sdhci_host *host, + void **desc, dma_addr_t addr, + int len, bool end) +{ + if (host && host->ops && host->ops->adma_write_desc) + host->ops->adma_write_desc(host, desc, addr, len, end); + else + sdhci_adma_write_desc(host, desc, addr, len, end); } /** * sdhci_prepare_adma_table() - Populate the ADMA table * + * @host: Pointer to the sdhci_host * @table: Pointer to the ADMA table * @data: Pointer to MMC data * @addr: DMA address to write to or read from @@ -39,25 +52,26 @@ static void sdhci_adma_desc(struct sdhci_adma_desc *desc, * Please note, that the table size depends on CONFIG_SYS_MMC_MAX_BLK_COUNT and * we don't have to check for overflow. */ -void sdhci_prepare_adma_table(struct sdhci_adma_desc *table, - struct mmc_data *data, dma_addr_t addr) +void sdhci_prepare_adma_table(struct sdhci_host *host, + struct sdhci_adma_desc *table, + struct mmc_data *data, dma_addr_t start_addr) { + dma_addr_t addr = start_addr; uint trans_bytes = data->blocksize * data->blocks; - uint desc_count = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); - struct sdhci_adma_desc *desc = table; - int i = desc_count; + void *next_desc = table; + int i = DIV_ROUND_UP(trans_bytes, ADMA_MAX_LEN); while (--i) { - sdhci_adma_desc(desc, addr, ADMA_MAX_LEN, false); + __sdhci_adma_write_desc(host, &next_desc, addr, + ADMA_MAX_LEN, false); addr += ADMA_MAX_LEN; trans_bytes -= ADMA_MAX_LEN; - desc++; } - sdhci_adma_desc(desc, addr, trans_bytes, true); + __sdhci_adma_write_desc(host, &next_desc, addr, trans_bytes, true); - flush_cache((dma_addr_t)table, - ROUND(desc_count * sizeof(struct sdhci_adma_desc), + flush_cache((phys_addr_t)table, + ROUND(next_desc - (void *)table, ARCH_DMA_MINALIGN)); } diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c index 327a05ad11d..07ec35a0463 100644 --- a/drivers/mmc/sdhci-cadence.c +++ b/drivers/mmc/sdhci-cadence.c @@ -4,7 +4,6 @@ * Author: Masahiro Yamada <yamada.masahiro@socionext.com> */ -#include <common.h> #include <dm.h> #include <asm/global_data.h> #include <dm/device_compat.h> @@ -224,7 +223,7 @@ static int __maybe_unused sdhci_cdns_execute_tuning(struct udevice *dev, for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) { if (sdhci_cdns_set_tune_val(plat, i) || - mmc_send_tuning(mmc, opcode, NULL)) { /* bad */ + mmc_send_tuning(mmc, opcode)) { /* bad */ cur_streak = 0; } else { /* good */ cur_streak++; @@ -274,7 +273,7 @@ static int sdhci_cdns_probe(struct udevice *dev) host->ops = &sdhci_cdns_ops; host->quirks |= SDHCI_QUIRK_WAIT_SEND_CMD; sdhci_cdns_mmc_ops = sdhci_ops; -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) sdhci_cdns_mmc_ops.execute_tuning = sdhci_cdns_execute_tuning; #endif diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 0178ed8a11e..560b7e889c7 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -7,7 +7,6 @@ * Murray.Jensen@cmst.csiro.au, 27-Jan-01. */ -#include <common.h> #include <cpu_func.h> #include <dm.h> #include <errno.h> @@ -15,6 +14,7 @@ #include <malloc.h> #include <mmc.h> #include <sdhci.h> +#include <time.h> #include <asm/cache.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -111,7 +111,7 @@ static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data, } #if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA) else if (host->flags & (USE_ADMA | USE_ADMA64)) { - sdhci_prepare_adma_table(host->adma_desc_table, data, + sdhci_prepare_adma_table(host, host->adma_desc_table, data, host->start_addr); sdhci_writel(host, lower_32_bits(host->adma_addr), @@ -351,7 +351,7 @@ static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, return -ECOMM; } -#if defined(CONFIG_DM_MMC) && defined(MMC_SUPPORTS_TUNING) +#if defined(CONFIG_DM_MMC) && CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) static int sdhci_execute_tuning(struct udevice *dev, uint opcode) { int err; @@ -848,7 +848,7 @@ const struct dm_mmc_ops sdhci_ops = { .set_ios = sdhci_set_ios, .get_cd = sdhci_get_cd, .deferred_probe = sdhci_deferred_probe, -#ifdef MMC_SUPPORTS_TUNING +#if CONFIG_IS_ENABLED(MMC_SUPPORTS_TUNING) .execute_tuning = sdhci_execute_tuning, #endif .wait_dat0 = sdhci_wait_dat0, @@ -897,14 +897,15 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, __func__); return -EINVAL; } - host->adma_desc_table = sdhci_adma_init(); - host->adma_addr = (dma_addr_t)host->adma_desc_table; + if (!host->adma_desc_table) { + host->adma_desc_table = sdhci_adma_init(); + host->adma_addr = virt_to_phys(host->adma_desc_table); + } -#ifdef CONFIG_DMA_ADDR_T_64BIT - host->flags |= USE_ADMA64; -#else - host->flags |= USE_ADMA; -#endif + if (IS_ENABLED(CONFIG_MMC_SDHCI_ADMA_64BIT)) + host->flags |= USE_ADMA64; + else + host->flags |= USE_ADMA; #endif if (host->quirks & SDHCI_QUIRK_REG32_RW) host->version = @@ -929,6 +930,15 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, debug("%s, caps_1: 0x%x\n", __func__, caps_1); host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; + + /* + * In case the value in Clock Multiplier is 0, then programmable + * clock mode is not supported, otherwise the actual clock + * multiplier is one more than the value of Clock Multiplier + * in the Capabilities Register. + */ + if (host->clk_mul) + host->clk_mul += 1; } if (host->max_clk == 0) { diff --git a/drivers/mmc/sh_mmcif.c b/drivers/mmc/sh_mmcif.c index 76dc1c68b82..06a30d5efb8 100644 --- a/drivers/mmc/sh_mmcif.c +++ b/drivers/mmc/sh_mmcif.c @@ -6,7 +6,6 @@ */ #include <config.h> -#include <common.h> #include <log.h> #include <watchdog.h> #include <command.h> diff --git a/drivers/mmc/snps_dw_mmc.c b/drivers/mmc/snps_dw_mmc.c index 0134399e393..9bdbe5070b1 100644 --- a/drivers/mmc/snps_dw_mmc.c +++ b/drivers/mmc/snps_dw_mmc.c @@ -7,7 +7,6 @@ * Author: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> */ -#include <common.h> #include <clk.h> #include <dm.h> #include <dwmmc.h> diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index 387cb8b6b50..f738019b835 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -3,7 +3,6 @@ * (C) Copyright 2013 Altera Corporation <www.altera.com> */ -#include <common.h> #include <log.h> #include <asm/arch/clock_manager.h> #include <asm/arch/secure_reg_helper.h> diff --git a/drivers/mmc/sti_sdhci.c b/drivers/mmc/sti_sdhci.c index 23a1dd43c9b..91018b7e21a 100644 --- a/drivers/mmc/sti_sdhci.c +++ b/drivers/mmc/sti_sdhci.c @@ -4,7 +4,6 @@ * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics. */ -#include <common.h> #include <dm.h> #include <log.h> #include <mmc.h> diff --git a/drivers/mmc/stm32_sdmmc2.c b/drivers/mmc/stm32_sdmmc2.c index a2b111a8435..9483fb57daf 100644 --- a/drivers/mmc/stm32_sdmmc2.c +++ b/drivers/mmc/stm32_sdmmc2.c @@ -6,7 +6,6 @@ #define LOG_CATEGORY UCLASS_MMC -#include <common.h> #include <clk.h> #include <cpu_func.h> #include <dm.h> @@ -220,9 +219,9 @@ static void stm32_sdmmc2_start_data(struct udevice *dev, if (data->flags & MMC_DATA_READ) { data_ctrl |= SDMMC_DCTRL_DTDIR; - idmabase0 = (u32)data->dest; + idmabase0 = (u32)(long)data->dest; } else { - idmabase0 = (u32)data->src; + idmabase0 = (u32)(long)data->src; } /* Set the SDMMC DataLength value */ @@ -463,8 +462,8 @@ retry_cmd: stm32_sdmmc2_start_cmd(dev, cmd, cmdat, &ctx); - dev_dbg(dev, "send cmd %d data: 0x%x @ 0x%x\n", - cmd->cmdidx, data ? ctx.data_length : 0, (unsigned int)data); + dev_dbg(dev, "send cmd %d data: 0x%x @ 0x%p\n", + cmd->cmdidx, data ? ctx.data_length : 0, data); ret = stm32_sdmmc2_end_cmd(dev, cmd, &ctx); @@ -789,6 +788,7 @@ static int stm32_sdmmc2_bind(struct udevice *dev) static const struct udevice_id stm32_sdmmc2_ids[] = { { .compatible = "st,stm32-sdmmc2" }, + { .compatible = "st,stm32mp25-sdmmc2" }, { } }; diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 714706d2411..0b56d1405be 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -13,7 +13,6 @@ * proper DM_MMC implementation at the end. */ -#include <common.h> #include <dm.h> #include <errno.h> #include <log.h> diff --git a/drivers/mmc/tangier_sdhci.c b/drivers/mmc/tangier_sdhci.c index 11564273324..ae65c310b68 100644 --- a/drivers/mmc/tangier_sdhci.c +++ b/drivers/mmc/tangier_sdhci.c @@ -2,7 +2,6 @@ /* * Copyright (c) 2017 Intel Corporation */ -#include <common.h> #include <dm.h> #include <dm/device.h> #include <linux/io.h> diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index c01fb3d0165..5ed7f01d3f3 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -7,7 +7,6 @@ */ #include <bouncebuf.h> -#include <common.h> #include <dm.h> #include <errno.h> #include <log.h> diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 890c496b535..0b396122b46 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -4,7 +4,6 @@ * Author: Masahiro Yamada <yamada.masahiro@socionext.com> */ -#include <common.h> #include <clk.h> #include <cpu_func.h> #include <fdtdec.h> @@ -299,7 +298,13 @@ static int tmio_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks; - while (!(tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)) { + for (;;) { + if (tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag) + break; + + if (tmio_sd_readl(priv, TMIO_SD_INFO1) & TMIO_SD_INFO1_CMP) + break; + if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT; diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 8cde4308aae..5b3650d52ee 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -4,7 +4,6 @@ * Author: Masahiro Yamada <yamada.masahiro@socionext.com> */ -#include <common.h> #include <clk.h> #include <fdtdec.h> #include <malloc.h> diff --git a/drivers/mmc/xenon_sdhci.c b/drivers/mmc/xenon_sdhci.c index 27dbe0404e0..0e4902fab77 100644 --- a/drivers/mmc/xenon_sdhci.c +++ b/drivers/mmc/xenon_sdhci.c @@ -14,7 +14,6 @@ * Stefan Roese <sr@denx.de> */ -#include <common.h> #include <dm.h> #include <fdtdec.h> #include <asm/global_data.h> diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 935540d1719..898be5a0913 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -7,7 +7,6 @@ */ #include <clk.h> -#include <common.h> #include <dm.h> #include <fdtdec.h> #include <linux/delay.h> |