aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorDaniel Drake <dsd@laptop.org>2010-03-05 16:43:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-06 14:26:37 -0500
commit6b5eda369ac3772dad416ef96d86064204d74770 (patch)
treecf137f4f28c62d8e8d1683590048b75830c1e9a2 /drivers/mmc
parent40216842dca4fa485cb1aa5eb231149a4a57cc85 (diff)
sdio: put active devices into 1-bit mode during suspend
And bring them back to 4-bit mode during resume. Signed-off-by: Daniel Drake <dsd@laptop.org> Signed-off-by: Nicolas Pitre <nico@marvell.com> 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/mmc')
-rw-r--r--drivers/mmc/core/sdio.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 5840de106b69..2dd4cfe7ca17 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -188,6 +188,40 @@ static int sdio_disable_cd(struct mmc_card *card)
188} 188}
189 189
190/* 190/*
191 * Devices that remain active during a system suspend are
192 * put back into 1-bit mode.
193 */
194static int sdio_disable_wide(struct mmc_card *card)
195{
196 int ret;
197 u8 ctrl;
198
199 if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
200 return 0;
201
202 if (card->cccr.low_speed && !card->cccr.wide_bus)
203 return 0;
204
205 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
206 if (ret)
207 return ret;
208
209 if (!(ctrl & SDIO_BUS_WIDTH_4BIT))
210 return 0;
211
212 ctrl &= ~SDIO_BUS_WIDTH_4BIT;
213 ctrl |= SDIO_BUS_ASYNC_INT;
214
215 ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
216 if (ret)
217 return ret;
218
219 mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1);
220
221 return 0;
222}
223
224/*
191 * Test if the card supports high-speed mode and, if so, switch to it. 225 * Test if the card supports high-speed mode and, if so, switch to it.
192 */ 226 */
193static int sdio_enable_hs(struct mmc_card *card) 227static int sdio_enable_hs(struct mmc_card *card)
@@ -427,6 +461,12 @@ static int mmc_sdio_suspend(struct mmc_host *host)
427 } 461 }
428 } 462 }
429 463
464 if (!err && host->pm_flags & MMC_PM_KEEP_POWER) {
465 mmc_claim_host(host);
466 sdio_disable_wide(host->card);
467 mmc_release_host(host);
468 }
469
430 return err; 470 return err;
431} 471}
432 472
@@ -441,6 +481,9 @@ static int mmc_sdio_resume(struct mmc_host *host)
441 mmc_claim_host(host); 481 mmc_claim_host(host);
442 err = mmc_sdio_init_card(host, host->ocr, host->card, 482 err = mmc_sdio_init_card(host, host->ocr, host->card,
443 (host->pm_flags & MMC_PM_KEEP_POWER)); 483 (host->pm_flags & MMC_PM_KEEP_POWER));
484 if (!err)
485 /* We may have switched to 1-bit mode during suspend. */
486 err = sdio_enable_wide(host->card);
444 if (!err && host->sdio_irqs) 487 if (!err && host->sdio_irqs)
445 mmc_signal_sdio_irq(host); 488 mmc_signal_sdio_irq(host);
446 mmc_release_host(host); 489 mmc_release_host(host);