On 10/01/17 09:00, Ritesh Harjani wrote: > This factors out sdhci_msm_hc_select_mode to later use > it during enhanced_strobe mode select. > It also further breaks sdhci_msm_hc_select_mode > into separate functions for configuring HS400 mode > or other modes. > > Signed-off-by: Ritesh Harjani <riteshh@xxxxxxxxxxxxxx> Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> > --- > drivers/mmc/host/sdhci-msm.c | 201 ++++++++++++++++++++++++------------------- > 1 file changed, 114 insertions(+), 87 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c > index 32879b8..1e42647 100644 > --- a/drivers/mmc/host/sdhci-msm.c > +++ b/drivers/mmc/host/sdhci-msm.c > @@ -464,6 +464,119 @@ static int msm_init_cm_dll(struct sdhci_host *host) > return 0; > } > > +static void msm_hc_select_default(struct sdhci_host *host) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); > + u32 config; > + > + if (!msm_host->use_cdclp533) { > + config = readl_relaxed(host->ioaddr + > + CORE_VENDOR_SPEC3); > + config &= ~CORE_PWRSAVE_DLL; > + writel_relaxed(config, host->ioaddr + > + CORE_VENDOR_SPEC3); > + } > + > + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > + config &= ~CORE_HC_MCLK_SEL_MASK; > + config |= CORE_HC_MCLK_SEL_DFLT; > + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > + > + /* > + * Disable HC_SELECT_IN to be able to use the UHS mode select > + * configuration from Host Control2 register for all other > + * modes. > + * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field > + * in VENDOR_SPEC_FUNC > + */ > + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > + config &= ~CORE_HC_SELECT_IN_EN; > + config &= ~CORE_HC_SELECT_IN_MASK; > + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > + > + /* > + * Make sure above writes impacting free running MCLK are completed > + * before changing the clk_rate at GCC. > + */ > + wmb(); > +} > + > +static void msm_hc_select_hs400(struct sdhci_host *host) > +{ > + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > + struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); > + u32 config, dll_lock; > + int rc; > + > + /* Select the divided clock (free running MCLK/2) */ > + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > + config &= ~CORE_HC_MCLK_SEL_MASK; > + config |= CORE_HC_MCLK_SEL_HS400; > + > + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > + /* > + * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC > + * register > + */ > + if (msm_host->tuning_done && !msm_host->calibration_done) { > + config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > + config |= CORE_HC_SELECT_IN_HS400; > + config |= CORE_HC_SELECT_IN_EN; > + writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > + } > + if (!msm_host->clk_rate && !msm_host->use_cdclp533) { > + /* > + * Poll on DLL_LOCK or DDR_DLL_LOCK bits in > + * CORE_DLL_STATUS to be set. This should get set > + * within 15 us at 200 MHz. > + */ > + rc = readl_relaxed_poll_timeout(host->ioaddr + > + CORE_DLL_STATUS, > + dll_lock, > + (dll_lock & > + (CORE_DLL_LOCK | > + CORE_DDR_DLL_LOCK)), 10, > + 1000); > + if (rc == -ETIMEDOUT) > + pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n", > + mmc_hostname(host->mmc), dll_lock); > + } > + /* > + * Make sure above writes impacting free running MCLK are completed > + * before changing the clk_rate at GCC. > + */ > + wmb(); > +} > + > +/* > + * sdhci_msm_hc_select_mode :- In general all timing modes are > + * controlled via UHS mode select in Host Control2 register. > + * eMMC specific HS200/HS400 doesn't have their respective modes > + * defined here, hence we use these values. > + * > + * HS200 - SDR104 (Since they both are equivalent in functionality) > + * HS400 - This involves multiple configurations > + * Initially SDR104 - when tuning is required as HS200 > + * Then when switching to DDR @ 400MHz (HS400) we use > + * the vendor specific HC_SELECT_IN to control the mode. > + * > + * In addition to controlling the modes we also need to select the > + * correct input clock for DLL depending on the mode. > + * > + * HS400 - divided clock (free running MCLK/2) > + * All other modes - default (free running MCLK) > + */ > +void sdhci_msm_hc_select_mode(struct sdhci_host *host) > +{ > + struct mmc_ios ios = host->mmc->ios; > + > + if (ios.timing == MMC_TIMING_MMC_HS400) > + msm_hc_select_hs400(host); > + else > + msm_hc_select_default(host); > +} > + > static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host) > { > struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > @@ -894,7 +1007,6 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) > struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); > struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host); > struct mmc_ios curr_ios = host->mmc->ios; > - u32 config, dll_lock; > int rc; > > if (!clock) { > @@ -913,93 +1025,8 @@ static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock) > curr_ios.timing == MMC_TIMING_MMC_DDR52 || > curr_ios.timing == MMC_TIMING_MMC_HS400) > clock *= 2; > - /* > - * In general all timing modes are controlled via UHS mode select in > - * Host Control2 register. eMMC specific HS200/HS400 doesn't have > - * their respective modes defined here, hence we use these values. > - * > - * HS200 - SDR104 (Since they both are equivalent in functionality) > - * HS400 - This involves multiple configurations > - * Initially SDR104 - when tuning is required as HS200 > - * Then when switching to DDR @ 400MHz (HS400) we use > - * the vendor specific HC_SELECT_IN to control the mode. > - * > - * In addition to controlling the modes we also need to select the > - * correct input clock for DLL depending on the mode. > - * > - * HS400 - divided clock (free running MCLK/2) > - * All other modes - default (free running MCLK) > - */ > - if (curr_ios.timing == MMC_TIMING_MMC_HS400) { > - /* Select the divided clock (free running MCLK/2) */ > - config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > - config &= ~CORE_HC_MCLK_SEL_MASK; > - config |= CORE_HC_MCLK_SEL_HS400; > > - writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > - /* > - * Select HS400 mode using the HC_SELECT_IN from VENDOR SPEC > - * register > - */ > - if (msm_host->tuning_done && !msm_host->calibration_done) { > - /* > - * Write 0x6 to HC_SELECT_IN and 1 to HC_SELECT_IN_EN > - * field in VENDOR_SPEC_FUNC > - */ > - config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > - config |= CORE_HC_SELECT_IN_HS400; > - config |= CORE_HC_SELECT_IN_EN; > - writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > - } > - if (!msm_host->clk_rate && !msm_host->use_cdclp533) { > - /* > - * Poll on DLL_LOCK or DDR_DLL_LOCK bits in > - * CORE_DLL_STATUS to be set. This should get set > - * within 15 us at 200 MHz. > - */ > - rc = readl_relaxed_poll_timeout(host->ioaddr + > - CORE_DLL_STATUS, > - dll_lock, > - (dll_lock & > - (CORE_DLL_LOCK | > - CORE_DDR_DLL_LOCK)), 10, > - 1000); > - if (rc == -ETIMEDOUT) > - pr_err("%s: Unable to get DLL_LOCK/DDR_DLL_LOCK, dll_status: 0x%08x\n", > - mmc_hostname(host->mmc), dll_lock); > - } > - } else { > - if (!msm_host->use_cdclp533) { > - config = readl_relaxed(host->ioaddr + > - CORE_VENDOR_SPEC3); > - config &= ~CORE_PWRSAVE_DLL; > - writel_relaxed(config, host->ioaddr + > - CORE_VENDOR_SPEC3); > - } > - > - config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > - config &= ~CORE_HC_MCLK_SEL_MASK; > - config |= CORE_HC_MCLK_SEL_DFLT; > - writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > - > - /* > - * Disable HC_SELECT_IN to be able to use the UHS mode select > - * configuration from Host Control2 register for all other > - * modes. > - * Write 0 to HC_SELECT_IN and HC_SELECT_IN_EN field > - * in VENDOR_SPEC_FUNC > - */ > - config = readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC); > - config &= ~CORE_HC_SELECT_IN_EN; > - config &= ~CORE_HC_SELECT_IN_MASK; > - writel_relaxed(config, host->ioaddr + CORE_VENDOR_SPEC); > - } > - > - /* > - * Make sure above writes impacting free running MCLK are completed > - * before changing the clk_rate at GCC. > - */ > - wmb(); > + sdhci_msm_hc_select_mode(host); > > rc = clk_set_rate(msm_host->clk, clock); > if (rc) { > -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html