/* Initialize the DLL (Programmable Delay Line) */ static int msm_init_cm_dll(struct sdhci_host *host) { struct mmc_host *mmc = host->mmc; int wait_cnt = 50; unsigned long flags; spin_lock_irqsave(&host->lock, flags); /* * Make sure that clock is always enabled when DLL * tuning is in progress. Keeping PWRSAVE ON may * turn off the clock. */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) & ~CORE_CLK_PWRSAVE), host->ioaddr + CORE_VENDOR_SPEC); /* Write 1 to DLL_RST bit of DLL_CONFIG register */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); /* Write 1 to DLL_PDN bit of DLL_CONFIG register */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); msm_cm_dll_set_freq(host); /* Write 0 to DLL_RST bit of DLL_CONFIG register */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & ~CORE_DLL_RST), host->ioaddr + CORE_DLL_CONFIG); /* Write 0 to DLL_PDN bit of DLL_CONFIG register */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) & ~CORE_DLL_PDN), host->ioaddr + CORE_DLL_CONFIG); /* Set DLL_EN bit to 1. */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | CORE_DLL_EN), host->ioaddr + CORE_DLL_CONFIG); /* Set CK_OUT_EN bit to 1. */ writel_relaxed((readl_relaxed(host->ioaddr + CORE_DLL_CONFIG) | CORE_CK_OUT_EN), host->ioaddr + CORE_DLL_CONFIG); /* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */ while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) & CORE_DLL_LOCK)) { /* max. wait for 50us sec for LOCK bit to be set */ if (--wait_cnt == 0) { dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n", mmc_hostname(mmc)); spin_unlock_irqrestore(&host->lock, flags); return -ETIMEDOUT; } udelay(1); } spin_unlock_irqrestore(&host->lock, flags); return 0; }
/* Initialize the DLL (Programmable Delay Line) */ static int msm_init_cm_dll(struct sdhci_host *host) { struct mmc_host *mmc = host->mmc; struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); int wait_cnt = 50; unsigned long flags; u32 config; spin_lock_irqsave(&host->lock, flags); /* * Make sure that clock is always enabled when DLL * tuning is in progress. Keeping PWRSAVE ON may * turn off the clock. */ config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); config &= ~CORE_CLK_PWRSAVE; writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); if (msm_host->use_14lpp_dll_reset) { config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config &= ~CORE_CK_OUT_EN; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2); config |= CORE_DLL_CLOCK_DISABLE; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2); } config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config |= CORE_DLL_RST; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config |= CORE_DLL_PDN; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); msm_cm_dll_set_freq(host); if (msm_host->use_14lpp_dll_reset && !IS_ERR_OR_NULL(msm_host->xo_clk)) { u32 mclk_freq = 0; config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2); config &= CORE_FLL_CYCLE_CNT; if (config) mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 8), clk_get_rate(msm_host->xo_clk)); else mclk_freq = DIV_ROUND_CLOSEST_ULL((host->clock * 4), clk_get_rate(msm_host->xo_clk)); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2); config &= ~(0xFF << 10); config |= mclk_freq << 10; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2); /* wait for 5us before enabling DLL clock */ udelay(5); } config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config &= ~CORE_DLL_RST; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config &= ~CORE_DLL_PDN; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); if (msm_host->use_14lpp_dll_reset) { msm_cm_dll_set_freq(host); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG_2); config &= ~CORE_DLL_CLOCK_DISABLE; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG_2); } config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config |= CORE_DLL_EN; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); config = readl_relaxed(host->ioaddr + CORE_DLL_CONFIG); config |= CORE_CK_OUT_EN; writel_relaxed(config, host->ioaddr + CORE_DLL_CONFIG); /* Wait until DLL_LOCK bit of DLL_STATUS register becomes '1' */ while (!(readl_relaxed(host->ioaddr + CORE_DLL_STATUS) & CORE_DLL_LOCK)) { /* max. wait for 50us sec for LOCK bit to be set */ if (--wait_cnt == 0) { dev_err(mmc_dev(mmc), "%s: DLL failed to LOCK\n", mmc_hostname(mmc)); spin_unlock_irqrestore(&host->lock, flags); return -ETIMEDOUT; } udelay(1); } spin_unlock_irqrestore(&host->lock, flags); return 0; }