From patchwork Thu Oct 2 07:08:46 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Linus Walleij X-Patchwork-Id: 38266 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f200.google.com (mail-lb0-f200.google.com [209.85.217.200]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3257520BF9 for ; Thu, 2 Oct 2014 07:09:01 +0000 (UTC) Received: by mail-lb0-f200.google.com with SMTP id b6sf779728lbj.3 for ; Thu, 02 Oct 2014 00:08:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:sender:precedence:list-id:x-original-sender :x-original-authentication-results:mailing-list:list-post:list-help :list-archive:list-unsubscribe; bh=/Lk4qC7UUdaYZT0T0CI2QixxgHiw75lOFehVz64nxUA=; b=TT0cO/Iz2Dv7+hEQzd6cm3S+GYMOwM1LnYW4CcN5hgEJd4ypuphVBafgFwYHy14dHn fgHW9ncoDlBv+KpEMY+2BUBACTr+veuTvaJq11LiTcsFU6iU+9Eao8R7KMB6A4rJcPFp gYUDq8eiRlPv3EhcAcJ2axCL2+R6PQoN+tiRkmCLCQXIMLDUtoz2QUHOJkRyKyrHnix0 HYYV3RK2qWyjV1vC5/EwQEaFju3X+t5QbWl2lFG6u+37fWK7Zat1D3hXTR3G/ZuhsKc3 ATmhNm6dfHwLcQzWd8gaU8znKIWKcssELLNVgui8M+Gw45MSn1aPQpktBpKiqYGduCV3 lvyw== X-Gm-Message-State: ALoCoQmISDgjTmPgFcnyBrzaLQkUTN6K2MiVaMjM1FbBFCvKiAkdFbCFXaEYullGbsE6y/74iM/X X-Received: by 10.112.184.197 with SMTP id ew5mr9157831lbc.0.1412233739700; Thu, 02 Oct 2014 00:08:59 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.7.197 with SMTP id l5ls203429laa.58.gmail; Thu, 02 Oct 2014 00:08:59 -0700 (PDT) X-Received: by 10.112.12.5 with SMTP id u5mr10452853lbb.87.1412233739558; Thu, 02 Oct 2014 00:08:59 -0700 (PDT) Received: from mail-la0-f42.google.com (mail-la0-f42.google.com [209.85.215.42]) by mx.google.com with ESMTPS id pg10si5019031lbb.127.2014.10.02.00.08.59 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 02 Oct 2014 00:08:59 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.42 as permitted sender) client-ip=209.85.215.42; Received: by mail-la0-f42.google.com with SMTP id mk6so1801437lab.15 for ; Thu, 02 Oct 2014 00:08:59 -0700 (PDT) X-Received: by 10.112.134.229 with SMTP id pn5mr31332712lbb.22.1412233739459; Thu, 02 Oct 2014 00:08:59 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.130.169 with SMTP id of9csp7493lbb; Thu, 2 Oct 2014 00:08:58 -0700 (PDT) X-Received: by 10.70.65.7 with SMTP id t7mr54768882pds.133.1412233737644; Thu, 02 Oct 2014 00:08:57 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ng8si3023739pdb.140.2014.10.02.00.08.57 for ; Thu, 02 Oct 2014 00:08:57 -0700 (PDT) Received-SPF: none (google.com: linux-gpio-owner@vger.kernel.org does not designate permitted sender hosts) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751285AbaJBHI4 (ORCPT ); Thu, 2 Oct 2014 03:08:56 -0400 Received: from mail-wi0-f172.google.com ([209.85.212.172]:54054 "EHLO mail-wi0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751185AbaJBHI4 (ORCPT ); Thu, 2 Oct 2014 03:08:56 -0400 Received: by mail-wi0-f172.google.com with SMTP id n3so2934369wiv.5 for ; Thu, 02 Oct 2014 00:08:54 -0700 (PDT) X-Received: by 10.194.103.41 with SMTP id ft9mr70701791wjb.93.1412233734405; Thu, 02 Oct 2014 00:08:54 -0700 (PDT) Received: from localhost.localdomain ([85.235.11.236]) by mx.google.com with ESMTPSA id u2sm3562542wjz.11.2014.10.02.00.08.52 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Oct 2014 00:08:53 -0700 (PDT) From: Linus Walleij To: linux-mmc@vger.kernel.org, Chris Ball , Ulf Hansson , Javier Martinez Canillas Cc: linux-gpio@vger.kernel.org, Linus Walleij Subject: [PATCH v4] mmc: core: restore detect line inversion semantics Date: Thu, 2 Oct 2014 09:08:46 +0200 Message-Id: <1412233726-16797-1-git-send-email-linus.walleij@linaro.org> X-Mailer: git-send-email 1.9.3 Sender: linux-gpio-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-gpio@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: linus.walleij@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.42 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , commit 98e90de99a0c43bd434da814c882c4332441871e "mmc: host: switch OF parser to use gpio descriptors" switched the semantic behaviour of card detect and read only flags such that the inversion capability flag would only be set if inversion was explicitly specified in the device tree, in the hopes that no-one was using double inversion. It turns out that the XOR:ing between the explicit inversion was indeed in use, so we need to restore the old semantics where both ways of inversion are checked and the end result XOR:ed. Reported-by: Javier Martinez Canillas Tested-by: Javier Martinez Canillas Signed-off-by: Linus Walleij --- ChangeLog v3->v4: - Fix breakage in sdhci-acpi.c due to changed function prototype. ChangeLog v2->v3: - Make it possible to pass NULL as pointer for the gpio_invert variable, so we don't need dummy variables in callers ChangeLog v1->v2: - Always set override_active_level when getting CD GPIO - Invert the return value from gpiod_is_active_low() to follow the old semantics --- drivers/mmc/core/host.c | 32 ++++++++++++++++++++++++++++---- drivers/mmc/core/slot-gpio.c | 14 ++++++++++++-- drivers/mmc/host/mmci.c | 4 ++-- drivers/mmc/host/sdhci-acpi.c | 2 +- include/linux/mmc/slot-gpio.h | 4 ++-- 5 files changed, 45 insertions(+), 11 deletions(-) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 31969436d77c..03c53b72a2d6 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -311,6 +311,7 @@ int mmc_of_parse(struct mmc_host *host) struct device_node *np; u32 bus_width; int len, ret; + bool cap_invert, gpio_invert; if (!host->parent || !host->parent->of_node) return 0; @@ -359,12 +360,15 @@ int mmc_of_parse(struct mmc_host *host) host->caps |= MMC_CAP_NONREMOVABLE; } else { if (of_property_read_bool(np, "cd-inverted")) - host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; + cap_invert = true; + else + cap_invert = false; if (of_find_property(np, "broken-cd", &len)) host->caps |= MMC_CAP_NEEDS_POLL; - ret = mmc_gpiod_request_cd(host, "cd", 0, false, 0); + ret = mmc_gpiod_request_cd(host, "cd", 0, true, + 0, &gpio_invert); if (ret) { if (ret == -EPROBE_DEFER) return ret; @@ -375,13 +379,29 @@ int mmc_of_parse(struct mmc_host *host) } } else dev_info(host->parent, "Got CD GPIO\n"); + + /* + * There are two ways to flag that the CD line is inverted: + * through the cd-inverted flag and by the GPIO line itself + * being inverted from the GPIO subsystem. This is a leftover + * from the times when the GPIO subsystem did not make it + * possible to flag a line as inverted. + * + * If the capability on the host AND the GPIO line are + * both inverted, the end result is that the CD line is + * not inverted. + */ + if (cap_invert ^ gpio_invert) + host->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; } /* Parse Write Protection */ if (of_property_read_bool(np, "wp-inverted")) - host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + cap_invert = true; + else + cap_invert = false; - ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0); + ret = mmc_gpiod_request_ro(host, "wp", 0, false, 0, &gpio_invert); if (ret) { if (ret == -EPROBE_DEFER) goto out; @@ -393,6 +413,10 @@ int mmc_of_parse(struct mmc_host *host) } else dev_info(host->parent, "Got WP GPIO\n"); + /* See the comment on CD inversion above */ + if (cap_invert ^ gpio_invert) + host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; + if (of_find_property(np, "cap-sd-highspeed", &len)) host->caps |= MMC_CAP_SD_HIGHSPEED; if (of_find_property(np, "cap-mmc-highspeed", &len)) diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 38f76555d4bf..69bbf2adb329 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c @@ -281,6 +281,8 @@ EXPORT_SYMBOL(mmc_gpio_free_cd); * @idx: index of the GPIO to obtain in the consumer * @override_active_level: ignore %GPIO_ACTIVE_LOW flag * @debounce: debounce time in microseconds + * @gpio_invert: will return whether the GPIO line is inverted or not, set + * to NULL to ignore * * Use this function in place of mmc_gpio_request_cd() to use the GPIO * descriptor API. Note that it is paired with mmc_gpiod_free_cd() not @@ -291,7 +293,7 @@ EXPORT_SYMBOL(mmc_gpio_free_cd); */ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, unsigned int idx, bool override_active_level, - unsigned int debounce) + unsigned int debounce, bool *gpio_invert) { struct mmc_gpio *ctx; struct gpio_desc *desc; @@ -316,6 +318,9 @@ int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, return ret; } + if (gpio_invert) + *gpio_invert = !gpiod_is_active_low(desc); + ctx->override_cd_active_level = override_active_level; ctx->cd_gpio = desc; @@ -330,6 +335,8 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd); * @idx: index of the GPIO to obtain in the consumer * @override_active_level: ignore %GPIO_ACTIVE_LOW flag * @debounce: debounce time in microseconds + * @gpio_invert: will return whether the GPIO line is inverted or not, + * set to NULL to ignore * * Use this function in place of mmc_gpio_request_ro() to use the GPIO * descriptor API. Note that it is paired with mmc_gpiod_free_ro() not @@ -339,7 +346,7 @@ EXPORT_SYMBOL(mmc_gpiod_request_cd); */ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, unsigned int idx, bool override_active_level, - unsigned int debounce) + unsigned int debounce, bool *gpio_invert) { struct mmc_gpio *ctx; struct gpio_desc *desc; @@ -364,6 +371,9 @@ int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, return ret; } + if (gpio_invert) + *gpio_invert = !gpiod_is_active_low(desc); + ctx->override_ro_active_level = override_active_level; ctx->ro_gpio = desc; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index c9dafed550f2..43af791e2e45 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1682,7 +1682,7 @@ static int mmci_probe(struct amba_device *dev, * silently of these do not exist and proceed to try platform data */ if (!np) { - ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0); + ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0, NULL); if (ret < 0) { if (ret == -EPROBE_DEFER) goto clk_disable; @@ -1693,7 +1693,7 @@ static int mmci_probe(struct amba_device *dev, } } - ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0); + ret = mmc_gpiod_request_ro(mmc, "wp", 0, false, 0, NULL); if (ret < 0) { if (ret == -EPROBE_DEFER) goto clk_disable; diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 3483c089baa7..327bc24ec8ce 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -352,7 +352,7 @@ static int sdhci_acpi_probe(struct platform_device *pdev) if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL); - if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0)) { + if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL)) { dev_warn(dev, "failed to setup card detect gpio\n"); c->use_runtime_pm = false; } diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h index a0d0442c15bf..e56fa24c9322 100644 --- a/include/linux/mmc/slot-gpio.h +++ b/include/linux/mmc/slot-gpio.h @@ -24,10 +24,10 @@ void mmc_gpio_free_cd(struct mmc_host *host); int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, unsigned int idx, bool override_active_level, - unsigned int debounce); + unsigned int debounce, bool *gpio_invert); int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, unsigned int idx, bool override_active_level, - unsigned int debounce); + unsigned int debounce, bool *gpio_invert); void mmc_gpiod_free_cd(struct mmc_host *host); void mmc_gpiod_request_cd_irq(struct mmc_host *host);