[0/4] Add eMMC 5.1 support for Versal NET

This patch series, - Add support for eMMC5.1 on Versal NET platform by adding new compatible string and PHY support. - Add support for input and output tap delays for eMMC - Add support for enabling HS400 in host capabilities by checking quirk. - Add quirk to support HS400 for Versal NET
Ashok Reddy Soma (4): mmc: zynq_sdhci: Add support for eMMC5.1 for Versal NET platform mmc: sdhci: Check and call config_dll callback functions mmc: sdhci: Enable HS400 support if available in caps mmc: zynq_sdhci: Add support and quirk for HS400
drivers/mmc/sdhci.c | 20 +++ drivers/mmc/zynq_sdhci.c | 292 ++++++++++++++++++++++++++++++++++++++- include/sdhci.h | 5 + 3 files changed, 314 insertions(+), 3 deletions(-)

Add support for eMMC 5.1 for Versal NET platform - Add new compatible string(xlnx,versal-net-5.1-emmc). - Add CONFIG_ARCH_VERSAL_NET condition wherever required. - Add DLL and Delay Chain mode support - Add input and output tap delays for eMMC. - Add Strobe select tap for HS400 mode.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com --- drivers/mmc/zynq_sdhci.c | 287 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 284 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 7dcf6ad842..8415da3373 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * (C) Copyright 2013 - 2015 Xilinx, Inc. + * (C) Copyright 2013 - 2022, Xilinx, Inc. + * (C) Copyright 2022, Advanced Micro Devices, Inc. * * Xilinx Zynq SD Host Controller Interface */ @@ -16,6 +17,7 @@ #include <dm/device_compat.h> #include <linux/err.h> #include <linux/libfdt.h> +#include <linux/iopoll.h> #include <asm/types.h> #include <linux/math64.h> #include <asm/cache.h> @@ -48,6 +50,41 @@ #define SD0_OTAPDLYSEL_MASK GENMASK(5, 0) #define SD1_OTAPDLYSEL_MASK GENMASK(21, 16)
+#define MIN_PHY_CLK_HZ 50000000 + +#define PHY_CTRL_REG1 0x270 +#define PHY_CTRL_ITAPDLY_ENA_MASK BIT(0) +#define PHY_CTRL_ITAPDLY_SEL_MASK GENMASK(5, 1) +#define PHY_CTRL_ITAPDLY_SEL_SHIFT 1 +#define PHY_CTRL_ITAP_CHG_WIN_MASK BIT(6) +#define PHY_CTRL_OTAPDLY_ENA_MASK BIT(8) +#define PHY_CTRL_OTAPDLY_SEL_MASK GENMASK(15, 12) +#define PHY_CTRL_OTAPDLY_SEL_SHIFT 12 +#define PHY_CTRL_STRB_SEL_MASK GENMASK(23, 16) +#define PHY_CTRL_STRB_SEL_SHIFT 16 +#define PHY_CTRL_TEST_CTRL_MASK GENMASK(31, 24) + +#define PHY_CTRL_REG2 0x274 +#define PHY_CTRL_EN_DLL_MASK BIT(0) +#define PHY_CTRL_DLL_RDY_MASK BIT(1) +#define PHY_CTRL_FREQ_SEL_MASK GENMASK(6, 4) +#define PHY_CTRL_FREQ_SEL_SHIFT 4 +#define PHY_CTRL_SEL_DLY_TX_MASK BIT(16) +#define PHY_CTRL_SEL_DLY_RX_MASK BIT(17) +#define FREQSEL_200M_170M 0x0 +#define FREQSEL_170M_140M 0x1 +#define FREQSEL_140M_110M 0x2 +#define FREQSEL_110M_80M 0x3 +#define FREQSEL_80M_50M 0x4 +#define FREQSEL_275M_250M 0x5 +#define FREQSEL_250M_225M 0x6 +#define FREQSEL_225M_200M 0x7 +#define PHY_DLL_TIMEOUT_MS 100 + +#define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN 39 +#define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL 146 +#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0X77 + struct arasan_sdhci_clk_data { int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; @@ -64,6 +101,7 @@ struct arasan_sdhci_priv { u32 node_id; u8 bank; u8 no_1p8; + bool internal_phy_reg; struct reset_ctl_bulk resets; };
@@ -84,7 +122,7 @@ __weak int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) return 1; }
-#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) /* Default settings for ZynqMP Clock Phases */ static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0}; @@ -97,6 +135,12 @@ static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0};
+/* Default settings for versal-net eMMC Clock Phases */ +static const u32 versal_net_emmc_iclk_phases[] = {0, 0, 0, 0, 0, 0, 0, 0, 39, + 0, 0}; +static const u32 versal_net_emmc_oclk_phases[] = {0, 113, 0, 0, 0, 0, 0, 0, + 113, 79, 45}; + static const u8 mode2timing[] = { [MMC_LEGACY] = MMC_TIMING_LEGACY, [MMC_HS] = MMC_TIMING_MMC_HS, @@ -111,6 +155,121 @@ static const u8 mode2timing[] = { [MMC_HS_200] = MMC_TIMING_MMC_HS200, };
+#if defined(CONFIG_ARCH_VERSAL_NET) +/** + * arasan_phy_set_delaychain - Set eMMC delay chain based Input/Output clock + * + * @host: Pointer to the sdhci_host structure + * @enable: Enable or disable Delay chain based Tx and Rx clock + * Return: None + * + * Enable or disable eMMC delay chain based Input and Output clock in + * PHY_CTRL_REG2 + */ +static void arasan_phy_set_delaychain(struct sdhci_host *host, bool enable) +{ + u32 reg; + + reg = sdhci_readw(host, PHY_CTRL_REG2); + if (enable) + reg |= PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK; + else + reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK); + + sdhci_writew(host, reg, PHY_CTRL_REG2); +} + +/** + * arasan_phy_set_dll - Set eMMC DLL clock + * + * @host: Pointer to the sdhci_host structure + * @enable: Enable or disable DLL clock + * Return: 0 if success or timeout error + * + * Enable or disable eMMC DLL clock in PHY_CTRL_REG2. When DLL enable is + * set, wait till DLL is locked + */ +static int arasan_phy_set_dll(struct sdhci_host *host, bool enable) +{ + u32 reg; + + reg = sdhci_readw(host, PHY_CTRL_REG2); + if (enable) + reg |= PHY_CTRL_EN_DLL_MASK; + else + reg &= ~PHY_CTRL_EN_DLL_MASK; + + sdhci_writew(host, reg, PHY_CTRL_REG2); + + /* If DLL is disabled return success */ + if (!enable) + return 0; + + /* If DLL is enabled wait till DLL loop is locked, which is + * indicated by dll_rdy bit(bit1) in PHY_CTRL_REG2 + */ + return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg, + (reg & PHY_CTRL_DLL_RDY_MASK), + 1000 * PHY_DLL_TIMEOUT_MS); +} + +/** + * arasan_phy_dll_set_freq - Select frequency range of DLL for eMMC + * + * @host: Pointer to the sdhci_host structure + * @clock: clock value + * Return: None + * + * Set frequency range bits based on the selected clock for eMMC + */ +static void arasan_phy_dll_set_freq(struct sdhci_host *host, int clock) +{ + u32 reg, freq_sel, freq; + + freq = DIV_ROUND_CLOSEST(clock, 1000000); + if (freq <= 200 && freq > 170) + freq_sel = FREQSEL_200M_170M; + else if (freq <= 170 && freq > 140) + freq_sel = FREQSEL_170M_140M; + else if (freq <= 140 && freq > 110) + freq_sel = FREQSEL_140M_110M; + else if (freq <= 110 && freq > 80) + freq_sel = FREQSEL_110M_80M; + else + freq_sel = FREQSEL_80M_50M; + + reg = sdhci_readw(host, PHY_CTRL_REG2); + reg &= ~PHY_CTRL_FREQ_SEL_MASK; + reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT); + sdhci_writew(host, reg, PHY_CTRL_REG2); +} + +static int arasan_sdhci_config_dll(struct sdhci_host *host, unsigned int clock, bool enable) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev); + + if (enable) { + if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ && enable) + arasan_phy_set_dll(host, 1); + return 0; + } + + if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) { + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + arasan_phy_set_dll(host, 0); + arasan_phy_set_delaychain(host, 0); + arasan_phy_dll_set_freq(host, clock); + return 0; + } + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + arasan_phy_set_delaychain(host, 1); + + return 0; +} +#endif + static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay) { int ret; @@ -585,6 +744,101 @@ static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host, return 0; }
+/** + * sdhci_versal_net_emmc_sdcardclk_set_phase - Set eMMC Output Clock Tap Delays + * + * @host: Pointer to the sdhci_host structure. + * @degrees: The clock phase shift between 0 - 359. + * Return: 0 + * + * Set eMMC Output Clock Tap Delays for Output path + */ +static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct sdhci_host *host, int degrees) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + int timing = mode2timing[mmc->selected_mode]; + u8 tap_delay, tap_max = 0; + u32 regval; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_MMC_DDR52: + tap_max = 16; + break; + case MMC_TIMING_MMC_HS200: + case MMC_TIMING_MMC_HS400: + /* For 200MHz clock, 32 Taps are available */ + tap_max = 32; + break; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + /* Set the Clock Phase */ + if (tap_delay) { + regval = sdhci_readl(host, PHY_CTRL_REG1); + regval |= PHY_CTRL_OTAPDLY_ENA_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK; + regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT; + sdhci_writel(host, regval, PHY_CTRL_REG1); + } + + return 0; +} + +/** + * sdhci_versal_net_emmc_sampleclk_set_phase - Set eMMC Input Clock Tap Delays + * + * @host: Pointer to the sdhci_host structure. + * @degrees: The clock phase shift between 0 - 359. + * Return: 0 + * + * Set eMMC Input Clock Tap Delays for Input path. If HS400 is selected, + * set strobe90 and strobe180 in PHY_CTRL_REG1. + */ +static int sdhci_versal_net_emmc_sampleclk_set_phase(struct sdhci_host *host, int degrees) +{ + struct mmc *mmc = (struct mmc *)host->mmc; + int timing = mode2timing[mmc->selected_mode]; + u8 tap_delay, tap_max = 0; + u32 regval; + + switch (timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_MMC_DDR52: + tap_max = 32; + break; + case MMC_TIMING_MMC_HS400: + /* Strobe select tap point for strb90 and strb180 */ + regval = sdhci_readl(host, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_STRB_SEL_MASK; + regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT; + sdhci_writel(host, regval, PHY_CTRL_REG1); + break; + default: + break; + } + + tap_delay = (degrees * tap_max) / 360; + /* Set the Clock Phase */ + if (tap_delay) { + regval = sdhci_readl(host, PHY_CTRL_REG1); + regval |= PHY_CTRL_ITAP_CHG_WIN_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval |= PHY_CTRL_ITAPDLY_ENA_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK; + regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT; + sdhci_writel(host, regval, PHY_CTRL_REG1); + regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK; + sdhci_writel(host, regval, PHY_CTRL_REG1); + } + + return 0; +} + static int arasan_sdhci_set_tapdelay(struct sdhci_host *host) { struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); @@ -616,6 +870,19 @@ static int arasan_sdhci_set_tapdelay(struct sdhci_host *host) ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase); if (ret) return ret; + } else if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) && + device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) { + if (mmc->clock >= MIN_PHY_CLK_HZ) + if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN) + iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL; + + ret = sdhci_versal_net_emmc_sampleclk_set_phase(host, iclk_phase); + if (ret) + return ret; + + ret = sdhci_versal_net_emmc_sdcardclk_set_phase(host, oclk_phase); + if (ret) + return ret; }
return 0; @@ -678,6 +945,14 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev) } }
+ if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) && + device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) { + for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) { + clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i]; + clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i]; + } + } + arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY, "clk-phase-legacy"); arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS, @@ -706,6 +981,9 @@ static const struct sdhci_ops arasan_ops = { .platform_execute_tuning = &arasan_sdhci_execute_tuning, .set_delay = &arasan_sdhci_set_tapdelay, .set_control_reg = &sdhci_set_control_reg, +#if defined(CONFIG_ARCH_VERSAL_NET) + .config_dll = &arasan_sdhci_config_dll, +#endif }; #endif
@@ -822,6 +1100,8 @@ static int arasan_sdhci_probe(struct udevice *dev) } } #endif + if (device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) + priv->internal_phy_reg = true;
ret = clk_get_by_index(dev, 0, &clk); if (ret < 0) { @@ -905,7 +1185,7 @@ static int arasan_sdhci_of_to_plat(struct udevice *dev)
priv->host->name = dev->name;
-#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) priv->host->ops = &arasan_ops; arasan_dt_parse_clk_phases(dev); #endif @@ -933,6 +1213,7 @@ static int arasan_sdhci_bind(struct udevice *dev)
static const struct udevice_id arasan_sdhci_ids[] = { { .compatible = "arasan,sdhci-8.9a" }, + { .compatible = "xlnx,versal-net-5.1-emmc" }, { } };

On 1/10/23 20:31, Ashok Reddy Soma wrote:
Add support for eMMC 5.1 for Versal NET platform
- Add new compatible string(xlnx,versal-net-5.1-emmc).
- Add CONFIG_ARCH_VERSAL_NET condition wherever required.
- Add DLL and Delay Chain mode support
- Add input and output tap delays for eMMC.
- Add Strobe select tap for HS400 mode.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/zynq_sdhci.c | 287 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 284 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 7dcf6ad842..8415da3373 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /*
- (C) Copyright 2013 - 2015 Xilinx, Inc.
- (C) Copyright 2013 - 2022, Xilinx, Inc.
*/
- (C) Copyright 2022, Advanced Micro Devices, Inc.
- Xilinx Zynq SD Host Controller Interface
@@ -16,6 +17,7 @@ #include <dm/device_compat.h> #include <linux/err.h> #include <linux/libfdt.h> +#include <linux/iopoll.h> #include <asm/types.h> #include <linux/math64.h> #include <asm/cache.h> @@ -48,6 +50,41 @@ #define SD0_OTAPDLYSEL_MASK GENMASK(5, 0) #define SD1_OTAPDLYSEL_MASK GENMASK(21, 16)
+#define MIN_PHY_CLK_HZ 50000000
+#define PHY_CTRL_REG1 0x270 +#define PHY_CTRL_ITAPDLY_ENA_MASK BIT(0) +#define PHY_CTRL_ITAPDLY_SEL_MASK GENMASK(5, 1) +#define PHY_CTRL_ITAPDLY_SEL_SHIFT 1 +#define PHY_CTRL_ITAP_CHG_WIN_MASK BIT(6) +#define PHY_CTRL_OTAPDLY_ENA_MASK BIT(8) +#define PHY_CTRL_OTAPDLY_SEL_MASK GENMASK(15, 12) +#define PHY_CTRL_OTAPDLY_SEL_SHIFT 12 +#define PHY_CTRL_STRB_SEL_MASK GENMASK(23, 16) +#define PHY_CTRL_STRB_SEL_SHIFT 16 +#define PHY_CTRL_TEST_CTRL_MASK GENMASK(31, 24)
+#define PHY_CTRL_REG2 0x274 +#define PHY_CTRL_EN_DLL_MASK BIT(0) +#define PHY_CTRL_DLL_RDY_MASK BIT(1) +#define PHY_CTRL_FREQ_SEL_MASK GENMASK(6, 4) +#define PHY_CTRL_FREQ_SEL_SHIFT 4 +#define PHY_CTRL_SEL_DLY_TX_MASK BIT(16) +#define PHY_CTRL_SEL_DLY_RX_MASK BIT(17) +#define FREQSEL_200M_170M 0x0 +#define FREQSEL_170M_140M 0x1 +#define FREQSEL_140M_110M 0x2 +#define FREQSEL_110M_80M 0x3 +#define FREQSEL_80M_50M 0x4 +#define FREQSEL_275M_250M 0x5 +#define FREQSEL_250M_225M 0x6 +#define FREQSEL_225M_200M 0x7 +#define PHY_DLL_TIMEOUT_MS 100
+#define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN 39 +#define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL 146 +#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0X77
struct arasan_sdhci_clk_data { int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; int clk_phase_out[MMC_TIMING_MMC_HS400 + 1]; @@ -64,6 +101,7 @@ struct arasan_sdhci_priv { u32 node_id; u8 bank; u8 no_1p8;
- bool internal_phy_reg; struct reset_ctl_bulk resets;
};
@@ -84,7 +122,7 @@ __weak int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id) return 1; }
-#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) /* Default settings for ZynqMP Clock Phases */ static const u32 zynqmp_iclk_phases[] = {0, 63, 63, 0, 63, 0, 0, 183, 54, 0, 0}; @@ -97,6 +135,12 @@ static const u32 versal_iclk_phases[] = {0, 132, 132, 0, 132, static const u32 versal_oclk_phases[] = {0, 60, 48, 0, 48, 72, 90, 36, 60, 90, 0};
+/* Default settings for versal-net eMMC Clock Phases */ +static const u32 versal_net_emmc_iclk_phases[] = {0, 0, 0, 0, 0, 0, 0, 0, 39,
0, 0};
+static const u32 versal_net_emmc_oclk_phases[] = {0, 113, 0, 0, 0, 0, 0, 0,
113, 79, 45};
static const u8 mode2timing[] = { [MMC_LEGACY] = MMC_TIMING_LEGACY, [MMC_HS] = MMC_TIMING_MMC_HS, @@ -111,6 +155,121 @@ static const u8 mode2timing[] = { [MMC_HS_200] = MMC_TIMING_MMC_HS200, };
+#if defined(CONFIG_ARCH_VERSAL_NET) +/**
- arasan_phy_set_delaychain - Set eMMC delay chain based Input/Output clock
- @host: Pointer to the sdhci_host structure
- @enable: Enable or disable Delay chain based Tx and Rx clock
- Return: None
- Enable or disable eMMC delay chain based Input and Output clock in
- PHY_CTRL_REG2
- */
+static void arasan_phy_set_delaychain(struct sdhci_host *host, bool enable) +{
- u32 reg;
- reg = sdhci_readw(host, PHY_CTRL_REG2);
- if (enable)
reg |= PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK;
- else
reg &= ~(PHY_CTRL_SEL_DLY_TX_MASK | PHY_CTRL_SEL_DLY_RX_MASK);
- sdhci_writew(host, reg, PHY_CTRL_REG2);
+}
+/**
- arasan_phy_set_dll - Set eMMC DLL clock
- @host: Pointer to the sdhci_host structure
- @enable: Enable or disable DLL clock
- Return: 0 if success or timeout error
- Enable or disable eMMC DLL clock in PHY_CTRL_REG2. When DLL enable is
- set, wait till DLL is locked
- */
+static int arasan_phy_set_dll(struct sdhci_host *host, bool enable) +{
- u32 reg;
- reg = sdhci_readw(host, PHY_CTRL_REG2);
- if (enable)
reg |= PHY_CTRL_EN_DLL_MASK;
- else
reg &= ~PHY_CTRL_EN_DLL_MASK;
- sdhci_writew(host, reg, PHY_CTRL_REG2);
- /* If DLL is disabled return success */
- if (!enable)
return 0;
- /* If DLL is enabled wait till DLL loop is locked, which is
* indicated by dll_rdy bit(bit1) in PHY_CTRL_REG2
*/
- return readl_relaxed_poll_timeout(host->ioaddr + PHY_CTRL_REG2, reg,
(reg & PHY_CTRL_DLL_RDY_MASK),
1000 * PHY_DLL_TIMEOUT_MS);
+}
+/**
- arasan_phy_dll_set_freq - Select frequency range of DLL for eMMC
- @host: Pointer to the sdhci_host structure
- @clock: clock value
- Return: None
- Set frequency range bits based on the selected clock for eMMC
- */
+static void arasan_phy_dll_set_freq(struct sdhci_host *host, int clock) +{
- u32 reg, freq_sel, freq;
- freq = DIV_ROUND_CLOSEST(clock, 1000000);
- if (freq <= 200 && freq > 170)
freq_sel = FREQSEL_200M_170M;
- else if (freq <= 170 && freq > 140)
freq_sel = FREQSEL_170M_140M;
- else if (freq <= 140 && freq > 110)
freq_sel = FREQSEL_140M_110M;
- else if (freq <= 110 && freq > 80)
freq_sel = FREQSEL_110M_80M;
- else
freq_sel = FREQSEL_80M_50M;
- reg = sdhci_readw(host, PHY_CTRL_REG2);
- reg &= ~PHY_CTRL_FREQ_SEL_MASK;
- reg |= (freq_sel << PHY_CTRL_FREQ_SEL_SHIFT);
- sdhci_writew(host, reg, PHY_CTRL_REG2);
+}
+static int arasan_sdhci_config_dll(struct sdhci_host *host, unsigned int clock, bool enable) +{
- struct mmc *mmc = (struct mmc *)host->mmc;
- struct arasan_sdhci_priv *priv = dev_get_priv(mmc->dev);
- if (enable) {
if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ && enable)
arasan_phy_set_dll(host, 1);
return 0;
- }
- if (priv->internal_phy_reg && clock >= MIN_PHY_CLK_HZ) {
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
arasan_phy_set_dll(host, 0);
arasan_phy_set_delaychain(host, 0);
arasan_phy_dll_set_freq(host, clock);
return 0;
- }
- sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
- arasan_phy_set_delaychain(host, 1);
- return 0;
+} +#endif
static inline int arasan_zynqmp_set_in_tapdelay(u32 node_id, u32 itap_delay) { int ret; @@ -585,6 +744,101 @@ static int sdhci_versal_sampleclk_set_phase(struct sdhci_host *host, return 0; }
+/**
- sdhci_versal_net_emmc_sdcardclk_set_phase - Set eMMC Output Clock Tap Delays
- @host: Pointer to the sdhci_host structure.
- @degrees: The clock phase shift between 0 - 359.
- Return: 0
- Set eMMC Output Clock Tap Delays for Output path
- */
+static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct sdhci_host *host, int degrees) +{
- struct mmc *mmc = (struct mmc *)host->mmc;
- int timing = mode2timing[mmc->selected_mode];
- u8 tap_delay, tap_max = 0;
- u32 regval;
- switch (timing) {
- case MMC_TIMING_MMC_HS:
- case MMC_TIMING_MMC_DDR52:
tap_max = 16;
break;
- case MMC_TIMING_MMC_HS200:
- case MMC_TIMING_MMC_HS400:
/* For 200MHz clock, 32 Taps are available */
tap_max = 32;
break;
- default:
break;
- }
- tap_delay = (degrees * tap_max) / 360;
- /* Set the Clock Phase */
- if (tap_delay) {
regval = sdhci_readl(host, PHY_CTRL_REG1);
regval |= PHY_CTRL_OTAPDLY_ENA_MASK;
sdhci_writel(host, regval, PHY_CTRL_REG1);
regval &= ~PHY_CTRL_OTAPDLY_SEL_MASK;
regval |= tap_delay << PHY_CTRL_OTAPDLY_SEL_SHIFT;
sdhci_writel(host, regval, PHY_CTRL_REG1);
- }
- return 0;
+}
+/**
- sdhci_versal_net_emmc_sampleclk_set_phase - Set eMMC Input Clock Tap Delays
- @host: Pointer to the sdhci_host structure.
- @degrees: The clock phase shift between 0 - 359.
- Return: 0
- Set eMMC Input Clock Tap Delays for Input path. If HS400 is selected,
- set strobe90 and strobe180 in PHY_CTRL_REG1.
- */
+static int sdhci_versal_net_emmc_sampleclk_set_phase(struct sdhci_host *host, int degrees) +{
- struct mmc *mmc = (struct mmc *)host->mmc;
- int timing = mode2timing[mmc->selected_mode];
- u8 tap_delay, tap_max = 0;
- u32 regval;
- switch (timing) {
- case MMC_TIMING_MMC_HS:
- case MMC_TIMING_MMC_DDR52:
tap_max = 32;
break;
- case MMC_TIMING_MMC_HS400:
/* Strobe select tap point for strb90 and strb180 */
regval = sdhci_readl(host, PHY_CTRL_REG1);
regval &= ~PHY_CTRL_STRB_SEL_MASK;
regval |= VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL << PHY_CTRL_STRB_SEL_SHIFT;
sdhci_writel(host, regval, PHY_CTRL_REG1);
break;
- default:
break;
- }
- tap_delay = (degrees * tap_max) / 360;
- /* Set the Clock Phase */
- if (tap_delay) {
regval = sdhci_readl(host, PHY_CTRL_REG1);
regval |= PHY_CTRL_ITAP_CHG_WIN_MASK;
sdhci_writel(host, regval, PHY_CTRL_REG1);
regval |= PHY_CTRL_ITAPDLY_ENA_MASK;
sdhci_writel(host, regval, PHY_CTRL_REG1);
regval &= ~PHY_CTRL_ITAPDLY_SEL_MASK;
regval |= tap_delay << PHY_CTRL_ITAPDLY_SEL_SHIFT;
sdhci_writel(host, regval, PHY_CTRL_REG1);
regval &= ~PHY_CTRL_ITAP_CHG_WIN_MASK;
sdhci_writel(host, regval, PHY_CTRL_REG1);
- }
- return 0;
+}
static int arasan_sdhci_set_tapdelay(struct sdhci_host *host) { struct arasan_sdhci_priv *priv = dev_get_priv(host->mmc->dev); @@ -616,6 +870,19 @@ static int arasan_sdhci_set_tapdelay(struct sdhci_host *host) ret = sdhci_versal_sdcardclk_set_phase(host, oclk_phase); if (ret) return ret;
} else if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) &&
device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) {
if (mmc->clock >= MIN_PHY_CLK_HZ)
if (iclk_phase == VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN)
iclk_phase = VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL;
ret = sdhci_versal_net_emmc_sampleclk_set_phase(host, iclk_phase);
if (ret)
return ret;
ret = sdhci_versal_net_emmc_sdcardclk_set_phase(host, oclk_phase);
if (ret)
return ret;
}
return 0;
@@ -678,6 +945,14 @@ static void arasan_dt_parse_clk_phases(struct udevice *dev) } }
- if (IS_ENABLED(CONFIG_ARCH_VERSAL_NET) &&
device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) {
for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
clk_data->clk_phase_in[i] = versal_net_emmc_iclk_phases[i];
clk_data->clk_phase_out[i] = versal_net_emmc_oclk_phases[i];
}
- }
- arasan_dt_read_clk_phase(dev, MMC_TIMING_LEGACY, "clk-phase-legacy"); arasan_dt_read_clk_phase(dev, MMC_TIMING_MMC_HS,
@@ -706,6 +981,9 @@ static const struct sdhci_ops arasan_ops = { .platform_execute_tuning = &arasan_sdhci_execute_tuning, .set_delay = &arasan_sdhci_set_tapdelay, .set_control_reg = &sdhci_set_control_reg, +#if defined(CONFIG_ARCH_VERSAL_NET)
- .config_dll = &arasan_sdhci_config_dll,
+#endif }; #endif
@@ -822,6 +1100,8 @@ static int arasan_sdhci_probe(struct udevice *dev) } } #endif
if (device_is_compatible(dev, "xlnx,versal-net-5.1-emmc"))
priv->internal_phy_reg = true;
ret = clk_get_by_index(dev, 0, &clk); if (ret < 0) {
@@ -905,7 +1185,7 @@ static int arasan_sdhci_of_to_plat(struct udevice *dev)
priv->host->name = dev->name;
-#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) +#if defined(CONFIG_ARCH_ZYNQMP) || defined(CONFIG_ARCH_VERSAL) || defined(CONFIG_ARCH_VERSAL_NET) priv->host->ops = &arasan_ops; arasan_dt_parse_clk_phases(dev); #endif @@ -933,6 +1213,7 @@ static int arasan_sdhci_bind(struct udevice *dev)
static const struct udevice_id arasan_sdhci_ids[] = { { .compatible = "arasan,sdhci-8.9a" },
- { .compatible = "xlnx,versal-net-5.1-emmc" }, { }
};

Check if the low level driver supports config_dll callback function and call it if it does. Call with dll disable before calling set_clock and with dll enable after it.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com --- drivers/mmc/sdhci.c | 16 ++++++++++++++++ include/sdhci.h | 2 ++ 2 files changed, 18 insertions(+)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index a80ad8329a..181ab9b7cb 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -396,6 +396,14 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock) } }
+ if (host->ops && host->ops->config_dll) { + ret = host->ops->config_dll(host, clock, false); + if (ret) { + printf("%s: Error while configuring dll\n", __func__); + return ret; + } + } + if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { /* * Check if the Host Controller supports Programmable Clock @@ -439,6 +447,14 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock) if (host->ops && host->ops->set_clock) host->ops->set_clock(host, div);
+ if (host->ops && host->ops->config_dll) { + ret = host->ops->config_dll(host, clock, true); + if (ret) { + printf("%s: Error while configuring dll\n", __func__); + return ret; + } + } + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT; diff --git a/include/sdhci.h b/include/sdhci.h index 24b4599b85..64a3d309da 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -272,6 +272,8 @@ struct sdhci_ops { void (*set_clock)(struct sdhci_host *host, u32 div); int (*platform_execute_tuning)(struct mmc *host, u8 opcode); int (*set_delay)(struct sdhci_host *host); + /* Callback function to set DLL clock configuration */ + int (*config_dll)(struct sdhci_host *host, u32 clock, bool enable); int (*deferred_probe)(struct sdhci_host *host);
/**

On 1/10/23 20:31, Ashok Reddy Soma wrote:
Check if the low level driver supports config_dll callback function and call it if it does. Call with dll disable before calling set_clock and with dll enable after it.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/sdhci.c | 16 ++++++++++++++++ include/sdhci.h | 2 ++ 2 files changed, 18 insertions(+)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index a80ad8329a..181ab9b7cb 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -396,6 +396,14 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock) } }
- if (host->ops && host->ops->config_dll) {
ret = host->ops->config_dll(host, clock, false);
if (ret) {
printf("%s: Error while configuring dll\n", __func__);
return ret;
}
- }
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { /*
- Check if the Host Controller supports Programmable Clock
@@ -439,6 +447,14 @@ int sdhci_set_clock(struct mmc *mmc, unsigned int clock) if (host->ops && host->ops->set_clock) host->ops->set_clock(host, div);
- if (host->ops && host->ops->config_dll) {
ret = host->ops->config_dll(host, clock, true);
if (ret) {
printf("%s: Error while configuring dll\n", __func__);
return ret;
}
- }
- clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) << SDHCI_DIVIDER_HI_SHIFT;
diff --git a/include/sdhci.h b/include/sdhci.h index 24b4599b85..64a3d309da 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -272,6 +272,8 @@ struct sdhci_ops { void (*set_clock)(struct sdhci_host *host, u32 div); int (*platform_execute_tuning)(struct mmc *host, u8 opcode); int (*set_delay)(struct sdhci_host *host);
/* Callback function to set DLL clock configuration */
int (*config_dll)(struct sdhci_host *host, u32 clock, bool enable);> int (*deferred_probe)(struct sdhci_host *host);
/**

HS400 is indicated in bit63 of capability register in few IP's. Add a quirk to check this and add HS400 to host capabilities.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com --- drivers/mmc/sdhci.c | 4 ++++ include/sdhci.h | 3 +++ 2 files changed, 7 insertions(+)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 181ab9b7cb..c6b250b9a1 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -995,6 +995,10 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, cfg->host_caps |= MMC_CAP(UHS_SDR50); }
+ if ((host->quirks & SDHCI_QUIRK_CAPS_BIT63_FOR_HS400) && + (caps_1 & SDHCI_SUPPORT_HS400)) + cfg->host_caps |= MMC_CAP(MMC_HS_400); + if (caps_1 & SDHCI_SUPPORT_DDR50) cfg->host_caps |= MMC_CAP(UHS_DDR50);
diff --git a/include/sdhci.h b/include/sdhci.h index 64a3d309da..70fefca2a9 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -189,6 +189,7 @@ #define SDHCI_SUPPORT_SDR50 0x00000001 #define SDHCI_SUPPORT_SDR104 0x00000002 #define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_SUPPORT_HS400 BIT(31) #define SDHCI_USE_SDR50_TUNING 0x00002000
#define SDHCI_CLOCK_MUL_MASK 0x00FF0000 @@ -248,6 +249,8 @@ #define SDHCI_QUIRK_USE_WIDE8 (1 << 8) #define SDHCI_QUIRK_NO_1_8_V (1 << 9) #define SDHCI_QUIRK_SUPPORT_SINGLE (1 << 10) +/* Capability register bit-63 indicates HS400 support */ +#define SDHCI_QUIRK_CAPS_BIT63_FOR_HS400 BIT(11)
/* to make gcc happy */ struct sdhci_host;

On 1/10/23 20:31, Ashok Reddy Soma wrote:
HS400 is indicated in bit63 of capability register in few IP's. Add a quirk to check this and add HS400 to host capabilities.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/sdhci.c | 4 ++++ include/sdhci.h | 3 +++ 2 files changed, 7 insertions(+)
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 181ab9b7cb..c6b250b9a1 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -995,6 +995,10 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, cfg->host_caps |= MMC_CAP(UHS_SDR50); }
- if ((host->quirks & SDHCI_QUIRK_CAPS_BIT63_FOR_HS400) &&
(caps_1 & SDHCI_SUPPORT_HS400))
cfg->host_caps |= MMC_CAP(MMC_HS_400);
- if (caps_1 & SDHCI_SUPPORT_DDR50) cfg->host_caps |= MMC_CAP(UHS_DDR50);
diff --git a/include/sdhci.h b/include/sdhci.h index 64a3d309da..70fefca2a9 100644 --- a/include/sdhci.h +++ b/include/sdhci.h @@ -189,6 +189,7 @@ #define SDHCI_SUPPORT_SDR50 0x00000001 #define SDHCI_SUPPORT_SDR104 0x00000002 #define SDHCI_SUPPORT_DDR50 0x00000004 +#define SDHCI_SUPPORT_HS400 BIT(31) #define SDHCI_USE_SDR50_TUNING 0x00002000
#define SDHCI_CLOCK_MUL_MASK 0x00FF0000 @@ -248,6 +249,8 @@ #define SDHCI_QUIRK_USE_WIDE8 (1 << 8) #define SDHCI_QUIRK_NO_1_8_V (1 << 9) #define SDHCI_QUIRK_SUPPORT_SINGLE (1 << 10) +/* Capability register bit-63 indicates HS400 support */ +#define SDHCI_QUIRK_CAPS_BIT63_FOR_HS400 BIT(11)
/* to make gcc happy */ struct sdhci_host;

