Add regulator support to pxamci.

This version was tested with and without CONFIG_REGULATOR, it uses the
regulator case CONFIG_REGULATOR is defined and a matching is regulator
is provided, or falls back to pdata->setpower otherwise.

Signed-off-by: Daniel Ribeiro <drw...@gmail.com>
---
 drivers/mmc/host/pxamci.c |   53 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 4300957..7dab21f 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -27,6 +27,7 @@
 #include <linux/err.h>
 #include <linux/mmc/host.h>
 #include <linux/io.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/sizes.h>
 
@@ -67,8 +68,48 @@ struct pxamci_host {
        unsigned int            dma_dir;
        unsigned int            dma_drcmrrx;
        unsigned int            dma_drcmrtx;
+
+       struct regulator        *vcc;
 };
 
+#ifdef CONFIG_REGULATOR
+static int pxamci_regulator_get(struct device *dev, struct pxamci_host *host)
+{
+       struct regulator *reg = regulator_get(dev, "vmmc");
+
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       host->vcc = reg;
+       return 0;
+}
+
+static int pxamci_regulator_get_ocrmask(struct pxamci_host *host)
+{
+       return mmc_regulator_get_ocrmask(host->vcc);
+}
+
+static int pxamci_regulator_set_ocr(struct pxamci_host *host,
+                                                       unsigned short vdd)
+{
+       return mmc_regulator_set_ocr(host->vcc, vdd);
+}
+#else
+static int pxamci_regulator_get(struct device *dev, struct pxamci_host *host)
+{
+       return -ENOTSUPP;
+}
+static int pxamci_regulator_get_ocrmask(struct pxamci_host *host)
+{
+       return 0;
+}
+static int pxamci_regulator_set_ocr(struct pxamci_host *host,
+                                                       unsigned short vdd)
+{
+       return 0;
+}
+#endif
+
 static void pxamci_stop_clock(struct pxamci_host *host)
 {
        if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -438,7 +479,9 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct 
mmc_ios *ios)
        if (host->power_mode != ios->power_mode) {
                host->power_mode = ios->power_mode;
 
-               if (host->pdata && host->pdata->setpower)
+               if (host->vcc)
+                       pxamci_regulator_set_ocr(host, ios->vdd);
+               else if (host->pdata && host->pdata->setpower)
                        host->pdata->setpower(mmc_dev(mmc), ios->vdd);
 
                if (ios->power_mode == MMC_POWER_ON)
@@ -562,7 +605,10 @@ static int pxamci_probe(struct platform_device *pdev)
        mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000
                                                          : host->clkrate;
 
-       mmc->ocr_avail = host->pdata ?
+       if (pxamci_regulator_get(&pdev->dev, host) == 0)
+               mmc->ocr_avail = pxamci_regulator_get_ocrmask(host);
+       else
+               mmc->ocr_avail = host->pdata ?
                         host->pdata->ocr_mask :
                         MMC_VDD_32_33|MMC_VDD_33_34;
        mmc->caps = 0;
@@ -661,6 +707,9 @@ static int pxamci_remove(struct platform_device *pdev)
        if (mmc) {
                struct pxamci_host *host = mmc_priv(mmc);
 
+               if (host->vcc)
+                       regulator_put(host->vcc);
+
                if (host->pdata && host->pdata->exit)
                        host->pdata->exit(&pdev->dev, mmc);
 
-- 
tg: (413f81e..) mmc/pxamci-regulator-support (depends on: master)
total: 0 errors, 0 warnings, 85 lines checked

pxamci-regulator-support.patch has no obvious style problems and is ready for 
submission.

-- 
Daniel Ribeiro


Reply via email to