Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a89c472d authored by Piotr Sroka's avatar Piotr Sroka Committed by Ulf Hansson
Browse files

mmc: sdhci-cadence: Update PHY delay configuration



DTS properties are used instead of fixed data
because PHY settings can be different for different chips/boards.

Signed-off-by: default avatarPiotr Sroka <piotrs@cadence.com>
Reviewed-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Acked-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 6f4b0919
Loading
Loading
Loading
Loading
+46 −7
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/mmc/host.h>
#include <linux/mmc/mmc.h>
#include <linux/of.h>

#include "sdhci-pltfm.h"

@@ -55,6 +56,9 @@
#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
@@ -68,6 +72,25 @@ struct sdhci_cdns_priv {
	bool enhanced_strobe;
};

struct sdhci_cdns_phy_cfg {
	const char *property;
	u8 addr;
};

static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
	{ "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
	{ "cdns,phy-input-delay-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
	{ "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
	{ "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
	{ "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
	{ "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
	{ "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
	{ "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
	{ "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
	{ "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
	{ "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
};

static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
				    u8 addr, u8 data)
{
@@ -92,13 +115,26 @@ static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
	return 0;
}

static void sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
static int sdhci_cdns_phy_init(struct device_node *np,
			       struct sdhci_cdns_priv *priv)
{
	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_HS, 4);
	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_SD_DEFAULT, 4);
	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_LEGACY, 9);
	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_SDR, 2);
	sdhci_cdns_write_phy_reg(priv, SDHCI_CDNS_PHY_DLY_EMMC_DDR, 3);
	u32 val;
	int ret, i;

	for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
		ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
					   &val);
		if (ret)
			continue;

		ret = sdhci_cdns_write_phy_reg(priv,
					       sdhci_cdns_phy_cfgs[i].addr,
					       val);
		if (ret)
			return ret;
	}

	return 0;
}

static inline void *sdhci_cdns_priv(struct sdhci_host *host)
@@ -267,6 +303,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
	struct sdhci_cdns_priv *priv;
	struct clk *clk;
	int ret;
	struct device *dev = &pdev->dev;

	clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(clk))
@@ -297,7 +334,9 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
	if (ret)
		goto free;

	sdhci_cdns_phy_init(priv);
	ret = sdhci_cdns_phy_init(dev->of_node, priv);
	if (ret)
		goto free;

	ret = sdhci_add_host(host);
	if (ret)