summaryrefslogtreecommitdiff
path: root/drivers/mmc/rockchip_sdhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/rockchip_sdhci.c')
-rw-r--r--drivers/mmc/rockchip_sdhci.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index c7071d8165..92873af484 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -37,6 +37,12 @@ DECLARE_GLOBAL_DATA_PTR;
#define PHYCTRL_FREQSEL_150M 0x3
/* Rockchip specific Registers */
+#define DWCMSHC_VER_ID 0x500
+#define DWCMSHC_VER_TYPE 0x504
+#define DWCMSHC_HOST_CTRL3 0x508
+#define DWCMSHC_EMMC_CONTROL 0x52c
+#define DWCMSHC_EMMC_ATCTRL 0x540
+
#define DWCMSHC_EMMC_DLL_CTRL 0x800
#define DWCMSHC_EMMC_DLL_RXCLK 0x804
#define DWCMSHC_EMMC_DLL_TXCLK 0x808
@@ -55,6 +61,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
#define DLL_RXCLK_NO_INVERTER 1
#define DLL_RXCLK_INVERTER 0
+#define DWCMSHC_EMMC_RST_N BIT(2)
+#define DWCMSHC_EMMC_RST_N_OE BIT(3)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
#define DLL_LOCK_WO_TMOUT(x) \
((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
@@ -369,6 +377,24 @@ static int rk3568_emmc_get_phy(struct udevice *dev)
return 0;
}
+static int rk3568_emmc_hw_reset(struct udevice *dev)
+{
+ struct rockchip_sdhc *prv = dev_get_priv(dev);
+ struct sdhci_host *host = &prv->host;
+ u32 extra;
+
+ extra = sdhci_readl(host, DWCMSHC_EMMC_CONTROL);
+ extra |= DWCMSHC_EMMC_RST_N_OE;
+ extra &= ~DWCMSHC_EMMC_RST_N;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_CONTROL);
+ udelay(20);
+
+ extra |= DWCMSHC_EMMC_RST_N;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_CONTROL);
+ udelay(300);
+ return 0;
+}
+
static int arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct rockchip_sdhc *priv =
@@ -455,6 +481,9 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->mmc->dev = dev;
upriv->mmc = host->mmc;
+ if (dev_read_bool(dev, "cap-mmc-hw-reset"))
+ rk3568_emmc_hw_reset(dev);
+
return sdhci_probe(dev);
}