aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/pxamci.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 430095725f9f..d7d7109ef47e 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -27,6 +27,7 @@
27#include <linux/err.h> 27#include <linux/err.h>
28#include <linux/mmc/host.h> 28#include <linux/mmc/host.h>
29#include <linux/io.h> 29#include <linux/io.h>
30#include <linux/regulator/consumer.h>
30 31
31#include <asm/sizes.h> 32#include <asm/sizes.h>
32 33
@@ -67,8 +68,42 @@ struct pxamci_host {
67 unsigned int dma_dir; 68 unsigned int dma_dir;
68 unsigned int dma_drcmrrx; 69 unsigned int dma_drcmrrx;
69 unsigned int dma_drcmrtx; 70 unsigned int dma_drcmrtx;
71
72 struct regulator *vcc;
70}; 73};
71 74
75static inline void pxamci_init_ocr(struct pxamci_host *host)
76{
77#ifdef CONFIG_REGULATOR
78 host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
79
80 if (IS_ERR(host->vcc))
81 host->vcc = NULL;
82 else {
83 host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
84 if (host->pdata && host->pdata->ocr_mask)
85 dev_warn(mmc_dev(host->mmc),
86 "ocr_mask/setpower will not be used\n");
87 }
88#endif
89 if (host->vcc == NULL) {
90 /* fall-back to platform data */
91 host->mmc->ocr_avail = host->pdata ?
92 host->pdata->ocr_mask :
93 MMC_VDD_32_33 | MMC_VDD_33_34;
94 }
95}
96
97static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
98{
99#ifdef CONFIG_REGULATOR
100 if (host->vcc)
101 mmc_regulator_set_ocr(host->vcc, vdd);
102#endif
103 if (!host->vcc && host->pdata && host->pdata->setpower)
104 host->pdata->setpower(mmc_dev(host->mmc), vdd);
105}
106
72static void pxamci_stop_clock(struct pxamci_host *host) 107static void pxamci_stop_clock(struct pxamci_host *host)
73{ 108{
74 if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { 109 if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -438,8 +473,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
438 if (host->power_mode != ios->power_mode) { 473 if (host->power_mode != ios->power_mode) {
439 host->power_mode = ios->power_mode; 474 host->power_mode = ios->power_mode;
440 475
441 if (host->pdata && host->pdata->setpower) 476 pxamci_set_power(host, ios->vdd);
442 host->pdata->setpower(mmc_dev(mmc), ios->vdd);
443 477
444 if (ios->power_mode == MMC_POWER_ON) 478 if (ios->power_mode == MMC_POWER_ON)
445 host->cmdat |= CMDAT_INIT; 479 host->cmdat |= CMDAT_INIT;
@@ -562,9 +596,8 @@ static int pxamci_probe(struct platform_device *pdev)
562 mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000 596 mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000
563 : host->clkrate; 597 : host->clkrate;
564 598
565 mmc->ocr_avail = host->pdata ? 599 pxamci_init_ocr(host);
566 host->pdata->ocr_mask : 600
567 MMC_VDD_32_33|MMC_VDD_33_34;
568 mmc->caps = 0; 601 mmc->caps = 0;
569 host->cmdat = 0; 602 host->cmdat = 0;
570 if (!cpu_is_pxa25x()) { 603 if (!cpu_is_pxa25x()) {
@@ -661,6 +694,9 @@ static int pxamci_remove(struct platform_device *pdev)
661 if (mmc) { 694 if (mmc) {
662 struct pxamci_host *host = mmc_priv(mmc); 695 struct pxamci_host *host = mmc_priv(mmc);
663 696
697 if (host->vcc)
698 regulator_put(host->vcc);
699
664 if (host->pdata && host->pdata->exit) 700 if (host->pdata && host->pdata->exit)
665 host->pdata->exit(&pdev->dev, mmc); 701 host->pdata->exit(&pdev->dev, mmc);
666 702