tegra sdhci: Enable/disable SDCLK source in set_clock host_op
authorTodd Poynor <toddpoynor@google.com>
Mon, 11 Oct 2010 22:31:42 +0000 (15:31 -0700)
committerTodd Poynor <toddpoynor@google.com>
Mon, 8 Nov 2010 23:37:55 +0000 (15:37 -0800)
Now with 100% more LP0 suspend support.  sdhci_resume_host accesses
the SDHCI controller, so enable the sdmmc<n> clock at resume, and
let the MMC card layer tell us (later on) whether SDCLK is needed or
not.

Change-Id: Ia66e54e93f607d03053315fdc3b9a0e9bea29b68
Signed-off-by: Todd Poynor <toddpoynor@google.com>
drivers/mmc/host/sdhci-tegra.c

index 361c8e7806837771c09bbe8434358192601ca2c0..19f522d3a59f7145bd0c624cb1f7c97baa64c013 100644 (file)
 
 #define DRIVER_NAME    "sdhci-tegra"
 
+#define SDHCI_VENDOR_CLOCK_CNTRL       0x100
+
 struct tegra_sdhci_host {
        struct sdhci_host *sdhci;
        struct clk *clk;
+       int clk_enabled;
 };
 
 static irqreturn_t carddetect_irq(int irq, void *data)
@@ -48,8 +51,31 @@ static int tegra_sdhci_enable_dma(struct sdhci_host *host)
        return 0;
 }
 
+static void tegra_sdhci_enable_clock(struct tegra_sdhci_host *host, int enable)
+{
+       if (enable && !host->clk_enabled) {
+               clk_enable(host->clk);
+               sdhci_writeb(host->sdhci, 1, SDHCI_VENDOR_CLOCK_CNTRL);
+               host->clk_enabled = 1;
+       } else if (!enable && host->clk_enabled) {
+               sdhci_writeb(host->sdhci, 0, SDHCI_VENDOR_CLOCK_CNTRL);
+               clk_disable(host->clk);
+               host->clk_enabled = 0;
+       }
+}
+
+static void tegra_sdhci_set_clock(struct sdhci_host *sdhci, unsigned int clock)
+{
+       struct tegra_sdhci_host *host = sdhci_priv(sdhci);
+       pr_info("tegra sdhci clock %s %u enabled=%d\n",
+               mmc_hostname(sdhci->mmc), clock, host->clk_enabled);
+
+       tegra_sdhci_enable_clock(host, clock);
+}
+
 static struct sdhci_ops tegra_sdhci_ops = {
        .enable_dma = tegra_sdhci_enable_dma,
+       .set_clock = tegra_sdhci_set_clock,
 };
 
 static int __devinit tegra_sdhci_probe(struct platform_device *pdev)
@@ -97,6 +123,7 @@ static int __devinit tegra_sdhci_probe(struct platform_device *pdev)
        if (rc != 0)
                goto err_clkput;
 
+       host->clk_enabled = 1;
        sdhci->hw_name = "tegra";
        sdhci->ops = &tegra_sdhci_ops;
        sdhci->irq = irq;
@@ -187,6 +214,7 @@ static int tegra_sdhci_resume(struct platform_device *pdev)
        struct tegra_sdhci_host *host = platform_get_drvdata(pdev);
        int ret;
 
+       tegra_sdhci_enable_clock(host, 1);
        ret = sdhci_resume_host(host->sdhci);
        if (ret)
                pr_err("%s: failed, error = %d\n", __func__, ret);