sdhci: tegra: enable sd dpd
Bitan Biswas [Mon, 25 Jun 2012 14:34:54 +0000 (19:34 +0530)]
This is a WAR solution that allows for the turning on
SD DPD feature.

The original issue is that enabling SD DPD immediately after device comes
out of LP0 causes ULPI disconnect. The root cause of that is
not known.

The WAR is to delay the enabling of SD DPD for 100ms after
device comes out of LP0.

Bug 929628

Change-Id: I946771a8e92459464ce571295f96f197db25c061
Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
(cherry picked from commit beba2b34af7ff9313aed074342b9bb86b12620a8)
Reviewed-on: http://git-master/r/113391
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Wen Yi <wyi@nvidia.com>
Tested-by: Wen Yi <wyi@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>

drivers/mmc/host/sdhci-tegra.c

index 609fd63..bec338f 100644 (file)
@@ -509,7 +509,12 @@ static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
 
        if (clock) {
                /* bring out sd instance from io dpd mode */
-               tegra_io_dpd_disable(tegra_host->dpd);
+               if (tegra_host->dpd) {
+                       mutex_lock(&tegra_host->dpd->delay_lock);
+                       cancel_delayed_work_sync(&tegra_host->dpd->delay_dpd);
+                       tegra_io_dpd_disable(tegra_host->dpd);
+                       mutex_unlock(&tegra_host->dpd->delay_lock);
+               }
 
                if (!tegra_host->clk_enabled) {
                        clk_enable(pltfm_host->clk);
@@ -530,7 +535,18 @@ static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
                clk_disable(pltfm_host->clk);
                tegra_host->clk_enabled = false;
                /* io dpd enable call for sd instance */
-               tegra_io_dpd_enable(tegra_host->dpd);
+
+               if (tegra_host->dpd) {
+                       mutex_lock(&tegra_host->dpd->delay_lock);
+                       if (tegra_host->dpd->need_delay_dpd) {
+                               schedule_delayed_work(
+                                       &tegra_host->dpd->delay_dpd,
+                                       msecs_to_jiffies(100));
+                       } else {
+                               tegra_io_dpd_enable(tegra_host->dpd);
+                       }
+                       mutex_unlock(&tegra_host->dpd->delay_lock);
+               }
        }
 }
 
@@ -865,6 +881,12 @@ static int tegra_sdhci_suspend(struct sdhci_host *sdhci, pm_message_t state)
                }
        }
 
+       if (tegra_host->dpd) {
+               mutex_lock(&tegra_host->dpd->delay_lock);
+               tegra_host->dpd->need_delay_dpd = 1;
+               mutex_unlock(&tegra_host->dpd->delay_lock);
+       }
+
        return 0;
 }