mmc: core: Restructure and simplify code for mmc sleep|awake
The mmc_card_sleep|awake APIs are not being used since the support is already properly encapsulated within the suspend sequence. Sleep|awake command is also specific for eMMC. We remove the sleep|awake bus_ops, the mmc_card_sleep|awake APIs and move the code into the mmc specific core instead. This also includes the mmc ops function, mmc_sleepawake. All releated functions have then become static and we have got far less code to maintain. Additionally this patch also simplifies the code from mmc_sleepawake, since it is only used to put the card to sleep and not awake. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:
parent
c4d770d724
commit
07a6821608
6 changed files with 41 additions and 123 deletions
|
@ -2550,52 +2550,6 @@ int mmc_power_restore_host(struct mmc_host *host)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_power_restore_host);
|
EXPORT_SYMBOL(mmc_power_restore_host);
|
||||||
|
|
||||||
int mmc_card_awake(struct mmc_host *host)
|
|
||||||
{
|
|
||||||
int err = -ENOSYS;
|
|
||||||
|
|
||||||
if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
mmc_bus_get(host);
|
|
||||||
|
|
||||||
if (host->bus_ops && !host->bus_dead && host->bus_ops->awake)
|
|
||||||
err = host->bus_ops->awake(host);
|
|
||||||
|
|
||||||
mmc_bus_put(host);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(mmc_card_awake);
|
|
||||||
|
|
||||||
int mmc_card_sleep(struct mmc_host *host)
|
|
||||||
{
|
|
||||||
int err = -ENOSYS;
|
|
||||||
|
|
||||||
if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
mmc_bus_get(host);
|
|
||||||
|
|
||||||
if (host->bus_ops && !host->bus_dead && host->bus_ops->sleep)
|
|
||||||
err = host->bus_ops->sleep(host);
|
|
||||||
|
|
||||||
mmc_bus_put(host);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(mmc_card_sleep);
|
|
||||||
|
|
||||||
int mmc_card_can_sleep(struct mmc_host *host)
|
|
||||||
{
|
|
||||||
struct mmc_card *card = host->card;
|
|
||||||
|
|
||||||
if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(mmc_card_can_sleep);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush the cache to the non-volatile storage.
|
* Flush the cache to the non-volatile storage.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,8 +16,6 @@
|
||||||
#define MMC_CMD_RETRIES 3
|
#define MMC_CMD_RETRIES 3
|
||||||
|
|
||||||
struct mmc_bus_ops {
|
struct mmc_bus_ops {
|
||||||
int (*awake)(struct mmc_host *);
|
|
||||||
int (*sleep)(struct mmc_host *);
|
|
||||||
void (*remove)(struct mmc_host *);
|
void (*remove)(struct mmc_host *);
|
||||||
void (*detect)(struct mmc_host *);
|
void (*detect)(struct mmc_host *);
|
||||||
int (*suspend)(struct mmc_host *);
|
int (*suspend)(struct mmc_host *);
|
||||||
|
|
|
@ -1321,6 +1321,45 @@ err:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mmc_can_sleep(struct mmc_card *card)
|
||||||
|
{
|
||||||
|
return (card && card->ext_csd.rev >= 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mmc_sleep(struct mmc_host *host)
|
||||||
|
{
|
||||||
|
struct mmc_command cmd = {0};
|
||||||
|
struct mmc_card *card = host->card;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (host->caps2 & MMC_CAP2_NO_SLEEP_CMD)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = mmc_deselect_cards(host);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
cmd.opcode = MMC_SLEEP_AWAKE;
|
||||||
|
cmd.arg = card->rca << 16;
|
||||||
|
cmd.arg |= 1 << 15;
|
||||||
|
|
||||||
|
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||||
|
err = mmc_wait_for_cmd(host, &cmd, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the host does not wait while the card signals busy, then we will
|
||||||
|
* will have to wait the sleep/awake timeout. Note, we cannot use the
|
||||||
|
* SEND_STATUS command to poll the status because that command (and most
|
||||||
|
* others) is invalid while the card sleeps.
|
||||||
|
*/
|
||||||
|
if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
|
||||||
|
mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int mmc_can_poweroff_notify(const struct mmc_card *card)
|
static int mmc_can_poweroff_notify(const struct mmc_card *card)
|
||||||
{
|
{
|
||||||
return card &&
|
return card &&
|
||||||
|
@ -1423,8 +1462,8 @@ static int mmc_suspend(struct mmc_host *host)
|
||||||
|
|
||||||
if (mmc_can_poweroff_notify(host->card))
|
if (mmc_can_poweroff_notify(host->card))
|
||||||
err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
|
err = mmc_poweroff_notify(host->card, EXT_CSD_POWER_OFF_SHORT);
|
||||||
else if (mmc_card_can_sleep(host))
|
else if (mmc_can_sleep(host->card))
|
||||||
err = mmc_card_sleep(host);
|
err = mmc_sleep(host);
|
||||||
else if (!mmc_host_is_spi(host))
|
else if (!mmc_host_is_spi(host))
|
||||||
err = mmc_deselect_cards(host);
|
err = mmc_deselect_cards(host);
|
||||||
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
|
host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200);
|
||||||
|
@ -1514,39 +1553,7 @@ static int mmc_power_restore(struct mmc_host *host)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmc_sleep(struct mmc_host *host)
|
|
||||||
{
|
|
||||||
struct mmc_card *card = host->card;
|
|
||||||
int err = -ENOSYS;
|
|
||||||
|
|
||||||
if (card && card->ext_csd.rev >= 3) {
|
|
||||||
err = mmc_card_sleepawake(host, 1);
|
|
||||||
if (err < 0)
|
|
||||||
pr_debug("%s: Error %d while putting card into sleep",
|
|
||||||
mmc_hostname(host), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mmc_awake(struct mmc_host *host)
|
|
||||||
{
|
|
||||||
struct mmc_card *card = host->card;
|
|
||||||
int err = -ENOSYS;
|
|
||||||
|
|
||||||
if (card && card->ext_csd.rev >= 3) {
|
|
||||||
err = mmc_card_sleepawake(host, 0);
|
|
||||||
if (err < 0)
|
|
||||||
pr_debug("%s: Error %d while awaking sleeping card",
|
|
||||||
mmc_hostname(host), err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct mmc_bus_ops mmc_ops = {
|
static const struct mmc_bus_ops mmc_ops = {
|
||||||
.awake = mmc_awake,
|
|
||||||
.sleep = mmc_sleep,
|
|
||||||
.remove = mmc_remove,
|
.remove = mmc_remove,
|
||||||
.detect = mmc_detect,
|
.detect = mmc_detect,
|
||||||
.suspend = NULL,
|
.suspend = NULL,
|
||||||
|
@ -1556,8 +1563,6 @@ static const struct mmc_bus_ops mmc_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mmc_bus_ops mmc_ops_unsafe = {
|
static const struct mmc_bus_ops mmc_ops_unsafe = {
|
||||||
.awake = mmc_awake,
|
|
||||||
.sleep = mmc_sleep,
|
|
||||||
.remove = mmc_remove,
|
.remove = mmc_remove,
|
||||||
.detect = mmc_detect,
|
.detect = mmc_detect,
|
||||||
.suspend = mmc_suspend,
|
.suspend = mmc_suspend,
|
||||||
|
|
|
@ -59,40 +59,6 @@ int mmc_deselect_cards(struct mmc_host *host)
|
||||||
return _mmc_select_card(host, NULL);
|
return _mmc_select_card(host, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mmc_card_sleepawake(struct mmc_host *host, int sleep)
|
|
||||||
{
|
|
||||||
struct mmc_command cmd = {0};
|
|
||||||
struct mmc_card *card = host->card;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if (sleep)
|
|
||||||
mmc_deselect_cards(host);
|
|
||||||
|
|
||||||
cmd.opcode = MMC_SLEEP_AWAKE;
|
|
||||||
cmd.arg = card->rca << 16;
|
|
||||||
if (sleep)
|
|
||||||
cmd.arg |= 1 << 15;
|
|
||||||
|
|
||||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
|
||||||
err = mmc_wait_for_cmd(host, &cmd, 0);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the host does not wait while the card signals busy, then we will
|
|
||||||
* will have to wait the sleep/awake timeout. Note, we cannot use the
|
|
||||||
* SEND_STATUS command to poll the status because that command (and most
|
|
||||||
* others) is invalid while the card sleeps.
|
|
||||||
*/
|
|
||||||
if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
|
|
||||||
mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000));
|
|
||||||
|
|
||||||
if (!sleep)
|
|
||||||
err = mmc_select_card(card);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mmc_go_idle(struct mmc_host *host)
|
int mmc_go_idle(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
|
@ -24,7 +24,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status);
|
||||||
int mmc_send_cid(struct mmc_host *host, u32 *cid);
|
int mmc_send_cid(struct mmc_host *host, u32 *cid);
|
||||||
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
|
int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp);
|
||||||
int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
|
int mmc_spi_set_crc(struct mmc_host *host, int use_crc);
|
||||||
int mmc_card_sleepawake(struct mmc_host *host, int sleep);
|
|
||||||
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
|
int mmc_bus_test(struct mmc_card *card, u8 bus_width);
|
||||||
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
|
int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status);
|
||||||
|
|
||||||
|
|
|
@ -425,10 +425,6 @@ static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int mmc_card_awake(struct mmc_host *host);
|
|
||||||
int mmc_card_sleep(struct mmc_host *host);
|
|
||||||
int mmc_card_can_sleep(struct mmc_host *host);
|
|
||||||
|
|
||||||
int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
|
int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);
|
||||||
|
|
||||||
/* Module parameter */
|
/* Module parameter */
|
||||||
|
|
Loading…
Add table
Reference in a new issue