aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/core/mmc_ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/core/mmc_ops.c')
-rw-r--r--drivers/mmc/core/mmc_ops.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 34ce2703d29a..d2cb5c634392 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -57,6 +57,42 @@ int mmc_deselect_cards(struct mmc_host *host)
57 return _mmc_select_card(host, NULL); 57 return _mmc_select_card(host, NULL);
58} 58}
59 59
60int mmc_card_sleepawake(struct mmc_host *host, int sleep)
61{
62 struct mmc_command cmd;
63 struct mmc_card *card = host->card;
64 int err;
65
66 if (sleep)
67 mmc_deselect_cards(host);
68
69 memset(&cmd, 0, sizeof(struct mmc_command));
70
71 cmd.opcode = MMC_SLEEP_AWAKE;
72 cmd.arg = card->rca << 16;
73 if (sleep)
74 cmd.arg |= 1 << 15;
75
76 cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
77 err = mmc_wait_for_cmd(host, &cmd, 0);
78 if (err)
79 return err;
80
81 /*
82 * If the host does not wait while the card signals busy, then we will
83 * will have to wait the sleep/awake timeout. Note, we cannot use the
84 * SEND_STATUS command to poll the status because that command (and most
85 * others) is invalid while the card sleeps.
86 */
87 if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
88 mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
89
90 if (!sleep)
91 err = mmc_select_card(card);
92
93 return err;
94}
95
60int mmc_go_idle(struct mmc_host *host) 96int mmc_go_idle(struct mmc_host *host)
61{ 97{
62 int err; 98 int err;
@@ -354,6 +390,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
354{ 390{
355 int err; 391 int err;
356 struct mmc_command cmd; 392 struct mmc_command cmd;
393 u32 status;
357 394
358 BUG_ON(!card); 395 BUG_ON(!card);
359 BUG_ON(!card->host); 396 BUG_ON(!card->host);
@@ -371,6 +408,28 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value)
371 if (err) 408 if (err)
372 return err; 409 return err;
373 410
411 /* Must check status to be sure of no errors */
412 do {
413 err = mmc_send_status(card, &status);
414 if (err)
415 return err;
416 if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
417 break;
418 if (mmc_host_is_spi(card->host))
419 break;
420 } while (R1_CURRENT_STATE(status) == 7);
421
422 if (mmc_host_is_spi(card->host)) {
423 if (status & R1_SPI_ILLEGAL_COMMAND)
424 return -EBADMSG;
425 } else {
426 if (status & 0xFDFFA000)
427 printk(KERN_WARNING "%s: unexpected status %#x after "
428 "switch", mmc_hostname(card->host), status);
429 if (status & R1_SWITCH_ERROR)
430 return -EBADMSG;
431 }
432
374 return 0; 433 return 0;
375} 434}
376 435