Hi there, May I know that these patches has any issue?
> -----Original Message----- > From: KuanLim.Lee <kuanlim....@starfivetech.com> > Sent: Tuesday, October 3, 2023 3:23 PM > To: u-boot@lists.denx.de > Cc: Yuklin Soo <yuklin....@starfivetech.com>; WeiLiang Lim > <weiliang....@starfivetech.com>; Kuan Lim Lee > <kuanlim....@linux.starfivetech.com>; KuanLim.Lee > <kuanlim....@starfivetech.com> > Subject: [PATCH] mmc: sdhci-cadence: Add support for Cadence sdmmc v6 > > From: Kuan Lim Lee <kuanlim....@linux.starfivetech.com> > > Cadence SDMMC v6 controller has a lot of changes on initialize compared to v4 > controller. PHY is needed by v6 controller. > > Signed-off-by: Kuan Lim Lee <kuanlim....@starfivetech.com> > Reviewed-by: Alex Soo <yuklin....@starfivetech.com> > Reviewed-by: Wei Liang Lim <weiliang....@starfivetech.com> > --- > drivers/mmc/Kconfig | 13 ++ > drivers/mmc/Makefile | 1 + > drivers/mmc/sdhci-cadence.c | 63 ++----- > drivers/mmc/sdhci-cadence.h | 68 +++++++ > drivers/mmc/sdhci-cadence6-phy.c | 302 > +++++++++++++++++++++++++++++++ > 5 files changed, 396 insertions(+), 51 deletions(-) create mode 100644 > drivers/mmc/sdhci-cadence.h create mode 100644 drivers/mmc/sdhci- > cadence6-phy.c > > diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index > de01b9687b..cec881d862 100644 > --- a/drivers/mmc/Kconfig > +++ b/drivers/mmc/Kconfig > @@ -573,6 +573,19 @@ config MMC_SDHCI_CADENCE > > If unsure, say N. > > +config MMC_SDHCI_CADENCE_V6 > + bool "SDHCI support for the Cadence SD/SDIO/eMMC controller & > driver version 6" > + depends on BLK && DM_MMC > + depends on MMC_SDHCI > + depends on OF_CONTROL > + select MMC_SDHCI_CADENCE > + help > + This selects the Cadence SD/SDIO/eMMC driver version 6. > + > + If you have a controller with this interface, say Y here. > + > + If unsure, say N. > + > config MMC_SDHCI_AM654 > bool "SDHCI Controller on TI's Am654 devices" > depends on ARCH_K3 > diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index > 2c65c4765a..cdcce55b8b 100644 > --- a/drivers/mmc/Makefile > +++ b/drivers/mmc/Makefile > @@ -61,6 +61,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += > atmel_sdhci.o > obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o > obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o > obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o > +obj-$(CONFIG_MMC_SDHCI_CADENCE_V6) += sdhci-cadence6-phy.o > obj-$(CONFIG_MMC_SDHCI_AM654) += am654_sdhci.o > obj-$(CONFIG_MMC_SDHCI_IPROC) += iproc_sdhci.o > obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o > diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c index > 327a05ad11..d7a270e74c 100644 > --- a/drivers/mmc/sdhci-cadence.c > +++ b/drivers/mmc/sdhci-cadence.c > @@ -17,56 +17,7 @@ > #include <linux/libfdt.h> > #include <mmc.h> > #include <sdhci.h> > - > -/* HRS - Host Register Set (specific to Cadence) */ > -#define SDHCI_CDNS_HRS04 0x10 /* PHY access port */ > -#define SDHCI_CDNS_HRS04_ACK BIT(26) > -#define SDHCI_CDNS_HRS04_RD BIT(25) > -#define SDHCI_CDNS_HRS04_WR BIT(24) > -#define SDHCI_CDNS_HRS04_RDATA GENMASK(23, 16) > -#define SDHCI_CDNS_HRS04_WDATA GENMASK(15, 8) > -#define SDHCI_CDNS_HRS04_ADDR GENMASK(5, 0) > - > -#define SDHCI_CDNS_HRS06 0x18 /* eMMC control */ > -#define SDHCI_CDNS_HRS06_TUNE_UP BIT(15) > -#define SDHCI_CDNS_HRS06_TUNE GENMASK(13, 8) > -#define SDHCI_CDNS_HRS06_MODE GENMASK(2, 0) > -#define SDHCI_CDNS_HRS06_MODE_SD 0x0 > -#define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2 > -#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3 > -#define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4 > -#define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5 > -#define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6 > - > -/* SRS - Slot Register Set (SDHCI-compatible) */ > -#define SDHCI_CDNS_SRS_BASE 0x200 > - > -/* PHY */ > -#define SDHCI_CDNS_PHY_DLY_SD_HS 0x00 > -#define SDHCI_CDNS_PHY_DLY_SD_DEFAULT 0x01 > -#define SDHCI_CDNS_PHY_DLY_UHS_SDR12 0x02 > -#define SDHCI_CDNS_PHY_DLY_UHS_SDR25 0x03 > -#define SDHCI_CDNS_PHY_DLY_UHS_SDR50 0x04 > -#define SDHCI_CDNS_PHY_DLY_UHS_DDR50 0x05 > -#define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06 > -#define SDHCI_CDNS_PHY_DLY_EMMC_SDR 0x07 > -#define SDHCI_CDNS_PHY_DLY_EMMC_DDR 0x08 > -#define SDHCI_CDNS_PHY_DLY_SDCLK 0x0b > -#define SDHCI_CDNS_PHY_DLY_HSMMC 0x0c > -#define SDHCI_CDNS_PHY_DLY_STROBE 0x0d > - > -/* > - * The tuned val register is 6 bit-wide, but not the whole of the range is > - * available. The range 0-42 seems to be available (then 43 wraps around to > 0) > - * but I am not quite sure if it is official. Use only 0 to 39 for safety. > - */ > -#define SDHCI_CDNS_MAX_TUNING_LOOP 40 > - > -struct sdhci_cdns_plat { > - struct mmc_config cfg; > - struct mmc mmc; > - void __iomem *hrs_addr; > -}; > +#include "sdhci-cadence.h" > > struct sdhci_cdns_phy_cfg { > const char *property; > @@ -112,8 +63,11 @@ static int sdhci_cdns_write_phy_reg(struct > sdhci_cdns_plat *plat, } > > static int sdhci_cdns_phy_init(struct sdhci_cdns_plat *plat, > - const void *fdt, int nodeoffset) > + const void *fdt, int nodeoffset) > { > + if (IS_ENABLED(CONFIG_MMC_SDHCI_CADENCE_V6)) > + return sdhci_cdns6_phy_init(plat, > SDHCI_CDNS_HRS06_MODE_SD); > + > const fdt32_t *prop; > int ret, i; > > @@ -163,6 +117,9 @@ static void sdhci_cdns_set_control_reg(struct > sdhci_host *host) > tmp &= ~SDHCI_CDNS_HRS06_MODE; > tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_MODE, mode); > writel(tmp, plat->hrs_addr + SDHCI_CDNS_HRS06); > + > + if (IS_ENABLED(CONFIG_MMC_SDHCI_CADENCE_V6)) > + sdhci_cdns6_phy_init(plat, mode); > } > > static const struct sdhci_ops sdhci_cdns_ops = { @@ -172,6 +129,9 @@ static > const struct sdhci_ops sdhci_cdns_ops = { static int > sdhci_cdns_set_tune_val(struct sdhci_cdns_plat *plat, > unsigned int val) > { > + if (IS_ENABLED(CONFIG_MMC_SDHCI_CADENCE_V6)) > + return sdhci_cdns6_set_tune_val(plat, val); > + > void __iomem *reg = plat->hrs_addr + SDHCI_CDNS_HRS06; > u32 tmp; > int i, ret; > @@ -301,6 +261,7 @@ static int sdhci_cdns_probe(struct udevice *dev) static > const struct udevice_id sdhci_cdns_match[] = { > { .compatible = "socionext,uniphier-sd4hc" }, > { .compatible = "cdns,sd4hc" }, > + { .compatible = "cdns,sd6hc" }, > { /* sentinel */ } > }; > > diff --git a/drivers/mmc/sdhci-cadence.h b/drivers/mmc/sdhci-cadence.h new > file mode 100644 index 0000000000..2c42cff2f3 > --- /dev/null > +++ b/drivers/mmc/sdhci-cadence.h > @@ -0,0 +1,68 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright (C) 2022 Starfive. > + * Author: Kuan Lim Lee <kuanlim....@starfivetech.com> > + */ > + > +#ifndef SDHCI_CADENCE_H_ > +#define SDHCI_CADENCE_H_ > + > +/* HRS - Host Register Set (specific to Cadence) */ > +/* PHY access port */ > +#define SDHCI_CDNS_HRS04 0x10 > +/* Cadence V4 HRS04 Description*/ > +#define SDHCI_CDNS_HRS04_ACK BIT(26) > +#define SDHCI_CDNS_HRS04_RD BIT(25) > +#define SDHCI_CDNS_HRS04_WR BIT(24) > +#define SDHCI_CDNS_HRS04_RDATA GENMASK(23, 16) > +#define SDHCI_CDNS_HRS04_WDATA GENMASK(15, 8) > +#define SDHCI_CDNS_HRS04_ADDR GENMASK(5, 0) > + > +#define SDHCI_CDNS_HRS05 0x14 > + > +/* eMMC control */ > +#define SDHCI_CDNS_HRS06 0x18 > +#define SDHCI_CDNS_HRS06_TUNE_UP BIT(15) > +#define SDHCI_CDNS_HRS06_TUNE GENMASK(13, 8) > +#define SDHCI_CDNS_HRS06_MODE GENMASK(2, 0) > +#define SDHCI_CDNS_HRS06_MODE_SD 0x0 > +#define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2 > +#define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3 > +#define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4 > +#define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5 > +#define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6 > + > +/* SRS - Slot Register Set (SDHCI-compatible) */ > +#define SDHCI_CDNS_SRS_BASE 0x200 > + > +/* Cadence V4 PHY Setting*/ > +#define SDHCI_CDNS_PHY_DLY_SD_HS 0x00 > +#define SDHCI_CDNS_PHY_DLY_SD_DEFAULT 0x01 > +#define SDHCI_CDNS_PHY_DLY_UHS_SDR12 0x02 > +#define SDHCI_CDNS_PHY_DLY_UHS_SDR25 0x03 > +#define SDHCI_CDNS_PHY_DLY_UHS_SDR50 0x04 > +#define SDHCI_CDNS_PHY_DLY_UHS_DDR50 0x05 > +#define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06 > +#define SDHCI_CDNS_PHY_DLY_EMMC_SDR 0x07 > +#define SDHCI_CDNS_PHY_DLY_EMMC_DDR 0x08 > +#define SDHCI_CDNS_PHY_DLY_SDCLK 0x0b > +#define SDHCI_CDNS_PHY_DLY_HSMMC 0x0c > +#define SDHCI_CDNS_PHY_DLY_STROBE 0x0d > + > +/* > + * The tuned val register is 6 bit-wide, but not the whole of the range > +is > + * available. The range 0-42 seems to be available (then 43 wraps > +around to 0) > + * but I am not quite sure if it is official. Use only 0 to 39 for safety. > + */ > +#define SDHCI_CDNS_MAX_TUNING_LOOP 40 > + > +struct sdhci_cdns_plat { > + struct mmc_config cfg; > + struct mmc mmc; > + void __iomem *hrs_addr; > +}; > + > +int sdhci_cdns6_phy_init(struct sdhci_cdns_plat *plat, u32 mode); int > +sdhci_cdns6_set_tune_val(struct sdhci_cdns_plat *plat, unsigned int > +val); > + > +#endif > diff --git a/drivers/mmc/sdhci-cadence6-phy.c b/drivers/mmc/sdhci-cadence6- > phy.c > new file mode 100644 > index 0000000000..dd3df27dc8 > --- /dev/null > +++ b/drivers/mmc/sdhci-cadence6-phy.c > @@ -0,0 +1,302 @@ > +// SPDX-License-Identifier: GPL-2.0-or-platform_driver > +/* > + * Copyright (C) 2022 Starfive. > + * Author: Kuan Lim Lee <kuanlim....@starfivetech.com> > + */ > + > +#include <common.h> > +#include <dm.h> > +#include <asm/global_data.h> > +#include <dm/device_compat.h> > +#include <linux/bitfield.h> > +#include <linux/bitops.h> > +#include <linux/bug.h> > +#include <linux/io.h> > +#include <linux/iopoll.h> > +#include <linux/sizes.h> > +#include <linux/libfdt.h> > +#include <mmc.h> > +#include <sdhci.h> > +#include "sdhci-cadence.h" > + > +/* IO Delay Information */ > +#define SDHCI_CDNS_HRS07 0X1C > +#define SDHCI_CDNS_HRS07_RW_COMPENSATE GENMASK(20, > 16) > +#define SDHCI_CDNS_HRS07_IDELAY_VAL GENMASK(4, > 0) > + > +#define SDHCI_CDNS_HRS09 0x24 /* PHY Control and > Status */ > +#define SDHCI_CDNS_HRS09_RDDATA_EN BIT(16) > +#define SDHCI_CDNS_HRS09_RDCMD_EN BIT(15) > +#define SDHCI_CDNS_HRS09_EXTENDED_WR_MODE BIT(3) > +#define SDHCI_CDNS_HRS09_EXTENDED_RD_MODE BIT(2) > +#define SDHCI_CDNS_HRS09_PHY_INIT_COMPLETE BIT(1) > +#define SDHCI_CDNS_HRS09_PHY_SW_RESET BIT(0) > + > +#define SDHCI_CDNS_HRS10 0x28 /* SDCLK adjustment > */ > +#define SDHCI_CDNS_HRS10_HCSDCLKADJ GENMASK(19, 16) > + > +#define SDHCI_CDNS_HRS16 0x40 /* CMD/DAT output > delay */ > + > +/* PHY Special Function Registers */ > +//#define DLL_PHY_REG_BASE 0x2000 > + > +/* register to control the DQ related timing */ > +#define PHY_DQ_TIMING_REG_ADDR 0x2000 > + > +/* register to control the DQS related timing */ > +#define PHY_DQS_TIMING_REG_ADDR 0x2004 > + > +/* register to control the gate and loopback control related timing */ > +#define PHY_GATE_LPBK_CTRL_REG_ADDR 0x2008 > + > +/* register to control the Master DLL logic */ > +#define PHY_DLL_MASTER_CTRL_REG_ADDR 0x200C > + > +/* register to control the Slave DLL logic */ > +#define PHY_DLL_SLAVE_CTRL_REG_ADDR 0x2010 > +#define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_CMD_DELAY GENMASK(31, > 24) > +#define PHY_DLL_SLAVE_CTRL_REG_READ_DQS_DELAY > GENMASK(7, 0) > + > +/* register to control the global settings for PHY */ > +#define PHY_CTRL_REG_ADDR 0x2080 > + > +struct phy_reg { > + u32 phy_dqs_timing; > + u32 phy_gate_lpbk_ctrl; > + //u32 phy_dll_master_ctrl; > + u32 phy_dll_slave_ctrl; > + //u32 phy_ctrl; > + u32 phy_dq_timing; > + //cp_sw_half_cycle_shift; ASIC > +}; > + > +struct controller_reg { > + u32 hrs07; > + u32 hrs09; > + u32 hrs10; > + u32 hrs16; > +}; > + > +static struct phy_reg sd_ds_phy_cfg = { > + 0x00380004, > + 0x01A00040, > + 0x00000000, > + 0x00000001, > +}; > + > +static struct phy_reg emmc_sdr_phy_cfg = { > + 0x00380004, > + 0x01A00040, > + 0x00000000, > + 0x00000001, > +}; > + > +static struct phy_reg emmc_ddr_phy_cfg = { > + 0x00380004, > + 0x01A00040, > + 0x00000000, > + 0x10000001, > +}; > + > +static struct phy_reg emmc_hs200_phy_cfg = { > + 0x00380004, > + 0x01A00040, > + 0x00DADA00, > + 0x00000001, > +}; > + > +static struct phy_reg emmc_hs400_phy_cfg = { > + 0x00280004, > + 0x01A00040, > + 0x00DAD800, > + 0x00000001, > +}; > + > +static struct controller_reg sd_ds_ctrl_cfg = { > + 0x00080000, > + 0x0001800C, > + 0x00020000, > + 0x00000000, > +}; > + > +static struct controller_reg emmc_sdr_ctrl_cfg = { > + 0x00080000, > + 0x0001800C, > + 0x00030000, > + 0x00000000, > +}; > + > +static struct controller_reg emmc_ddr_ctrl_cfg = { > + 0x00090001, > + 0x0001800C, > + 0x00020000, > + 0x11000001, > +}; > + > +static struct controller_reg emmc_hs200_ctrl_cfg = { > + 0x00090000, > + 0x00018000, > + 0x00080000, > + 0x00000000, > +}; > + > +static struct controller_reg emmc_hs400_ctrl_cfg = { > + 0x00080000, > + 0x00018000, > + 0x00080000, > + 0x11000000, > +}; > + > +static unsigned int sdhci_cdns6_read_phy_reg(struct sdhci_cdns_plat *plat, > + u32 addr) > +{ > + u32 data = 0; > + > + writel(addr, plat->hrs_addr + SDHCI_CDNS_HRS04); > + data = readl(plat->hrs_addr + SDHCI_CDNS_HRS05); > + return data; > +} > + > +static void sdhci_cdns6_write_phy_reg(struct sdhci_cdns_plat *plat, > + u32 addr, u32 data) > +{ > + u32 readdat = 0; > + > + writel(addr, plat->hrs_addr + SDHCI_CDNS_HRS04); > + writel(data, plat->hrs_addr + SDHCI_CDNS_HRS05); > + readdat = readl(plat->hrs_addr + SDHCI_CDNS_HRS05); > + > + if (readdat != data) { > + pr_err("Error, %s: Writing failed!: address: 0x%x, value : 0x%x, > + readval: 0x%x\n", __func__, addr, data, readdat); > + } > +} > + > +static int sdhci_cdns6_reset_phy_dll(struct sdhci_cdns_plat *plat, > + unsigned int reset) > +{ > + void __iomem *reg = plat->hrs_addr + SDHCI_CDNS_HRS09; > + u32 tmp; > + int ret; > + > + tmp = readl(reg); > + tmp &= ~SDHCI_CDNS_HRS09_PHY_SW_RESET; > + > + if (reset) /* Switch On DLL Reset */ > + tmp |= FIELD_PREP(SDHCI_CDNS_HRS09_PHY_SW_RESET, 0); > + else /* Switch Off DLL Reset */ > + tmp |= FIELD_PREP(SDHCI_CDNS_HRS09_PHY_SW_RESET, 1); > + > + writel(tmp, reg); > + > + if (!reset) { > + ret = readl_poll_timeout(reg, tmp, > + (tmp & > SDHCI_CDNS_HRS09_PHY_INIT_COMPLETE), > + 3000); > + } > + > + return ret; > +} > + > +int sdhci_cdns6_phy_init(struct sdhci_cdns_plat *plat, u32 mode) { > + struct phy_reg *phy_cfgs; > + struct controller_reg *ctrl_cfgs; > + void __iomem *reg = NULL; > + u32 tmp; > + int ret; > + > + switch (mode) { > + case SDHCI_CDNS_HRS06_MODE_SD: > + phy_cfgs = &sd_ds_phy_cfg; > + ctrl_cfgs = &sd_ds_ctrl_cfg; > + break; > + > + case SDHCI_CDNS_HRS06_MODE_MMC_SDR: > + phy_cfgs = &emmc_sdr_phy_cfg; > + ctrl_cfgs = &emmc_sdr_ctrl_cfg; > + break; > + > + case SDHCI_CDNS_HRS06_MODE_MMC_DDR: > + phy_cfgs = &emmc_ddr_phy_cfg; > + ctrl_cfgs = &emmc_ddr_ctrl_cfg; > + break; > + > + case SDHCI_CDNS_HRS06_MODE_MMC_HS200: > + phy_cfgs = &emmc_hs200_phy_cfg; > + ctrl_cfgs = &emmc_hs200_ctrl_cfg; > + break; > + > + case SDHCI_CDNS_HRS06_MODE_MMC_HS400: > + phy_cfgs = &emmc_hs400_phy_cfg; > + ctrl_cfgs = &emmc_hs400_ctrl_cfg; > + break; > + } > + > + /* Switch On the DLL Reset */ > + sdhci_cdns6_reset_phy_dll(plat, 1); > + > + sdhci_cdns6_write_phy_reg(plat, PHY_DQS_TIMING_REG_ADDR, > + phy_cfgs->phy_dqs_timing); > + sdhci_cdns6_write_phy_reg(plat, PHY_GATE_LPBK_CTRL_REG_ADDR, > + phy_cfgs->phy_gate_lpbk_ctrl); > + sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR, > + phy_cfgs->phy_dll_slave_ctrl); > + > + /* Switch Off the DLL Reset */ > + ret = sdhci_cdns6_reset_phy_dll(plat, 0); > + if (ret) { > + printf("sdhci_cdns6_reset_phy is not completed\n"); > + return ret; > + } > + > + /* Set PHY DQ TIMING control register */ > + sdhci_cdns6_write_phy_reg(plat, PHY_DQ_TIMING_REG_ADDR, > + phy_cfgs->phy_dq_timing); > + > + /* Set HRS09 register */ > + reg = plat->hrs_addr + SDHCI_CDNS_HRS09; > + tmp = readl(reg); > + tmp &= ~(SDHCI_CDNS_HRS09_EXTENDED_WR_MODE | > + SDHCI_CDNS_HRS09_EXTENDED_RD_MODE | > + SDHCI_CDNS_HRS09_RDDATA_EN | > + SDHCI_CDNS_HRS09_RDCMD_EN); > + tmp |= ctrl_cfgs->hrs09; > + writel(tmp, reg); > + > + /* Set HRS10 register */ > + reg = plat->hrs_addr + SDHCI_CDNS_HRS10; > + tmp = readl(reg); > + tmp &= ~SDHCI_CDNS_HRS10_HCSDCLKADJ; > + tmp |= ctrl_cfgs->hrs10; > + writel(tmp, reg); > + > + /* Set HRS16 register */ > + reg = plat->hrs_addr + SDHCI_CDNS_HRS16; > + tmp = ctrl_cfgs->hrs16; > + writel(tmp, reg); > + > + /* Set HRS07 register */ > + reg = plat->hrs_addr + SDHCI_CDNS_HRS07; > + tmp = ctrl_cfgs->hrs07; > + writel(tmp, reg); > + > + return 0; > +} > + > +int sdhci_cdns6_set_tune_val(struct sdhci_cdns_plat *plat, > + unsigned int val) > +{ > + u32 tmp, tuneval; > + > + tuneval = (val * 256) / SDHCI_CDNS_MAX_TUNING_LOOP; > + > + tmp = sdhci_cdns6_read_phy_reg(plat, > PHY_DLL_SLAVE_CTRL_REG_ADDR); > + tmp &= ~(PHY_DLL_SLAVE_CTRL_REG_READ_DQS_CMD_DELAY | > + PHY_DLL_SLAVE_CTRL_REG_READ_DQS_DELAY); > + tmp |= > FIELD_PREP(PHY_DLL_SLAVE_CTRL_REG_READ_DQS_CMD_DELAY, tuneval) | > + FIELD_PREP(PHY_DLL_SLAVE_CTRL_REG_READ_DQS_DELAY, > tuneval); > + sdhci_cdns6_write_phy_reg(plat, PHY_DLL_SLAVE_CTRL_REG_ADDR, > tmp); > + > + return 0; > +} > -- > 2.34.1