summaryrefslogtreecommitdiff
path: root/drivers/mmc/host/sdhci-tegra.c
diff options
context:
space:
mode:
authorPradeep Goudagunta <pgoudagunta@nvidia.com>2011-11-16 00:15:18 +0530
committerDan Willemsen <dwillemsen@nvidia.com>2011-11-30 21:50:16 -0800
commit1c12f692f33a57a1d9cac8df1b5b16bd82ebf47c (patch)
tree0aabc2cace19fb2961b73ffb5eb27336c3dc2a7f /drivers/mmc/host/sdhci-tegra.c
parentd42e1fd52adbed786f13bd22dce41fee58146465 (diff)
mmc: sdhci-tegra: add platform code for UHS signaling
Tegra SD controller requires clk divisor to be set to 1 for DDR50 mode. Bug 899940 Change-Id: Ibc15e5f61b11e2e87b78eade8d004ff2c56b3b74 Reviewed-on: http://git-master/r/64510 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com> Rebase-Id: Rf958d23dedd38a3d84efaf555d5ec0a31678da37
Diffstat (limited to 'drivers/mmc/host/sdhci-tegra.c')
-rw-r--r--drivers/mmc/host/sdhci-tegra.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index e91a54c9c4b1..72ef8e1e0f5d 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -154,6 +154,43 @@ static void tegra3_sdhci_post_reset_init(struct sdhci_host *sdhci)
sdhci_writew(sdhci, ctrl, SDHCI_VENDOR_MISC_CNTRL);
}
+static int tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
+ unsigned int uhs)
+{
+ u16 clk, ctrl_2;
+ ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+
+ /* Select Bus Speed Mode for host */
+ ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
+ switch (uhs) {
+ case MMC_TIMING_UHS_SDR12:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
+ break;
+ case MMC_TIMING_UHS_SDR25:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
+ break;
+ case MMC_TIMING_UHS_SDR50:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
+ break;
+ case MMC_TIMING_UHS_SDR104:
+ ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
+ break;
+ case MMC_TIMING_UHS_DDR50:
+ ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
+ break;
+ }
+
+ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+
+ if (uhs == MMC_TIMING_UHS_DDR50) {
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk &= ~(0xFF << SDHCI_DIVIDER_SHIFT);
+ clk |= 1 << SDHCI_DIVIDER_SHIFT;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+ }
+ return 0;
+}
+
static void tegra_sdhci_reset_exit(struct sdhci_host *sdhci, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(sdhci);
@@ -240,6 +277,10 @@ static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int
if (clock == 0)
goto out;
+ if (sdhci->mmc->ios.timing == MMC_TIMING_UHS_DDR50) {
+ div = 1;
+ goto set_clk;
+ }
if (sdhci->version >= SDHCI_SPEC_300) {
/* Version 3.00 divisors must be a multiple of 2. */
@@ -268,7 +309,7 @@ static void tegra_3x_sdhci_set_card_clock(struct sdhci_host *sdhci, unsigned int
* - Wait for 5 usec and do a dummy write.
* - Poll for clk stable and disable PADPIPE_CLK_OVERRIDE.
*/
-
+set_clk:
/* Enable PADPIPE clk override */
ctrl = sdhci_readb(sdhci, SDHCI_VENDOR_CLOCK_CNTRL);
ctrl |= SDHCI_VENDOR_CLOCK_CNTRL_PADPIPE_CLKEN_OVERRIDE;
@@ -407,6 +448,7 @@ static struct sdhci_ops tegra_sdhci_ops = {
.suspend = tegra_sdhci_suspend,
.resume = tegra_sdhci_resume,
.platform_reset_exit = tegra_sdhci_reset_exit,
+ .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
};
static struct sdhci_pltfm_data sdhci_tegra_pdata = {
@@ -568,6 +610,8 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
host->mmc->caps |= MMC_CAP_ERASE;
host->mmc->caps |= MMC_CAP_DISABLE;
+ /* enable 1/8V DDR capable */
+ host->mmc->caps |= MMC_CAP_1_8V_DDR;
if (plat->is_8bit)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
host->mmc->caps |= MMC_CAP_SDIO_IRQ;