]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
mmc: tegra: Boost sclk and emc clk's for sdmmc4
authorNaveen Kumar Arepalli <naveenk@nvidia.com>
Wed, 24 Apr 2013 07:53:10 +0000 (13:23 +0530)
committerDan Willemsen <dwillemsen@nvidia.com>
Sat, 14 Sep 2013 20:13:44 +0000 (13:13 -0700)
Boost emc clock to 100 MHz
Enable sclk for sdmmc4 and set 80MHz

Bug 1262190

Reviewed-on: http://git-master/r/222371
(cherry picked from commit da84c968d1abebe3bc678f32c77e667a61b12f0a)
Change-Id: Ibb5725ab1a65e57da52250c679bce9f41b181db9
Signed-off-by: Naveen Kumar Arepalli <naveenk@nvidia.com>
Reviewed-on: http://git-master/r/225622
Reviewed-by: Mrutyunjay Sawant <msawant@nvidia.com>
Tested-by: Mrutyunjay Sawant <msawant@nvidia.com>
drivers/mmc/host/sdhci-tegra.c

index ff86c2fd055c743eb89a20778a19e7de07dae82b..e05de06f64a647d2ef123744eed7a7093dfdeffa 100644 (file)
@@ -99,6 +99,8 @@
 #define TUNING_VOLTAGES_COUNT  2
 
 #define TUNING_RETRIES 1
+#define SDMMC_AHB_MAX_FREQ     80000000
+#define SDMMC_EMC_MAX_FREQ     100000000
 
 static unsigned int uhs_max_freq_MHz[] = {
        [MMC_TIMING_UHS_SDR50] = 100,
@@ -261,6 +263,9 @@ struct sdhci_tegra {
        bool card_present;
        bool is_rail_enabled;
        struct clk *emc_clk;
+       bool is_sdmmc_emc_clk_on;
+       struct clk *sclk;
+       bool is_sdmmc_sclk_on;
        unsigned int emc_max_clk;
        struct sdhci_tegra_sd_stats *sd_stat_head;
        struct notifier_block reboot_notify;
@@ -1051,7 +1056,23 @@ static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
                        tegra_host->clk_enabled = true;
                }
                tegra_sdhci_set_clk_rate(sdhci, clock);
+               if (tegra_host->emc_clk && (!tegra_host->is_sdmmc_emc_clk_on)) {
+                       clk_prepare_enable(tegra_host->emc_clk);
+                       tegra_host->is_sdmmc_emc_clk_on = true;
+               }
+               if (tegra_host->sclk && (!tegra_host->is_sdmmc_sclk_on)) {
+                       clk_prepare_enable(tegra_host->sclk);
+                       tegra_host->is_sdmmc_sclk_on = true;
+               }
        } else if (!clock && tegra_host->clk_enabled) {
+               if (tegra_host->emc_clk && tegra_host->is_sdmmc_emc_clk_on) {
+                       clk_disable_unprepare(tegra_host->emc_clk);
+                       tegra_host->is_sdmmc_emc_clk_on = false;
+               }
+               if (tegra_host->sclk && tegra_host->is_sdmmc_sclk_on) {
+                       clk_disable_unprepare(tegra_host->sclk);
+                       tegra_host->is_sdmmc_sclk_on = false;
+               }
                ctrl = sdhci_readb(sdhci, SDHCI_VNDR_CLK_CTRL);
                ctrl &= ~SDHCI_VNDR_CLK_CTRL_SDMMC_CLK;
                sdhci_writeb(sdhci, ctrl, SDHCI_VNDR_CLK_CTRL);
@@ -2345,14 +2366,23 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
        if (!strcmp(dev_name(mmc_dev(host->mmc)), "sdhci-tegra.3")) {
                tegra_host->emc_clk = clk_get(mmc_dev(host->mmc), "emc");
                if (IS_ERR(tegra_host->emc_clk)) {
-                       dev_err(mmc_dev(host->mmc), "clk err\n");
+                       dev_err(mmc_dev(host->mmc), "Can't get emc clk\n");
                        rc = PTR_ERR(tegra_host->emc_clk);
                        goto err_clk_put;
                }
                tegra_host->emc_max_clk =
                        clk_round_rate(tegra_host->emc_clk, ULONG_MAX);
+               clk_set_rate(tegra_host->emc_clk, SDMMC_EMC_MAX_FREQ);
        }
 
+       tegra_host->sclk = clk_get(mmc_dev(host->mmc), "sclk");
+       if (IS_ERR_OR_NULL(tegra_host->sclk)) {
+               dev_err(mmc_dev(host->mmc), "Can't get sclk clock\n");
+               clk_put(tegra_host->sclk);
+               tegra_host->sclk = NULL;
+       } else {
+               clk_set_rate(tegra_host->sclk, SDMMC_AHB_MAX_FREQ);
+       }
        pltfm_host->priv = tegra_host;
        tegra_host->clk_enabled = true;
        tegra_host->max_clk_limit = plat->max_clk_limit;
@@ -2502,6 +2532,16 @@ static int sdhci_tegra_remove(struct platform_device *pdev)
        }
        clk_put(pltfm_host->clk);
 
+       if (tegra_host->emc_clk) {
+               if (tegra_host->is_sdmmc_emc_clk_on)
+                       clk_disable_unprepare(tegra_host->emc_clk);
+               clk_put(tegra_host->emc_clk);
+       }
+       if (tegra_host->sclk) {
+               if (tegra_host->is_sdmmc_sclk_on)
+                       clk_disable_unprepare(tegra_host->sclk);
+               clk_put(tegra_host->sclk);
+       }
        if (plat->power_off_rail)
                unregister_reboot_notifier(&tegra_host->reboot_notify);