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);
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;
}
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;
return -ETIMEDOUT;
}
- ret = tmio_sd_check_error(dev);
+ ret = tmio_sd_check_error(dev, cmd);
if (ret)
return ret;
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;
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;
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;
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;
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;
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,
tmio_sd_writel(priv, tmp, TMIO_SD_IF_MODE);
}
-static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv,
- struct mmc *mmc)
+static ulong tmio_sd_clk_get_rate(struct tmio_sd_priv *priv)
{
- unsigned int divisor;
- u32 val, tmp;
+ return priv->clk_get_rate(priv);
+}
- if (!mmc->clock)
- return;
-
- divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
-
- if (divisor <= 1)
- val = (priv->caps & TMIO_SD_CAP_RCAR) ?
- TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
- else if (divisor <= 2)
- val = TMIO_SD_CLKCTL_DIV2;
- else if (divisor <= 4)
- val = TMIO_SD_CLKCTL_DIV4;
- else if (divisor <= 8)
- val = TMIO_SD_CLKCTL_DIV8;
- else if (divisor <= 16)
- val = TMIO_SD_CLKCTL_DIV16;
- else if (divisor <= 32)
- val = TMIO_SD_CLKCTL_DIV32;
- else if (divisor <= 64)
- val = TMIO_SD_CLKCTL_DIV64;
- else if (divisor <= 128)
- val = TMIO_SD_CLKCTL_DIV128;
- else if (divisor <= 256)
- val = TMIO_SD_CLKCTL_DIV256;
- else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
- val = TMIO_SD_CLKCTL_DIV512;
- else
- val = TMIO_SD_CLKCTL_DIV1024;
+static void tmio_sd_set_clk_rate(struct tmio_sd_priv *priv, struct mmc *mmc)
+{
+ unsigned int divisor;
+ u32 tmp, val = 0;
+ ulong mclk;
+
+ if (mmc->clock) {
+ mclk = tmio_sd_clk_get_rate(priv);
+
+ divisor = DIV_ROUND_UP(mclk, mmc->clock);
+
+ /* Do not set divider to 0xff in DDR mode */
+ if (mmc->ddr_mode && (divisor == 1))
+ divisor = 2;
+
+ if (divisor <= 1)
+ val = (priv->caps & TMIO_SD_CAP_RCAR) ?
+ TMIO_SD_CLKCTL_RCAR_DIV1 : TMIO_SD_CLKCTL_DIV1;
+ else if (divisor <= 2)
+ val = TMIO_SD_CLKCTL_DIV2;
+ else if (divisor <= 4)
+ val = TMIO_SD_CLKCTL_DIV4;
+ else if (divisor <= 8)
+ val = TMIO_SD_CLKCTL_DIV8;
+ else if (divisor <= 16)
+ val = TMIO_SD_CLKCTL_DIV16;
+ else if (divisor <= 32)
+ val = TMIO_SD_CLKCTL_DIV32;
+ else if (divisor <= 64)
+ val = TMIO_SD_CLKCTL_DIV64;
+ else if (divisor <= 128)
+ val = TMIO_SD_CLKCTL_DIV128;
+ else if (divisor <= 256)
+ val = TMIO_SD_CLKCTL_DIV256;
+ else if (divisor <= 512 || !(priv->caps & TMIO_SD_CAP_DIV1024))
+ val = TMIO_SD_CLKCTL_DIV512;
+ else
+ val = TMIO_SD_CLKCTL_DIV1024;
+ }
tmp = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
- if (tmp & TMIO_SD_CLKCTL_SCLKEN &&
- (tmp & TMIO_SD_CLKCTL_DIV_MASK) == val)
- return;
+ if (mmc->clock &&
+ !((tmp & TMIO_SD_CLKCTL_SCLKEN) &&
+ ((tmp & TMIO_SD_CLKCTL_DIV_MASK) == val))) {
+ /*
+ * Stop the clock before changing its rate
+ * to avoid a glitch signal
+ */
+ tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+ tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
- /* stop the clock before changing its rate to avoid a glitch signal */
- tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
- tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+ /* Change the clock rate. */
+ tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
+ tmp |= val;
+ }
- tmp &= ~TMIO_SD_CLKCTL_DIV_MASK;
- tmp |= val | TMIO_SD_CLKCTL_OFFEN;
- tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
+ /* Enable or Disable the clock */
+ if (mmc->clk_disable) {
+ tmp |= TMIO_SD_CLKCTL_OFFEN;
+ tmp &= ~TMIO_SD_CLKCTL_SCLKEN;
+ } else {
+ tmp &= ~TMIO_SD_CLKCTL_OFFEN;
+ tmp |= TMIO_SD_CLKCTL_SCLKEN;
+ }
- tmp |= TMIO_SD_CLKCTL_SCLKEN;
tmio_sd_writel(priv, tmp, TMIO_SD_CLKCTL);
udelay(1000);
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;
struct tmio_sd_priv *priv = dev_get_priv(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
fdt_addr_t base;
+ ulong mclk;
int ret;
base = devfdt_get_addr(dev);
#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);
tmio_sd_host_init(priv);
+ mclk = tmio_sd_clk_get_rate(priv);
+
plat->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
- plat->cfg.f_min = priv->mclk /
+ plat->cfg.f_min = mclk /
(priv->caps & TMIO_SD_CAP_DIV1024 ? 1024 : 512);
- plat->cfg.f_max = priv->mclk;
+ plat->cfg.f_max = mclk;
plat->cfg.b_max = U32_MAX; /* max value of TMIO_SD_SECCNT */
upriv->mmc = &plat->mmc;