diff options
author | Pavan Kunapuli <pkunapuli@nvidia.com> | 2012-04-18 09:18:02 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-04-22 11:17:39 -0400 |
commit | ca5879d3ffebd967e94b2dc3b1a3dc089709206f (patch) | |
tree | d60744e61e5621c7a7d3b482137b1aa56e87dc33 /drivers/mmc/host/sdhci-tegra.c | |
parent | bbbc4c4d8c5face097d695f9bf3a39647ba6b7e7 (diff) |
mmc: tegra: support SDHCI SPEC 300
Tegra3 SDHOST controller doesn't advertise v3.00 support by default.
This support has to be enabled by configuring a vendor register in
the tegra3 sd host address space.
Signed-off-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sdhci-tegra.c')
-rw-r--r-- | drivers/mmc/host/sdhci-tegra.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 53b26502f6e2..cff0c522b4ab 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -32,8 +32,13 @@ | |||
32 | 32 | ||
33 | #include "sdhci-pltfm.h" | 33 | #include "sdhci-pltfm.h" |
34 | 34 | ||
35 | /* Tegra SDHOST controller vendor register definitions */ | ||
36 | #define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 | ||
37 | #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 | ||
38 | |||
35 | #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) | 39 | #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) |
36 | #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) | 40 | #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) |
41 | #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) | ||
37 | 42 | ||
38 | struct sdhci_tegra_soc_data { | 43 | struct sdhci_tegra_soc_data { |
39 | struct sdhci_pltfm_data *pdata; | 44 | struct sdhci_pltfm_data *pdata; |
@@ -120,6 +125,25 @@ static irqreturn_t carddetect_irq(int irq, void *data) | |||
120 | return IRQ_HANDLED; | 125 | return IRQ_HANDLED; |
121 | }; | 126 | }; |
122 | 127 | ||
128 | static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask) | ||
129 | { | ||
130 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
131 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
132 | const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; | ||
133 | |||
134 | if (!(mask & SDHCI_RESET_ALL)) | ||
135 | return; | ||
136 | |||
137 | /* Erratum: Enable SDHCI spec v3.00 support */ | ||
138 | if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) { | ||
139 | u32 misc_ctrl; | ||
140 | |||
141 | misc_ctrl = sdhci_readb(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); | ||
142 | misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; | ||
143 | sdhci_writeb(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); | ||
144 | } | ||
145 | } | ||
146 | |||
123 | static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width) | 147 | static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width) |
124 | { | 148 | { |
125 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 149 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
@@ -148,6 +172,7 @@ static struct sdhci_ops tegra_sdhci_ops = { | |||
148 | .read_w = tegra_sdhci_readw, | 172 | .read_w = tegra_sdhci_readw, |
149 | .write_l = tegra_sdhci_writel, | 173 | .write_l = tegra_sdhci_writel, |
150 | .platform_8bit_width = tegra_sdhci_8bit, | 174 | .platform_8bit_width = tegra_sdhci_8bit, |
175 | .platform_reset_exit = tegra_sdhci_reset_exit, | ||
151 | }; | 176 | }; |
152 | 177 | ||
153 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | 178 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
@@ -178,6 +203,7 @@ static struct sdhci_pltfm_data sdhci_tegra30_pdata = { | |||
178 | 203 | ||
179 | static struct sdhci_tegra_soc_data soc_data_tegra30 = { | 204 | static struct sdhci_tegra_soc_data soc_data_tegra30 = { |
180 | .pdata = &sdhci_tegra30_pdata, | 205 | .pdata = &sdhci_tegra30_pdata, |
206 | .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300, | ||
181 | }; | 207 | }; |
182 | #endif | 208 | #endif |
183 | 209 | ||