Add support for HS400 in mode2timing array. Add a quirk for Versal NET platform to indicate that HS400 is supported through bit63 of capability register.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com --- drivers/mmc/zynq_sdhci.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 8415da3373..72de6c6227 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -153,6 +153,7 @@ static const u8 mode2timing[] = { [UHS_DDR50] = MMC_TIMING_UHS_DDR50, [UHS_SDR104] = MMC_TIMING_UHS_SDR104, [MMC_HS_200] = MMC_TIMING_MMC_HS200, + [MMC_HS_400] = MMC_TIMING_MMC_HS400, };
#if defined(CONFIG_ARCH_VERSAL_NET) @@ -1133,6 +1134,10 @@ static int arasan_sdhci_probe(struct udevice *dev) if (priv->no_1p8) host->quirks |= SDHCI_QUIRK_NO_1_8_V;
+ if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) && + device_is_compatible(dev, "xlnx,versal-net-5.1-emmc")) + host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400; + plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
ret = mmc_of_parse(dev, &plat->cfg);

On 1/10/23 20:31, Ashok Reddy Soma wrote:
Add support for HS400 in mode2timing array. Add a quirk for Versal NET platform to indicate that HS400 is supported through bit63 of capability register.
Signed-off-by: Ashok Reddy Soma ashok.reddy.soma@amd.com
Reviewd-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
drivers/mmc/zynq_sdhci.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 8415da3373..72de6c6227 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -153,6 +153,7 @@ static const u8 mode2timing[] = { [UHS_DDR50] = MMC_TIMING_UHS_DDR50, [UHS_SDR104] = MMC_TIMING_UHS_SDR104, [MMC_HS_200] = MMC_TIMING_MMC_HS200,
- [MMC_HS_400] = MMC_TIMING_MMC_HS400,
};
#if defined(CONFIG_ARCH_VERSAL_NET) @@ -1133,6 +1134,10 @@ static int arasan_sdhci_probe(struct udevice *dev) if (priv->no_1p8) host->quirks |= SDHCI_QUIRK_NO_1_8_V;
if (CONFIG_IS_ENABLED(ARCH_VERSAL_NET) &&
device_is_compatible(dev, "xlnx,versal-net-5.1-emmc"))
host->quirks |= SDHCI_QUIRK_CAPS_BIT63_FOR_HS400;
plat->cfg.f_max = CONFIG_ZYNQ_SDHCI_MAX_FREQ;
ret = mmc_of_parse(dev, &plat->cfg);

