diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-09-22 19:45:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 10:39:37 -0400 |
commit | 81b39802468fe4bf5c6b038837319b608acfdd3e (patch) | |
tree | aa5e95bcee95cb4dd7a4811abd8e740f4ef4a958 /drivers | |
parent | c08592698534f390afe726c38301aa8f1620c361 (diff) |
sdhci-of: fix high-speed cards recognition
eSDHC fails to recognize some SDHS cards, throwing timeout errors:
mmc0: error -110 whilst initialising SD card
That's because we calculate timeout value in a wrong way: on eSDHC hosts
the timeout clock is derivied from the SD clock, which is set dynamically.
As David Vrabel suggested, deriving timeout clock from SD clock is a
common scheme, so let's implement DATA_TIMEOUT_USES_SDCLK quirk and use it
for eSDHC hosts.
Also, from now on we don't need esdhc_get_timeout_clock() callback, so
remove it.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Cc: Pierre Ossman <pierre@ossman.eu>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: David Vrabel <david.vrabel@csr.com>
Cc: Ben Dooks <ben@fluff.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: <linux-mmc@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/host/sdhci-of.c | 9 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 9 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 2 |
3 files changed, 10 insertions, 10 deletions
diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c index 3439fc118904..56041dc74ce1 100644 --- a/drivers/mmc/host/sdhci-of.c +++ b/drivers/mmc/host/sdhci-of.c | |||
@@ -172,19 +172,13 @@ static unsigned int esdhc_get_min_clock(struct sdhci_host *host) | |||
172 | return of_host->clock / 256 / 16; | 172 | return of_host->clock / 256 / 16; |
173 | } | 173 | } |
174 | 174 | ||
175 | static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host) | ||
176 | { | ||
177 | struct sdhci_of_host *of_host = sdhci_priv(host); | ||
178 | |||
179 | return of_host->clock / 1000; | ||
180 | } | ||
181 | |||
182 | static struct sdhci_of_data sdhci_esdhc = { | 175 | static struct sdhci_of_data sdhci_esdhc = { |
183 | .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 | | 176 | .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 | |
184 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | | 177 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | |
185 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT | | 178 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT | |
186 | SDHCI_QUIRK_NO_BUSY_IRQ | | 179 | SDHCI_QUIRK_NO_BUSY_IRQ | |
187 | SDHCI_QUIRK_NONSTANDARD_CLOCK | | 180 | SDHCI_QUIRK_NONSTANDARD_CLOCK | |
181 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | | ||
188 | SDHCI_QUIRK_PIO_NEEDS_DELAY | | 182 | SDHCI_QUIRK_PIO_NEEDS_DELAY | |
189 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | | 183 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | |
190 | SDHCI_QUIRK_NO_CARD_NO_RESET, | 184 | SDHCI_QUIRK_NO_CARD_NO_RESET, |
@@ -199,7 +193,6 @@ static struct sdhci_of_data sdhci_esdhc = { | |||
199 | .enable_dma = esdhc_enable_dma, | 193 | .enable_dma = esdhc_enable_dma, |
200 | .get_max_clock = esdhc_get_max_clock, | 194 | .get_max_clock = esdhc_get_max_clock, |
201 | .get_min_clock = esdhc_get_min_clock, | 195 | .get_min_clock = esdhc_get_min_clock, |
202 | .get_timeout_clock = esdhc_get_timeout_clock, | ||
203 | }, | 196 | }, |
204 | }; | 197 | }; |
205 | 198 | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7f7f45b4b07b..38a78743fc51 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -591,6 +591,9 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | |||
591 | target_timeout = data->timeout_ns / 1000 + | 591 | target_timeout = data->timeout_ns / 1000 + |
592 | data->timeout_clks / host->clock; | 592 | data->timeout_clks / host->clock; |
593 | 593 | ||
594 | if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) | ||
595 | host->timeout_clk = host->clock / 1000; | ||
596 | |||
594 | /* | 597 | /* |
595 | * Figure out needed cycles. | 598 | * Figure out needed cycles. |
596 | * We do this in steps in order to fit inside a 32 bit int. | 599 | * We do this in steps in order to fit inside a 32 bit int. |
@@ -1757,13 +1760,15 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1757 | host->timeout_clk = | 1760 | host->timeout_clk = |
1758 | (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; | 1761 | (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; |
1759 | if (host->timeout_clk == 0) { | 1762 | if (host->timeout_clk == 0) { |
1760 | if (!host->ops->get_timeout_clock) { | 1763 | if (host->ops->get_timeout_clock) { |
1764 | host->timeout_clk = host->ops->get_timeout_clock(host); | ||
1765 | } else if (!(host->quirks & | ||
1766 | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { | ||
1761 | printk(KERN_ERR | 1767 | printk(KERN_ERR |
1762 | "%s: Hardware doesn't specify timeout clock " | 1768 | "%s: Hardware doesn't specify timeout clock " |
1763 | "frequency.\n", mmc_hostname(mmc)); | 1769 | "frequency.\n", mmc_hostname(mmc)); |
1764 | return -ENODEV; | 1770 | return -ENODEV; |
1765 | } | 1771 | } |
1766 | host->timeout_clk = host->ops->get_timeout_clock(host); | ||
1767 | } | 1772 | } |
1768 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) | 1773 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) |
1769 | host->timeout_clk *= 1000; | 1774 | host->timeout_clk *= 1000; |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index c77e9ff30223..afda7f126e0d 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -232,6 +232,8 @@ struct sdhci_host { | |||
232 | #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) | 232 | #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) |
233 | /* Controller needs 10ms delay between applying power and clock */ | 233 | /* Controller needs 10ms delay between applying power and clock */ |
234 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) | 234 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) |
235 | /* Controller uses SDCLK instead of TMCLK for data timeouts */ | ||
236 | #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) | ||
235 | 237 | ||
236 | int irq; /* Device IRQ */ | 238 | int irq; /* Device IRQ */ |
237 | void __iomem * ioaddr; /* Mapped address */ | 239 | void __iomem * ioaddr; /* Mapped address */ |