From patchwork Thu Feb 23 16:23:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 9588559 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B495760210 for ; Thu, 23 Feb 2017 16:24:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A528F28932 for ; Thu, 23 Feb 2017 16:24:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9935B28934; Thu, 23 Feb 2017 16:24:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0497328932 for ; Thu, 23 Feb 2017 16:24:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751188AbdBWQYb (ORCPT ); Thu, 23 Feb 2017 11:24:31 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:34683 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751126AbdBWQYV (ORCPT ); Thu, 23 Feb 2017 11:24:21 -0500 Received: by mail-wm0-f68.google.com with SMTP id m70so710697wma.1; Thu, 23 Feb 2017 08:23:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=gqDyqoNlA3IvR+7wxKZ95cZXk0x/owzNCjFIa70sOLk=; b=TGhEGIH65YXWgF81JgXVxtWb5NGPZijsqSSPDYnYLv2gdEWzDBdCLJNIvG6e7Xf8xK BETihNLrrLB1w5phrTQiCaJjigpCKvk+5uv7f7FKUBhu60IXbmOTlj7zFzlvkkBd4b6M yYdBbluqarciH5T/bA1sHyc2BH0/EgVv4yuKo3JhySngxuT8N99iOUyl456IEJlLJyYG BHGC8wQ7xKLl2lt+jOAFP6NGHG5AdpJMOO9ytT5tRYzLQj26p4l817de/j4OBHW4AHgK ehzBh51z/DLJOPiWPckWhV4XtDIRp8LhErciU2Esgk0q2sRmoNLLqkkKHeK4RxqivDfe QDmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=gqDyqoNlA3IvR+7wxKZ95cZXk0x/owzNCjFIa70sOLk=; b=ltV6DV9gkSIg9Cjz1BPZ6MtXPfZ8zmCukGLc+2XGXM9aj4AXez45EFBtHuZAxl10qP z6um+rpmt0U9nbM6j5UJQ89hj21VzD1HM96FabF4Tfgj1BHtAdV7LaE3qCEpHon6MA7d 09qu72HUM4MaZ6/GwhMGpF4FUDbuiJLTJuIVTEyb79rFHXGZERSe6ota/0+h6Kzi3rBd 4htOiAz/sybCSbtUFyJkOWKTpr3et1PUHwAneOI6nQjRhEqEMQAhbhXLtXvndRU4TJXc 22INwGaJ6oYwHm9uc6b1uaMvoxtsDUjQ5JvTBMYvRFQ+KqQ+KttKd8ckE6rxnPlh92gL CNcA== X-Gm-Message-State: AMke39mkNLiIBPlknnsP9NTFLa3KxHrf6inC9It6LUIZglpvoxWa6x+waSFN5rWQpGxZjQ== X-Received: by 10.28.16.70 with SMTP id 67mr3568558wmq.142.1487867024451; Thu, 23 Feb 2017 08:23:44 -0800 (PST) Received: from localhost (port-435.pppoe.wtnet.de. [84.46.1.180]) by smtp.gmail.com with ESMTPSA id j39sm6585985wrj.45.2017.02.23.08.23.43 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 23 Feb 2017 08:23:43 -0800 (PST) From: Thierry Reding To: Adrian Hunter , Ulf Hansson Cc: Jon Hunter , Alexandre Courbot , linux-mmc@vger.kernel.org, linux-tegra@vger.kernel.org Subject: [PATCH v2 1/2] mmc: tegra: Support module reset Date: Thu, 23 Feb 2017 17:23:41 +0100 Message-Id: <20170223162342.15911-1-thierry.reding@gmail.com> X-Mailer: git-send-email 2.11.1 Sender: linux-mmc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-mmc@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Reding The device tree binding for the SDHCI controller found on Tegra SoCs specifies that a reset control can be provided by the device tree. No code was ever added to support the module reset, which can cause the driver to try and access registers from a module that's in reset. On most Tegra SoC generations doing so would cause a hang. Note that it's unlikely to see this happen because on most platforms these resets will have been deasserted by the bootloader. However the portability can be improved by making sure the driver deasserts the reset before accessing any registers. Since resets are synchronous on Tegra SoCs, the platform driver needs to implement a custom ->remove() callback now to make sure the clock is disabled after the reset is asserted. Signed-off-by: Thierry Reding Acked-by: Adrian Hunter --- Changes in v2: - assert reset in ->probe() error path - remove unneeded PCI specific quirk drivers/mmc/host/sdhci-tegra.c | 43 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 20b6ff5b4af1..9ae5895678e8 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,8 @@ struct sdhci_tegra { struct gpio_desc *power_gpio; bool ddr_signaling; bool pad_calib_required; + + struct reset_control *rst; }; static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) @@ -489,6 +492,25 @@ static int sdhci_tegra_probe(struct platform_device *pdev) clk_prepare_enable(clk); pltfm_host->clk = clk; + tegra_host->rst = devm_reset_control_get(&pdev->dev, "sdhci"); + if (IS_ERR(tegra_host->rst)) { + rc = PTR_ERR(tegra_host->rst); + dev_err(&pdev->dev, "failed to get reset control: %d\n", rc); + goto err_rst_get; + } + + rc = reset_control_assert(tegra_host->rst); + if (rc) + goto err_rst_get; + + usleep_range(2000, 4000); + + rc = reset_control_deassert(tegra_host->rst); + if (rc) + goto err_rst_get; + + usleep_range(2000, 4000); + rc = sdhci_add_host(host); if (rc) goto err_add_host; @@ -496,6 +518,8 @@ static int sdhci_tegra_probe(struct platform_device *pdev) return 0; err_add_host: + reset_control_assert(tegra_host->rst); +err_rst_get: clk_disable_unprepare(pltfm_host->clk); err_clk_get: err_power_req: @@ -504,6 +528,23 @@ static int sdhci_tegra_probe(struct platform_device *pdev) return rc; } +static int sdhci_tegra_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *platform = sdhci_priv(host); + struct sdhci_tegra *tegra = sdhci_pltfm_priv(platform); + + sdhci_remove_host(host, 0); + + reset_control_assert(tegra->rst); + usleep_range(2000, 4000); + clk_disable_unprepare(platform->clk); + + sdhci_pltfm_free(pdev); + + return 0; +} + static struct platform_driver sdhci_tegra_driver = { .driver = { .name = "sdhci-tegra", @@ -511,7 +552,7 @@ static struct platform_driver sdhci_tegra_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_tegra_probe, - .remove = sdhci_pltfm_unregister, + .remove = sdhci_tegra_remove, }; module_platform_driver(sdhci_tegra_driver);