[PATCH] dts: rockchip: rk3399: enable emmc phy for spl

2021-10-31 Thread Yifeng Zhao
adapting commit ac804143cf ("mmc: rockchip_sdhci: add phy and clock
config for rk3399") to fix the issue "Not found emmc phy device".

Signed-off-by: Yifeng Zhao 
---

 arch/arm/dts/rk3399-u-boot.dtsi | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi
index 73922c328a..716b9a433a 100644
--- a/arch/arm/dts/rk3399-u-boot.dtsi
+++ b/arch/arm/dts/rk3399-u-boot.dtsi
@@ -88,6 +88,10 @@
u-boot,dm-pre-reloc;
 };
 
+_phy {
+   u-boot,dm-pre-reloc;
+};
+
  {
u-boot,dm-pre-reloc;
 };
-- 
2.17.1





[PATCH] mmc: rockchip_sdhci: enable strobe line for HS400

2021-10-15 Thread Yifeng Zhao
The default configuration of rk3399 EMMC PHY does not enable the
strobe line, and EMMC controller will got data transmission error
at HS400 mode.

Signed-off-by: Yifeng Zhao 
---

 drivers/mmc/rockchip_sdhci.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index 1ac00587d4..278473899c 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -143,6 +143,9 @@ static void rk3399_emmc_phy_power_on(struct 
rockchip_emmc_phy *phy, u32 clock)
writel(RK_CLRSETBITS(3 << 12, freqsel << 12), >emmcphy_con[0]);
writel(RK_CLRSETBITS(1 << 1, 1 << 1), >emmcphy_con[6]);
 
+   /* REN Enable on STRB Line for HS400 */
+   writel(RK_CLRSETBITS(0, 1 << 9), >emmcphy_con[2]);
+
read_poll_timeout(readl, >emmcphy_status, dllrdy,
  PHYCTRL_DLL_LOCK_WO_TMOUT(dllrdy), 1, 5000);
 }
-- 
2.17.1





[PATCH v3 1/3] mmc: rockchip_sdhci: add phy and clock config for rk3399

2021-06-29 Thread Yifeng Zhao
Add clock, phy and other configuration, it is convenient to support
new controller. Here a short summary of the changes:
- Add mmc_of_parse to parse dts config.
- Remove OF_PLATDATA related code.
- Reorder header inclusion.
- Add phy ops.
- add ops set_ios_post to modify the parameters of phy when the
  clock changes.
- Add execute tuning api for hs200 tuning.

Signed-off-by: Yifeng Zhao 
---

Changes in v3:
- Optimize hs200 tuning function.
- Add check for callback function.
- Add return value for tuning function.
- Fixed source clock rate with host->max_clk, the interface clock is divided
  from the source clock.

Changes in v2:
- Add mmc_of_parse to parse dts config.
- Used read_poll_timeout api to check dll lock status
- Add execute tuning api for hs200 tuning

 drivers/mmc/rockchip_sdhci.c | 313 +++
 1 file changed, 277 insertions(+), 36 deletions(-)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index d95f8b2a15..eff134c8f5 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -6,90 +6,322 @@
  */
 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include "mmc_private.h"
 #include 
-#include 
+#include 
+#include 
+#include 
 
 /* 400KHz is max freq for card ID etc. Use that as min */
 #define EMMC_MIN_FREQ  40
+#define KHz(1000)
+#define MHz(1000 * KHz)
+#define SDHCI_TUNING_LOOP_COUNT40
+
+#define PHYCTRL_CALDONE_MASK   0x1
+#define PHYCTRL_CALDONE_SHIFT  0x6
+#define PHYCTRL_CALDONE_DONE   0x1
+#define PHYCTRL_DLLRDY_MASK0x1
+#define PHYCTRL_DLLRDY_SHIFT   0x5
+#define PHYCTRL_DLLRDY_DONE0x1
+#define PHYCTRL_FREQSEL_200M   0x0
+#define PHYCTRL_FREQSEL_50M0x1
+#define PHYCTRL_FREQSEL_100M   0x2
+#define PHYCTRL_FREQSEL_150M   0x3
+#define PHYCTRL_DLL_LOCK_WO_TMOUT(x)   \
+   x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
+   PHYCTRL_DLLRDY_DONE)
 
 struct rockchip_sdhc_plat {
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
-   struct dtd_rockchip_rk3399_sdhci_5_1 dtplat;
-#endif
struct mmc_config cfg;
struct mmc mmc;
 };
 
