From: Sumit Garg <[email protected]> Introduce an SDHCI ops hook (config_dll) for MSM SDHCI and implement a minimal DLL control routine that ensures the core DLL is disabled when the bus clock is at or below 100 MHz. This approach mirrors the Linux MSM SDHCI driver.
Signed-off-by: Sumit Garg <[email protected]> Signed-off-by: Loic Poulain <[email protected]> --- drivers/mmc/msm_sdhci.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index ec003991928..38dc36a2194 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -36,6 +36,11 @@ #define CORE_VENDOR_SPEC_POR_VAL 0xa9c +#define CORE_DLL_PDN BIT(29) +#define CORE_DLL_RST BIT(30) + +#define MHZ(X) ((X) * 1000000UL) + struct msm_sdhc_plat { struct mmc_config cfg; struct mmc mmc; @@ -51,6 +56,7 @@ struct msm_sdhc { struct msm_sdhc_variant_info { bool mci_removed; + u32 core_dll_config; u32 core_vendor_spec; u32 core_vendor_spec_capabilities0; }; @@ -149,6 +155,34 @@ static int msm_sdc_mci_init(struct msm_sdhc *prv) return 0; } +static int msm_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable) +{ + struct udevice *dev = mmc_to_dev(host->mmc); + const struct msm_sdhc_variant_info *var_info = (void *)dev_get_driver_data(dev); + u32 config; + + if (enable && clock < MHZ(100)) { + /* + * DLL is not required for clock <= 100MHz + * Thus, make sure DLL is disabled when not required + */ + config = readl(host->ioaddr + var_info->core_dll_config); + config |= CORE_DLL_RST; + writel(config, host->ioaddr + var_info->core_dll_config); + + config = readl(host->ioaddr + var_info->core_dll_config); + config |= CORE_DLL_PDN; + writel(config, host->ioaddr + var_info->core_dll_config); + } + + return 0; +} + +struct sdhci_ops msm_sdhci_ops = { + .config_dll = &msm_sdhci_config_dll, + .set_control_reg = &sdhci_set_control_reg, +}; + static int msm_sdc_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -223,6 +257,7 @@ static int msm_sdc_probe(struct udevice *dev) host->mmc = &plat->mmc; host->mmc->dev = dev; + host->ops = &msm_sdhci_ops; ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0); if (ret) return ret; @@ -288,6 +323,7 @@ static int msm_sdc_bind(struct udevice *dev) static const struct msm_sdhc_variant_info msm_sdhc_mci_var = { .mci_removed = false, + .core_dll_config = 0x100, .core_vendor_spec = 0x10c, .core_vendor_spec_capabilities0 = 0x11c, }; @@ -295,6 +331,7 @@ static const struct msm_sdhc_variant_info msm_sdhc_mci_var = { static const struct msm_sdhc_variant_info msm_sdhc_v5_var = { .mci_removed = true, + .core_dll_config = 0x200, .core_vendor_spec = 0x20c, .core_vendor_spec_capabilities0 = 0x21c, }; -- 2.34.1

