diff options
author | Pavan Kunapuli <pkunapuli@nvidia.com> | 2015-01-28 11:45:16 -0500 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2015-01-29 05:21:58 -0500 |
commit | 352ee868dda03ca72e60d4853356881ff161ec23 (patch) | |
tree | 67cfefe825be4832549c896202cb3c8aedee3403 | |
parent | 0501be6429e4eb02f417ad83eacd84b8c57b0283 (diff) |
mmc: tegra: Write xfer_mode, CMD regs in together
If there is a gap between xfer mode and command register writes,
tegra SDMMC controller can sometimes issue a spurious command before
the CMD register is written. To avoid this, these two registers need
to be written together in a single write operation.
This is implemented as an NVQUIRK as it applies to T114, T124 and
T132.
Signed-off-by: Pavan Kunapuli <pkunapuli@nvidia.com>
Signed-off-by: Rhyland Klein <rklein@nvidia.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/sdhci-tegra.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 59797106af93..f3778d58d1cd 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #define NVQUIRK_DISABLE_SDR50 BIT(3) | 41 | #define NVQUIRK_DISABLE_SDR50 BIT(3) |
42 | #define NVQUIRK_DISABLE_SDR104 BIT(4) | 42 | #define NVQUIRK_DISABLE_SDR104 BIT(4) |
43 | #define NVQUIRK_DISABLE_DDR50 BIT(5) | 43 | #define NVQUIRK_DISABLE_DDR50 BIT(5) |
44 | #define NVQUIRK_SHADOW_XFER_MODE_REG BIT(6) | ||
44 | 45 | ||
45 | struct sdhci_tegra_soc_data { | 46 | struct sdhci_tegra_soc_data { |
46 | const struct sdhci_pltfm_data *pdata; | 47 | const struct sdhci_pltfm_data *pdata; |
@@ -67,6 +68,31 @@ static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) | |||
67 | return readw(host->ioaddr + reg); | 68 | return readw(host->ioaddr + reg); |
68 | } | 69 | } |
69 | 70 | ||
71 | static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) | ||
72 | { | ||
73 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
74 | struct sdhci_tegra *tegra_host = pltfm_host->priv; | ||
75 | const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; | ||
76 | |||
77 | if (soc_data->nvquirks & NVQUIRK_SHADOW_XFER_MODE_REG) { | ||
78 | switch (reg) { | ||
79 | case SDHCI_TRANSFER_MODE: | ||
80 | /* | ||
81 | * Postpone this write, we must do it together with a | ||
82 | * command write that is down below. | ||
83 | */ | ||
84 | pltfm_host->xfer_mode_shadow = val; | ||
85 | return; | ||
86 | case SDHCI_COMMAND: | ||
87 | writel((val << 16) | pltfm_host->xfer_mode_shadow, | ||
88 | host->ioaddr + SDHCI_TRANSFER_MODE); | ||
89 | return; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | writew(val, host->ioaddr + reg); | ||
94 | } | ||
95 | |||
70 | static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) | 96 | static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) |
71 | { | 97 | { |
72 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 98 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
@@ -147,6 +173,7 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width) | |||
147 | static const struct sdhci_ops tegra_sdhci_ops = { | 173 | static const struct sdhci_ops tegra_sdhci_ops = { |
148 | .get_ro = tegra_sdhci_get_ro, | 174 | .get_ro = tegra_sdhci_get_ro, |
149 | .read_w = tegra_sdhci_readw, | 175 | .read_w = tegra_sdhci_readw, |
176 | .write_w = tegra_sdhci_writew, | ||
150 | .write_l = tegra_sdhci_writel, | 177 | .write_l = tegra_sdhci_writel, |
151 | .set_clock = sdhci_set_clock, | 178 | .set_clock = sdhci_set_clock, |
152 | .set_bus_width = tegra_sdhci_set_bus_width, | 179 | .set_bus_width = tegra_sdhci_set_bus_width, |
@@ -201,7 +228,8 @@ static struct sdhci_tegra_soc_data soc_data_tegra114 = { | |||
201 | .pdata = &sdhci_tegra114_pdata, | 228 | .pdata = &sdhci_tegra114_pdata, |
202 | .nvquirks = NVQUIRK_DISABLE_SDR50 | | 229 | .nvquirks = NVQUIRK_DISABLE_SDR50 | |
203 | NVQUIRK_DISABLE_DDR50 | | 230 | NVQUIRK_DISABLE_DDR50 | |
204 | NVQUIRK_DISABLE_SDR104, | 231 | NVQUIRK_DISABLE_SDR104 | |
232 | NVQUIRK_SHADOW_XFER_MODE_REG, | ||
205 | }; | 233 | }; |
206 | 234 | ||
207 | static const struct of_device_id sdhci_tegra_dt_match[] = { | 235 | static const struct of_device_id sdhci_tegra_dt_match[] = { |