]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
mmc: tegra: Set clk parent explicitly
authorAnubhav Jain <anubhavj@nvidia.com>
Thu, 14 Jul 2016 06:51:15 +0000 (12:21 +0530)
committerAnubhav Jain <anubhavj@nvidia.com>
Fri, 15 Jul 2016 13:53:04 +0000 (06:53 -0700)
Set clk parent for sdhci device to avoid
wrong clk parent settings issues on T18x
platforms.

Bug 200218065

Change-Id: Ia4d73febc36fda92d7ea21f2bb935027574b18df
Signed-off-by: Anubhav Jain <anubhavj@nvidia.com>
Signed-off-by: R Raj Kumar <rrajk@nvidia.com>
Reviewed-on: http://git-master/r/1181184
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
drivers/mmc/host/sdhci-tegra.c
include/linux/platform_data/mmc-sdhci-tegra.h

index dd39458a5b4def319a6aaba30be7c110d5e5f412..1bb806054351fbf556576331a8303f6dcf501c38 100644 (file)
 #define NVQUIRK_ENABLE_SDR50_TUNING            BIT(15)
 /* Enable T210 specific SDMMC WAR - Tuning Step Size, Tuning Iterations*/
 #define NVQUIRK_UPDATE_HW_TUNING_CONFG         BIT(16)
+#define NVQUIRK2_SET_PLL_CLK_PARENT            BIT(17)
 
 /* Common quirks for Tegra 12x and later versions of sdmmc controllers */
 #define TEGRA_SDHCI_QUIRKS (SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | \
@@ -524,6 +525,19 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
        sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
 
        /* Mask any bus speed modes if set in platform data */
+       if (plat->uhs_mask & MMC_UHS_MASK_SDR12)
+               host->mmc->caps &= ~MMC_CAP_UHS_SDR12;
+
+       if (plat->uhs_mask & MMC_UHS_MASK_SDR25)
+               host->mmc->caps &= ~MMC_CAP_UHS_SDR25;
+
+       if (plat->uhs_mask & MMC_UHS_MASK_SDR50)
+               host->mmc->caps &= ~MMC_CAP_UHS_SDR50;
+
+       if (plat->uhs_mask & MMC_UHS_MASK_SDR104)
+               host->mmc->caps &= ~MMC_CAP_UHS_SDR104;
+
+
        if (plat->uhs_mask & MMC_UHS_MASK_DDR50) {
                host->mmc->caps &= ~MMC_CAP_UHS_DDR50;
                host->mmc->caps &= ~MMC_CAP_1_8V_DDR;
@@ -606,6 +620,19 @@ static void tegra_sdhci_clock_set_parent(struct sdhci_host *host,
        if (!pll_source[0].pll_rate || !pll_source[1].pll_rate)
                return;
 
+       if ((tegra_host->soc_data->nvquirks2 & NVQUIRK2_SET_PLL_CLK_PARENT) &&
+               pll_source[0].pll_rate && !pll_source[1].pll_rate) {
+               rc = clk_set_rate(pltfm_host->clk, desired_rate);
+               if (!tegra_host->is_parent_pll_source_1) {
+                       rc = clk_set_parent(pltfm_host->clk, pll_source[0].pll);
+                       if (rc)
+                               pr_err("%s: failed to set pll parent clock %d\n",
+                                       mmc_hostname(host->mmc), rc);
+                       tegra_host->is_parent_pll_source_1 = true;
+               }
+               return;
+       }
+
        pll_source_1_freq = get_nearest_clock_freq(pll_source[0].pll_rate,
                        desired_rate);
        pll_source_2_freq = get_nearest_clock_freq(pll_source[1].pll_rate,
@@ -1421,6 +1448,7 @@ static struct sdhci_tegra_soc_data soc_data_tegra186 = {
                NVQUIRK_SET_SDMEMCOMP_VREF_SEL |
                NVQUIRK_SET_PAD_E_INPUT_OR_E_PWRD,
        .nvquirks2 = NVQUIRK2_ADD_DELAY_AUTO_CALIBRATION |
+               NVQUIRK2_SET_PLL_CLK_PARENT |
                NVQUIRK2_SET_PAD_E_INPUT_VOL,
 };
 
@@ -1520,6 +1548,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
        struct sdhci_tegra *tegra_host;
        const struct tegra_sdhci_platform_data *plat;
        struct clk *clk;
+       struct clk *sdmmc_default_parent;
        const char *parent_clk_list[TEGRA_SDHCI_MAX_PLL_SOURCE];
        int rc, i;
        int signal_voltage = MMC_SIGNAL_VOLTAGE_330;
@@ -1618,6 +1647,14 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
                        "Client registration for eMC Successful\n");
 
        pltfm_host->clk = clk;
+       if (clk_get_parent(pltfm_host->clk) == tegra_host->pll_source[0].pll)
+               tegra_host->is_parent_pll_source_1 = true;
+       if (tegra_host->soc_data->nvquirks2 & NVQUIRK2_SET_PLL_CLK_PARENT) {
+               sdmmc_default_parent = devm_clk_get(&pdev->dev, "pll_p");
+               clk_set_parent(pltfm_host->clk, sdmmc_default_parent);
+               if (strcmp(parent_clk_list[0], "pll_p"))
+                       tegra_host->is_parent_pll_source_1 = true;
+       }
 
        /* Reset the sdhci controller to clear all previous status.*/
 
index f23a3e82452e3ac1485f0c629c43a4743dcb262f..a8880ec154ef17cf4529130dc03656802daafb31 100644 (file)
 
 
 /* uhs mask can be used to mask any of the UHS modes support */
+#define MMC_UHS_MASK_SDR12     0x1
+#define MMC_UHS_MASK_SDR25     0x2
+#define MMC_UHS_MASK_SDR50     0x4
 #define MMC_UHS_MASK_DDR50     0x8
+#define MMC_UHS_MASK_SDR104    0x10
 #define MMC_MASK_HS200         0x20
 #define MMC_MASK_HS400         0x40