From patchwork Fri Aug 19 14:00:03 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 9290383 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 96C09600CB for ; Fri, 19 Aug 2016 14:00:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8857D2931B for ; Fri, 19 Aug 2016 14:00:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7CF292941B; Fri, 19 Aug 2016 14:00:10 +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.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, 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 D604C2931B for ; Fri, 19 Aug 2016 14:00:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754820AbcHSOAI (ORCPT ); Fri, 19 Aug 2016 10:00:08 -0400 Received: from mail-wm0-f66.google.com ([74.125.82.66]:33760 "EHLO mail-wm0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754215AbcHSOAH (ORCPT ); Fri, 19 Aug 2016 10:00:07 -0400 Received: by mail-wm0-f66.google.com with SMTP id o80so3571504wme.0; Fri, 19 Aug 2016 07:00:06 -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; bh=fGlwL70DP/m+a+9CCItNECzqHCylI4t6HQ5SKa3NDaQ=; b=YC3nu8hVa8kZ6fJGBQgByB92Lo+ZRcne/3AL4tGxEgNKAq1ry4/4/c5VH6+Vl5lBzG 9sQBw3h1kNsHWwnvtd4PlYeIIbipqkmpBrK/pkjeqgjR2rjkYJRPJNdKAk1jd63EhhoN 5m38JlbzNfIEupD14u51jZOzCnhntbDmWhTh0C7Vn476WSnwq8v9cPqaLnGRNv+LwbHQ jNDcjerRDd8HPNIjOeZAYJ6/tgw56niHP6Kn89W57illAmh11Ka7Z0lAoPzUPcES2tMq DqEW3hVbptDYp6Npow5W9JlLmwt/63fIngUDeaXPZGxK+O0l9KN+/ySjIBv04d9GfJCW 66pA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=fGlwL70DP/m+a+9CCItNECzqHCylI4t6HQ5SKa3NDaQ=; b=OmGfTf19XtPXBY+oQ6gDaIW1jv/jEQlLwA/xcs8oUqnvPHd79KBHE90TfXHTa5MBPd e8XxVWPIdmleEiDL4pjrru1FszGWZozoVSTjzl9MtndrsOjFmo9vSu1bH1TqwAVONaAA LDSOgSSIpKOcZ+TcRUyyHhBpWl5NNfA4GZj3DDYKYCLY8S+vZTEsjbukl2dp79ljR5yg TxVom7Bu9/go2XPZARLLOK1wUVfO6Bm5ew+2R54+ShwMJm5P9rPALw8MmFsEXU1y/d52 0P+FsIqHY6v1yGLVGdJjjqGm3qYZyRUuFOpyB7MaPx6D7Gu7SEX/pzAylFTjT7It0I0E LgsQ== X-Gm-Message-State: AEkoouuzz28MZub66N7tTMrNL+atNvBAUTk7plZ2kttmLvt6dnxMEijsvhKPmESJlBwwPw== X-Received: by 10.28.28.70 with SMTP id c67mr4398065wmc.8.1471615206132; Fri, 19 Aug 2016 07:00:06 -0700 (PDT) Received: from localhost (port-23876.pppoe.wtnet.de. [46.59.154.247]) by smtp.gmail.com with ESMTPSA id r127sm4561710wmf.23.2016.08.19.07.00.04 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 19 Aug 2016 07:00:04 -0700 (PDT) From: Thierry Reding To: Adrian Hunter , Ulf Hansson Cc: Jon Hunter , linux-mmc@vger.kernel.org, linux-tegra@vger.kernel.org Subject: [PATCH] mmc: tegra: Support module reset Date: Fri, 19 Aug 2016 16:00:03 +0200 Message-Id: <20160819140003.22608-1-thierry.reding@gmail.com> X-Mailer: git-send-email 2.9.0 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 --- drivers/mmc/host/sdhci-tegra.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 1e93dc4e303e..4c29a64721aa 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) @@ -464,6 +467,16 @@ 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_clk_get; + } + + reset_control_deassert(tegra_host->rst); + usleep_range(2000, 4000); + rc = sdhci_add_host(host); if (rc) goto err_add_host; @@ -479,6 +492,29 @@ err_parse_dt: 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); + int dead = 0; + u32 value; + + value = readl(host->ioaddr + SDHCI_INT_STATUS); + if (value == 0xffffffff) + dead = 1; + + sdhci_remove_host(host, dead); + + 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", @@ -486,7 +522,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);