+struct rockchip_emmc_phy {
+   u32 emmcphy_con[7];
+   u32 reserved;
+   u32 emmcphy_status;
+};
+
 struct rockchip_sdhc {
struct sdhci_host host;
+   struct udevice *dev;
void *base;
+   struct rockchip_emmc_phy *phy;
+   struct clk emmc_clk;
+};
+
+struct sdhci_data {
+   int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
+   int (*emmc_phy_init)(struct udevice *dev);
+   int (*get_phy)(struct udevice *dev);
+};
+
+static int rk3399_emmc_phy_init(struct udevice *dev)
+{
+   return 0;
+}
+
+static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
+{
+   u32 caldone, dllrdy, freqsel;
+
+   writel(RK_CLRSETBITS(7 << 4, 0), >emmcphy_con[6]);
+   writel(RK_CLRSETBITS(1 << 11, 1 << 11), >emmcphy_con[0]);
+   writel(RK_CLRSETBITS(0xf << 7, 6 << 7), >emmcphy_con[0]);
+
+   /*
+* According to the user manual, calpad calibration
+* cycle takes more than 2us without the minimal recommended
+* value, so we may need a little margin here
+*/
+   udelay(3);
+   writel(RK_CLRSETBITS(1, 1), >emmcphy_con[6]);
+
+   /*
+* According to the user manual, it asks driver to
+* wait 5us for calpad busy trimming. But it seems that
+* 5us of caldone isn't enough for all cases.
+*/
+   udelay(500);
+   caldone = readl(>emmcphy_status);
+   caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
+   if (caldone != PHYCTRL_CALDONE_DONE) {
+   printf("%s: caldone timeout.\n", __func__);
+   return;
+   }
+
+   /* Set the frequency of the DLL operation */
+   if (clock < 75 * MHz)
+   freqsel = PHYCTRL_FREQSEL_50M;
+   else if (clock < 125 * MHz)
+   freqsel = PHYCTRL_FREQSEL_100M;
+   else if (clock < 175 * MHz)
+   freqsel = PHYCTRL_FREQSEL_150M;
+   else
+   freqsel = PHYCTRL_FREQSEL_200M;
+
+   /* Set the frequency of the DLL operation */
+   writel(RK_CLRSETBITS(3 << 12, freqsel << 12), >emmcphy_con[0]);
+   writel(RK_CLRSETBITS(1 << 1, 1 << 1), >emmcphy_con[6]);
+
+   read_poll_timeout(readl, >emmcphy_status, dllrdy,
+ PHYCTRL_DLL_LOCK_WO_TMOUT(dllrdy), 1, 5000);
+}
+
+static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy)
+{
+   writel(RK_CLRSETBITS(1, 0), >emmcphy_con[6]);
+   writel(RK_CLRSETBITS(1 << 1, 0), >emmcphy_con[6]);
+}
+
+static int rk3399_emmc_get_phy(struct udevice *dev)
+

[PATCH v3 2/3] mmc: rockchip_sdhci: Add support for RK3568

2021-06-29 Thread Yifeng Zhao
This patch adds support for the RK3568 platform to this driver.

Signed-off-by: Yifeng Zhao 
---

Changes in v3:
- Config the interface clock by clk_set_rate directly

Changes in v2:
- Used sdhci_set_clock api to set clock.
- Used read_poll_timeout api to check dll status.

 drivers/mmc/rockchip_sdhci.c | 109 +++
 1 file changed, 109 insertions(+)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index eff134c8f5..1ac00587d4 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -42,6 +42,34 @@
x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
PHYCTRL_DLLRDY_DONE)
 
