X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fmmc%2Ffsl_esdhc_imx.c;h=e5409ade1bc12c8fedda2ee59aeb7d171310804a;hb=5a1a8a63be8f7262a300eddafb18020926b12fb6;hp=f7b754bd9d37f520e92ecfcbb59c92a6d1eeb583;hpb=d8a3f5259a36e76d1de127f65714c40918e8ee4c;p=platform%2Fkernel%2Fu-boot.git diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index f7b754b..e5409ad 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -17,8 +17,14 @@ #include #include #include +#include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -27,6 +33,10 @@ #include #include #include +#include +#include +#include +#include #if !CONFIG_IS_ENABLED(BLK) #include "mmc_private.h" @@ -78,7 +88,7 @@ struct fsl_esdhc { uint vendorspec; uint mmcboot; uint vendorspec2; - uint tuning_ctrl; /* on i.MX6/7/8 */ + uint tuning_ctrl; /* on i.MX6/7/8/RT */ char reserved5[44]; uint hostver; /* Host controller version register */ char reserved6[4]; /* reserved */ @@ -96,6 +106,11 @@ struct fsl_esdhc { }; struct fsl_esdhc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + /* Put this first since driver model will copy the data here */ + struct dtd_fsl_esdhc dtplat; +#endif + struct mmc_config cfg; struct mmc mmc; }; @@ -115,6 +130,7 @@ struct esdhc_soc_data { * Following is used when Driver Model is enabled for MMC * @dev: pointer for the device * @non_removable: 0: removable; 1: non-removable + * @broken_cd: 0: use GPIO for card detect; 1: Do not use GPIO for card detect * @wp_enable: 1: enable checking wp; 0: no check * @vs18_enable: 1: use 1.8V voltage; 0: use 3.3V * @flags: ESDHC_FLAG_xx in include/fsl_esdhc_imx.h @@ -138,6 +154,7 @@ struct fsl_esdhc_priv { #endif struct udevice *dev; int non_removable; + int broken_cd; int wp_enable; int vs18_enable; u32 flags; @@ -445,13 +462,6 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc, while (esdhc_read32(®s->prsstat) & PRSSTAT_DLA) ; - /* Wait at least 8 SD clock cycles before the next command */ - /* - * Note: This is way more than 8 cycles, but 1ms seems to - * resolve timing issues with some cards - */ - udelay(1000); - /* Set up for a data transfer if we have one */ if (data) { err = esdhc_setup_data(priv, mmc, data); @@ -615,6 +625,8 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) { struct fsl_esdhc *regs = priv->esdhc_regs; int div = 1; + u32 tmp; + int ret; #ifdef ARCH_MXC #ifdef CONFIG_MX53 /* For i.MX53 eSDHCv3, SYSCTL.SDCLKFS may not be set to 0. */ @@ -648,7 +660,9 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) esdhc_clrsetbits32(®s->sysctl, SYSCTL_CLOCK_MASK, clk); - udelay(10000); + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDSTB, 100); + if (ret) + pr_warn("fsl_esdhc_imx: Internal clock never stabilised.\n"); #ifdef CONFIG_FSL_USDHC esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN); @@ -659,35 +673,6 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) priv->clock = clock; } -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK -static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable) -{ - struct fsl_esdhc *regs = priv->esdhc_regs; - u32 value; - u32 time_out; - - value = esdhc_read32(®s->sysctl); - - if (enable) - value |= SYSCTL_CKEN; - else - value &= ~SYSCTL_CKEN; - - esdhc_write32(®s->sysctl, value); - - time_out = 20; - value = PRSSTAT_SDSTB; - while (!(esdhc_read32(®s->prsstat) & value)) { - if (time_out == 0) { - printf("fsl_esdhc: Internal clock never stabilised.\n"); - break; - } - time_out--; - mdelay(1); - } -} -#endif - #ifdef MMC_SUPPORTS_TUNING static int esdhc_change_pinstate(struct udevice *dev) { @@ -737,7 +722,7 @@ static void esdhc_set_strobe_dll(struct mmc *mmc) u32 val; if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) { - writel(ESDHC_STROBE_DLL_CTRL_RESET, ®s->strobe_dllctrl); + esdhc_write32(®s->strobe_dllctrl, ESDHC_STROBE_DLL_CTRL_RESET); /* * enable strobe dll ctrl and adjust the delay target @@ -746,10 +731,10 @@ static void esdhc_set_strobe_dll(struct mmc *mmc) val = ESDHC_STROBE_DLL_CTRL_ENABLE | (priv->strobe_dll_delay_target << ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_SHIFT); - writel(val, ®s->strobe_dllctrl); + esdhc_write32(®s->strobe_dllctrl, val); /* wait 1us to make sure strobe dll status register stable */ mdelay(1); - val = readl(®s->strobe_dllstat); + val = esdhc_read32(®s->strobe_dllstat); if (!(val & ESDHC_STROBE_DLL_STS_REF_LOCK)) pr_warn("HS400 strobe DLL status REF not lock!\n"); if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK)) @@ -763,20 +748,18 @@ static int esdhc_set_timing(struct mmc *mmc) struct fsl_esdhc *regs = priv->esdhc_regs; u32 mixctrl; - mixctrl = readl(®s->mixctrl); + mixctrl = esdhc_read32(®s->mixctrl); mixctrl &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN); switch (mmc->selected_mode) { case MMC_LEGACY: - case SD_LEGACY: esdhc_reset_tuning(mmc); - writel(mixctrl, ®s->mixctrl); + esdhc_write32(®s->mixctrl, mixctrl); break; case MMC_HS_400: case MMC_HS_400_ES: mixctrl |= MIX_CTRL_DDREN | MIX_CTRL_HS400_EN; - writel(mixctrl, ®s->mixctrl); - esdhc_set_strobe_dll(mmc); + esdhc_write32(®s->mixctrl, mixctrl); break; case MMC_HS: case MMC_HS_52: @@ -786,12 +769,12 @@ static int esdhc_set_timing(struct mmc *mmc) case UHS_SDR25: case UHS_SDR50: case UHS_SDR104: - writel(mixctrl, ®s->mixctrl); + esdhc_write32(®s->mixctrl, mixctrl); break; case UHS_DDR50: case MMC_DDR_52: mixctrl |= MIX_CTRL_DDREN; - writel(mixctrl, ®s->mixctrl); + esdhc_write32(®s->mixctrl, mixctrl); break; default: printf("Not supported %d\n", mmc->selected_mode); @@ -813,7 +796,7 @@ static int esdhc_set_voltage(struct mmc *mmc) switch (mmc->signal_voltage) { case MMC_SIGNAL_VOLTAGE_330: if (priv->vs18_enable) - return -EIO; + return -ENOTSUPP; #if CONFIG_IS_ENABLED(DM_REGULATOR) if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) { ret = regulator_set_value(priv->vqmmc_dev, 3300000); @@ -871,8 +854,8 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) struct fsl_esdhc_priv *priv = dev_get_priv(dev); struct fsl_esdhc *regs = priv->esdhc_regs; struct mmc *mmc = &plat->mmc; - u32 irqstaten = readl(®s->irqstaten); - u32 irqsigen = readl(®s->irqsigen); + u32 irqstaten = esdhc_read32(®s->irqstaten); + u32 irqsigen = esdhc_read32(®s->irqsigen); int i, ret = -ETIMEDOUT; u32 val, mixctrl; @@ -882,25 +865,25 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) /* This is readw/writew SDHCI_HOST_CONTROL2 when tuning */ if (priv->flags & ESDHC_FLAG_STD_TUNING) { - val = readl(®s->autoc12err); - mixctrl = readl(®s->mixctrl); + val = esdhc_read32(®s->autoc12err); + mixctrl = esdhc_read32(®s->mixctrl); val &= ~MIX_CTRL_SMPCLK_SEL; mixctrl &= ~(MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN); val |= MIX_CTRL_EXE_TUNE; mixctrl |= MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN; - writel(val, ®s->autoc12err); - writel(mixctrl, ®s->mixctrl); + esdhc_write32(®s->autoc12err, val); + esdhc_write32(®s->mixctrl, mixctrl); } /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); */ - mixctrl = readl(®s->mixctrl); + mixctrl = esdhc_read32(®s->mixctrl); mixctrl = MIX_CTRL_DTDSEL_READ | (mixctrl & ~MIX_CTRL_SDHCI_MASK); - writel(mixctrl, ®s->mixctrl); + esdhc_write32(®s->mixctrl, mixctrl); - writel(IRQSTATEN_BRR, ®s->irqstaten); - writel(IRQSTATEN_BRR, ®s->irqsigen); + esdhc_write32(®s->irqstaten, IRQSTATEN_BRR); + esdhc_write32(®s->irqsigen, IRQSTATEN_BRR); /* * Issue opcode repeatedly till Execute Tuning is set to 0 or the number @@ -911,41 +894,31 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200) { if (mmc->bus_width == 8) - writel(0x7080, ®s->blkattr); + esdhc_write32(®s->blkattr, 0x7080); else if (mmc->bus_width == 4) - writel(0x7040, ®s->blkattr); + esdhc_write32(®s->blkattr, 0x7040); } else { - writel(0x7040, ®s->blkattr); + esdhc_write32(®s->blkattr, 0x7040); } /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE) */ - val = readl(®s->mixctrl); + val = esdhc_read32(®s->mixctrl); val = MIX_CTRL_DTDSEL_READ | (val & ~MIX_CTRL_SDHCI_MASK); - writel(val, ®s->mixctrl); + esdhc_write32(®s->mixctrl, val); /* We are using STD tuning, no need to check return value */ mmc_send_tuning(mmc, opcode, NULL); - ctrl = readl(®s->autoc12err); + ctrl = esdhc_read32(®s->autoc12err); if ((!(ctrl & MIX_CTRL_EXE_TUNE)) && (ctrl & MIX_CTRL_SMPCLK_SEL)) { - /* - * need to wait some time, make sure sd/mmc fininsh - * send out tuning data, otherwise, the sd/mmc can't - * response to any command when the card still out - * put the tuning data. - */ - mdelay(1); ret = 0; break; } - - /* Add 1ms delay for SD and eMMC */ - mdelay(1); } - writel(irqstaten, ®s->irqstaten); - writel(irqsigen, ®s->irqsigen); + esdhc_write32(®s->irqstaten, irqstaten); + esdhc_write32(®s->irqsigen, irqsigen); esdhc_stop_tuning(mmc); @@ -959,12 +932,23 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) int ret __maybe_unused; u32 clock; -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - /* Select to use peripheral clock */ - esdhc_clock_control(priv, false); - esdhc_setbits32(®s->scr, ESDHCCTL_PCS); - esdhc_clock_control(priv, true); +#ifdef MMC_SUPPORTS_TUNING + /* + * call esdhc_set_timing() before update the clock rate, + * This is because current we support DDR and SDR mode, + * Once the DDR_EN bit is set, the card clock will be + * divide by 2 automatically. So need to do this before + * setting clock rate. + */ + if (priv->mode != mmc->selected_mode) { + ret = esdhc_set_timing(mmc); + if (ret) { + printf("esdhc_set_timing error %d\n", ret); + return ret; + } + } #endif + /* Set the clock speed */ clock = mmc->clock; if (clock < mmc->cfg->f_min) @@ -989,18 +973,19 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) #endif } - if (priv->mode != mmc->selected_mode) { - ret = esdhc_set_timing(mmc); - if (ret) { - printf("esdhc_set_timing error %d\n", ret); - return ret; - } - } + /* + * For HS400/HS400ES mode, make sure set the strobe dll in the + * target clock rate. So call esdhc_set_strobe_dll() after the + * clock updated. + */ + if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) + esdhc_set_strobe_dll(mmc); if (priv->signal_voltage != mmc->signal_voltage) { ret = esdhc_set_voltage(mmc); if (ret) { - printf("esdhc_set_voltage error %d\n", ret); + if (ret != -ENOTSUPP) + printf("esdhc_set_voltage error %d\n", ret); return ret; } } @@ -1093,6 +1078,9 @@ static int esdhc_getcd_common(struct fsl_esdhc_priv *priv) #if CONFIG_IS_ENABLED(DM_MMC) if (priv->non_removable) return 1; + + if (priv->broken_cd) + return 1; #if CONFIG_IS_ENABLED(DM_GPIO) if (dm_gpio_is_valid(&priv->cd_gpio)) return dm_gpio_get_value(&priv->cd_gpio); @@ -1200,7 +1188,7 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, if (priv->vs18_enable) esdhc_setbits32(®s->vendorspec, ESDHC_VENDORSPEC_VSELECT); - writel(SDHCI_IRQ_EN_BITS, ®s->irqstaten); + esdhc_write32(®s->irqstaten, SDHCI_IRQ_EN_BITS); cfg = &plat->cfg; #ifndef CONFIG_DM_MMC memset(cfg, '\0', sizeof(*cfg)); @@ -1281,17 +1269,29 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - writel(0, ®s->dllctrl); + esdhc_write32(®s->dllctrl, 0); if (priv->flags & ESDHC_FLAG_USDHC) { if (priv->flags & ESDHC_FLAG_STD_TUNING) { - u32 val = readl(®s->tuning_ctrl); + u32 val = esdhc_read32(®s->tuning_ctrl); val |= ESDHC_STD_TUNING_EN; val &= ~ESDHC_TUNING_START_TAP_MASK; val |= priv->tuning_start_tap; val &= ~ESDHC_TUNING_STEP_MASK; val |= (priv->tuning_step) << ESDHC_TUNING_STEP_SHIFT; - writel(val, ®s->tuning_ctrl); + + /* Disable the CMD CRC check for tuning, if not, need to + * add some delay after every tuning command, because + * hardware standard tuning logic will directly go to next + * step once it detect the CMD CRC error, will not wait for + * the card side to finally send out the tuning data, trigger + * the buffer read ready interrupt immediately. If usdhc send + * the next tuning command some eMMC card will stuck, can't + * response, block the tuning procedure or the first command + * after the whole tuning procedure always can't get any response. + */ + val |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE; + esdhc_write32(®s->tuning_ctrl, val); } } @@ -1314,7 +1314,7 @@ static int fsl_esdhc_cfg_to_priv(struct fsl_esdhc_cfg *cfg, return 0; }; -int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) +int fsl_esdhc_initialize(struct bd_info *bis, struct fsl_esdhc_cfg *cfg) { struct fsl_esdhc_plat *plat; struct fsl_esdhc_priv *priv; @@ -1358,7 +1358,7 @@ int fsl_esdhc_initialize(bd_t *bis, struct fsl_esdhc_cfg *cfg) return 0; } -int fsl_esdhc_mmc_init(bd_t *bis) +int fsl_esdhc_mmc_init(struct bd_info *bis) { struct fsl_esdhc_cfg *cfg; @@ -1382,20 +1382,15 @@ __weak int esdhc_status_fixup(void *blob, const char *compat) return 0; } -void fdt_fixup_esdhc(void *blob, bd_t *bd) +void fdt_fixup_esdhc(void *blob, struct bd_info *bd) { const char *compat = "fsl,esdhc"; if (esdhc_status_fixup(blob, compat)) return; -#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK - do_fixup_by_compat_u32(blob, compat, "peripheral-frequency", - gd->arch.sdhc_clk, 1); -#else do_fixup_by_compat_u32(blob, compat, "clock-frequency", gd->arch.sdhc_clk, 1); -#endif } #endif @@ -1405,25 +1400,19 @@ __weak void init_clk_usdhc(u32 index) { } -static int fsl_esdhc_probe(struct udevice *dev) +static int fsl_esdhc_ofdata_to_platdata(struct udevice *dev) { - struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); - struct fsl_esdhc_plat *plat = dev_get_platdata(dev); +#if !CONFIG_IS_ENABLED(OF_PLATDATA) struct fsl_esdhc_priv *priv = dev_get_priv(dev); - const void *fdt = gd->fdt_blob; - int node = dev_of_offset(dev); - struct esdhc_soc_data *data = - (struct esdhc_soc_data *)dev_get_driver_data(dev); #if CONFIG_IS_ENABLED(DM_REGULATOR) struct udevice *vqmmc_dev; + int ret; #endif + const void *fdt = gd->fdt_blob; + int node = dev_of_offset(dev); + fdt_addr_t addr; unsigned int val; - struct mmc *mmc; -#if !CONFIG_IS_ENABLED(BLK) - struct blk_desc *bdesc; -#endif - int ret; addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) @@ -1431,8 +1420,6 @@ static int fsl_esdhc_probe(struct udevice *dev) priv->esdhc_regs = (struct fsl_esdhc *)addr; priv->dev = dev; priv->mode = -1; - if (data) - priv->flags = data->flags; val = dev_read_u32_default(dev, "bus-width", -1); if (val == 8) @@ -1451,6 +1438,9 @@ static int fsl_esdhc_probe(struct udevice *dev) ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT); priv->strobe_dll_delay_target = val; + if (dev_read_bool(dev, "broken-cd")) + priv->broken_cd = 1; + if (dev_read_bool(dev, "non-removable")) { priv->non_removable = 1; } else { @@ -1482,6 +1472,7 @@ static int fsl_esdhc_probe(struct udevice *dev) if (ret) { dev_dbg(dev, "no vqmmc-supply\n"); } else { + priv->vqmmc_dev = vqmmc_dev; ret = regulator_set_enable(vqmmc_dev, true); if (ret) { dev_err(dev, "fail to enable vqmmc-supply\n"); @@ -1492,6 +1483,60 @@ static int fsl_esdhc_probe(struct udevice *dev) priv->vs18_enable = 1; } #endif +#endif + return 0; +} + +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); + struct esdhc_soc_data *data = + (struct esdhc_soc_data *)dev_get_driver_data(dev); + struct mmc *mmc; +#if !CONFIG_IS_ENABLED(BLK) + struct blk_desc *bdesc; +#endif + int ret; + +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_fsl_esdhc *dtplat = &plat->dtplat; + unsigned int val; + + priv->esdhc_regs = map_sysmem(dtplat->reg[0], dtplat->reg[1]); + val = plat->dtplat.bus_width; + if (val == 8) + priv->bus_width = 8; + else if (val == 4) + priv->bus_width = 4; + else + priv->bus_width = 1; + + if (dtplat->non_removable) + priv->non_removable = 1; + else + priv->non_removable = 0; + + if (CONFIG_IS_ENABLED(DM_GPIO) && !priv->non_removable) { + struct udevice *gpiodev; + + ret = device_get_by_driver_info_idx(dtplat->cd_gpios->idx, + &gpiodev); + if (ret) + return ret; + + ret = gpio_dev_request_index(gpiodev, gpiodev->name, "cd-gpios", + dtplat->cd_gpios->arg[0], GPIOD_IS_IN, + dtplat->cd_gpios->arg[1], &priv->cd_gpio); + + if (ret) + return ret; + } +#endif + + if (data) + priv->flags = data->flags; /* * TODO: @@ -1515,27 +1560,27 @@ static int fsl_esdhc_probe(struct udevice *dev) init_clk_usdhc(dev->seq); - if (CONFIG_IS_ENABLED(CLK)) { - /* Assigned clock already set clock */ - ret = clk_get_by_name(dev, "per", &priv->per_clk); - if (ret) { - printf("Failed to get per_clk\n"); - return ret; - } - ret = clk_enable(&priv->per_clk); - if (ret) { - printf("Failed to enable per_clk\n"); - return ret; - } +#if CONFIG_IS_ENABLED(CLK) + /* Assigned clock already set clock */ + ret = clk_get_by_name(dev, "per", &priv->per_clk); + if (ret) { + printf("Failed to get per_clk\n"); + return ret; + } + ret = clk_enable(&priv->per_clk); + if (ret) { + printf("Failed to enable per_clk\n"); + return ret; + } - priv->sdhc_clk = clk_get_rate(&priv->per_clk); - } else { - priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq); - if (priv->sdhc_clk <= 0) { - dev_err(dev, "Unable to get clk for %s\n", dev->name); - return -EINVAL; - } + priv->sdhc_clk = clk_get_rate(&priv->per_clk); +#else + priv->sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK + dev->seq); + if (priv->sdhc_clk <= 0) { + dev_err(dev, "Unable to get clk for %s\n", dev->name); + return -EINVAL; } +#endif ret = fsl_esdhc_init(priv, plat); if (ret) { @@ -1543,9 +1588,11 @@ static int fsl_esdhc_probe(struct udevice *dev) return ret; } +#if !CONFIG_IS_ENABLED(OF_PLATDATA) ret = mmc_of_parse(dev, &plat->cfg); if (ret) return ret; +#endif mmc = &plat->mmc; mmc->cfg = &plat->cfg; @@ -1607,14 +1654,28 @@ static int fsl_esdhc_set_enhanced_strobe(struct udevice *dev) struct fsl_esdhc *regs = priv->esdhc_regs; u32 m; - m = readl(®s->mixctrl); + m = esdhc_read32(®s->mixctrl); m |= MIX_CTRL_HS400_ES; - writel(m, ®s->mixctrl); + esdhc_write32(®s->mixctrl, m); return 0; } #endif +static int fsl_esdhc_wait_dat0(struct udevice *dev, int state, + int timeout_us) +{ + int ret; + u32 tmp; + struct fsl_esdhc_priv *priv = dev_get_priv(dev); + struct fsl_esdhc *regs = priv->esdhc_regs; + + ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, + !!(tmp & PRSSTAT_DAT0) == !!state, + timeout_us); + return ret; +} + static const struct dm_mmc_ops fsl_esdhc_ops = { .get_cd = fsl_esdhc_get_cd, .send_cmd = fsl_esdhc_send_cmd, @@ -1625,6 +1686,7 @@ static const struct dm_mmc_ops fsl_esdhc_ops = { #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) .set_enhanced_strobe = fsl_esdhc_set_enhanced_strobe, #endif + .wait_dat0 = fsl_esdhc_wait_dat0, }; #endif @@ -1652,6 +1714,7 @@ static const struct udevice_id fsl_esdhc_ids[] = { { .compatible = "fsl,imx8mm-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, { .compatible = "fsl,imx8mn-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, { .compatible = "fsl,imx8mq-usdhc", .data = (ulong)&usdhc_imx8qm_data,}, + { .compatible = "fsl,imxrt-usdhc", }, { .compatible = "fsl,esdhc", }, { /* sentinel */ } }; @@ -1666,9 +1729,10 @@ static int fsl_esdhc_bind(struct udevice *dev) #endif U_BOOT_DRIVER(fsl_esdhc) = { - .name = "fsl-esdhc-mmc", + .name = "fsl_esdhc", .id = UCLASS_MMC, .of_match = fsl_esdhc_ids, + .ofdata_to_platdata = fsl_esdhc_ofdata_to_platdata, .ops = &fsl_esdhc_ops, #if CONFIG_IS_ENABLED(BLK) .bind = fsl_esdhc_bind, @@ -1677,4 +1741,6 @@ U_BOOT_DRIVER(fsl_esdhc) = { .platdata_auto_alloc_size = sizeof(struct fsl_esdhc_plat), .priv_auto_alloc_size = sizeof(struct fsl_esdhc_priv), }; + +U_BOOT_DRIVER_ALIAS(fsl_esdhc, fsl_imx6q_usdhc) #endif