Hi Jaehoon,
On 1/10/23 12:31, Ashok Reddy Soma wrote:
This patch series,
- Add support for eMMC5.1 on Versal NET platform by adding new compatible string and PHY support.
- Add support for input and output tap delays for eMMC
- Add support for enabling HS400 in host capabilities by checking quirk.
- Add quirk to support HS400 for Versal NET
Ashok Reddy Soma (4): mmc: zynq_sdhci: Add support for eMMC5.1 for Versal NET platform mmc: sdhci: Check and call config_dll callback functions mmc: sdhci: Enable HS400 support if available in caps mmc: zynq_sdhci: Add support and quirk for HS400
drivers/mmc/sdhci.c | 20 +++ drivers/mmc/zynq_sdhci.c | 292 ++++++++++++++++++++++++++++++++++++++- include/sdhci.h | 5 + 3 files changed, 314 insertions(+), 3 deletions(-)
Can you please review this series?
Thanks, Michal

Hi,
-----Original Message----- From: Michal Simek michal.simek@amd.com Sent: Tuesday, January 24, 2023 10:02 PM To: Ashok Reddy Soma ashok.reddy.soma@amd.com; u-boot@lists.denx.de; Jaehoon Chung jh80.chung@samsung.com Cc: peng.fan@nxp.com; kever.yang@rock-chips.com; hayashi.kunihiko@socionext.com; alpernebiyasak@gmail.com; xypron.glpk@gmx.de; git@amd.com Subject: Re: [0/4] Add eMMC 5.1 support for Versal NET
Hi Jaehoon,
On 1/10/23 12:31, Ashok Reddy Soma wrote:
This patch series,
- Add support for eMMC5.1 on Versal NET platform by adding new compatible string and PHY support.
- Add support for input and output tap delays for eMMC
- Add support for enabling HS400 in host capabilities by checking quirk.
- Add quirk to support HS400 for Versal NET
Ashok Reddy Soma (4): mmc: zynq_sdhci: Add support for eMMC5.1 for Versal NET platform mmc: sdhci: Check and call config_dll callback functions mmc: sdhci: Enable HS400 support if available in caps mmc: zynq_sdhci: Add support and quirk for HS400
drivers/mmc/sdhci.c | 20 +++ drivers/mmc/zynq_sdhci.c | 292 ++++++++++++++++++++++++++++++++++++++- include/sdhci.h | 5 + 3 files changed, 314 insertions(+), 3 deletions(-)
Can you please review this series?
Sorry for too late. I will review them.
Best Regards, Jaehoon Chung
Thanks, Michal

