From patchwork Fri Jun 7 21:49:57 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Lindgren X-Patchwork-Id: 2690241 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id CBC29DFB78 for ; Fri, 7 Jun 2013 21:51:34 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ul4YU-0007s0-QU; Fri, 07 Jun 2013 21:50:43 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ul4YK-0000fe-CX; Fri, 07 Jun 2013 21:50:32 +0000 Received: from mho-02-ewr.mailhop.org ([204.13.248.72]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Ul4Y7-0000dB-48 for linux-arm-kernel@lists.infradead.org; Fri, 07 Jun 2013 21:50:23 +0000 Received: from c-50-131-214-131.hsd1.ca.comcast.net ([50.131.214.131] helo=[127.0.0.1]) by mho-02-ewr.mailhop.org with esmtpa (Exim 4.72) (envelope-from ) id 1Ul4Xm-000CNs-PS; Fri, 07 Jun 2013 21:49:58 +0000 X-Mail-Handler: Dyn Standard SMTP by Dyn X-Originating-IP: 50.131.214.131 X-Report-Abuse-To: abuse@dyndns.com (see http://www.dyndns.com/services/sendlabs/outbound_abuse.html for abuse reporting information) X-MHO-User: U2FsdGVkX198NtSnj8bC021rMQ0xutWc Subject: [PATCH 3/4] mmc: omap_hsmmc: Remux pins to support SDIO interrupt and PM runtime To: cjb@laptop.org From: Tony Lindgren Date: Fri, 07 Jun 2013 14:49:57 -0700 Message-ID: <20130607214957.18581.90624.stgit@localhost> In-Reply-To: <20130607214557.18581.75288.stgit@localhost> References: <20130607214557.18581.75288.stgit@localhost> User-Agent: StGit/0.16-1-ga54b MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130607_175019_362679_04ECB821 X-CRM114-Status: GOOD ( 15.91 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [204.13.248.72 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Balaji T K , Linus Walleij , Andreas Fenkart , linux-mmc@vger.kernel.org, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org On some omaps we need to remux MMC pins for PM, and for some omaps we need to remux the SDIO IRQ pin. Based on an earlier patch by Andreas Fenkart . Cc: Andreas Fenkart Cc: Balaji T K Cc: Linus Walleij Signed-off-by: Tony Lindgren --- drivers/mmc/host/omap_hsmmc.c | 93 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 7e28501..8ca08fb 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -185,6 +185,8 @@ struct omap_hsmmc_host { int req_in_progress; struct omap_hsmmc_next next_data; bool sdio_irq_en; + struct pinctrl *pinctrl; + struct pinctrl_state *fixed, *active, *idle; bool active_pinmux; struct omap_mmc_platform_data *pdata; }; @@ -473,6 +475,67 @@ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) gpio_free(pdata->slots[0].gpio_cirq); } +static int omap_hsmmc_pin_init(struct omap_hsmmc_host *host) +{ + int ret; + + host->pinctrl = devm_pinctrl_get(host->dev); + if (IS_ERR(host->pinctrl)) { + dev_dbg(host->dev, "no pinctrl handle\n"); + ret = 0; + goto out; + } + + host->fixed = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(host->fixed)) { + dev_dbg(host->dev, + "pins are not configured from the driver\n"); + host->fixed = NULL; + ret = 0; + goto out; + } + + ret = pinctrl_select_state(host->pinctrl, host->fixed); + if (ret < 0) + goto err; + + /* For most cases we don't have wake-ups, and exit after this */ + host->active = pinctrl_lookup_state(host->pinctrl, "active"); + if (IS_ERR(host->active)) { + ret = PTR_ERR(host->active); + host->active = NULL; + return 0; + } + + host->idle = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_IDLE); + if (IS_ERR(host->idle)) { + ret = PTR_ERR(host->idle); + host->idle = NULL; + goto err; + } + + /* Let's make sure the active and idle states work */ + ret = pinctrl_select_state(host->pinctrl, host->idle); + if (ret < 0) + goto err; + + ret = pinctrl_select_state(host->pinctrl, host->active); + if (ret < 0) + goto err; + + dev_info(mmc_dev(host->mmc), "pins configured for wake-up events\n"); + + return 0; + +err: + dev_err(mmc_dev(host->mmc), "pins configuration error: %i\n", ret); + +out: + return ret; +} + /* * Start clock to the card */ @@ -1854,7 +1917,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; - struct pinctrl *pinctrl; match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); if (match) { @@ -2086,21 +2148,19 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_disable_irq(host); - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, - "pins are not configured from the driver\n"); - /* - * For now, only support SDIO interrupt if we are doing - * muxing of dat1 when booted with DT. This is because the + * For now, only support SDIO interrupt if we are doing dynamic + * remuxing of dat1 when booted with DT. This is because the * supposedly the wake-up events for CTPL don't work from deeper * idle states. And we don't want to add new legacy mux platform * init code callbacks any longer as we are moving to DT based * booting anyways. */ if (match) { - if (!IS_ERR(pinctrl) && mmc_slot(host).sdio_irq) + ret = omap_hsmmc_pin_init(host); + if (ret) + goto err_pinctrl_state; + else if (host->idle && mmc_slot(host).sdio_irq) mmc->caps |= MMC_CAP_SDIO_IRQ; } @@ -2128,6 +2188,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev) err_slot_name: mmc_remove_host(mmc); +err_pinctrl_state: + devm_pinctrl_put(host->pinctrl); if ((mmc_slot(host).sdio_irq)) free_irq(mmc_slot(host).sdio_irq, host); err_irq_sdio: @@ -2185,6 +2247,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) dma_release_channel(host->tx_chan); if (host->rx_chan) dma_release_channel(host->rx_chan); + devm_pinctrl_put(host->pinctrl); pm_runtime_put_sync(host->dev); pm_runtime_disable(host->dev); @@ -2320,6 +2383,12 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); spin_unlock_irqrestore(&host->irq_lock, flags); + if (host->pinctrl && host->idle) { + ret = pinctrl_select_state(host->pinctrl, host->idle); + if (ret < 0) + dev_warn(mmc_dev(host->mmc), "Unable to select idle pinmux\n"); + } + if (mmc_slot(host).sdio_irq) enable_irq(mmc_slot(host).sdio_irq); } @@ -2343,6 +2412,12 @@ static int omap_hsmmc_runtime_resume(struct device *dev) if (mmc_slot(host).sdio_irq) disable_irq(mmc_slot(host).sdio_irq); + if (host->pinctrl && host->active) { + ret = pinctrl_select_state(host->pinctrl, host->active); + if (ret < 0) + dev_warn(mmc_dev(host->mmc), "Unable to select active pinmux\n"); + } + spin_lock_irqsave(&host->irq_lock, flags); host->active_pinmux = true;