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
---
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
#include
#include
+#include
#include
@@ -67,8 +68,48 @@ struct pxamci_host {
unsigned intdma_dir;
unsigned intdma_drcmrrx;
unsigned intdma_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()) ? 2600
: 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