+/* Rockchip specific Registers */
+#define DWCMSHC_EMMC_DLL_CTRL  0x800
+#define DWCMSHC_EMMC_DLL_CTRL_RESETBIT(1)
+#define DWCMSHC_EMMC_DLL_RXCLK 0x804
+#define DWCMSHC_EMMC_DLL_TXCLK 0x808
+#define DWCMSHC_EMMC_DLL_STRBIN0x80c
+#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_DLYENABIT(27)
+#define DLL_TXCLK_TAPNUM_DEFAULT   0x10
+#define DLL_STRBIN_TAPNUM_DEFAULT  0x3
+#define DLL_TXCLK_TAPNUM_FROM_SW   BIT(24)
+#define DWCMSHC_EMMC_DLL_LOCKEDBIT(8)
+#define DWCMSHC_EMMC_DLL_TIMEOUT   BIT(9)
+#define DLL_RXCLK_NO_INVERTER  1
+#define DLL_RXCLK_INVERTER 0
+#define DWCMSHC_ENHANCED_STROBEBIT(8)
+#define DLL_LOCK_WO_TMOUT(x) \
+   x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
+   (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
+#define ROCKCHIP_MAX_CLKS  3
+
 struct rockchip_sdhc_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -167,6 +195,77 @@ static int rk3399_sdhci_emmc_set_clock(struct sdhci_host 
*host, unsigned int clo
return 0;
 }
 
+static int rk3568_emmc_phy_init(struct udevice *dev)
+{
+   struct rockchip_sdhc *prv = dev_get_priv(dev);
+   struct sdhci_host *host = >host;
+   u32 extra;
+
+   extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+
+   return 0;
+}
+
+static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int 
clock)
+{
+   struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, 
host);
+   int val, ret;
+   u32 extra;
+
+   if (clock > host->max_clk)
+   clock = host->max_clk;
+   if (clock)
+   clk_set_rate(>emmc_clk, clock);
+
+   sdhci_set_clock(host->mmc, clock);
+
+   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);
+
+   /* Init DLL settings */
+   extra = DWCMSHC_EMMC_DLL_START_DEFAULT << 
DWCMSHC_EMMC_DLL_START_POINT |
+   DWCMSHC_EMMC_DLL_INC_VALUE << DWCMSHC_EMMC_DLL_INC |
+   DWCMSHC_EMMC_DLL_START;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
+
+   ret = read_poll_timeout(readl, host->ioaddr + 
DWCMSHC_EMMC_DLL_STATUS0,
+   val, DLL_LOCK_WO_TMOUT(val), 1, 500);
+   if (ret)
+   return ret;
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_TXCLK_TAPNUM_DEFAULT |
+   DLL_TXCLK_TAPNUM_FROM_SW;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_STRBIN_TAPNUM_DEFAULT;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
+   } else {
+   /* reset the clock phase when the frequency is lower than 
100MHz */
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+   extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
+   }
+
+   return 0;
+}
+
+static int rk3568_emmc_get_phy(struct udevice *dev)
+{
+   return 0;
+}
+
 static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
 {
struct rockchip_

[PATCH v3 0/3] Add hs400 support for rk3399 and rk3568

2021-06-29 Thread Yifeng Zhao


RK3399 and RK3568 are use different sdhci controllers.
The drivers need to be updated to support these two platforms
and it's easy to support new platforms.


Changes in v3:
- Optimize hs200 tuning function.
- Add check for callback function.
- Add return value for tuning function.
- Fixed source clock rate with host->max_clk, the interface clock is divided
  from the source clock.
- Config the interface clock by clk_set_rate directly
- Enable SDMA.

Changes in v2:
- Add mmc_of_parse to parse dts config.
- Used read_poll_timeout api to check dll lock status
- Add execute tuning api for hs200 tuning
- Used sdhci_set_clock api to set clock.
- Used read_poll_timeout api to check dll status.

Yifeng Zhao (3):
  mmc: rockchip_sdhci: add phy and clock config for rk3399
  mmc: rockchip_sdhci: Add support for RK3568
  rockchip: config: evb-rk3399: add hs400 and SDMA support

 configs/evb-rk3399_defconfig |   2 +
 drivers/mmc/rockchip_sdhci.c | 422 ---
 2 files changed, 388 insertions(+), 36 deletions(-)

-- 
2.17.1





[PATCH v3 3/3] rockchip: config: evb-rk3399: add hs400 and SDMA support

2021-06-29 Thread Yifeng Zhao
This enable hs400 and SDMA support for emmc on evb-rk3399.

Signed-off-by: Yifeng Zhao 
---

Changes in v3:
- Enable SDMA.

 configs/evb-rk3399_defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
index 21477719dc..d5eba1d903 100644
--- a/configs/evb-rk3399_defconfig
+++ b/configs/evb-rk3399_defconfig
@@ -29,9 +29,11 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MISC=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_SDMA=y
 CONFIG_MMC_SDHCI_ROCKCHIP=y
 CONFIG_SF_DEFAULT_SPEED=2000
 CONFIG_DM_ETH=y
-- 
2.17.1





[PATCH v2 1/3] mmc: rockchip_sdhci: add phy and clock config for rk3399

2021-06-28 Thread Yifeng Zhao
Add clock, phy and other configuration, it is convenient to support
new controller. Here a short summary of the changes:
- Add mmc_of_parse to parse dts config.
- Remove OF_PLATDATA related code.
- Reorder header inclusion.
- Add phy ops.
- add ops set_ios_post to modify the parameters of phy when the
  clock changes.
- Add execute tuning api for hs200 tuning

Signed-off-by: Yifeng Zhao 
---

Changes in v2:
- Add mmc_of_parse to parse dts config.
- Used read_poll_timeout api to check dll lock status
- Add execute tuning api for hs200 tuning

 drivers/mmc/rockchip_sdhci.c | 310 +++
 1 file changed, 274 insertions(+), 36 deletions(-)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index d95f8b2a15..2973911446 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -6,90 +6,319 @@
  */
 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include "mmc_private.h"
 #include 
-#include 
+#include 
+#include 
+#include 
 
 /* 400KHz is max freq for card ID etc. Use that as min */
 #define EMMC_MIN_FREQ  40
+#define KHz(1000)
+#define MHz(1000 * KHz)
+#define SDHCI_TUNING_LOOP_COUNT40
+
+#define PHYCTRL_CALDONE_MASK   0x1
+#define PHYCTRL_CALDONE_SHIFT  0x6
+#define PHYCTRL_CALDONE_DONE   0x1
+#define PHYCTRL_DLLRDY_MASK0x1
+#define PHYCTRL_DLLRDY_SHIFT   0x5
+#define PHYCTRL_DLLRDY_DONE0x1
+#define PHYCTRL_FREQSEL_200M   0x0
+#define PHYCTRL_FREQSEL_50M0x1
+#define PHYCTRL_FREQSEL_100M   0x2
+#define PHYCTRL_FREQSEL_150M   0x3
+#define PHYCTRL_DLL_LOCK_WO_TMOUT(x)   \
+   x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
+   PHYCTRL_DLLRDY_DONE)
 
 struct rockchip_sdhc_plat {
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
-   struct dtd_rockchip_rk3399_sdhci_5_1 dtplat;
-#endif
struct mmc_config cfg;
struct mmc mmc;
 };
 
