aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/core/core.c34
-rw-r--r--drivers/mmc/core/core.h2
-rw-r--r--drivers/mmc/core/mmc.c11
-rw-r--r--drivers/mmc/core/sd.c11
-rw-r--r--include/linux/mmc/host.h3
5 files changed, 61 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 02f2b1871a38..be1fc013fbe9 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1151,6 +1151,40 @@ void mmc_stop_host(struct mmc_host *host)
1151 mmc_power_off(host); 1151 mmc_power_off(host);
1152} 1152}
1153 1153
1154void mmc_power_save_host(struct mmc_host *host)
1155{
1156 mmc_bus_get(host);
1157
1158 if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
1159 mmc_bus_put(host);
1160 return;
1161 }
1162
1163 if (host->bus_ops->power_save)
1164 host->bus_ops->power_save(host);
1165
1166 mmc_bus_put(host);
1167
1168 mmc_power_off(host);
1169}
1170EXPORT_SYMBOL(mmc_power_save_host);
1171
1172void mmc_power_restore_host(struct mmc_host *host)
1173{
1174 mmc_bus_get(host);
1175
1176 if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) {
1177 mmc_bus_put(host);
1178 return;
1179 }
1180
1181 mmc_power_up(host);
1182 host->bus_ops->power_restore(host);
1183
1184 mmc_bus_put(host);
1185}
1186EXPORT_SYMBOL(mmc_power_restore_host);
1187
1154#ifdef CONFIG_PM 1188#ifdef CONFIG_PM
1155 1189
1156/** 1190/**
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index c819effa1032..f7eb4c4ca014 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -20,6 +20,8 @@ struct mmc_bus_ops {
20 void (*detect)(struct mmc_host *); 20 void (*detect)(struct mmc_host *);
21 void (*suspend)(struct mmc_host *); 21 void (*suspend)(struct mmc_host *);
22 void (*resume)(struct mmc_host *); 22 void (*resume)(struct mmc_host *);
23 void (*power_save)(struct mmc_host *);
24 void (*power_restore)(struct mmc_host *);
23}; 25};
24 26
25void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); 27void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 995db1853a81..27e842df6a6f 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -549,6 +549,14 @@ static void mmc_resume(struct mmc_host *host)
549 549
550} 550}
551 551
552static void mmc_power_restore(struct mmc_host *host)
553{
554 host->card->state &= ~MMC_STATE_HIGHSPEED;
555 mmc_claim_host(host);
556 mmc_init_card(host, host->ocr, host->card);
557 mmc_release_host(host);
558}
559
552#ifdef CONFIG_MMC_UNSAFE_RESUME 560#ifdef CONFIG_MMC_UNSAFE_RESUME
553 561
554static const struct mmc_bus_ops mmc_ops = { 562static const struct mmc_bus_ops mmc_ops = {
@@ -556,6 +564,7 @@ static const struct mmc_bus_ops mmc_ops = {
556 .detect = mmc_detect, 564 .detect = mmc_detect,
557 .suspend = mmc_suspend, 565 .suspend = mmc_suspend,
558 .resume = mmc_resume, 566 .resume = mmc_resume,
567 .power_restore = mmc_power_restore,
559}; 568};
560 569
561static void mmc_attach_bus_ops(struct mmc_host *host) 570static void mmc_attach_bus_ops(struct mmc_host *host)
@@ -570,6 +579,7 @@ static const struct mmc_bus_ops mmc_ops = {
570 .detect = mmc_detect, 579 .detect = mmc_detect,
571 .suspend = NULL, 580 .suspend = NULL,
572 .resume = NULL, 581 .resume = NULL,
582 .power_restore = mmc_power_restore,
573}; 583};
574 584
575static const struct mmc_bus_ops mmc_ops_unsafe = { 585static const struct mmc_bus_ops mmc_ops_unsafe = {
@@ -577,6 +587,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
577 .detect = mmc_detect, 587 .detect = mmc_detect,
578 .suspend = mmc_suspend, 588 .suspend = mmc_suspend,
579 .resume = mmc_resume, 589 .resume = mmc_resume,
590 .power_restore = mmc_power_restore,
580}; 591};
581 592
582static void mmc_attach_bus_ops(struct mmc_host *host) 593static void mmc_attach_bus_ops(struct mmc_host *host)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 92fa9dceca79..222a60928cdb 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -603,6 +603,14 @@ static void mmc_sd_resume(struct mmc_host *host)
603 603
604} 604}
605 605
606static void mmc_sd_power_restore(struct mmc_host *host)
607{
608 host->card->state &= ~MMC_STATE_HIGHSPEED;
609 mmc_claim_host(host);
610 mmc_sd_init_card(host, host->ocr, host->card);
611 mmc_release_host(host);
612}
613
606#ifdef CONFIG_MMC_UNSAFE_RESUME 614#ifdef CONFIG_MMC_UNSAFE_RESUME
607 615
608static const struct mmc_bus_ops mmc_sd_ops = { 616static const struct mmc_bus_ops mmc_sd_ops = {
@@ -610,6 +618,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {
610 .detect = mmc_sd_detect, 618 .detect = mmc_sd_detect,
611 .suspend = mmc_sd_suspend, 619 .suspend = mmc_sd_suspend,
612 .resume = mmc_sd_resume, 620 .resume = mmc_sd_resume,
621 .power_restore = mmc_sd_power_restore,
613}; 622};
614 623
615static void mmc_sd_attach_bus_ops(struct mmc_host *host) 624static void mmc_sd_attach_bus_ops(struct mmc_host *host)
@@ -624,6 +633,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {
624 .detect = mmc_sd_detect, 633 .detect = mmc_sd_detect,
625 .suspend = NULL, 634 .suspend = NULL,
626 .resume = NULL, 635 .resume = NULL,
636 .power_restore = mmc_sd_power_restore,
627}; 637};
628 638
629static const struct mmc_bus_ops mmc_sd_ops_unsafe = { 639static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
@@ -631,6 +641,7 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
631 .detect = mmc_sd_detect, 641 .detect = mmc_sd_detect,
632 .suspend = mmc_sd_suspend, 642 .suspend = mmc_sd_suspend,
633 .resume = mmc_sd_resume, 643 .resume = mmc_sd_resume,
644 .power_restore = mmc_sd_power_restore,
634}; 645};
635 646
636static void mmc_sd_attach_bus_ops(struct mmc_host *host) 647static void mmc_sd_attach_bus_ops(struct mmc_host *host)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index bb867d2c26bd..c1cbe598d470 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -223,6 +223,9 @@ static inline void *mmc_priv(struct mmc_host *host)
223extern int mmc_suspend_host(struct mmc_host *, pm_message_t); 223extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
224extern int mmc_resume_host(struct mmc_host *); 224extern int mmc_resume_host(struct mmc_host *);
225 225
226extern void mmc_power_save_host(struct mmc_host *host);
227extern void mmc_power_restore_host(struct mmc_host *host);
228
226extern void mmc_detect_change(struct mmc_host *, unsigned long delay); 229extern void mmc_detect_change(struct mmc_host *, unsigned long delay);
227extern void mmc_request_done(struct mmc_host *, struct mmc_request *); 230extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
228 231