summaryrefslogtreecommitdiffstats
path: root/drivers/mci/stm32_sdmmc2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mci/stm32_sdmmc2.c')
-rw-r--r--drivers/mci/stm32_sdmmc2.c47
1 files changed, 22 insertions, 25 deletions
diff --git a/drivers/mci/stm32_sdmmc2.c b/drivers/mci/stm32_sdmmc2.c
index 1a41c34d24..0c26869b03 100644
--- a/drivers/mci/stm32_sdmmc2.c
+++ b/drivers/mci/stm32_sdmmc2.c
@@ -185,31 +185,31 @@ struct stm32_sdmmc2_priv {
#define to_mci_host(mci) container_of(mci, struct stm32_sdmmc2_priv, mci)
-/*
- * Reset the SDMMC with the RCC.SDMMCxRST register bit.
- * This will reset the SDMMC to the reset state and the CPSM and DPSM
- * to the Idle state. SDMMC is disabled, Signals Hiz.
- */
static int stm32_sdmmc2_reset(struct mci_host *mci, struct device_d *mci_dev)
{
struct stm32_sdmmc2_priv *priv = to_mci_host(mci);
+ /*
+ * Reset the SDMMC with the RCC.SDMMCxRST register bit.
+ * This will reset the SDMMC to the reset state and the CPSM and DPSM
+ * to the Idle state. SDMMC is disabled, Signals Hiz.
+ */
reset_control_assert(priv->reset_ctl);
udelay(2);
reset_control_deassert(priv->reset_ctl);
- /* init the needed SDMMC register after reset */
- writel(priv->pwr_reg_msk, priv->base + SDMMC_POWER);
+ /*
+ * Set the SDMMC in power-cycle state.
+ * This will make that the SDMMC_D[7:0],
+ * SDMMC_CMD and SDMMC_CK are driven low, to prevent the card from being
+ * supplied through the signal lines.
+ */
+ writel(SDMMC_POWER_PWRCTRL_CYCLE | priv->pwr_reg_msk,
+ priv->base + SDMMC_POWER);
return 0;
}
-/*
- * Set the SDMMC in power-cycle state.
- * This will make that the SDMMC_D[7:0],
- * SDMMC_CMD and SDMMC_CK are driven low, to prevent the card from being
- * supplied through the signal lines.
- */
static void stm32_sdmmc2_pwrcycle(struct stm32_sdmmc2_priv *priv)
{
if ((readl(priv->base + SDMMC_POWER) & SDMMC_POWER_PWRCTRL_MASK) ==
@@ -217,8 +217,6 @@ static void stm32_sdmmc2_pwrcycle(struct stm32_sdmmc2_priv *priv)
return;
stm32_sdmmc2_reset(&priv->mci, priv->dev);
- writel(SDMMC_POWER_PWRCTRL_CYCLE | priv->pwr_reg_msk,
- priv->base + SDMMC_POWER);
}
/*
@@ -256,6 +254,7 @@ static void stm32_sdmmc2_pwron(struct stm32_sdmmc2_priv *priv)
priv->base + SDMMC_POWER);
/* during the first 74 SDMMC_CK cycles the SDMMC is still disabled. */
+ udelay(DIV_ROUND_UP(74 * USEC_PER_SEC, priv->mci.clock));
}
static void stm32_sdmmc2_start_data(struct stm32_sdmmc2_priv *priv,
@@ -535,8 +534,6 @@ retry_cmd:
dev_warn(priv->dev, "%s: cmd %d failed, retrying ...\n",
__func__, cmd->cmdidx);
- stm32_sdmmc2_pwrcycle(priv);
- stm32_sdmmc2_pwron(priv);
retry--;
goto retry_cmd;
@@ -555,7 +552,7 @@ static void stm32_sdmmc2_set_ios(struct mci_host *mci, struct mci_ios *ios)
u32 sys_clock = clk_get_rate(priv->clk);
u32 clk = 0;
- dev_dbg(priv->dev, "%s: bus_with = %d, clock = %d\n", __func__,
+ dev_dbg(priv->dev, "%s: bus_width = %d, clock = %d\n", __func__,
mci->bus_width, mci->clock);
if (mci->clock)
@@ -577,9 +574,9 @@ static void stm32_sdmmc2_set_ios(struct mci_host *mci, struct mci_ios *ios)
clk = SDMMC_CLKCR_CLKDIV_MAX;
}
- if (mci->bus_width == 4)
+ if (mci->bus_width == MMC_BUS_WIDTH_4)
clk |= SDMMC_CLKCR_WIDBUS_4;
- if (mci->bus_width == 8)
+ if (mci->bus_width == MMC_BUS_WIDTH_8)
clk |= SDMMC_CLKCR_WIDBUS_8;
writel(clk | priv->clk_reg_msk | SDMMC_CLKCR_HWFC_EN,
@@ -625,7 +622,7 @@ static int stm32_sdmmc2_probe(struct amba_device *adev,
priv->reset_ctl = reset_control_get(dev, NULL);
if (IS_ERR(priv->reset_ctl))
- priv->reset_ctl = NULL;
+ return PTR_ERR(priv->reset_ctl);
mci->f_min = 400000;
/* f_max is taken from kernel v5.3 variant_stm32_sdmmc */
@@ -634,10 +631,10 @@ static int stm32_sdmmc2_probe(struct amba_device *adev,
mci_of_parse(&priv->mci);
- if (mci->host_caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
- dev_notice(dev, "Fixing bus-width to 1 due to driver limitation\n");
- mci->host_caps &= ~(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
- }
+ if (mci->f_max >= 26000000)
+ mci->host_caps |= MMC_CAP_MMC_HIGHSPEED;
+ if (mci->f_max >= 52000000)
+ mci->host_caps |= MMC_CAP_MMC_HIGHSPEED_52MHZ;
return mci_register(&priv->mci);