diff options
author | Adrian Hunter <adrian.hunter@nokia.com> | 2009-09-22 19:44:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 10:39:35 -0400 |
commit | 9b7c18e070d59ba0acfdb936fd613dfa1d2a4e7d (patch) | |
tree | bb816920c3fdafd27ee59b4e1256843d136c8c8d /arch/arm | |
parent | dd498effcfa6a196ba097adae3c5aa641115df88 (diff) |
ARM: OMAP: mmc-twl4030: add regulator sleep / wake function
Add the ability for the driver to put the card power regulators to sleep
and wake them up again.
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com>
Acked-by: Matt Fleming <matt@console-pimps.org>
Cc: Ian Molton <ian@mnementh.co.uk>
Cc: "Roberto A. Foglietta" <roberto.foglietta@gmail.com>
Cc: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Cc: Denis Karpov <ext-denis.2.karpov@nokia.com>
Cc: Pierre Ossman <pierre@ossman.eu>
Cc: Philip Langdale <philipl@overt.org>
Cc: "Madhusudhan" <madhu.cr@ti.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 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/mmc-twl4030.c | 57 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/mach/mmc.h | 2 |
2 files changed, 59 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index cb1cbd7934ae..c9c59a2db4e2 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c | |||
@@ -340,6 +340,61 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v | |||
340 | return ret; | 340 | return ret; |
341 | } | 341 | } |
342 | 342 | ||
343 | static int twl_mmc1_set_sleep(struct device *dev, int slot, int sleep, int vdd, | ||
344 | int cardsleep) | ||
345 | { | ||
346 | struct twl_mmc_controller *c = &hsmmc[0]; | ||
347 | int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
348 | |||
349 | return regulator_set_mode(c->vcc, mode); | ||
350 | } | ||
351 | |||
352 | static int twl_mmc23_set_sleep(struct device *dev, int slot, int sleep, int vdd, | ||
353 | int cardsleep) | ||
354 | { | ||
355 | struct twl_mmc_controller *c = NULL; | ||
356 | struct omap_mmc_platform_data *mmc = dev->platform_data; | ||
357 | int i, err, mode; | ||
358 | |||
359 | for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { | ||
360 | if (mmc == hsmmc[i].mmc) { | ||
361 | c = &hsmmc[i]; | ||
362 | break; | ||
363 | } | ||
364 | } | ||
365 | |||
366 | if (c == NULL) | ||
367 | return -ENODEV; | ||
368 | |||
369 | /* | ||
370 | * If we don't see a Vcc regulator, assume it's a fixed | ||
371 | * voltage always-on regulator. | ||
372 | */ | ||
373 | if (!c->vcc) | ||
374 | return 0; | ||
375 | |||
376 | mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; | ||
377 | |||
378 | if (!c->vcc_aux) | ||
379 | return regulator_set_mode(c->vcc, mode); | ||
380 | |||
381 | if (cardsleep) { | ||
382 | /* VCC can be turned off if card is asleep */ | ||
383 | struct regulator *vcc_aux = c->vcc_aux; | ||
384 | |||
385 | c->vcc_aux = NULL; | ||
386 | if (sleep) | ||
387 | err = twl_mmc23_set_power(dev, slot, 0, 0); | ||
388 | else | ||
389 | err = twl_mmc23_set_power(dev, slot, 1, vdd); | ||
390 | c->vcc_aux = vcc_aux; | ||
391 | } else | ||
392 | err = regulator_set_mode(c->vcc, mode); | ||
393 | if (err) | ||
394 | return err; | ||
395 | return regulator_set_mode(c->vcc_aux, mode); | ||
396 | } | ||
397 | |||
343 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; | 398 | static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; |
344 | 399 | ||
345 | void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | 400 | void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) |
@@ -433,6 +488,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
433 | case 1: | 488 | case 1: |
434 | /* on-chip level shifting via PBIAS0/PBIAS1 */ | 489 | /* on-chip level shifting via PBIAS0/PBIAS1 */ |
435 | mmc->slots[0].set_power = twl_mmc1_set_power; | 490 | mmc->slots[0].set_power = twl_mmc1_set_power; |
491 | mmc->slots[0].set_sleep = twl_mmc1_set_sleep; | ||
436 | break; | 492 | break; |
437 | case 2: | 493 | case 2: |
438 | if (c->ext_clock) | 494 | if (c->ext_clock) |
@@ -443,6 +499,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) | |||
443 | case 3: | 499 | case 3: |
444 | /* off-chip level shifting, or none */ | 500 | /* off-chip level shifting, or none */ |
445 | mmc->slots[0].set_power = twl_mmc23_set_power; | 501 | mmc->slots[0].set_power = twl_mmc23_set_power; |
502 | mmc->slots[0].set_sleep = twl_mmc23_set_sleep; | ||
446 | break; | 503 | break; |
447 | default: | 504 | default: |
448 | pr_err("MMC%d configuration not supported!\n", c->mmc); | 505 | pr_err("MMC%d configuration not supported!\n", c->mmc); |
diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 82f1e29f5e53..939029742758 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h | |||
@@ -95,6 +95,8 @@ struct omap_mmc_platform_data { | |||
95 | int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); | 95 | int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); |
96 | int (* set_power)(struct device *dev, int slot, int power_on, int vdd); | 96 | int (* set_power)(struct device *dev, int slot, int power_on, int vdd); |
97 | int (* get_ro)(struct device *dev, int slot); | 97 | int (* get_ro)(struct device *dev, int slot); |
98 | int (*set_sleep)(struct device *dev, int slot, int sleep, | ||
99 | int vdd, int cardsleep); | ||
98 | 100 | ||
99 | /* return MMC cover switch state, can be NULL if not supported. | 101 | /* return MMC cover switch state, can be NULL if not supported. |
100 | * | 102 | * |