diff options
author | Tom Rini <trini@konsulko.com> | 2017-08-18 18:24:36 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2017-08-18 18:24:36 -0400 |
commit | 1fdafb2e3dfecdc4129a8062ad25b1adb32b0efb (patch) | |
tree | 6c6a74d4cb4e8a19bfd47510ade9fdcc3d08cb01 /drivers/mmc | |
parent | a6dd10c70be9be863488d9d7afede057a4d99823 (diff) | |
parent | a191ccaf12fb4fadedcd3c76df6327e2bb0f182b (diff) | |
download | u-boot-1fdafb2e3dfecdc4129a8062ad25b1adb32b0efb.tar.gz |
Merge branch 'master' of git://git.denx.de/u-boot-mmc
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/Kconfig | 40 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 8 | ||||
-rw-r--r-- | drivers/mmc/fsl_esdhc.c | 261 | ||||
-rw-r--r-- | drivers/mmc/gen_atmel_mci.c | 64 | ||||
-rw-r--r-- | drivers/mmc/mmc-uclass.c | 4 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 12 | ||||
-rw-r--r-- | drivers/mmc/mmc_boot.c | 17 | ||||
-rw-r--r-- | drivers/mmc/mmc_legacy.c | 2 | ||||
-rw-r--r-- | drivers/mmc/pci_mmc.c | 7 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 8 | ||||
-rw-r--r-- | drivers/mmc/sh_sdhi.c | 283 | ||||
-rw-r--r-- | drivers/mmc/uniphier-sd.c | 14 |
12 files changed, 486 insertions, 234 deletions
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 51a87cdd77..56c352e72a 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -20,16 +20,6 @@ config DM_MMC appear as block devices in U-Boot and can support filesystems such as EXT4 and FAT. -config DM_MMC_OPS - bool "Support MMC controller operations using Driver Model" - depends on DM_MMC - default y if DM_MMC - help - Driver model provides a means of supporting device operations. This - option moves MMC operations under the control of driver model. The - option will be removed as soon as all DM_MMC drivers use it, as it - will the only supported behaviour. - config SPL_DM_MMC bool "Enable MMC controllers using Driver Model in SPL" depends on SPL_DM && DM_MMC @@ -41,16 +31,6 @@ config SPL_DM_MMC appear as block devices in U-Boot and can support filesystems such as EXT4 and FAT. -config SPL_DM_MMC_OPS - bool "Support MMC controller operations using Driver Model in SPL" - depends on SPL_DM && DM_MMC_OPS - default y - help - Driver model provides a means of supporting device operations. This - option moves MMC operations under the control of driver model. The - option will be removed as soon as all DM_MMC drivers use it, as it - will the only supported behaviour. - if MMC config SPL_MMC_TINY @@ -124,7 +104,7 @@ config MMC_DW_SOCFPGA config MMC_MESON_GX bool "Meson GX EMMC controller support" - depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_MESON + depends on DM_MMC && BLK && ARCH_MESON help Support for EMMC host controller on Meson GX ARM SoCs platform (S905) @@ -155,7 +135,7 @@ config MMC_PCI config MMC_OMAP_HS bool "TI OMAP High Speed Multimedia Card Interface support" - select DM_MMC_OPS if DM_MMC + select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR help This selects the TI OMAP High Speed Multimedia card Interface. If you have an omap2plus board with a Multimedia Card slot, @@ -184,7 +164,7 @@ config SH_SDHI config MMC_UNIPHIER bool "UniPhier SD/MMC Host Controller support" depends on ARCH_UNIPHIER - depends on BLK && DM_MMC_OPS + depends on BLK && DM_MMC depends on OF_CONTROL help This selects support for the SD/MMC Host Controller on UniPhier SoCs. @@ -192,7 +172,7 @@ config MMC_UNIPHIER config MMC_SANDBOX bool "Sandbox MMC support" depends on SANDBOX - depends on BLK && DM_MMC_OPS && OF_CONTROL + depends on BLK && DM_MMC && OF_CONTROL help This select a dummy sandbox MMC driver. At present this does nothing other than allow sandbox to be build with MMC support. This @@ -227,7 +207,7 @@ config MMC_SDHCI_SDMA config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 - depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91 + depends on DM_MMC && BLK && ARCH_AT91 depends on MMC_SDHCI help This enables support for the Atmel SDHCI controller, which supports @@ -251,7 +231,7 @@ config MMC_SDHCI_BCM2835 config MMC_SDHCI_CADENCE bool "SDHCI support for the Cadence SD/SDIO/eMMC controller" - depends on BLK && DM_MMC_OPS + depends on BLK && DM_MMC depends on MMC_SDHCI depends on OF_CONTROL help @@ -273,7 +253,7 @@ config MMC_SDHCI_KONA config MMC_SDHCI_MSM bool "Qualcomm SDHCI controller" - depends on BLK && DM_MMC_OPS + depends on BLK && DM_MMC depends on MMC_SDHCI help Enables support for SDHCI 2.0 controller present on some Qualcomm @@ -303,7 +283,7 @@ config MMC_SDHCI_PIC32 config MMC_SDHCI_ROCKCHIP bool "Arasan SDHCI controller for Rockchip support" depends on ARCH_ROCKCHIP - depends on DM_MMC && BLK && DM_MMC_OPS + depends on DM_MMC && BLK depends on MMC_SDHCI help Support for Arasan SDHCI host controller on Rockchip ARM SoCs platform @@ -376,7 +356,7 @@ config MMC_SDHCI_TEGRA config MMC_SDHCI_ZYNQ bool "Arasan SDHCI controller support" depends on ARCH_ZYNQ || ARCH_ZYNQMP - depends on DM_MMC && OF_CONTROL && BLK && DM_MMC_OPS + depends on DM_MMC && OF_CONTROL && BLK depends on MMC_SDHCI help Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform @@ -391,7 +371,7 @@ config MMC_SUNXI config GENERIC_ATMEL_MCI bool "Atmel Multimedia Card Interface support" - depends on DM_MMC && BLK && DM_MMC_OPS && ARCH_AT91 + depends on DM_MMC && BLK && ARCH_AT91 help This enables support for Atmel High Speed Multimedia Card Interface (HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3, diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 700f764432..23f642980b 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -184,7 +184,7 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host, return mode; } -#ifdef CONFIG_DM_MMC_OPS +#ifdef CONFIG_DM_MMC static int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { @@ -383,7 +383,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) return 0; } -#ifdef CONFIG_DM_MMC_OPS +#ifdef CONFIG_DM_MMC static int dwmci_set_ios(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -466,7 +466,7 @@ static int dwmci_init(struct mmc *mmc) return 0; } -#ifdef CONFIG_DM_MMC_OPS +#ifdef CONFIG_DM_MMC int dwmci_probe(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -491,7 +491,7 @@ void dwmci_setup_cfg(struct mmc_config *cfg, struct dwmci_host *host, u32 max_clk, u32 min_clk) { cfg->name = host->name; -#ifndef CONFIG_DM_MMC_OPS +#ifndef CONFIG_DM_MMC cfg->ops = &dwmci_ops; #endif cfg->f_min = min_clk; diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index b69c9b71e4..cc188c4260 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -81,6 +81,11 @@ struct fsl_esdhc { uint scr; /* eSDHC control register */ }; +struct fsl_esdhc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + /** * struct fsl_esdhc_priv * @@ -101,8 +106,9 @@ struct fsl_esdhc_priv { struct fsl_esdhc *esdhc_regs; unsigned int sdhc_clk; unsigned int bus_width; - struct mmc_config cfg; +#if !CONFIG_IS_ENABLED(BLK) struct mmc *mmc; +#endif struct udevice *dev; int non_removable; int wp_enable; @@ -156,10 +162,9 @@ static uint esdhc_xfertyp(struct mmc_cmd *cmd, struct mmc_data *data) /* * PIO Read/Write Mode reduce the performace as DMA is not used in this mode. */ -static void -esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data) +static void esdhc_pio_read_write(struct fsl_esdhc_priv *priv, + struct mmc_data *data) { - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; uint blocks; char *buffer; @@ -218,10 +223,10 @@ esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data) } #endif -static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) +static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc, + struct mmc_data *data) { int timeout; - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; #if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) dma_addr_t addr; @@ -349,13 +354,12 @@ static void check_and_invalidate_dcache_range * Sends a command out on the bus. Takes the mmc pointer, * a command pointer, and an optional data pointer. */ -static int -esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc, + struct mmc_cmd *cmd, struct mmc_data *data) { int err = 0; uint xfertyp; uint irqstat; - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; #ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111 @@ -384,7 +388,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Set up for a data transfer if we have one */ if (data) { - err = esdhc_setup_data(mmc, data); + err = esdhc_setup_data(priv, mmc, data); if(err) return err; @@ -470,7 +474,7 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) /* Wait until all of the blocks are transferred */ if (data) { #ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO - esdhc_pio_read_write(mmc, data); + esdhc_pio_read_write(priv, data); #else do { irqstat = esdhc_read32(®s->irqstat); @@ -522,7 +526,7 @@ out: return err; } -static void set_sysctl(struct mmc *mmc, uint clock) +static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) { int div = 1; #ifdef ARCH_MXC @@ -531,7 +535,6 @@ static void set_sysctl(struct mmc *mmc, uint clock) int pre_div = 2; #endif int ddr_pre_div = mmc->ddr_mode ? 2 : 1; - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; int sdhc_clk = priv->sdhc_clk; uint clk; @@ -569,9 +572,8 @@ static void set_sysctl(struct mmc *mmc, uint clock) } #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK -static void esdhc_clock_control(struct mmc *mmc, bool enable) +static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) { - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; u32 value; u32 time_out; @@ -598,19 +600,18 @@ static void esdhc_clock_control(struct mmc *mmc, bool enable) } #endif -static int esdhc_set_ios(struct mmc *mmc) +static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) { - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; #ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK /* Select to use peripheral clock */ - esdhc_clock_control(mmc, false); + esdhc_clock_control(priv, false); esdhc_setbits32(®s->scr, ESDHCCTL_PCS); - esdhc_clock_control(mmc, true); + esdhc_clock_control(priv, true); #endif /* Set the clock speed */ - set_sysctl(mmc, mmc->clock); + set_sysctl(priv, mmc, mmc->clock); /* Set the bus width */ esdhc_clrbits32(®s->proctl, PROCTL_DTW_4 | PROCTL_DTW_8); @@ -623,18 +624,20 @@ static int esdhc_set_ios(struct mmc *mmc) return 0; } -static int esdhc_init(struct mmc *mmc) +static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) { - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; - int timeout = 1000; + ulong start; /* Reset the entire host controller */ esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); /* Wait until the controller is available */ - while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) - udelay(1000); + start = get_timer(0); + while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { + if (get_timer(start) > 1000) + return -ETIMEDOUT; + } #if defined(CONFIG_FSL_USDHC) /* RSTA doesn't reset MMC_BOOT register, so manually reset it */ @@ -679,9 +682,8 @@ static int esdhc_init(struct mmc *mmc) return 0; } -static int esdhc_getcd(struct mmc *mmc) +static int esdhc_getcd_common(struct fsl_esdhc_priv *priv) { - struct fsl_esdhc_priv *priv = mmc->priv; struct fsl_esdhc *regs = priv->esdhc_regs; int timeout = 1000; @@ -690,7 +692,7 @@ static int esdhc_getcd(struct mmc *mmc) return 1; #endif -#ifdef CONFIG_DM_MMC +#if CONFIG_IS_ENABLED(DM_MMC) if (priv->non_removable) return 1; #ifdef CONFIG_DM_GPIO @@ -705,32 +707,70 @@ static int esdhc_getcd(struct mmc *mmc) return timeout > 0; } -static void esdhc_reset(struct fsl_esdhc *regs) +static int esdhc_reset(struct fsl_esdhc *regs) { - unsigned long timeout = 100; /* wait max 100 ms */ + ulong start; /* reset the controller */ esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); /* hardware clears the bit when it is done */ - while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA) && --timeout) - udelay(1000); - if (!timeout) - printf("MMC/SD: Reset never completed.\n"); + start = get_timer(0); + while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { + if (get_timer(start) > 100) { + printf("MMC/SD: Reset never completed.\n"); + return -ETIMEDOUT; + } + } + + return 0; +} + +#if !CONFIG_IS_ENABLED(DM_MMC) +static int esdhc_getcd(struct mmc *mmc) +{ + struct fsl_esdhc_priv *priv = mmc->priv; + + return esdhc_getcd_common(priv); +} + +static int esdhc_init(struct mmc *mmc) +{ + struct fsl_esdhc_priv *priv = mmc->priv; + + return esdhc_init_common(priv, mmc); +} + +static int esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct fsl_esdhc_priv *priv = mmc->priv; + + return esdhc_send_cmd_common(priv, mmc, cmd, data); +} + +static int esdhc_set_ios(struct mmc *mmc) +{ + struct fsl_esdhc_priv *priv = mmc->priv; + + return esdhc_set_ios_common(priv, mmc); } static const struct mmc_ops esdhc_ops = { + .getcd = esdhc_getcd, + .init = esdhc_init, .send_cmd = esdhc_send_cmd, .set_ios = esdhc_set_ios, - .init = esdhc_init, - .getcd = esdhc_getcd, }; +#endif -static int fsl_esdhc_init(struct fsl_esdhc_priv *priv) +static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, + struct fsl_esdhc_plat *plat) { + struct mmc_config *cfg; struct fsl_esdhc *regs; - struct mmc *mmc; u32 caps, voltage_caps; + int ret; if (!priv) return -EINVAL; @@ -738,7 +778,9 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv) regs = priv->esdhc_regs; /* First reset the eSDHC controller */ - esdhc_reset(regs); + ret = esdhc_reset(regs); + if (ret) + return ret; #ifndef CONFIG_FSL_USDHC esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN @@ -752,7 +794,10 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv) esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten); - memset(&priv->cfg, 0, sizeof(priv->cfg)); + cfg = &plat->cfg; +#ifndef CONFIG_DM_MMC + memset(cfg, '\0', sizeof(*cfg)); +#endif voltage_caps = 0; caps = esdhc_read32(®s->hostcapblt); @@ -774,58 +819,54 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv) if (caps & ESDHC_HOSTCAPBLT_VS33) voltage_caps |= MMC_VDD_32_33 | MMC_VDD_33_34; - priv->cfg.name = "FSL_SDHC"; - priv->cfg.ops = &esdhc_ops; + cfg->name = "FSL_SDHC"; +#if !CONFIG_IS_ENABLED(DM_MMC) + cfg->ops = &esdhc_ops; +#endif #ifdef CONFIG_SYS_SD_VOLTAGE - priv->cfg.voltages = CONFIG_SYS_SD_VOLTAGE; + cfg->voltages = CONFIG_SYS_SD_VOLTAGE; #else - priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; + cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; #endif - if ((priv->cfg.voltages & voltage_caps) == 0) { + if ((cfg->voltages & voltage_caps) == 0) { printf("voltage not supported by controller\n"); return -1; } if (priv->bus_width == 8) - priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; + cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; else if (priv->bus_width == 4) - priv->cfg.host_caps = MMC_MODE_4BIT; + cfg->host_caps = MMC_MODE_4BIT; - priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; + cfg->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; #ifdef CONFIG_SYS_FSL_ESDHC_HAS_DDR_MODE - priv->cfg.host_caps |= MMC_MODE_DDR_52MHz; + cfg->host_caps |= MMC_MODE_DDR_52MHz; #endif if (priv->bus_width > 0) { if (priv->bus_width < 8) - priv->cfg.host_caps &= ~MMC_MODE_8BIT; + cfg->host_caps &= ~MMC_MODE_8BIT; if (priv->bus_width < 4) - priv->cfg.host_caps &= ~MMC_MODE_4BIT; + cfg->host_caps &= ~MMC_MODE_4BIT; } if (caps & ESDHC_HOSTCAPBLT_HSS) - priv->cfg.host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; + cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; #ifdef CONFIG_ESDHC_DETECT_8_BIT_QUIRK if (CONFIG_ESDHC_DETECT_8_BIT_QUIRK) - priv->cfg.host_caps &= ~MMC_MODE_8BIT; + cfg->host_caps &= ~MMC_MODE_8BIT; #endif - priv->cfg.f_min = 400000; - priv->cfg.f_max = min(priv->sdhc_clk, (u32)52000000); - - priv->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - - mmc = mmc_create(&priv->cfg, priv); - if (mmc == NULL) - return -1; + cfg->f_min = 400000; + cfg->f_max = min(priv->sdhc_clk, (u32)52000000); - priv->mmc = mmc; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; return 0; } -#ifndef CONFIG_DM_MMC +#if !CONFIG_IS_ENABLED(DM_MMC) static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg, struct fsl_esdhc_priv *priv) { @@ -843,7 +884,9 @@ static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg, int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) { + struct fsl_esdhc_plat *plat; struct fsl_esdhc_priv *priv; + struct mmc *mmc; int ret; if (!cfg) @@ -852,21 +895,34 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) priv = calloc(sizeof(struct fsl_esdhc_priv), 1); if (!priv) return -ENOMEM; + plat = calloc(sizeof(struct fsl_esdhc_plat), 1); + if (!plat) { + free(priv); + return -ENOMEM; + } ret = fsl_esdhc_cfg_to_priv(cfg, priv); if (ret) { debug("%s xlate failure\n", __func__); + free(plat); free(priv); return ret; } - ret = fsl_esdhc_init(priv); + ret = fsl_esdhc_init(priv, plat); if (ret) { debug("%s init failure\n", __func__); + free(plat); free(priv); return ret; } + mmc = mmc_create(&plat->cfg, priv); + if (!mmc) + return -EIO; + + priv->mmc = mmc; + return 0; } @@ -954,7 +1010,7 @@ void fdt_fixup_esdhc(void *blob, bd_t *bd) } #endif -#ifdef CONFIG_DM_MMC +#if CONFIG_IS_ENABLED(DM_MMC) #include <asm/arch/clock.h> __weak void init_clk_usdhc(u32 index) { @@ -963,24 +1019,24 @@ __weak void init_clk_usdhc(u32 index) static int fsl_esdhc_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct fsl_esdhc_plat *plat = dev_get_platdata(dev); struct fsl_esdhc_priv *priv = dev_get_priv(dev); - const void *fdt = gd->fdt_blob; - int node = dev_of_offset(dev); #ifdef CONFIG_DM_REGULATOR struct udevice *vqmmc_dev; #endif fdt_addr_t addr; unsigned int val; + struct mmc *mmc; int ret; - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; priv->esdhc_regs = (struct fsl_esdhc *)addr; priv->dev = dev; - val = fdtdec_get_int(fdt, node, "bus-width", -1); + val = dev_read_u32_default(dev, "bus-width", -1); if (val == 8) priv->bus_width = 8; else if (val == 4) @@ -988,21 +1044,21 @@ static int fsl_esdhc_probe(struct udevice *dev) else priv->bus_width = 1; - if (fdt_get_property(fdt, node, "non-removable", NULL)) { + if (dev_read_bool(dev, "non-removable")) { priv->non_removable = 1; } else { priv->non_removable = 0; #ifdef CONFIG_DM_GPIO - gpio_request_by_name_nodev(offset_to_ofnode(node), "cd-gpios", - 0, &priv->cd_gpio, GPIOD_IS_IN); + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, + GPIOD_IS_IN); #endif } priv->wp_enable = 1; #ifdef CONFIG_DM_GPIO - ret = gpio_request_by_name_nodev(offset_to_ofnode(node), "wp-gpios", 0, - &priv->wp_gpio, GPIOD_IS_IN); + ret = gpio_request_by_name(dev, "wp-gpios", 0, &priv->wp_gpio, + GPIOD_IS_IN); if (ret) priv->wp_enable = 0; #endif @@ -1057,18 +1113,53 @@ static int fsl_esdhc_probe(struct udevice *dev) return -EINVAL; } - ret = fsl_esdhc_init(priv); + ret = fsl_esdhc_init(priv, plat); if (ret) { dev_err(dev, "fsl_esdhc_init failure\n"); return ret; } - upriv->mmc = priv->mmc; - priv->mmc->dev = dev; + mmc = &plat->mmc; + mmc->cfg = &plat->cfg; + mmc->dev = dev; + upriv->mmc = mmc; - return 0; + return esdhc_init_common(priv, mmc); } +#if CONFIG_IS_ENABLED(DM_MMC) +static int fsl_esdhc_get_cd(struct udevice *dev) +{ + struct fsl_esdhc_priv *priv = dev_get_priv(dev); + + return true; + return esdhc_getcd_common(priv); +} + +static int fsl_esdhc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct fsl_esdhc_plat *plat = dev_get_platdata(dev); + struct fsl_esdhc_priv *priv = dev_get_priv(dev); + + return esdhc_send_cmd_common(priv, &plat->mmc, cmd, data); +} + +static int fsl_esdhc_set_ios(struct udevice *dev) +{ + struct fsl_esdhc_plat *plat = dev_get_platdata(dev); + struct fsl_esdhc_priv *priv = dev_get_priv(dev); + + return esdhc_set_ios_common(priv, &plat->mmc); +} + +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, +}; +#endif + static const struct udevice_id fsl_esdhc_ids[] = { { .compatible = "fsl,imx6ul-usdhc", }, { .compatible = "fsl,imx6sx-usdhc", }, @@ -1080,11 +1171,25 @@ static const struct udevice_id fsl_esdhc_ids[] = { { /* sentinel */ } }; +#if CONFIG_IS_ENABLED(BLK) +static int fsl_esdhc_bind(struct udevice *dev) +{ + struct fsl_esdhc_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} +#endif + U_BOOT_DRIVER(fsl_esdhc) = { .name = "fsl-esdhc-mmc", .id = UCLASS_MMC, .of_match = fsl_esdhc_ids, + .ops = &fsl_esdhc_ops, +#if CONFIG_IS_ENABLED(BLK) + .bind = fsl_esdhc_bind, +#endif .probe = fsl_esdhc_probe, + .platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat), .priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv), }; #endif diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c index e9f061e55d..22154d13d7 100644 --- a/drivers/mmc/gen_atmel_mci.c +++ b/drivers/mmc/gen_atmel_mci.c @@ -36,13 +36,22 @@ DECLARE_GLOBAL_DATA_PTR; # define MCI_BUS 0 #endif +#ifdef CONFIG_DM_MMC +struct atmel_mci_plat { + struct mmc mmc; + struct mmc_config cfg; + struct atmel_mci *mci; +}; +#endif + struct atmel_mci_priv { +#ifndef CONFIG_DM_MMC struct mmc_config cfg; struct atmel_mci *mci; +#endif unsigned int initialized:1; unsigned int curr_clk; #ifdef CONFIG_DM_MMC - struct mmc mmc; ulong bus_clk_rate; #endif }; @@ -67,18 +76,21 @@ static void dump_cmd(u32 cmdr, u32 arg, u32 status, const char* msg) /* Setup for MCI Clock and Block Size */ #ifdef CONFIG_DM_MMC -static void mci_set_mode(struct atmel_mci_priv *priv, u32 hz, u32 blklen) +static void mci_set_mode(struct udevice *dev, u32 hz, u32 blklen) { - struct mmc *mmc = &priv->mmc; + struct atmel_mci_plat *plat = dev_get_platdata(dev); + struct atmel_mci_priv *priv = dev_get_priv(dev); + struct mmc *mmc = &plat->mmc; u32 bus_hz = priv->bus_clk_rate; + atmel_mci_t *mci = plat->mci; #else static void mci_set_mode(struct mmc *mmc, u32 hz, u32 blklen) { struct atmel_mci_priv *priv = mmc->priv; u32 bus_hz = get_mci_clk_rate(); + atmel_mci_t *mci = priv->mci; #endif - atmel_mci_t *mci = priv->mci; u32 clkdiv = 255; unsigned int version = atmel_mci_get_version(mci); u32 clkodd = 0; @@ -222,15 +234,17 @@ io_fail: static int atmel_mci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { + struct atmel_mci_plat *plat = dev_get_platdata(dev); struct atmel_mci_priv *priv = dev_get_priv(dev); struct mmc *mmc = mmc_get_mmc_dev(dev); + atmel_mci_t *mci = plat->mci; #else static int mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { struct atmel_mci_priv *priv = mmc->priv; -#endif atmel_mci_t *mci = priv->mci; +#endif u32 cmdr; u32 error_flags = 0; u32 status; @@ -362,22 +376,23 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) #ifdef CONFIG_DM_MMC static int atmel_mci_set_ios(struct udevice *dev) { - struct atmel_mci_priv *priv = dev_get_priv(dev); + struct atmel_mci_plat *plat = dev_get_platdata(dev); struct mmc *mmc = mmc_get_mmc_dev(dev); + atmel_mci_t *mci = plat->mci; #else /* Entered into mmc structure during driver init */ static int mci_set_ios(struct mmc *mmc) { struct atmel_mci_priv *priv = mmc->priv; -#endif atmel_mci_t *mci = priv->mci; +#endif int bus_width = mmc->bus_width; unsigned int version = atmel_mci_get_version(mci); int busw; /* Set the clock speed */ #ifdef CONFIG_DM_MMC - mci_set_mode(priv, mmc->clock, MMC_DEFAULT_BLKLEN); + mci_set_mode(dev, mmc->clock, MMC_DEFAULT_BLKLEN); #else mci_set_mode(mmc, mmc->clock, MMC_DEFAULT_BLKLEN); #endif @@ -410,15 +425,17 @@ static int mci_set_ios(struct mmc *mmc) } #ifdef CONFIG_DM_MMC -static int atmel_mci_hw_init(struct atmel_mci_priv *priv) +static int atmel_mci_hw_init(struct udevice *dev) { + struct atmel_mci_plat *plat = dev_get_platdata(dev); + atmel_mci_t *mci = plat->mci; #else /* Entered into mmc structure during driver init */ static int mci_init(struct mmc *mmc) { struct atmel_mci_priv *priv = mmc->priv; -#endif atmel_mci_t *mci = priv->mci; +#endif /* Initialize controller */ writel(MMCI_BIT(SWRST), &mci->cr); /* soft reset */ @@ -433,7 +450,7 @@ static int mci_init(struct mmc *mmc) /* Set default clocks and blocklen */ #ifdef CONFIG_DM_MMC - mci_set_mode(priv, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN); + mci_set_mode(dev, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN); #else mci_set_mode(mmc, CONFIG_SYS_MMC_CLK_OD, MMC_DEFAULT_BLKLEN); #endif @@ -509,12 +526,14 @@ static const struct dm_mmc_ops atmel_mci_mmc_ops = { .set_ios = atmel_mci_set_ios, }; -static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv) +static void atmel_mci_setup_cfg(struct udevice *dev) { + struct atmel_mci_plat *plat = dev_get_platdata(dev); + struct atmel_mci_priv *priv = dev_get_priv(dev); struct mmc_config *cfg; u32 version; - cfg = &priv->cfg; + cfg = &plat->cfg; cfg->name = "Atmel mci"; cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; @@ -522,7 +541,7 @@ static void atmel_mci_setup_cfg(struct atmel_mci_priv *priv) * If the version is above 3.0, the capabilities of the 8-bit * bus width and high speed are supported. */ - version = atmel_mci_get_version(priv->mci); + version = atmel_mci_get_version(plat->mci); if ((version & 0xf00) >= 0x300) { cfg->host_caps = MMC_MODE_8BIT | MMC_MODE_HS | MMC_MODE_HS_52MHz; @@ -568,7 +587,7 @@ failed: static int atmel_mci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); - struct atmel_mci_priv *priv = dev_get_priv(dev); + struct atmel_mci_plat *plat = dev_get_platdata(dev); struct mmc *mmc; int ret; @@ -576,25 +595,25 @@ static int atmel_mci_probe(struct udevice *dev) if (ret) return ret; - priv->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev); + plat->mci = (struct atmel_mci *)devfdt_get_addr_ptr(dev); - atmel_mci_setup_cfg(priv); + atmel_mci_setup_cfg(dev); - mmc = &priv->mmc; - mmc->cfg = &priv->cfg; + mmc = &plat->mmc; + mmc->cfg = &plat->cfg; mmc->dev = dev; upriv->mmc = mmc; - atmel_mci_hw_init(priv); + atmel_mci_hw_init(dev); return 0; } static int atmel_mci_bind(struct udevice *dev) { - struct atmel_mci_priv *priv = dev_get_priv(dev); + struct atmel_mci_plat *plat = dev_get_platdata(dev); - return mmc_bind(dev, &priv->mmc, &priv->cfg); + return mmc_bind(dev, &plat->mmc, &plat->cfg); } static const struct udevice_id atmel_mci_ids[] = { @@ -608,6 +627,7 @@ U_BOOT_DRIVER(atmel_mci) = { .of_match = atmel_mci_ids, .bind = atmel_mci_bind, .probe = atmel_mci_probe, + .platdata_auto_alloc_size = sizeof(struct atmel_mci_plat), .priv_auto_alloc_size = sizeof(struct atmel_mci_priv), .ops = &atmel_mci_mmc_ops, }; diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 3e907253ea..5dda20cda5 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -15,7 +15,6 @@ DECLARE_GLOBAL_DATA_PTR; -#if CONFIG_IS_ENABLED(DM_MMC_OPS) int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { @@ -79,7 +78,6 @@ int mmc_getcd(struct mmc *mmc) { return dm_mmc_get_cd(mmc->dev); } -#endif struct mmc *mmc_get_mmc_dev(struct udevice *dev) { @@ -198,10 +196,8 @@ int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) struct udevice *bdev; int ret, devnum = -1; -#if CONFIG_IS_ENABLED(DM_MMC_OPS) if (!mmc_get_ops(dev)) return -ENOSYS; -#endif #ifndef CONFIG_SPL_BUILD /* Use the fixed index with aliase node's index */ ret = dev_read_alias_seq(dev, &devnum); diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 38e1c800e1..38d2e07dd5 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -53,7 +53,7 @@ struct blk_desc *mmc_get_blk_desc(struct mmc *mmc) } #endif -#if !CONFIG_IS_ENABLED(DM_MMC_OPS) +#if !CONFIG_IS_ENABLED(DM_MMC) __weak int board_mmc_getwp(struct mmc *mmc) { return -1; @@ -149,7 +149,7 @@ void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd) } #endif -#if !CONFIG_IS_ENABLED(DM_MMC_OPS) +#if !CONFIG_IS_ENABLED(DM_MMC) int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { int ret; @@ -839,7 +839,7 @@ int mmc_hwpart_config(struct mmc *mmc, return 0; } -#if !CONFIG_IS_ENABLED(DM_MMC_OPS) +#if !CONFIG_IS_ENABLED(DM_MMC) int mmc_getcd(struct mmc *mmc) { int cd; @@ -1075,7 +1075,7 @@ static const u8 multipliers[] = { 80, }; -#if !CONFIG_IS_ENABLED(DM_MMC_OPS) +#if !CONFIG_IS_ENABLED(DM_MMC) static void mmc_set_ios(struct mmc *mmc) { if (mmc->cfg->ops->set_ios) @@ -1652,7 +1652,7 @@ int mmc_start_init(struct mmc *mmc) /* we pretend there's no card when init is NULL */ no_card = mmc_getcd(mmc) == 0; -#if !CONFIG_IS_ENABLED(DM_MMC_OPS) +#if !CONFIG_IS_ENABLED(DM_MMC) no_card = no_card || (mmc->cfg->ops->init == NULL); #endif if (no_card) { @@ -1673,7 +1673,7 @@ int mmc_start_init(struct mmc *mmc) if (err) return err; -#if CONFIG_IS_ENABLED(DM_MMC_OPS) +#if CONFIG_IS_ENABLED(DM_MMC) /* The device has already been probed ready for use */ #else /* made sure it's not NULL earlier */ diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c index ac6f56f157..6d77ce95e7 100644 --- a/drivers/mmc/mmc_boot.c +++ b/drivers/mmc/mmc_boot.c @@ -100,10 +100,19 @@ int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode) */ int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access) { - return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, - EXT_CSD_BOOT_ACK(ack) | - EXT_CSD_BOOT_PART_NUM(part_num) | - EXT_CSD_PARTITION_ACCESS(access)); + int ret; + u8 part_conf; + + part_conf = EXT_CSD_BOOT_ACK(ack) | + EXT_CSD_BOOT_PART_NUM(part_num) | + EXT_CSD_PARTITION_ACCESS(access); + + ret = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, + part_conf); + if (!ret) + mmc->part_config = part_conf; + + return ret; } /* diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c index 59dc3df35f..100b931e5b 100644 --- a/drivers/mmc/mmc_legacy.c +++ b/drivers/mmc/mmc_legacy.c @@ -150,7 +150,7 @@ struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) cfg->f_max == 0 || cfg->b_max == 0) return NULL; -#if !CONFIG_IS_ENABLED(DM_MMC_OPS) +#if !CONFIG_IS_ENABLED(DM_MMC) if (cfg->ops == NULL || cfg->ops->send_cmd == NULL) return NULL; #endif diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 6db89779ba..05c0044a7a 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -64,12 +64,7 @@ U_BOOT_DRIVER(pci_mmc) = { }; static struct pci_device_id mmc_supported[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SDIO) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SD) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_EMMC2) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1) }, + { PCI_DEVICE_CLASS(PCI_CLASS_SYSTEM_SDHCI << 8, 0xffff00) }, {}, }; diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 161a6b1399..11d1f0c24c 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -134,7 +134,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, #define SDHCI_CMD_DEFAULT_TIMEOUT 100 #define SDHCI_READ_STATUS_TIMEOUT 1000 -#ifdef CONFIG_DM_MMC_OPS +#ifdef CONFIG_DM_MMC static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { @@ -422,7 +422,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); } -#ifdef CONFIG_DM_MMC_OPS +#ifdef CONFIG_DM_MMC static int sdhci_set_ios(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -502,7 +502,7 @@ static int sdhci_init(struct mmc *mmc) return 0; } -#ifdef CONFIG_DM_MMC_OPS +#ifdef CONFIG_DM_MMC int sdhci_probe(struct udevice *dev) { struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -543,7 +543,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, host->version = sdhci_readw(host, SDHCI_HOST_VERSION); cfg->name = host->name; -#ifndef CONFIG_DM_MMC_OPS +#ifndef CONFIG_DM_MMC cfg->ops = &sdhci_ops; #endif diff --git a/drivers/mmc/sh_sdhi.c b/drivers/mmc/sh_sdhi.c index d181b63905..eef061abb2 100644 --- a/drivers/mmc/sh_sdhi.c +++ b/drivers/mmc/sh_sdhi.c @@ -13,21 +13,26 @@ #include <common.h> #include <malloc.h> #include <mmc.h> +#include <dm.h> #include <linux/errno.h> -#include <asm/io.h> +#include <linux/compat.h> +#include <linux/io.h> +#include <linux/sizes.h> #include <asm/arch/rmobile.h> #include <asm/arch/sh_sdhi.h> +#include <clk.h> #define DRIVER_NAME "sh-sdhi" struct sh_sdhi_host { - unsigned long addr; + void __iomem *addr; int ch; int bus_shift; unsigned long quirks; unsigned char wait_int; unsigned char sd_error; unsigned char detect_waiting; + unsigned char app_cmd; }; static inline void sh_sdhi_writeq(struct sh_sdhi_host *host, int reg, u64 val) @@ -50,11 +55,6 @@ static inline u16 sh_sdhi_readw(struct sh_sdhi_host *host, int reg) return readw(host->addr + (reg << host->bus_shift)); } -static void *mmc_priv(struct mmc *mmc) -{ - return (void *)mmc->priv; -} - static void sh_sdhi_detect(struct sh_sdhi_host *host) { sh_sdhi_writew(host, SDHI_OPTION, @@ -477,65 +477,64 @@ static void sh_sdhi_get_response(struct sh_sdhi_host *host, struct mmc_cmd *cmd) static unsigned short sh_sdhi_set_cmd(struct sh_sdhi_host *host, struct mmc_data *data, unsigned short opc) { - switch (opc) { - case SD_CMD_APP_SEND_OP_COND: - case SD_CMD_APP_SEND_SCR: - opc |= SDHI_APP; - break; - case SD_CMD_APP_SET_BUS_WIDTH: - /* SD_APP_SET_BUS_WIDTH*/ + if (host->app_cmd) { if (!data) - opc |= SDHI_APP; - else /* SD_SWITCH */ - opc = SDHI_SD_SWITCH; - break; - case MMC_CMD_SEND_OP_COND: - opc = SDHI_MMC_SEND_OP_COND; - break; + host->app_cmd = 0; + return opc | BIT(6); + } + + switch (opc) { + case MMC_CMD_SWITCH: + return opc | (data ? 0x1c00 : 0x40); case MMC_CMD_SEND_EXT_CSD: - if (data) - opc = SDHI_MMC_SEND_EXT_CSD; - break; + return opc | (data ? 0x1c00 : 0); + case MMC_CMD_SEND_OP_COND: + return opc | 0x0700; + case MMC_CMD_APP_CMD: + host->app_cmd = 1; default: - break; + return opc; } - return opc; } static unsigned short sh_sdhi_data_trans(struct sh_sdhi_host *host, struct mmc_data *data, unsigned short opc) { - unsigned short ret; - - switch (opc) { - case MMC_CMD_READ_MULTIPLE_BLOCK: - ret = sh_sdhi_multi_read(host, data); - break; - case MMC_CMD_WRITE_MULTIPLE_BLOCK: - ret = sh_sdhi_multi_write(host, data); - break; - case MMC_CMD_WRITE_SINGLE_BLOCK: - ret = sh_sdhi_single_write(host, data); - break; - case MMC_CMD_READ_SINGLE_BLOCK: - case SDHI_SD_APP_SEND_SCR: - case SDHI_SD_SWITCH: /* SD_SWITCH */ - case SDHI_MMC_SEND_EXT_CSD: - ret = sh_sdhi_single_read(host, data); - break; - default: - printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc); - ret = -EINVAL; - break; + if (host->app_cmd) { + host->app_cmd = 0; + switch (opc) { + case SD_CMD_APP_SEND_SCR: + case SD_CMD_APP_SD_STATUS: + return sh_sdhi_single_read(host, data); + default: + printf(DRIVER_NAME": SD: NOT SUPPORT APP CMD = d'%04d\n", + opc); + return -EINVAL; + } + } else { + switch (opc) { + case MMC_CMD_WRITE_MULTIPLE_BLOCK: + return sh_sdhi_multi_write(host, data); + case MMC_CMD_READ_MULTIPLE_BLOCK: + return sh_sdhi_multi_read(host, data); + case MMC_CMD_WRITE_SINGLE_BLOCK: + return sh_sdhi_single_write(host, data); + case MMC_CMD_READ_SINGLE_BLOCK: + case MMC_CMD_SWITCH: + case MMC_CMD_SEND_EXT_CSD:; + return sh_sdhi_single_read(host, data); + default: + printf(DRIVER_NAME": SD: NOT SUPPORT CMD = d'%04d\n", opc); + return -EINVAL; + } } - return ret; } static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, struct mmc_data *data, struct mmc_cmd *cmd) { long time; - unsigned short opc = cmd->cmdidx; + unsigned short shcmd, opc = cmd->cmdidx; int ret = 0; unsigned long timeout; @@ -563,7 +562,8 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, } sh_sdhi_writew(host, SDHI_SIZE, data->blocksize); } - opc = sh_sdhi_set_cmd(host, data, opc); + + shcmd = sh_sdhi_set_cmd(host, data, opc); /* * U-Boot cannot use interrupt. @@ -594,11 +594,12 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, INFO2M_RESP_TIMEOUT | INFO2M_ILA) & sh_sdhi_readw(host, SDHI_INFO2_MASK)); - sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(opc & CMD_MASK)); - + sh_sdhi_writew(host, SDHI_CMD, (unsigned short)(shcmd & CMD_MASK)); time = sh_sdhi_wait_interrupt_flag(host); - if (!time) + if (!time) { + host->app_cmd = 0; return sh_sdhi_error_manage(host); + } if (host->sd_error) { switch (cmd->cmdidx) { @@ -616,15 +617,20 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, } host->sd_error = 0; host->wait_int = 0; + host->app_cmd = 0; return ret; } - if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) + + if (sh_sdhi_readw(host, SDHI_INFO1) & INFO1_RESP_END) { + host->app_cmd = 0; return -EINVAL; + } if (host->wait_int) { sh_sdhi_get_response(host, cmd); host->wait_int = 0; } + if (data) ret = sh_sdhi_data_trans(host, data, opc); @@ -634,23 +640,17 @@ static int sh_sdhi_start_cmd(struct sh_sdhi_host *host, return ret; } -static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) +static int sh_sdhi_send_cmd_common(struct sh_sdhi_host *host, + struct mmc_cmd *cmd, struct mmc_data *data) { - struct sh_sdhi_host *host = mmc_priv(mmc); - int ret; - host->sd_error = 0; - ret = sh_sdhi_start_cmd(host, data, cmd); - - return ret; + return sh_sdhi_start_cmd(host, data, cmd); } -static int sh_sdhi_set_ios(struct mmc *mmc) +static int sh_sdhi_set_ios_common(struct sh_sdhi_host *host, struct mmc *mmc) { int ret; - struct sh_sdhi_host *host = mmc_priv(mmc); ret = sh_sdhi_clock_control(host, mmc->clock); if (ret) @@ -674,9 +674,8 @@ static int sh_sdhi_set_ios(struct mmc *mmc) return 0; } -static int sh_sdhi_initialize(struct mmc *mmc) +static int sh_sdhi_initialize_common(struct sh_sdhi_host *host) { - struct sh_sdhi_host *host = mmc_priv(mmc); int ret = sh_sdhi_sync_reset(host); sh_sdhi_writew(host, SDHI_PORTSEL, USE_1PORT); @@ -692,6 +691,34 @@ static int sh_sdhi_initialize(struct mmc *mmc) return ret; } +#ifndef CONFIG_DM_MMC +static void *mmc_priv(struct mmc *mmc) +{ + return (void *)mmc->priv; +} + +static int sh_sdhi_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct sh_sdhi_host *host = mmc_priv(mmc); + + return sh_sdhi_send_cmd_common(host, cmd, data); +} + +static int sh_sdhi_set_ios(struct mmc *mmc) +{ + struct sh_sdhi_host *host = mmc_priv(mmc); + + return sh_sdhi_set_ios_common(host, mmc); +} + +static int sh_sdhi_initialize(struct mmc *mmc) +{ + struct sh_sdhi_host *host = mmc_priv(mmc); + + return sh_sdhi_initialize_common(host); +} + static const struct mmc_ops sh_sdhi_ops = { .send_cmd = sh_sdhi_send_cmd, .set_ios = sh_sdhi_set_ios, @@ -743,7 +770,7 @@ int sh_sdhi_init(unsigned long addr, int ch, unsigned long quirks) } host->ch = ch; - host->addr = addr; + host->addr = (void __iomem *)addr; host->quirks = quirks; if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF) @@ -757,3 +784,123 @@ error: free(host); return ret; } + +#else + +struct sh_sdhi_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +int sh_sdhi_dm_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct sh_sdhi_host *host = dev_get_priv(dev); + + return sh_sdhi_send_cmd_common(host, cmd, data); +} + +int sh_sdhi_dm_set_ios(struct udevice *dev) +{ + struct sh_sdhi_host *host = dev_get_priv(dev); + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return sh_sdhi_set_ios_common(host, mmc); +} + +static const struct dm_mmc_ops sh_sdhi_dm_ops = { + .send_cmd = sh_sdhi_dm_send_cmd, + .set_ios = sh_sdhi_dm_set_ios, +}; + +static int sh_sdhi_dm_bind(struct udevice *dev) +{ + struct sh_sdhi_plat *plat = dev_get_platdata(dev); + + return mmc_bind(dev, &plat->mmc, &plat->cfg); +} + +static int sh_sdhi_dm_probe(struct udevice *dev) +{ + struct sh_sdhi_plat *plat = dev_get_platdata(dev); + struct sh_sdhi_host *host = dev_get_priv(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct clk sh_sdhi_clk; + const u32 quirks = dev_get_driver_data(dev); + fdt_addr_t base; + int ret; + + base = devfdt_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + host->addr = devm_ioremap(dev, base, SZ_2K); + if (!host->addr) + return -ENOMEM; + + ret = clk_get_by_index(dev, 0, &sh_sdhi_clk); + if (ret) { + debug("failed to get clock, ret=%d\n", ret); + return ret; + } + + ret = clk_enable(&sh_sdhi_clk); + if (ret) { + debug("failed to enable clock, ret=%d\n", ret); + return ret; + } + + host->quirks = quirks; + + if (host->quirks & SH_SDHI_QUIRK_64BIT_BUF) + host->bus_shift = 2; + else if (host->quirks & SH_SDHI_QUIRK_16BIT_BUF) + host->bus_shift = 1; + + plat->cfg.name = dev->name; + plat->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; + + switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width", + 1)) { + case 8: + plat->cfg.host_caps |= MMC_MODE_8BIT; + break; + case 4: + plat->cfg.host_caps |= MMC_MODE_4BIT; + break; + case 1: + break; + default: + dev_err(dev, "Invalid \"bus-width\" value\n"); + return -EINVAL; + } + + sh_sdhi_initialize_common(host); + + plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; + plat->cfg.f_min = CLKDEV_INIT; + plat->cfg.f_max = CLKDEV_HS_DATA; + plat->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + upriv->mmc = &plat->mmc; + + return 0; +} + +static const struct udevice_id sh_sdhi_sd_match[] = { + { .compatible = "renesas,sdhi-r8a7795", .data = SH_SDHI_QUIRK_64BIT_BUF }, + { .compatible = "renesas,sdhi-r8a7796", .data = SH_SDHI_QUIRK_64BIT_BUF }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sh_sdhi_mmc) = { + .name = "sh-sdhi-mmc", + .id = UCLASS_MMC, + .of_match = sh_sdhi_sd_match, + .bind = sh_sdhi_dm_bind, + .probe = sh_sdhi_dm_probe, + .priv_auto_alloc_size = sizeof(struct sh_sdhi_host), + .platdata_auto_alloc_size = sizeof(struct sh_sdhi_plat), + .ops = &sh_sdhi_dm_ops, +}; +#endif diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 3c462bd583..e272b14153 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -470,13 +470,13 @@ static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32); u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10); - cmd->response[0] = (rsp_127_104 & 0xffffff) << 8 | - (rsp_103_72 & 0xff); - cmd->response[1] = (rsp_103_72 & 0xffffff) << 8 | - (rsp_71_40 & 0xff); - cmd->response[2] = (rsp_71_40 & 0xffffff) << 8 | - (rsp_39_8 & 0xff); - cmd->response[3] = (rsp_39_8 & 0xffffff) << 8; + cmd->response[0] = ((rsp_127_104 & 0x00ffffff) << 8) | + ((rsp_103_72 & 0xff000000) >> 24); + cmd->response[1] = ((rsp_103_72 & 0x00ffffff) << 8) | + ((rsp_71_40 & 0xff000000) >> 24); + cmd->response[2] = ((rsp_71_40 & 0x00ffffff) << 8) | + ((rsp_39_8 & 0xff000000) >> 24); + cmd->response[3] = (rsp_39_8 & 0xffffff) << 8; } else { /* bit 39-8 */ cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10); |