Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 218996
b: refs/heads/master
c: 99fc513
h: refs/heads/master
v: v3
  • Loading branch information
Linus Walleij authored and Chris Ball committed Oct 23, 2010
1 parent 235d4c4 commit 9a3240c
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 38 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4d0b8611cd4da64f075b8e07a126f0eb498fb153
refs/heads/master: 99fc5131018cbdc3cf42ce09fb394a4e8b053c74
26 changes: 16 additions & 10 deletions trunk/drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,24 +772,22 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask);

/**
* mmc_regulator_set_ocr - set regulator to match host->ios voltage
* @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
* @mmc: the host to regulate
* @supply: regulator to use
* @vdd_bit: zero for power off, else a bit number (host->ios.vdd)
*
* Returns zero on success, else negative errno.
*
* MMC host drivers may use this to enable or disable a regulator using
* a particular supply voltage. This would normally be called from the
* set_ios() method.
*/
int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit)
{
int result = 0;
int min_uV, max_uV;
int enabled;

enabled = regulator_is_enabled(supply);
if (enabled < 0)
return enabled;

if (vdd_bit) {
int tmp;
Expand Down Expand Up @@ -820,17 +818,25 @@ int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit)
else
result = 0;

if (result == 0 && !enabled)
if (result == 0 && !mmc->regulator_enabled) {
result = regulator_enable(supply);
} else if (enabled) {
if (!result)
mmc->regulator_enabled = true;
}
} else if (mmc->regulator_enabled) {
result = regulator_disable(supply);
if (result == 0)
mmc->regulator_enabled = false;
}

if (result)
dev_err(mmc_dev(mmc),
"could not set regulator OCR (%d)\n", result);
return result;
}
EXPORT_SYMBOL(mmc_regulator_set_ocr);

#endif
#endif /* CONFIG_REGULATOR */

/*
* Mask off any voltages we don't support and select
Expand Down
28 changes: 18 additions & 10 deletions trunk/drivers/mmc/host/mmci.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,19 +523,27 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
struct mmci_host *host = mmc_priv(mmc);
u32 pwr = 0;
unsigned long flags;
int ret;

switch (ios->power_mode) {
case MMC_POWER_OFF:
if(host->vcc &&
regulator_is_enabled(host->vcc))
regulator_disable(host->vcc);
if (host->vcc)
ret = mmc_regulator_set_ocr(mmc, host->vcc, 0);
break;
case MMC_POWER_UP:
#ifdef CONFIG_REGULATOR
if (host->vcc)
/* This implicitly enables the regulator */
mmc_regulator_set_ocr(host->vcc, ios->vdd);
#endif
if (host->vcc) {
ret = mmc_regulator_set_ocr(mmc, host->vcc, ios->vdd);
if (ret) {
dev_err(mmc_dev(mmc), "unable to set OCR\n");
/*
* The .set_ios() function in the mmc_host_ops
* struct return void, and failing to set the
* power should be rare so we print an error
* and return here.
*/
return;
}
}
if (host->plat->vdd_handler)
pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd,
ios->power_mode);
Expand Down Expand Up @@ -869,8 +877,8 @@ static int __devexit mmci_remove(struct amba_device *dev)
clk_disable(host->clk);
clk_put(host->clk);

if (regulator_is_enabled(host->vcc))
regulator_disable(host->vcc);
if (host->vcc)
mmc_regulator_set_ocr(mmc, host->vcc, 0);
regulator_put(host->vcc);

mmc_free_host(mmc);
Expand Down
21 changes: 13 additions & 8 deletions trunk/drivers/mmc/host/omap_hsmmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,9 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on,
mmc_slot(host).before_set_reg(dev, slot, power_on, vdd);

if (power_on)
ret = mmc_regulator_set_ocr(host->vcc, vdd);
ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
else
ret = mmc_regulator_set_ocr(host->vcc, 0);
ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0);

