From patchwork Sat Jul 20 23:07:48 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrea Adami X-Patchwork-Id: 2830864 Return-Path: X-Original-To: patchwork-linux-mmc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 5F0B59F3EB for ; Sat, 20 Jul 2013 23:09:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 55D4C20111 for ; Sat, 20 Jul 2013 23:09:46 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 50A23200D0 for ; Sat, 20 Jul 2013 23:09:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755270Ab3GTXIN (ORCPT ); Sat, 20 Jul 2013 19:08:13 -0400 Received: from mail-ea0-f172.google.com ([209.85.215.172]:48178 "EHLO mail-ea0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755234Ab3GTXHw (ORCPT ); Sat, 20 Jul 2013 19:07:52 -0400 Received: by mail-ea0-f172.google.com with SMTP id q10so3116065eaj.3 for ; Sat, 20 Jul 2013 16:07:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer; bh=v6NHxnFrJcZiOdyTzam1IXKv4Ar/CB5/sRggX7sq1cQ=; b=RFHKyM1itKGM3a1VYdkiTljFAER/LdhurXs0bEsYql6XBy7+NIX52P7hNCCiyCwY9G sq3rIRe/GfjsMJicbnjfH1i7JXaKgamgRoMilupnlNyAq8WFqEzwpm/hbLZ/kEqMz/Zk VSVOMFkZmD4G4Kkb49B36WIJCuYry8880wLO1NWUz1S56tREg5k5k25hF6vQa1dBII0C jxfFb8GoQKH5e1XWMQM2rY5MC1nL7HSyXE3HczvkDSRkt+0m2pOji89ppzIKs4stgw7t m2d2K3qFkGumSESLt+pKc4fUpGC3vkPdZ6S/sE57LdBUV+mIB4Obk96/O5oXC2SAkv8z hSew== X-Received: by 10.14.173.70 with SMTP id u46mr21199899eel.92.1374361670586; Sat, 20 Jul 2013 16:07:50 -0700 (PDT) Received: from mizar.localdomain (host133-7-dynamic.20-79-r.retail.telecomitalia.it. [79.20.7.133]) by mx.google.com with ESMTPSA id m1sm38613381eex.17.2013.07.20.16.07.49 for (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 20 Jul 2013 16:07:50 -0700 (PDT) From: Andrea Adami To: linux-mmc@vger.kernel.org Cc: Chris Ball , Russell King , linux-kernel@vger.kernel.org, Marko Katic Subject: [PATCH] mmc: pxamci: Refactor regulator support Date: Sun, 21 Jul 2013 01:07:48 +0200 Message-Id: <1374361668-3184-1-git-send-email-andrea.adami@gmail.com> X-Mailer: git-send-email 1.8.1.5 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Marko Katic Here's an interesting scenario. The spitz machine has an Intersil 6271A voltage regulator and an ADS7846 touchscreen controller. The ADS7846 driver _requires_ the use of a voltage regulator or if not present, CONFIG_REGULATOR_DUMMY should be used for proper operation. This was made mandatory by the following commit: ======================================== 91143379b01b2020d8878d627ebe9dfb9d6eb4c8 Input: ads7846 - add regulator support The ADS7846/TSC2046 touchscreen controllers can (and usually are) connected to various regulators for power, so add regulator support. Valid regulator will now be required, so boards without complete regulator setup should either disable regulator framework or enable CONFIG_REGULATOR_DUMMY. ======================================== The ADS7846 in spitz machines is not connected to any power regulator so it needs CONFIG_REGULATOR_DUMMY enabled. So to support both the Intersil 6271A regulator and the ADS7846 controller, CONFIG_REGULATOR and CONFIG_REGULATOR_DUMMY have to be defined. However, enabling CONFIG_REGULATOR and CONFIG_REGULATOR_DUMMY will break pxamci driver and cause the following error output: pxa2xx-mci.0 supply vmmc not found, using dummy regulator pxa2xx-mci pxa2xx-mci.0: ocr_mask/setpower will not be used pxa2xx-mci pxa2xx-mci.0: could not set regulator OCR (-22) pxa2xx-mci pxa2xx-mci.0: unable to set power pxa2xx-mci pxa2xx-mci.0: could not set regulator OCR (-22) pxa2xx-mci pxa2xx-mci.0: unable to set power Above failures occur in two functions; pxamci_init_ocr() and pxamci_set_power(). Regulator support in pxamci_init_ocr() is not written with the existence of the dummy regulator driver in mind. It does not check the return value of mmc_regulator_get_ocrmask() and it will only fall back to platform data if no regulator was found. pxamci_set_power() fails because it does not even try to fall back to platform data if mmc_regulator_set_ocr() fails. It expects a proper regulator or no regulator at all. It will only fall back to platform data if no regulator was found. It does not properly handle the possible existence of the dummy regulator. This patch refactors pxamci_init_ocr() and pxamci_set_power() regulator support to be more modular, to do more checks and to always fall back to platform data. Signed-off-by: Marko Katic [andrea.adami@gmail.com: checkpatch.pl dislikes lines over 80 chars] Signed-off-by: Andrea Adami --- drivers/mmc/host/pxamci.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2b2f65a..341d5dc 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -83,18 +83,26 @@ struct pxamci_host { static inline void pxamci_init_ocr(struct pxamci_host *host) { #ifdef CONFIG_REGULATOR + int ocr_mask; 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) + ocr_mask = mmc_regulator_get_ocrmask(host->vcc); + if (ocr_mask <= 0) + host->mmc->ocr_avail = 0; + else + host->mmc->ocr_avail = ocr_mask; + + if (host->pdata && + host->pdata->ocr_mask && + host->mmc->ocr_avail) dev_warn(mmc_dev(host->mmc), "ocr_mask/setpower will not be used\n"); } #endif - if (host->vcc == NULL) { + if (host->vcc == NULL || host->mmc->ocr_avail == 0) { /* fall-back to platform data */ host->mmc->ocr_avail = host->pdata ? host->pdata->ocr_mask : @@ -108,26 +116,32 @@ static inline int pxamci_set_power(struct pxamci_host *host, { int on; +#ifdef CONFIG_REGULATOR if (host->vcc) { - int ret; + int ret = 0; - if (power_mode == MMC_POWER_UP) { + if (power_mode == MMC_POWER_UP) ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); - if (ret) - return ret; - } else if (power_mode == MMC_POWER_OFF) { + + if (power_mode == MMC_POWER_OFF) ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); - if (ret) - return ret; - } + + if (ret == 0) + return 0; + else + dev_warn(mmc_dev(host->mmc), + "mmc_regulator_set_ocr failed, " + "falling back to platform data\n"); } - if (!host->vcc && host->pdata && +#endif + + if (host->pdata && gpio_is_valid(host->pdata->gpio_power)) { on = ((1 << vdd) & host->pdata->ocr_mask); gpio_set_value(host->pdata->gpio_power, !!on ^ host->pdata->gpio_power_invert); } - if (!host->vcc && host->pdata && host->pdata->setpower) + if (host->pdata && host->pdata->setpower) host->pdata->setpower(mmc_dev(host->mmc), vdd); return 0;