diff options
author | Pradeep Goudagunta <pgoudagunta@nvidia.com> | 2011-11-16 00:15:18 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:50:16 -0800 |
commit | 1c12f692f33a57a1d9cac8df1b5b16bd82ebf47c (patch) | |
tree | 0aabc2cace19fb2961b73ffb5eb27336c3dc2a7f /drivers/mmc/host/sdhci-tegra.c | |
parent | d42e1fd52adbed786f13bd22dce41fee58146465 (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.c | 46 |
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; |