diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/dw_mmc.c | 4 | ||||
-rw-r--r-- | drivers/mmc/renesas-sdhi.c | 48 | ||||
-rw-r--r-- | drivers/mmc/tmio-common.c | 76 |
3 files changed, 76 insertions, 52 deletions
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 3c702b3ed8..7544b84ab6 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -317,6 +317,10 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, } else if (mask & DWMCI_INTMSK_RE) { debug("%s: Response Error.\n", __func__); return -EIO; + } else if ((cmd->resp_type & MMC_RSP_CRC) && + (mask & DWMCI_INTMSK_RCRC)) { + debug("%s: Response CRC Error.\n", __func__); + return -EIO; } diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index f8dc5f57ce..e7f96f8bf2 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -34,6 +34,8 @@ #define RENESAS_SDHI_SCC_RVSREQ_RVSERR BIT(2) #define RENESAS_SDHI_SCC_SMPCMP 0x818 #define RENESAS_SDHI_SCC_TMPPORT2 0x81c +#define RENESAS_SDHI_SCC_TMPPORT2_HS400EN BIT(31) +#define RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL BIT(4) #define RENESAS_SDHI_MAX_TAP 3 @@ -49,12 +51,9 @@ static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv) tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL); /* Set sampling clock selection range */ - tmio_sd_writel(priv, 0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT, - RENESAS_SDHI_SCC_DTCNTL); - - reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL); - reg |= RENESAS_SDHI_SCC_DTCNTL_TAPEN; - tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_DTCNTL); + tmio_sd_writel(priv, (0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) | + RENESAS_SDHI_SCC_DTCNTL_TAPEN, + RENESAS_SDHI_SCC_DTCNTL); reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL); reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL; @@ -90,6 +89,11 @@ static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv) reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL; tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL); + reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_TMPPORT2); + reg &= ~(RENESAS_SDHI_SCC_TMPPORT2_HS400EN | + RENESAS_SDHI_SCC_TMPPORT2_HS400OSEL); + tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_TMPPORT2); + reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL); reg |= TMIO_SD_CLKCTL_SCLKEN; tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL); @@ -294,19 +298,45 @@ static int renesas_sdhi_set_ios(struct udevice *dev) #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) struct tmio_sd_priv *priv = dev_get_priv(dev); - renesas_sdhi_reset_tuning(priv); + if (priv->caps & TMIO_SD_CAP_RCAR_UHS) + renesas_sdhi_reset_tuning(priv); #endif return ret; } +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) +static int renesas_sdhi_wait_dat0(struct udevice *dev, int state, int timeout) +{ + int ret = -ETIMEDOUT; + bool dat0_high; + bool target_dat0_high = !!state; + struct tmio_sd_priv *priv = dev_get_priv(dev); + + timeout = DIV_ROUND_UP(timeout, 10); /* check every 10 us. */ + while (timeout--) { + dat0_high = !!(tmio_sd_readl(priv, TMIO_SD_INFO2) & TMIO_SD_INFO2_DAT0); + if (dat0_high == target_dat0_high) { + ret = 0; + break; + } + udelay(10); + } + + return ret; +} +#endif + static const struct dm_mmc_ops renesas_sdhi_ops = { .send_cmd = tmio_sd_send_cmd, .set_ios = renesas_sdhi_set_ios, .get_cd = tmio_sd_get_cd, -#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) .execute_tuning = renesas_sdhi_execute_tuning, #endif +#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) + .wait_dat0 = renesas_sdhi_wait_dat0, +#endif }; #define RENESAS_GEN2_QUIRKS TMIO_SD_CAP_RCAR_GEN2 @@ -373,7 +403,7 @@ static int renesas_sdhi_probe(struct udevice *dev) ret = tmio_sd_probe(dev, quirks); #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) - if (!ret) + if (!ret && (priv->caps & TMIO_SD_CAP_RCAR_UHS)) renesas_sdhi_reset_tuning(priv); #endif return ret; diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 138de59470..0eca83a0f4 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -95,7 +95,7 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size, invalidate_dcache_range(addr, addr + size); } -static int tmio_sd_check_error(struct udevice *dev) +static int tmio_sd_check_error(struct udevice *dev, struct mmc_cmd *cmd) { struct tmio_sd_priv *priv = dev_get_priv(dev); u32 info2 = tmio_sd_readl(priv, TMIO_SD_INFO2); @@ -116,7 +116,9 @@ static int tmio_sd_check_error(struct udevice *dev) if (info2 & (TMIO_SD_INFO2_ERR_END | TMIO_SD_INFO2_ERR_CRC | TMIO_SD_INFO2_ERR_IDX)) { - dev_err(dev, "communication out of sync\n"); + if ((cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK) && + (cmd->cmdidx != MMC_CMD_SEND_TUNING_BLOCK_HS200)) + dev_err(dev, "communication out of sync\n"); return -EILSEQ; } @@ -129,8 +131,8 @@ static int tmio_sd_check_error(struct udevice *dev) return 0; } -static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg, - u32 flag) +static int tmio_sd_wait_for_irq(struct udevice *dev, struct mmc_cmd *cmd, + unsigned int reg, u32 flag) { struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000; @@ -142,7 +144,7 @@ static int tmio_sd_wait_for_irq(struct udevice *dev, unsigned int reg, return -ETIMEDOUT; } - ret = tmio_sd_check_error(dev); + ret = tmio_sd_check_error(dev, cmd); if (ret) return ret; @@ -178,15 +180,15 @@ tmio_pio_read_fifo(64, q) tmio_pio_read_fifo(32, l) tmio_pio_read_fifo(16, w) -static int tmio_sd_pio_read_one_block(struct udevice *dev, char *pbuf, - uint blocksize) +static int tmio_sd_pio_read_one_block(struct udevice *dev, struct mmc_cmd *cmd, + char *pbuf, uint blocksize) { struct tmio_sd_priv *priv = dev_get_priv(dev); int ret; /* wait until the buffer is filled with data */ - ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, - TMIO_SD_INFO2_BRE); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, + TMIO_SD_INFO2_BRE); if (ret) return ret; @@ -231,15 +233,15 @@ tmio_pio_write_fifo(64, q) tmio_pio_write_fifo(32, l) tmio_pio_write_fifo(16, w) -static int tmio_sd_pio_write_one_block(struct udevice *dev, +static int tmio_sd_pio_write_one_block(struct udevice *dev, struct mmc_cmd *cmd, const char *pbuf, uint blocksize) { struct tmio_sd_priv *priv = dev_get_priv(dev); int ret; /* wait until the buffer becomes empty */ - ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, - TMIO_SD_INFO2_BWE); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, + TMIO_SD_INFO2_BWE); if (ret) return ret; @@ -255,7 +257,8 @@ static int tmio_sd_pio_write_one_block(struct udevice *dev, return 0; } -static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) +static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) { const char *src = data->src; char *dest = data->dest; @@ -263,10 +266,10 @@ static int tmio_sd_pio_xfer(struct udevice *dev, struct mmc_data *data) for (i = 0; i < data->blocks; i++) { if (data->flags & MMC_DATA_READ) - ret = tmio_sd_pio_read_one_block(dev, dest, + ret = tmio_sd_pio_read_one_block(dev, cmd, dest, data->blocksize); else - ret = tmio_sd_pio_write_one_block(dev, src, + ret = tmio_sd_pio_write_one_block(dev, cmd, src, data->blocksize); if (ret) return ret; @@ -468,8 +471,8 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, cmd->cmdidx, tmp, cmd->cmdarg); tmio_sd_writel(priv, tmp, TMIO_SD_CMD); - ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, - TMIO_SD_INFO1_RSP); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1, + TMIO_SD_INFO1_RSP); if (ret) return ret; @@ -497,17 +500,18 @@ int tmio_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, tmio_sd_addr_is_dmaable(data->src)) ret = tmio_sd_dma_xfer(dev, data); else - ret = tmio_sd_pio_xfer(dev, data); + ret = tmio_sd_pio_xfer(dev, cmd, data); + if (ret) + return ret; - ret = tmio_sd_wait_for_irq(dev, TMIO_SD_INFO1, - TMIO_SD_INFO1_CMP); + ret = tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO1, + TMIO_SD_INFO1_CMP); if (ret) return ret; } - tmio_sd_wait_for_irq(dev, TMIO_SD_INFO2, TMIO_SD_INFO2_SCLKDIVEN); - - return ret; + return tmio_sd_wait_for_irq(dev, cmd, TMIO_SD_INFO2, + TMIO_SD_INFO2_SCLKDIVEN); } static int tmio_sd_set_bus_width(struct tmio_sd_priv *priv, @@ -622,26 +626,10 @@ static void tmio_sd_set_pins(struct udevice *dev) #endif #ifdef CONFIG_PINCTRL - switch (mmc->selected_mode) { - case MMC_LEGACY: - case SD_LEGACY: - case MMC_HS: - case SD_HS: - case MMC_HS_52: - case MMC_DDR_52: - pinctrl_select_state(dev, "default"); - break; - case UHS_SDR12: - case UHS_SDR25: - case UHS_SDR50: - case UHS_DDR50: - case UHS_SDR104: - case MMC_HS_200: + if (mmc->signal_voltage == MMC_SIGNAL_VOLTAGE_180) pinctrl_select_state(dev, "state_uhs"); - break; - default: - break; - } + else + pinctrl_select_state(dev, "default"); #endif } @@ -654,11 +642,11 @@ int tmio_sd_set_ios(struct udevice *dev) dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n", mmc->clock, mmc->ddr_mode, mmc->bus_width); + tmio_sd_set_clk_rate(priv, mmc); ret = tmio_sd_set_bus_width(priv, mmc); if (ret) return ret; tmio_sd_set_ddr_mode(priv, mmc); - tmio_sd_set_clk_rate(priv, mmc); tmio_sd_set_pins(dev); return 0; @@ -732,6 +720,8 @@ int tmio_sd_probe(struct udevice *dev, u32 quirks) #ifdef CONFIG_DM_REGULATOR device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc_dev); + if (priv->vqmmc_dev) + regulator_set_value(priv->vqmmc_dev, 3300000); #endif ret = mmc_of_parse(dev, &plat->cfg); |