Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b7c18e0 authored by Adrian Hunter's avatar Adrian Hunter Committed by Linus Torvalds
Browse files

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: default avatarAdrian Hunter <adrian.hunter@nokia.com>
Acked-by: default avatarMatt 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent dd498eff
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -340,6 +340,61 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v
	return ret;
}

static int twl_mmc1_set_sleep(struct device *dev, int slot, int sleep, int vdd,
			      int cardsleep)
{
	struct twl_mmc_controller *c = &hsmmc[0];
	int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;

	return regulator_set_mode(c->vcc, mode);
}

static int twl_mmc23_set_sleep(struct device *dev, int slot, int sleep, int vdd,
			       int cardsleep)
{
	struct twl_mmc_controller *c = NULL;
	struct omap_mmc_platform_data *mmc = dev->platform_data;
	int i, err, mode;

	for (i = 1; i < ARRAY_SIZE(hsmmc); i++) {
		if (mmc == hsmmc[i].mmc) {
			c = &hsmmc[i];
			break;
		}
	}

	if (c == NULL)
		return -ENODEV;

	/*
	 * If we don't see a Vcc regulator, assume it's a fixed
	 * voltage always-on regulator.
	 */
	if (!c->vcc)
		return 0;

	mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL;

	if (!c->vcc_aux)
		return regulator_set_mode(c->vcc, mode);

	if (cardsleep) {
		/* VCC can be turned off if card is asleep */
		struct regulator *vcc_aux = c->vcc_aux;

		c->vcc_aux = NULL;
		if (sleep)
			err = twl_mmc23_set_power(dev, slot, 0, 0);
		else
			err = twl_mmc23_set_power(dev, slot, 1, vdd);
		c->vcc_aux = vcc_aux;
	} else
		err = regulator_set_mode(c->vcc, mode);
	if (err)
		return err;
	return regulator_set_mode(c->vcc_aux, mode);
}

static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;

void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
@@ -433,6 +488,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
		case 1:
			/* on-chip level shifting via PBIAS0/PBIAS1 */
			mmc->slots[0].set_power = twl_mmc1_set_power;
			mmc->slots[0].set_sleep = twl_mmc1_set_sleep;
			break;
		case 2:
			if (c->ext_clock)
@@ -443,6 +499,7 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers)
		case 3:
			/* off-chip level shifting, or none */
			mmc->slots[0].set_power = twl_mmc23_set_power;
			mmc->slots[0].set_sleep = twl_mmc23_set_sleep;
			break;
		default:
			pr_err("MMC%d configuration not supported!\n", c->mmc);
+2 −0
Original line number Diff line number Diff line
@@ -95,6 +95,8 @@ struct omap_mmc_platform_data {
		int (* set_bus_mode)(struct device *dev, int slot, int bus_mode);
		int (* set_power)(struct device *dev, int slot, int power_on, int vdd);
		int (* get_ro)(struct device *dev, int slot);
		int (*set_sleep)(struct device *dev, int slot, int sleep,
				 int vdd, int cardsleep);

		/* return MMC cover switch state, can be NULL if not supported.
		 *