Hi Jaehoon,
On 1/26/23 03:29, Jaehoon Chung wrote:
Hi,
-----Original Message----- From: Michal Simek michal.simek@amd.com Sent: Tuesday, January 24, 2023 10:02 PM To: Ashok Reddy Soma ashok.reddy.soma@amd.com; u-boot@lists.denx.de; Jaehoon Chung jh80.chung@samsung.com Cc: peng.fan@nxp.com; kever.yang@rock-chips.com; hayashi.kunihiko@socionext.com; alpernebiyasak@gmail.com; xypron.glpk@gmx.de; git@amd.com Subject: Re: [0/4] Add eMMC 5.1 support for Versal NET
Hi Jaehoon,
On 1/10/23 12:31, Ashok Reddy Soma wrote:
This patch series,
- Add support for eMMC5.1 on Versal NET platform by adding new compatible string and PHY support.
- Add support for input and output tap delays for eMMC
- Add support for enabling HS400 in host capabilities by checking quirk.
- Add quirk to support HS400 for Versal NET
Ashok Reddy Soma (4): mmc: zynq_sdhci: Add support for eMMC5.1 for Versal NET platform mmc: sdhci: Check and call config_dll callback functions mmc: sdhci: Enable HS400 support if available in caps mmc: zynq_sdhci: Add support and quirk for HS400
drivers/mmc/sdhci.c | 20 +++ drivers/mmc/zynq_sdhci.c | 292 ++++++++++++++++++++++++++++++++++++++- include/sdhci.h | 5 + 3 files changed, 314 insertions(+), 3 deletions(-)
Can you please review this series?
Sorry for too late. I will review them.
I see you just reviewed it. Are you going to pick it up to your tree or do you want me to queue it via my tree? Both ways work for me.
Thanks, Michal