+struct rockchip_emmc_phy {
+   u32 emmcphy_con[7];
+   u32 reserved;
+   u32 emmcphy_status;
+};
+
 struct rockchip_sdhc {
struct sdhci_host host;
+   struct udevice *dev;
void *base;
+   struct rockchip_emmc_phy *phy;
+   struct clk emmc_clk;
+};
+
+struct sdhci_data {
+   int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
+   int (*emmc_phy_init)(struct udevice *dev);
+   int (*get_phy)(struct udevice *dev);
+};
+
+static int rk3399_emmc_phy_init(struct udevice *dev)
+{
+   return 0;
+}
+
+static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
+{
+   u32 caldone, dllrdy, freqsel;
+
+   writel(RK_CLRSETBITS(7 << 4, 0), >emmcphy_con[6]);
+   writel(RK_CLRSETBITS(1 << 11, 1 << 11), >emmcphy_con[0]);
+   writel(RK_CLRSETBITS(0xf << 7, 6 << 7), >emmcphy_con[0]);
+
+   /*
+* According to the user manual, calpad calibration
+* cycle takes more than 2us without the minimal recommended
+* value, so we may need a little margin here
+*/
+   udelay(3);
+   writel(RK_CLRSETBITS(1, 1), >emmcphy_con[6]);
+
+   /*
+* According to the user manual, it asks driver to
+* wait 5us for calpad busy trimming. But it seems that
+* 5us of caldone isn't enough for all cases.
+*/
+   udelay(500);
+   caldone = readl(>emmcphy_status);
+   caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
+   if (caldone != PHYCTRL_CALDONE_DONE) {
+   printf("%s: caldone timeout.\n", __func__);
+   return;
+   }
+
+   /* Set the frequency of the DLL operation */
+   if (clock < 75 * MHz)
+   freqsel = PHYCTRL_FREQSEL_50M;
+   else if (clock < 125 * MHz)
+   freqsel = PHYCTRL_FREQSEL_100M;
+   else if (clock < 175 * MHz)
+   freqsel = PHYCTRL_FREQSEL_150M;
+   else
+   freqsel = PHYCTRL_FREQSEL_200M;
+
+   /* Set the frequency of the DLL operation */
+   writel(RK_CLRSETBITS(3 << 12, freqsel << 12), >emmcphy_con[0]);
+   writel(RK_CLRSETBITS(1 << 1, 1 << 1), >emmcphy_con[6]);
+
+   read_poll_timeout(readl, >emmcphy_status, dllrdy,
+ PHYCTRL_DLL_LOCK_WO_TMOUT(dllrdy), 1, 5000);
+}
+
+static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy)
+{
+   writel(RK_CLRSETBITS(1, 0), >emmcphy_con[6]);
+   writel(RK_CLRSETBITS(1 << 1, 0), >emmcphy_con[6]);
+}
+
+static int rk3399_emmc_get_phy(struct udevice *dev)
+{
+   struct rockchip_sdhc *priv = dev_get_priv(dev);
+
+   ofnode phy_node;
+   void *grf_base;
+   u32 grf_phy_offset, phandle;
+
+   phandle = dev_read_u32_default(dev, "phys", 0);
+   phy_node 

[PATCH v2 2/3] mmc: rockchip_sdhci: Add support for RK3568

2021-06-28 Thread Yifeng Zhao
This patch adds support for the RK3568 platform to this driver.

Signed-off-by: Yifeng Zhao 
---

Changes in v2:
- Used sdhci_set_clock api to set clock.
- Used read_poll_timeout api to check dll status.

 drivers/mmc/rockchip_sdhci.c | 117 +++
 1 file changed, 117 insertions(+)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index 2973911446..5ac524c9c9 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -42,6 +42,34 @@
x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
PHYCTRL_DLLRDY_DONE)
 
