On Thu, May 14, 2009 at 5:31 PM, Daniel Ribeiro <drw...@gmail.com> wrote:
> Em Qui, 2009-05-14 às 17:11 +0800, Eric Miao escreveu:
>> I'd rather it's implemented something like below (it's only for illustration
>> purpose):
>
> I dont think we can set ocr_avail on set_ios(). See mmc_power_up().
>

Yes, so that's for illustration purpose only. My point is to abstract
the operation and hide the detail there, and make the driver logic
part generic. Following your ideas, let me know whether something
below looks better:

diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 4300957..881eacf 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -67,8 +67,42 @@ struct pxamci_host {
        unsigned int            dma_dir;
        unsigned int            dma_drcmrrx;
        unsigned int            dma_drcmrtx;
+
+       struct regulator        *vcc;
 };

+static inline void pxamci_init_ocr(struct pxamci_host *host)
+{
+#ifdef CONFIG_REGULATOR
+       host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc");
+
+       if (IS_ERR(host->vcc))
+               host->vcc = NULL;
+       else {
+               mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc);
+               if (host->pdata && host->pdata->ocr_mask)
+                       dev_warn(mmc_dev(host->mmc),
+                               "ocr_mask/setpower will not be used\n");
+       }
+#endif
+       if (host->vcc == NULL) {
+               /* fall-back to platform data */
+               mmc->ocr_avail = host->pdata ?
+                       host->pdata->ocr_mask :
+                       MMC_VDD_32_33 | MMC_VDD_33_34;
+       }
+}
+
+static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd)
+{
+#ifdef CONFIG_REGULATOR
+       if (host->vcc)
+               mmc_regulator_set_ocr(host->vcc, vdd);
+#endif
+       if (host->pdata && host->pdata->setpower)
+               host->pdata->setpower(mmc_dev(host->mmc), vdd);
+}
+
 static void pxamci_stop_clock(struct pxamci_host *host)
 {
        if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
@@ -438,8 +472,7 @@ 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)
-                       host->pdata->setpower(mmc_dev(mmc), ios->vdd);
+               pxamci_set_power(host, ios->vdd);

                if (ios->power_mode == MMC_POWER_ON)
                        host->cmdat |= CMDAT_INIT;
@@ -562,9 +595,8 @@ 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 ?
-                        host->pdata->ocr_mask :
-                        MMC_VDD_32_33|MMC_VDD_33_34;
+       pxamci_init_ocr(host);
+
        mmc->caps = 0;
        host->cmdat = 0;
        if (!cpu_is_pxa25x()) {
@@ -661,6 +693,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);

Reply via email to