Hi,
-----Original Message----- From: Michal Simek michal.simek@amd.com Sent: Tuesday, January 31, 2023 10:08 PM To: Jaehoon Chung jh80.chung@samsung.com; 'Ashok Reddy Soma' ashok.reddy.soma@amd.com; u- boot@lists.denx.de Cc: peng.fan@nxp.com; kever.yang@rock-chips.com; hayashi.kunihiko@socionext.com; alpernebiyasak@gmail.com; xypron.glpk@gmx.de; git@amd.com Subject: Re: [0/4] Add eMMC 5.1 support for Versal NET
Hi Jaehoon,
On 1/26/23 03:29, Jaehoon Chung wrote:
Hi,
-----Original Message----- From: Michal Simek michal.simek@amd.com Sent: Tuesday, January 24, 2023 10:02 PM To: Ashok Reddy Soma ashok.reddy.soma@amd.com; u-boot@lists.denx.de; Jaehoon Chung jh80.chung@samsung.com Cc: peng.fan@nxp.com; kever.yang@rock-chips.com; hayashi.kunihiko@socionext.com; alpernebiyasak@gmail.com; xypron.glpk@gmx.de; git@amd.com Subject: Re: [0/4] Add eMMC 5.1 support for Versal NET
Hi Jaehoon,
On 1/10/23 12:31, Ashok Reddy Soma wrote:
This patch series,
- Add support for eMMC5.1 on Versal NET platform by adding new compatible string and PHY support.
- Add support for input and output tap delays for eMMC
- Add support for enabling HS400 in host capabilities by checking quirk.
- Add quirk to support HS400 for Versal NET
Ashok Reddy Soma (4): mmc: zynq_sdhci: Add support for eMMC5.1 for Versal NET platform mmc: sdhci: Check and call config_dll callback functions mmc: sdhci: Enable HS400 support if available in caps mmc: zynq_sdhci: Add support and quirk for HS400
drivers/mmc/sdhci.c | 20 +++ drivers/mmc/zynq_sdhci.c | 292 ++++++++++++++++++++++++++++++++++++++- include/sdhci.h | 5 + 3 files changed, 314 insertions(+), 3 deletions(-)
Can you please review this series?
Sorry for too late. I will review them.
I see you just reviewed it. Are you going to pick it up to your tree or do you want me to queue it via my tree? Both ways work for me.
I have picked this and I will do PR today.
Best Regards, Jaehoon Chung
Thanks, Michal
participants (4)
-
Ashok Reddy Soma
-
Jaehoon Chung
-
Jaehoon Chung
-
Michal Simek