+/* Rockchip specific Registers */
+#define DWCMSHC_EMMC_DLL_CTRL  0x800
+#define DWCMSHC_EMMC_DLL_CTRL_RESETBIT(1)
+#define DWCMSHC_EMMC_DLL_RXCLK 0x804
+#define DWCMSHC_EMMC_DLL_TXCLK 0x808
+#define DWCMSHC_EMMC_DLL_STRBIN0x80c
+#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_DLYENABIT(27)
+#define DLL_TXCLK_TAPNUM_DEFAULT   0x10
+#define DLL_STRBIN_TAPNUM_DEFAULT  0x3
+#define DLL_TXCLK_TAPNUM_FROM_SW   BIT(24)
+#define DWCMSHC_EMMC_DLL_LOCKEDBIT(8)
+#define DWCMSHC_EMMC_DLL_TIMEOUT   BIT(9)
+#define DLL_RXCLK_NO_INVERTER  1
+#define DLL_RXCLK_INVERTER 0
+#define DWCMSHC_ENHANCED_STROBEBIT(8)
+#define DLL_LOCK_WO_TMOUT(x) \
+   x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
+   (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
+#define ROCKCHIP_MAX_CLKS  3
+
 struct rockchip_sdhc_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -178,6 +206,85 @@ static int rk3399_sdhci_emmc_set_clock(struct sdhci_host 
*host, unsigned int clo
return 0;
 }
 
+static int rk3568_emmc_phy_init(struct udevice *dev)
+{
+   struct rockchip_sdhc *prv = dev_get_priv(dev);
+   struct sdhci_host *host = >host;
+   u32 extra;
+
+   extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+
+   return 0;
+}
+
+static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int 
clock)
+{
+   struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, 
host);
+   int max_clk = host->max_clk;
+   unsigned long mmc_clock;
+   int val, ret;
+   u32 extra;
+
+   if (clock) {
+   mmc_clock = clk_set_rate(>emmc_clk, clock);
+   if (IS_ERR_VALUE(mmc_clock))
+   host->max_clk = max_clk;
+   else
+   host->max_clk = mmc_clock;
+   }
+
+   sdhci_set_clock(host->mmc, clock);
+   if (!clock)
+   return 0;
+   host->max_clk = max_clk;
+
+   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);
+
+   /* Init DLL settings */
+   extra = DWCMSHC_EMMC_DLL_START_DEFAULT << 
DWCMSHC_EMMC_DLL_START_POINT |
+   DWCMSHC_EMMC_DLL_INC_VALUE << DWCMSHC_EMMC_DLL_INC |
+   DWCMSHC_EMMC_DLL_START;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
+
+   ret = read_poll_timeout(readl, host->ioaddr + 
DWCMSHC_EMMC_DLL_STATUS0,
+   val, DLL_LOCK_WO_TMOUT(val), 1, 500);
+   if (ret)
+   return ret;
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_TXCLK_TAPNUM_DEFAULT |
+   DLL_TXCLK_TAPNUM_FROM_SW;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_STRBIN_TAPNUM_DEFAULT;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
+   } else {
+   /* reset the clock phase when the frequency is lower than 
100MHz */
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+   extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
+  

[PATCH v2 3/3] rockchip: config: evb-rk3399: add hs200 and hs400 support

2021-06-28 Thread Yifeng Zhao
This enable hs200 and hs400 support for emmc on evb-rk3399.

Signed-off-by: Yifeng Zhao 
---

(no changes since v1)

 configs/evb-rk3399_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/evb-rk3399_defconfig b/configs/evb-rk3399_defconfig
index 909c68822c..687aeec26c 100644
--- a/configs/evb-rk3399_defconfig
+++ b/configs/evb-rk3399_defconfig
@@ -29,6 +29,7 @@ CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_ROCKCHIP_GPIO=y
 CONFIG_SYS_I2C_ROCKCHIP=y
 CONFIG_MISC=y
+CONFIG_MMC_HS400_SUPPORT=y
 CONFIG_MMC_DW=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SDHCI=y
-- 
2.17.1





[PATCH v2 0/3]

2021-06-28 Thread Yifeng Zhao
RK3399 and RK3568 are use different sdhci controllers.
The drivers need to be updated to support these two platforms
and it's easy to support new platforms.


Changes in v2:
- Add mmc_of_parse to parse dts config.
- Used read_poll_timeout api to check dll lock status
- Add execute tuning api for hs200 tuning
- Used sdhci_set_clock api to set clock.
- Used read_poll_timeout api to check dll status.

Yifeng Zhao (3):
  mmc: rockchip_sdhci: add phy and clock config for rk3399
  mmc: rockchip_sdhci: Add support for RK3568
  rockchip: config: evb-rk3399: add hs200 and hs400 support

 configs/evb-rk3399_defconfig |   1 +
 drivers/mmc/rockchip_sdhci.c | 427 ---
 2 files changed, 392 insertions(+), 36 deletions(-)

-- 
2.17.1





[PATCH] mtd: nand: NFC drivers for RK3308, RK2928 and others

2021-06-07 Thread Yifeng Zhao
This driver supports Rockchip NFC (NAND Flash Controller) found on
RK3308, RK2928, RKPX30, RV1108 and other SOCs. The driver has been
tested using 8-bit NAND interface on the ARM based RK3308 platform.

Support Rockchip SoCs and NFC versions:
- PX30 and RK3326(NFCv900).
ECC: 16/40/60/70 bits/1KB.
CLOCK: ahb and nfc.
- RK3308 and RV1108(NFCv800).
ECC: 16 bits/1KB.
CLOCK: ahb and nfc.
- RK3036 and RK3128(NFCv622).
ECC: 16/24/40/60 bits/1KB.
CLOCK: ahb and nfc.
- RK3066, RK3188 and RK2928(NFCv600).
ECC: 16/24/40/60 bits/1KB.
CLOCK: ahb.

Supported features:
- Read full page data by DMA.
- Support HW ECC(one step is 1KB).
- Support 2 - 32K page size.
- Support 8 CS(depend on SoCs)

Limitations:
- No support for the ecc step size is 512.
- Untested on some SoCs.
- No support for subpages.
- No support for the builtin randomizer.
- The original bad block mask is not supported. It is recommended to
  use  the BBT(bad block table).

Signed-off-by: Yifeng Zhao 
---

 drivers/mtd/nand/raw/Kconfig|   16 +
 drivers/mtd/nand/raw/Makefile   |1 +
 drivers/mtd/nand/raw/rockchip_nfc.c | 1253 +++
 3 files changed, 1270 insertions(+)
 create mode 100644 drivers/mtd/nand/raw/rockchip_nfc.c

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index ed151ee0a5..a901ce5511 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -333,6 +333,22 @@ config CORTINA_NAND
  The controller supports a maximum 8k page size and supports
  a maximum 40-bit error correction per sector of 1024 bytes.
 
+config ROCKCHIP_NAND
+   bool "Support for NAND controller on Rockchip SoCs"
+   depends on ARCH_ROCKCHIP
+   select SYS_NAND_SELF_INIT
+   select DM_MTD
+   imply CMD_NAND
+   help
+ Enables support for NAND Flash chips on Rockchip SoCs platform.
+ This controller is found on Rockchip SoCs.
+ There are four different versions of NAND FLASH Controllers,
+ including:
+   NFC v600: RK2928, RK3066, RK3188
+   NFC v622: RK3036, RK3128
+   NFC v800: RK3308, RV1108
+   NFC v900: PX30, RK3326
+
 comment "Generic NAND options"
 
 config SYS_NAND_BLOCK_SIZE
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index f3f0e15a15..a5ed2c536f 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
 obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o
 obj-$(CONFIG_NAND_STM32_FMC2) += stm32_fmc2_nand.o
 obj-$(CONFIG_CORTINA_NAND) += cortina_nand.o
+obj-$(CONFIG_ROCKCHIP_NAND) += rockchip_nfc.o
 
 else  # minimal SPL drivers
 
diff --git a/drivers/mtd/nand/raw/rockchip_nfc.c 
b/drivers/mtd/nand/raw/rockchip_nfc.c
new file mode 100644
index 00..21776f3b14
--- /dev/null
+++ b/drivers/mtd/nand/raw/rockchip_nfc.c
@@ -0,0 +1,1253 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Rockchip NAND Flash controller driver.
+ * Copyright (C) 2021 Rockchip Inc.
+ * Author: Yifeng Zhao 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * NFC Page Data Layout:
+ * 1024 bytes data + 4Bytes sys data + 28Bytes~124Bytes ECC data +
+ * 1024 bytes data + 4Bytes sys data + 28Bytes~124Bytes ECC data +
+ * ..
+ * NAND Page Data Layout:
+ * 1024 * n data + m Bytes oob
+ * Original Bad Block Mask Location:
+ * First byte of oob(spare).
+ * nand_chip->oob_poi data layout:
+ * 4Bytes sys data +  + 4Bytes sys data + ECC data.
+ */
+
+/* NAND controller register definition */
+#define NFC_READ   (0)
+#define NFC_WRITE  (1)
+
+#define NFC_FMCTL  (0x00)
+#define   FMCTL_CE_SEL_M   0xFF
+#define   FMCTL_CE_SEL(x)  (1 << (x))
+#define   FMCTL_WP BIT(8)
+#define   FMCTL_RDYBIT(9)
+
+#define NFC_FMWAIT (0x04)
+#define   FLCTL_RSTBIT(0)
+#define   FLCTL_WR (1) /* 0: read, 1: write */
+#define   FLCTL_XFER_STBIT(2)
+#define   FLCTL_XFER_ENBIT(3)
+#define   FLCTL_ACORRECT   BIT(10) /* Auto correct error bits. */
+#define   FLCTL_XFER_READY BIT(20)
+#define   FLCTL_XFER_SECTOR(22)
+#define   FLCTL_TOG_FIXBIT(29)
+
+#define   BCHCTL_BANK_M(7 << 5)
+#define   BCHCTL_BANK  (5)
+
+#define   DMA_ST   BIT(0)
+#define   DMA_WR   (1) /* 0: write, 1: read */
+#define   DMA_EN   BIT(2)
+#define   DMA_AHB_SIZE (3) /* 0: 1, 1: 2

[PATCH v1 1/2] mmc: rockchip_sdhci: add phy and clock config for rk3399

2021-06-07 Thread Yifeng Zhao
Add clock, phy and other configuration, it is convenient to support
new controller. Here a short summary of the changes:
- support HS200 and HS400 config by dts
- Remove OF_PLATDATA related code
- Reorder header inclusion
- Add data width config for 1, 4, 8 bits
- Add phy ops
- add ops set_ios_post to modify the parameters of phy when the
  clock changes

Signed-off-by: Yifeng Zhao 
---

 drivers/mmc/rockchip_sdhci.c | 334 +++
 1 file changed, 303 insertions(+), 31 deletions(-)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index d95f8b2a15..05ed998eca 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -6,33 +6,285 @@
  */
 
 #include 
+#include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 
+#include 
+#include 
 /* 400KHz is max freq for card ID etc. Use that as min */
 #define EMMC_MIN_FREQ  40
+#define KHz(1000)
+#define MHz(1000 * KHz)
+
+#define PHYCTRL_CALDONE_MASK   0x1
+#define PHYCTRL_CALDONE_SHIFT  0x6
+#define PHYCTRL_CALDONE_DONE   0x1
+#define PHYCTRL_DLLRDY_MASK0x1
+#define PHYCTRL_DLLRDY_SHIFT   0x5
+#define PHYCTRL_DLLRDY_DONE0x1
+#define PHYCTRL_FREQSEL_200M   0x0
+#define PHYCTRL_FREQSEL_50M0x1
+#define PHYCTRL_FREQSEL_100M   0x2
+#define PHYCTRL_FREQSEL_150M   0x3
 
 struct rockchip_sdhc_plat {
-#if CONFIG_IS_ENABLED(OF_PLATDATA)
-   struct dtd_rockchip_rk3399_sdhci_5_1 dtplat;
-#endif
struct mmc_config cfg;
struct mmc mmc;
 };
 
+struct rockchip_emmc_phy {
+   u32 emmcphy_con[7];
+   u32 reserved;
+   u32 emmcphy_status;
+};
+
 struct rockchip_sdhc {
struct sdhci_host host;
+   struct udevice *dev;
void *base;
+   struct rockchip_emmc_phy *phy;
+   struct clk emmc_clk;
+};
+
+struct sdhci_data {
+   int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
+   int (*emmc_phy_init)(struct udevice *dev);
+   int (*get_phy)(struct udevice *dev);
+};
+
+static int rk3399_emmc_phy_init(struct udevice *dev)
+{
+   return 0;
+}
+
+static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
+{
+   u32 caldone, dllrdy, freqsel;
+   uint start;
+
+   writel(RK_CLRSETBITS(7 << 4, 0), >emmcphy_con[6]);
+   writel(RK_CLRSETBITS(1 << 11, 1 << 11), >emmcphy_con[0]);
+   writel(RK_CLRSETBITS(0xf << 7, 6 << 7), >emmcphy_con[0]);
+
+   /*
+* According to the user manual, calpad calibration
+* cycle takes more than 2us without the minimal recommended
+* value, so we may need a little margin here
+*/
+   udelay(3);
+   writel(RK_CLRSETBITS(1, 1), >emmcphy_con[6]);
+
+   /*
+* According to the user manual, it asks driver to
+* wait 5us for calpad busy trimming. But it seems that
+* 5us of caldone isn't enough for all cases.
+*/
+   udelay(500);
+   caldone = readl(>emmcphy_status);
+   caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
+   if (caldone != PHYCTRL_CALDONE_DONE) {
+   printf("%s: caldone timeout.\n", __func__);
+   return;
+   }
+
+   /* Set the frequency of the DLL operation */
+   if (clock < 75 * MHz)
+   freqsel = PHYCTRL_FREQSEL_50M;
+   else if (clock < 125 * MHz)
+   freqsel = PHYCTRL_FREQSEL_100M;
+   else if (clock < 175 * MHz)
+   freqsel = PHYCTRL_FREQSEL_150M;
+   else
+   freqsel = PHYCTRL_FREQSEL_200M;
+
+   /* Set the frequency of the DLL operation */
+   writel(RK_CLRSETBITS(3 << 12, freqsel << 12), >emmcphy_con[0]);
+   writel(RK_CLRSETBITS(1 << 1, 1 << 1), >emmcphy_con[6]);
+
+   start = get_timer(0);
+
+   do {
+   udelay(1);
+   dllrdy = readl(>emmcphy_status);
+   dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK;
+   if (dllrdy == PHYCTRL_DLLRDY_DONE)
+   break;
+   } while (get_timer(start) < 5);
+
+   if (dllrdy != PHYCTRL_DLLRDY_DONE)
+   printf("%s: dllrdy timeout.\n", __func__);
+}
+
+static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy)
+{
+   writel(RK_CLRSETBITS(1, 0), >emmcphy_con[6]);
+   writel(RK_CLRSETBITS(1 << 1, 0), >emmcphy_con[6]);
+}
+
+static int rockchip_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+   unsigned int div, clk = 0, timeout;
+   unsigned int input_clk;
+   struct rockchip_sdhc *priv =
+   container_of(host, struct rockchip_sdhc, host);
+
+   /* Wait max 20 ms */
+   timeout = 2000;
+   while (sd

[PATCH v1 2/2] mmc: rockchip_sdhci: Add support for RK3568

2021-06-07 Thread Yifeng Zhao
This patch adds support for the RK3568 platform to this driver.

Signed-off-by: Yifeng Zhao 
---

 drivers/mmc/rockchip_sdhci.c | 103 +++
 1 file changed, 103 insertions(+)

diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index 05ed998eca..befe48e061 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -36,6 +36,31 @@
 #define PHYCTRL_FREQSEL_100M   0x2
 #define PHYCTRL_FREQSEL_150M   0x3
 
+/* Rockchip specific Registers */
+#define DWCMSHC_EMMC_DLL_CTRL  0x800
+#define DWCMSHC_EMMC_DLL_RXCLK 0x804
+#define DWCMSHC_EMMC_DLL_TXCLK 0x808
+#define DWCMSHC_EMMC_DLL_STRBIN0x80c
+#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_INC   8
+#define DWCMSHC_EMMC_DLL_DLYENABIT(27)
+#define DLL_TXCLK_TAPNUM_DEFAULT   0x10
+#define DLL_STRBIN_TAPNUM_DEFAULT  0x3
+#define DLL_TXCLK_TAPNUM_FROM_SW   BIT(24)
+#define DWCMSHC_EMMC_DLL_LOCKEDBIT(8)
+#define DWCMSHC_EMMC_DLL_TIMEOUT   BIT(9)
+#define DLL_RXCLK_NO_INVERTER  1
+#define DLL_RXCLK_INVERTER 0
+#define DWCMSHC_ENHANCED_STROBEBIT(8)
+#define DLL_LOCK_WO_TMOUT(x) \
+   x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
+   (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
+#define ROCKCHIP_MAX_CLKS  3
+
 struct rockchip_sdhc_plat {
struct mmc_config cfg;
struct mmc mmc;
@@ -267,6 +292,74 @@ static int rk3399_sdhci_emmc_set_clock(struct sdhci_host 
*host, unsigned int clo
return 0;
 }
 
+static int rk3568_emmc_phy_init(struct udevice *dev)
+{
+   struct rockchip_sdhc *prv = dev_get_priv(dev);
+   struct sdhci_host *host = >host;
+   u32 extra;
+
+   extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+   return 0;
+}
+
+static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int 
clock)
+{
+   u32 extra;
+   int timeout = 500, ret;
+
+   ret = rockchip_emmc_set_clock(host, clock);
+
+   if (clock >= 50 * 100) {
+   sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL);
+   udelay(1);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+   /* Init DLL settings */
+   extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT |
+   0x2 << DWCMSHC_EMMC_DLL_INC |
+   DWCMSHC_EMMC_DLL_START;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
+
+   while (1) {
+   if (timeout < 0)
+   return -ETIMEDOUT;
+   if (DLL_LOCK_WO_TMOUT((sdhci_readl(host, 
DWCMSHC_EMMC_DLL_STATUS0
+   break;
+   udelay(1);
+   timeout--;
+   }
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_TXCLK_TAPNUM_DEFAULT |
+   DLL_TXCLK_TAPNUM_FROM_SW;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
+
+   extra = DWCMSHC_EMMC_DLL_DLYENA |
+   DLL_STRBIN_TAPNUM_DEFAULT;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
+   udelay(1);
+   } else {
+   /* reset the clock phase when the frequency is lower than 52MHz 
*/
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
+   extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
+   sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
+   sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
+   udelay(1);
+   }
+
+   return ret;
+}
+
+static int rk3568_emmc_get_phy(struct udevice *dev)
+{
+   return 0;
+}
+
 static int sdhci_set_ios_post(struct sdhci_host *host)
 {
struct mmc *mmc = host->mmc;
@@ -370,11 +463,21 @@ static const struct sdhci_data rk3399_data = {
.emmc_phy_init = rk3399_emmc_phy_init,
 };
 
+static const struct sdhci_data rk3568_data = {
+   .emmc_set_clock = rk3568_sdhci_emmc_set_clock,
+   .get_phy = rk3568_emmc_get_phy,
+   .emmc_phy_init = rk3568_emmc_phy_init,
+};
+
 static const struct udevice_id sdhci_ids[] = {
{
.compatible = "arasan,sdhci-5.1",
.data = (ulong)_data,
   

[PATCH v1 0/2]

2021-06-07 Thread Yifeng Zhao
RK3399 and RK3568 are use different sdhci controllers.
The drivers need to be updated to support these two platforms
and it's easy to support new platforms.

Yifeng Zhao (2):
  mmc: rockchip_sdhci: add phy and clock config for rk3399
  mmc: rockchip_sdhci: Add support for RK3568

 drivers/mmc/rockchip_sdhci.c | 437 ---
 1 file changed, 406 insertions(+), 31 deletions(-)

-- 
2.17.1