diff options
author | Nicolas Pitre <nico@fluxnic.net> | 2010-03-05 16:43:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-03-06 14:26:36 -0500 |
commit | da68c4eb258cd9f3f0b8aeb7e46b8118bb6358b6 (patch) | |
tree | b7767ce0b0d05d16dec6eeeadd21bd70cc458ac7 /drivers/mmc/core/core.c | |
parent | 9e506f35b1dc327c448d4791bc098f07b9b2efe9 (diff) |
sdio: introduce API for special power management features
This patch series provides the core changes needed to allow SDIO cards to
remain powered and active while the host system is suspended, and let them
wake up the host system when needed. This is used to implement
wake-on-lan with SDIO wireless cards at the moment. Patches to add that
support to the libertas driver will be posted separately.
This patch:
Some SDIO cards have the ability to keep on running autonomously when the
host system is suspended, and wake it up when needed. This however
requires that the host controller preserve power to the card, and
configure itself appropriately for wake-up.
There is however 4 layers of abstractions involved: the host controller
driver, the MMC core code, the SDIO card management code, and the actual
SDIO function driver. To make things simple and manageable, host drivers
must advertise their PM capabilities with a feature bitmask, then function
drivers can query and set those features from their suspend method. Then
each layer in the suspend call chain is expected to act upon those bits
accordingly.
[akpm@linux-foundation.org: fix typo in comment]
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/core/core.c')
-rw-r--r-- | drivers/mmc/core/core.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 30acd5265821..f4b97d3c3d0f 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1151,6 +1151,9 @@ void mmc_stop_host(struct mmc_host *host) | |||
1151 | cancel_delayed_work(&host->detect); | 1151 | cancel_delayed_work(&host->detect); |
1152 | mmc_flush_scheduled_work(); | 1152 | mmc_flush_scheduled_work(); |
1153 | 1153 | ||
1154 | /* clear pm flags now and let card drivers set them as needed */ | ||
1155 | host->pm_flags = 0; | ||
1156 | |||
1154 | mmc_bus_get(host); | 1157 | mmc_bus_get(host); |
1155 | if (host->bus_ops && !host->bus_dead) { | 1158 | if (host->bus_ops && !host->bus_dead) { |
1156 | if (host->bus_ops->remove) | 1159 | if (host->bus_ops->remove) |
@@ -1273,12 +1276,13 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) | |||
1273 | mmc_claim_host(host); | 1276 | mmc_claim_host(host); |
1274 | mmc_detach_bus(host); | 1277 | mmc_detach_bus(host); |
1275 | mmc_release_host(host); | 1278 | mmc_release_host(host); |
1279 | host->pm_flags = 0; | ||
1276 | err = 0; | 1280 | err = 0; |
1277 | } | 1281 | } |
1278 | } | 1282 | } |
1279 | mmc_bus_put(host); | 1283 | mmc_bus_put(host); |
1280 | 1284 | ||
1281 | if (!err) | 1285 | if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) |
1282 | mmc_power_off(host); | 1286 | mmc_power_off(host); |
1283 | 1287 | ||
1284 | return err; | 1288 | return err; |
@@ -1296,8 +1300,10 @@ int mmc_resume_host(struct mmc_host *host) | |||
1296 | 1300 | ||
1297 | mmc_bus_get(host); | 1301 | mmc_bus_get(host); |
1298 | if (host->bus_ops && !host->bus_dead) { | 1302 | if (host->bus_ops && !host->bus_dead) { |
1299 | mmc_power_up(host); | 1303 | if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { |
1300 | mmc_select_voltage(host, host->ocr); | 1304 | mmc_power_up(host); |
1305 | mmc_select_voltage(host, host->ocr); | ||
1306 | } | ||
1301 | BUG_ON(!host->bus_ops->resume); | 1307 | BUG_ON(!host->bus_ops->resume); |
1302 | err = host->bus_ops->resume(host); | 1308 | err = host->bus_ops->resume(host); |
1303 | if (err) { | 1309 | if (err) { |