From 244b2c5ca8b14627e4a17755e5922221e121c771 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 09 Oct 2024 06:15:07 +0000
Subject: [PATCH] change system file
---
u-boot/drivers/mmc/rockchip_sdhci.c | 212 ++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 169 insertions(+), 43 deletions(-)
diff --git a/u-boot/drivers/mmc/rockchip_sdhci.c b/u-boot/drivers/mmc/rockchip_sdhci.c
index d6224da..327c0d2 100644
--- a/u-boot/drivers/mmc/rockchip_sdhci.c
+++ b/u-boot/drivers/mmc/rockchip_sdhci.c
@@ -39,6 +39,12 @@
((((x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
PHYCTRL_DLLRDY_DONE)
+#define ARASAN_VENDOR_REGISTER 0x78
+#define ARASAN_VENDOR_ENHANCED_STROBE BIT(0)
+
+/* DWC IP vendor area 1 pointer */
+#define DWCMSHC_P_VENDOR_AREA1 0xe8
+#define DWCMSHC_AREA1_MASK GENMASK(11, 0)
/* Rockchip specific Registers */
#define DWCMSHC_CTRL_HS400 0x7
#define DWCMSHC_CARD_IS_EMMC BIT(0)
@@ -46,6 +52,7 @@
#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_CTRL_RESET BIT(1)
#define DWCMSHC_EMMC_DLL_RXCLK 0x804
@@ -55,25 +62,31 @@
#define DWCMSHC_EMMC_DLL_STATUS0 0x840
#define DWCMSHC_EMMC_DLL_STATUS1 0x844
#define DWCMSHC_EMMC_DLL_START BIT(0)
-#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
#define DWCMSHC_EMMC_DLL_START_POINT 16
#define DWCMSHC_EMMC_DLL_START_DEFAULT 5
#define DWCMSHC_EMMC_DLL_INC_VALUE 2
#define DWCMSHC_EMMC_DLL_INC 8
+#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
-#define DLL_TXCLK_TAPNUM_90_DEGREES 0x8
-#define DLL_STRBIN_TAPNUM_DEFAULT 0x3
+#define DLL_TXCLK_TAPNUM_90_DEGREES 0x9
+#define DLL_STRBIN_TAPNUM_DEFAULT 0x4
+#define DLL_STRBIN_DELAY_NUM_OFFSET 16
+#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
+#define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
#define DLL_TXCLK_NO_INVERTER BIT(29)
#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
-#define DLL_RXCLK_NO_INVERTER 1
-#define DLL_RXCLK_INVERTER 0
+#define DLL_TAP_VALUE_SEL BIT(25)
+#define DLL_TAP_VALUE_OFFSET 8
+#define DLL_RXCLK_NO_INVERTER BIT(29)
+#define DLL_RXCLK_ORI_GATE BIT(31)
#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
#define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
+#define DLL_CMDOUT_BOTH_CLK_EDGE BIT(30)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
#define DLL_LOCK_WO_TMOUT(x) \
@@ -106,10 +119,18 @@
struct sdhci_data {
int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
void (*set_ios_post)(struct sdhci_host *host);
+ int (*set_enhanced_strobe)(struct sdhci_host *host);
int (*get_phy)(struct udevice *dev);
u32 flags;
#define RK_DLL_CMD_OUT BIT(1)
#define RK_RXCLK_NO_INVERTER BIT(2)
+#define RK_TAP_VALUE_SEL BIT(3)
+
+ u8 hs200_tx_tap;
+ u8 hs400_tx_tap;
+ u8 hs400_cmd_tap;
+ u8 hs400_strbin_tap;
+ u8 ddr50_strbin_delay_num;
};
static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
@@ -254,21 +275,7 @@
clk |= SDHCI_CLOCK_INT_EN;
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- /* Wait max 20 ms */
- timeout = 20;
- while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
- & SDHCI_CLOCK_INT_STABLE)) {
- if (timeout == 0) {
- printf("%s: Internal clock never stabilised.\n",
- __func__);
- return -EBUSY;
- }
- timeout--;
- udelay(1000);
- }
- clk |= SDHCI_CLOCK_CARD_EN;
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
- host->clock = clock;
+ sdhci_enable_clk(host, clk);
return 0;
}
@@ -323,16 +330,24 @@
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
- u32 extra;
+ u32 txclk_tapnum, extra, dll_lock_value;
int timeout = 500, ret;
ret = rockchip_emmc_set_clock(host, clock);
+
+ /* Disable output clock while config DLL */
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
if (clock >= 100 * MHz) {
/* reset DLL */
sdhci_writel(host, DWCMSHC_EMMC_DLL_CTRL_RESET, DWCMSHC_EMMC_DLL_CTRL);
udelay(1);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+
+ extra = 0x1 << 16 | /* tune clock stop en */
+ 0x2 << 17 | /* pre-change delay */
+ 0x3 << 19; /* post-change delay */
+ sdhci_writel(host, extra, DWCMSHC_EMMC_ATCTRL);
/* Init DLL settings */
extra = DWCMSHC_EMMC_DLL_START_DEFAULT << DWCMSHC_EMMC_DLL_START_POINT |
@@ -341,48 +356,106 @@
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
while (1) {
- if (timeout < 0)
- return -ETIMEDOUT;
+ if (timeout < 0) {
+ ret = -ETIMEDOUT;
+ goto exit;
+ }
if (DLL_LOCK_WO_TMOUT((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0))))
break;
udelay(1);
timeout--;
}
- extra = DWCMSHC_EMMC_DLL_DLYENA;
+ dll_lock_value = ((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0) & 0xFF) * 2 ) & 0xFF;
+ extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
if (data->flags & RK_RXCLK_NO_INVERTER)
- extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+ extra |= DLL_RXCLK_NO_INVERTER;
+ if (data->flags & RK_TAP_VALUE_SEL)
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+
+ txclk_tapnum = data->hs200_tx_tap;
+ if ((data->flags & RK_DLL_CMD_OUT) &&
+ (host->mmc->timing == MMC_TIMING_MMC_HS400 ||
+ host->mmc->timing == MMC_TIMING_MMC_HS400ES)) {
+ txclk_tapnum = data->hs400_tx_tap;
+
+ extra = DLL_CMDOUT_SRC_CLK_NEG |
+ DLL_CMDOUT_BOTH_CLK_EDGE |
+ DWCMSHC_EMMC_DLL_DLYENA |
+ data->hs400_cmd_tap |
+ DLL_CMDOUT_TAPNUM_FROM_SW;
+ if (data->flags & RK_TAP_VALUE_SEL)
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
+ sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
+ }
extra = DWCMSHC_EMMC_DLL_DLYENA |
DLL_TXCLK_TAPNUM_FROM_SW |
DLL_TXCLK_NO_INVERTER|
- DLL_TXCLK_TAPNUM_DEFAULT;
-
+ txclk_tapnum;
+ if (data->flags & RK_TAP_VALUE_SEL)
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
extra = DWCMSHC_EMMC_DLL_DLYENA |
- DLL_STRBIN_TAPNUM_DEFAULT;
+ data->hs400_strbin_tap |
+ DLL_STRBIN_TAPNUM_FROM_SW;
+ if (data->flags & RK_TAP_VALUE_SEL)
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
} else {
+ /* disable dll */
+ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+
/* Disable cmd conflict check */
extra = sdhci_readl(host, DWCMSHC_HOST_CTRL3);
extra &= ~BIT(0);
sdhci_writel(host, extra, DWCMSHC_HOST_CTRL3);
/* reset the clock phase when the frequency is lower than 100MHz */
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK);
+ sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
+ sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
+ /*
+ * Before switching to hs400es mode, the driver will enable
+ * enhanced strobe first. PHY needs to configure the parameters
+ * of enhanced strobe first.
+ */
+ extra = DWCMSHC_EMMC_DLL_DLYENA |
+ DLL_STRBIN_DELAY_NUM_SEL |
+ data->ddr50_strbin_delay_num << DLL_STRBIN_DELAY_NUM_OFFSET;
+ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
}
+
+exit:
+ /* enable output clock */
+ sdhci_enable_clk(host, 0);
+
return ret;
+}
+
+static int dwcmshc_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+{
+ struct mmc *mmc = host->mmc;
+ u32 vendor;
+
+ vendor = sdhci_readl(host, DWCMSHC_EMMC_CONTROL);
+ if (mmc->timing == MMC_TIMING_MMC_HS400ES)
+ vendor |= DWCMSHC_ENHANCED_STROBE;
+ else
+ vendor &= ~DWCMSHC_ENHANCED_STROBE;
+ sdhci_writel(host, vendor, DWCMSHC_EMMC_CONTROL);
+
+ /* some emmc device need a delay before send command */
+ udelay(100);
+
+ return 0;
}
static void dwcmshc_sdhci_set_ios_post(struct sdhci_host *host)
{
u16 ctrl;
- u32 extra;
u32 timing = host->mmc->timing;
if (timing == MMC_TIMING_MMC_HS400 || timing == MMC_TIMING_MMC_HS400ES) {
@@ -395,16 +468,6 @@
ctrl = sdhci_readw(host, DWCMSHC_EMMC_CONTROL);
ctrl |= DWCMSHC_CARD_IS_EMMC;
sdhci_writew(host, ctrl, DWCMSHC_EMMC_CONTROL);
-
- extra = DLL_CMDOUT_SRC_CLK_NEG |
- DLL_CMDOUT_EN_SRC_CLK_NEG;
- sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
-
- extra = DWCMSHC_EMMC_DLL_DLYENA |
- DLL_TXCLK_TAPNUM_FROM_SW |
- DLL_TXCLK_NO_INVERTER|
- DLL_TXCLK_TAPNUM_90_DEGREES;
- sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
}
}
@@ -434,9 +497,21 @@
data->set_ios_post(host);
}
+static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+ if (data->set_enhanced_strobe)
+ return data->set_enhanced_strobe(host);
+
+ return -ENOTSUPP;
+}
+
static struct sdhci_ops rockchip_sdhci_ops = {
.set_clock = rockchip_sdhci_set_clock,
.set_ios_post = rockchip_sdhci_set_ios_post,
+ .set_enhanced_strobe = rockchip_sdhci_set_enhanced_strobe,
};
static int rockchip_sdhci_probe(struct udevice *dev)
@@ -496,7 +571,13 @@
host->host_caps |= MMC_MODE_HS200;
else if (dev_read_bool(dev, "mmc-hs400-1_8v"))
host->host_caps |= MMC_MODE_HS400;
+
+ if (data->set_enhanced_strobe && dev_read_bool(dev, "mmc-hs400-enhanced-strobe"))
+ host->host_caps |= MMC_MODE_HS400ES;
+
ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
+
+ plat->cfg.fixed_drv_type = dev_read_u32_default(dev, "fixed-emmc-driver-type", 0);
host->mmc = &plat->mmc;
if (ret)
@@ -536,13 +617,50 @@
.emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
.get_phy = dwcmshc_emmc_get_phy,
.flags = RK_RXCLK_NO_INVERTER,
+ .hs200_tx_tap = 16,
+ .hs400_tx_tap = 8,
+ .hs400_cmd_tap = 8,
+ .hs400_strbin_tap = 3,
+ .ddr50_strbin_delay_num = 16,
};
static const struct sdhci_data rk3588_data = {
.emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
.get_phy = dwcmshc_emmc_get_phy,
.set_ios_post = dwcmshc_sdhci_set_ios_post,
- .flags = RK_DLL_CMD_OUT | RK_RXCLK_NO_INVERTER,
+ .set_enhanced_strobe = dwcmshc_sdhci_set_enhanced_strobe,
+ .flags = RK_DLL_CMD_OUT,
+ .hs200_tx_tap = 16,
+ .hs400_tx_tap = 9,
+ .hs400_cmd_tap = 8,
+ .hs400_strbin_tap = 3,
+ .ddr50_strbin_delay_num = 16,
+};
+
+static const struct sdhci_data rk3528_data = {
+ .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
+ .get_phy = dwcmshc_emmc_get_phy,
+ .set_ios_post = dwcmshc_sdhci_set_ios_post,
+ .set_enhanced_strobe = dwcmshc_sdhci_set_enhanced_strobe,
+ .flags = RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
+ .hs200_tx_tap = 12,
+ .hs400_tx_tap = 6,
+ .hs400_cmd_tap = 6,
+ .hs400_strbin_tap = 3,
+ .ddr50_strbin_delay_num = 10,
+};
+
+static const struct sdhci_data rk3562_data = {
+ .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
+ .get_phy = dwcmshc_emmc_get_phy,
+ .set_ios_post = dwcmshc_sdhci_set_ios_post,
+ .set_enhanced_strobe = dwcmshc_sdhci_set_enhanced_strobe,
+ .flags = RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
+ .hs200_tx_tap = 12,
+ .hs400_tx_tap = 6,
+ .hs400_cmd_tap = 6,
+ .hs400_strbin_tap = 3,
+ .ddr50_strbin_delay_num = 10,
};
static const struct udevice_id sdhci_ids[] = {
@@ -555,6 +673,14 @@
.data = (ulong)&rk3568_data,
},
{
+ .compatible = "rockchip,rk3528-dwcmshc",
+ .data = (ulong)&rk3528_data,
+ },
+ {
+ .compatible = "rockchip,rk3562-dwcmshc",
+ .data = (ulong)&rk3562_data,
+ },
+ {
.compatible = "rockchip,rk3588-dwcmshc",
.data = (ulong)&rk3588_data,
},
--
Gitblit v1.6.2