From patchwork Fri Apr 22 12:43:11 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Ospite X-Patchwork-Id: 727451 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3MChoUv014282 for ; Fri, 22 Apr 2011 12:43:50 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752284Ab1DVMnp (ORCPT ); Fri, 22 Apr 2011 08:43:45 -0400 Received: from smtp208.alice.it ([82.57.200.104]:39257 "EHLO smtp208.alice.it" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750851Ab1DVMno (ORCPT ); Fri, 22 Apr 2011 08:43:44 -0400 Received: from jcn (82.61.46.40) by smtp208.alice.it (8.5.124.08) id 4C1A271617C6BB45; Fri, 22 Apr 2011 14:43:42 +0200 Received: from ao2 by jcn with local (Exim 4.75) (envelope-from ) id 1QDFi1-0005Np-2D; Fri, 22 Apr 2011 14:43:41 +0200 From: Antonio Ospite To: linux-mmc@vger.kernel.org Cc: Antonio Ospite , Chris Ball , Grant Likely , Mark Brown , openezx-devel@lists.openezx.org, spi-devel-general@lists.sourceforge.net Subject: [PATCH v2 4/4] mmc_spi.c: add support for the regulator framework Date: Fri, 22 Apr 2011 14:43:11 +0200 Message-Id: <1303476191-20663-1-git-send-email-ospite@studenti.unina.it> X-Mailer: git-send-email 1.7.4.4 In-Reply-To: <20110421124041.GF11788@opensource.wolfsonmicro.com> References: <20110421124041.GF11788@opensource.wolfsonmicro.com> X-Face: z*RaLf`X<@C75u6Ig9}{oW$H; 1_\2t5)({*|jhM/Vb; ]yA5\I~93>J<_`<4)A{':UrE Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 22 Apr 2011 12:43:50 +0000 (UTC) Add support for powering up SD cards driven by regulators. This makes the mmc_spi driver work also with the Motorola A910 phone. Signed-off-by: Antonio Ospite --- Changes since v1: - Remove the ifdef CONFIG_REGULATOR as regulator_get() degenerates to a stub as well when the regulator framework is disabled. - Release the regulator in mmc_spi_remove() Thanks, Antonio drivers/mmc/host/mmc_spi.c | 63 +++++++++++++++++++++++++++++++++++-------- 1 files changed, 51 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 0f3672d..62b3b02 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -150,11 +151,13 @@ struct mmc_spi_host { */ void *ones; dma_addr_t ones_dma; + + struct regulator *vcc; }; static inline int mmc_spi_canpower(struct mmc_spi_host *host) { - return host->pdata && host->pdata->setpower; + return (host->pdata && host->pdata->setpower) || host->vcc; } /****************************************************************************/ @@ -1225,17 +1228,35 @@ static inline int mmc_spi_setpower(struct mmc_spi_host *host, unsigned char power_mode, unsigned int vdd) { + if (!mmc_spi_canpower(host)) + return -ENOSYS; + /* switch power on/off if possible, accounting for * max 250msec powerup time if needed. */ - if (mmc_spi_canpower(host)) { - switch (power_mode) { - case MMC_POWER_OFF: - case MMC_POWER_UP: + switch (power_mode) { + case MMC_POWER_OFF: + if (host->vcc) { + int ret = mmc_regulator_set_ocr(host->mmc, + host->vcc, 0); + if (ret) + return ret; + } else { + host->pdata->setpower(&host->spi->dev, vdd); + } + break; + + case MMC_POWER_UP: + if (host->vcc) { + int ret = mmc_regulator_set_ocr(host->mmc, + host->vcc, vdd); + if (ret) + return ret; + } else { host->pdata->setpower(&host->spi->dev, vdd); - if (power_mode == MMC_POWER_UP) - msleep(host->powerup_msecs); } + msleep(host->powerup_msecs); + break; } return 0; @@ -1420,12 +1441,27 @@ static int mmc_spi_probe(struct spi_device *spi) * and power switching gpios. */ host->pdata = mmc_spi_get_pdata(spi); - if (host->pdata) - mmc->ocr_avail = host->pdata->ocr_mask; - if (!mmc->ocr_avail) { - dev_warn(&spi->dev, "ASSUMING 3.2-3.4 V slot power\n"); - mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + + host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); + if (IS_ERR(host->vcc)) { + host->vcc = NULL; + } else { + host->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"); } + + if (host->vcc == NULL) { + /* fall-back to platform data */ + if (host->pdata) + mmc->ocr_avail = host->pdata->ocr_mask; + if (!mmc->ocr_avail) { + dev_warn(&spi->dev, "ASSUMING 3.2-3.4 V slot power\n"); + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + } + } + if (mmc_spi_canpower(host)) { host->powerup_msecs = host->pdata->powerup_msecs; if (!host->powerup_msecs || host->powerup_msecs > 250) @@ -1523,6 +1559,9 @@ static int __devexit mmc_spi_remove(struct spi_device *spi) if (host->pdata && host->pdata->exit) host->pdata->exit(&spi->dev, mmc); + if (host->vcc) + regulator_put(host->vcc); + mmc_remove_host(mmc); if (host->dma_dev) {