if (mmc_slot(host).after_set_reg)
mmc_slot(host).after_set_reg(dev, slot, power_on, vdd);
Expand Down Expand Up @@ -291,18 +291,23 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
* chips/cards need an interface voltage rail too.
*/
if (power_on) {
ret = mmc_regulator_set_ocr(host->vcc, vdd);
ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
/* Enable interface voltage rail, if needed */
if (ret == 0 && host->vcc_aux) {
ret = regulator_enable(host->vcc_aux);
if (ret < 0)
ret = mmc_regulator_set_ocr(host->vcc, 0);
ret = mmc_regulator_set_ocr(host->mmc,
host->vcc, 0);
}
} else {
/* Shut down the rail */
if (host->vcc_aux)
ret = regulator_disable(host->vcc_aux);
if (ret == 0)
ret = mmc_regulator_set_ocr(host->vcc, 0);
if (!ret) {
/* Then proceed to shut down the local regulator */
ret = mmc_regulator_set_ocr(host->mmc,
host->vcc, 0);
}
}

if (mmc_slot(host).after_set_reg)
Expand Down Expand Up @@ -343,9 +348,9 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
if (cardsleep) {
/* VCC can be turned off if card is asleep */
if (sleep)
err = mmc_regulator_set_ocr(host->vcc, 0);
err = mmc_regulator_set_ocr(host->mmc, host->vcc, 0);
else
err = mmc_regulator_set_ocr(host->vcc, vdd);
err = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
} else
err = regulator_set_mode(host->vcc, mode);
if (err)
Expand Down
41 changes: 33 additions & 8 deletions trunk/drivers/mmc/host/pxamci.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,25 @@ static inline void pxamci_init_ocr(struct pxamci_host *host)
}
}

static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
static inline int pxamci_set_power(struct pxamci_host *host,
unsigned char power_mode,
unsigned int vdd)
{
int on;

#ifdef CONFIG_REGULATOR
if (host->vcc)
mmc_regulator_set_ocr(host->vcc, vdd);
#endif
if (host->vcc) {
int ret;

if (power_mode == MMC_POWER_UP) {
ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd);
if (ret)
return ret;
} else if (power_mode == MMC_POWER_OFF) {
ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0);
if (ret)
return ret;
}
}
if (!host->vcc && host->pdata &&
gpio_is_valid(host->pdata->gpio_power)) {
on = ((1 << vdd) & host->pdata->ocr_mask);
Expand All @@ -115,6 +126,8 @@ static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
}
if (!host->vcc && host->pdata && host->pdata->setpower)
host->pdata->setpower(mmc_dev(host->mmc), vdd);

return 0;
}

static void pxamci_stop_clock(struct pxamci_host *host)
Expand Down Expand Up @@ -490,9 +503,21 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}

if (host->power_mode != ios->power_mode) {
int ret;

host->power_mode = ios->power_mode;

pxamci_set_power(host, ios->vdd);
ret = pxamci_set_power(host, ios->power_mode, ios->vdd);
if (ret) {
dev_err(mmc_dev(mmc), "unable to set power\n");
/*
* The .set_ios() function in the mmc_host_ops
* struct return void, and failing to set the
* power should be rare so we print an error and
* return here.
*/
return;
}

if (ios->power_mode == MMC_POWER_ON)
host->cmdat |= CMDAT_INIT;
Expand All @@ -503,8 +528,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
else
host->cmdat &= ~CMDAT_SD_4DAT;

pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
host->clkrt, host->cmdat);
dev_dbg(mmc_dev(mmc), "PXAMCI: clkrt = %x cmdat = %x\n",
host->clkrt, host->cmdat);
}

static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable)
Expand Down
22 changes: 21 additions & 1 deletion trunk/include/linux/mmc/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ struct mmc_host {
struct led_trigger *led; /* activity led */
#endif

#ifdef CONFIG_REGULATOR
bool regulator_enabled; /* regulator state */
#endif

struct dentry *debugfs_root;

unsigned long private[0] ____cacheline_aligned;
Expand Down Expand Up @@ -250,8 +254,24 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)

struct regulator;

#ifdef CONFIG_REGULATOR
int mmc_regulator_get_ocrmask(struct regulator *supply);
int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit);
int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit);
#else
static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
{
return 0;
}

static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
struct regulator *supply,
unsigned short vdd_bit)
{
return 0;
}
#endif

int mmc_card_awake(struct mmc_host *host);
int mmc_card_sleep(struct mmc_host *host);
Expand Down

0 comments on commit 9a3240c

Please sign in to comment.