All of lore.kernel.org
 help / color / mirror / Atom feed
From: KuanLim.Lee <kuanlim.lee@starfivetech.com>
To: "u-boot@lists.denx.de" <u-boot@lists.denx.de>
Cc: Yuklin Soo <yuklin.soo@starfivetech.com>,
	WeiLiang Lim <weiliang.lim@starfivetech.com>
Subject: RE: [PATCH] mmc: sdhci-cadence: Add support for Cadence sdmmc v6
Date: Tue, 17 Oct 2023 04:53:40 +0000	[thread overview]
Message-ID: <dc2b29d1903746038737ba5ff8c3ccc9@EXMBX066.cuchost.com> (raw)
In-Reply-To: <20231003072320.2008-1-kuanlim.lee@starfivetech.com>

Hi maintainers,

Could anyone of you help to review the patch?


> -----Original Message-----
> From: KuanLim.Lee <kuanlim.lee@starfivetech.com>
> Sent: Tuesday, October 3, 2023 3:23 PM
> To: u-boot@lists.denx.de
> Cc: Yuklin Soo <yuklin.soo@starfivetech.com>; WeiLiang Lim
> <weiliang.lim@starfivetech.com>; Kuan Lim Lee
> <kuanlim.lee@linux.starfivetech.com>; KuanLim.Lee
> <kuanlim.lee@starfivetech.com>
> Subject: [PATCH] mmc: sdhci-cadence: Add support for Cadence sdmmc v6
> 
> From: Kuan Lim Lee <kuanlim.lee@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.lee@starfivetech.com>
> Reviewed-by: Alex Soo <yuklin.soo@starfivetech.com>
> Reviewed-by: Wei Liang Lim <weiliang.lim@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.lee@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.lee@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


  parent reply	other threads:[~2023-10-17  4:54 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20231101001948epcas1p21f7980fd9ab6a99e884eeb08409b1f48@epcas1p2.samsung.com>
2023-10-03  7:22 ` [PATCH] mmc: sdhci-cadence: Add support for Cadence sdmmc v6 Kuan Lim Lee
2023-10-10  8:18   ` KuanLim.Lee
2023-10-17  4:53   ` KuanLim.Lee [this message]
2023-11-01  0:19   ` Jaehoon Chung
2023-11-07  6:23     ` KuanLim.Lee
2023-11-15  3:36       ` KuanLim.Lee
2023-11-15 12:16         ` Jaehoon Chung

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dc2b29d1903746038737ba5ff8c3ccc9@EXMBX066.cuchost.com \
    --to=kuanlim.lee@starfivetech.com \
    --cc=u-boot@lists.denx.de \
    --cc=weiliang.lim@starfivetech.com \
    --cc=yuklin.soo@starfivetech.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.