From patchwork Mon Aug 21 16:02:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 9913377 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 ABD1A60382 for ; Mon, 21 Aug 2017 17:20:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 93B9928708 for ; Mon, 21 Aug 2017 17:20:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8873F2879D; Mon, 21 Aug 2017 17:20:28 +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=-2.6 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 2A15228708 for ; Mon, 21 Aug 2017 17:20:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=e6ksBeRSAM5W3F/YnSTDRQkA9BiY0AC0v4xMaFjCX1U=; b=aF3airbGN7m+Oe4nZT2rXIoy8q fXTQ1bdQsTUlnGIRFW656AwAVsDHQxyOEP5P6awyVri/alqGJqKveft6ibEVIwCLcqmfUI77G9JOQ O7CB3L+sNAtBTm8nSRGQ0aM+DQ8EjMMMdmEVaMSCWmu7ptyMcCEMevT3Qpzc8TwCyFi3sRkCl8BU2 yf12Dg3WQWrO0IbCzql0efhy0jNrykULui5AMwQ1SBoQwjOqN4D1lCFuhpq50YMnvL6dPVDyh4o/0 Hwyg2FyxIZsI4GQrlJocqubverCfN0JQDVQ4so+tBdYE1er1ujf7straGnfcier/hHqyyVBiTykhY O5FxlLDQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1djqNE-0008C5-DJ; Mon, 21 Aug 2017 17:20:24 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1djqLn-0005WC-Lp for linux-arm-kernel@bombadil.infradead.org; Mon, 21 Aug 2017 17:18:55 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=DNSoQjIsa7AEBBP0HwX0AdrS4mGgMCPVhLtHMVbz0Ng=; b=ZJLDK2ZKals+5hhzALMUDf/7b KFJoWjXv9PpDrElwiLAkYWJPyNNy4ItimBxElp67RapoAgQLV/wlnD2HcNFlAEvBrl9yzg3RmFP2z GcuBH2AUTgjFR0FRALMO+HiPWipcCwa7v1JPWHJtsZFPa6U5zFEsHghA1ufq/c+hZGRFaHEoixqwf rYoWRWMmeS+9Swdp6hF74AHCpJuTXW/VAH6VgqB8CVLooPZ9Wg5vH04XyJc2zQS3lQaxEI4XUfPeD A/RaNsrcH/yWXM+F+nZrLn23Tn1zzwjDABw6g2M/GnSRQBH9Ff5+lBgC6PBOnTXiJ0J+8TuZg4wrU m1Ir3XtYw==; Received: from mail-wr0-x22a.google.com ([2a00:1450:400c:c0c::22a]) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1djpB0-0006dQ-65 for linux-arm-kernel@lists.infradead.org; Mon, 21 Aug 2017 16:03:43 +0000 Received: by mail-wr0-x22a.google.com with SMTP id p8so39041345wrf.5 for ; Mon, 21 Aug 2017 09:03:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=DNSoQjIsa7AEBBP0HwX0AdrS4mGgMCPVhLtHMVbz0Ng=; b=hegMe4qdTA+IbI+SsXB4G/n42nL+yDmAmXEGFi2LaLR4z51RiJkCJQIOsoEiRIpdX5 2JdV15kp9yzqN1IgoGZ9+AphwWdBq4niiXO6dpMHuupdOoAXWQ7B7Y2t2NXNy/RpwHjF Gc+1kSGf8P5r5fMEBemE4H0Ayz1WT40Q80kaESgP8AKh7idZOFbeKTF1ga5fyCaA1fhb c5Vrzc/w/w/OvtjHm8xNAUVOPOiM3TLA7s8xANZwxLJSFD10tfZuSZAW9VpMFc3aep9A L3Ai8m5cHCRejZhWDEZr4hsZ6gv5lg1R2KaP8Y6N83AauU5W68IvhH/jg/DQCtU7rMSE 9fxQ== 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:in-reply-to :references; bh=DNSoQjIsa7AEBBP0HwX0AdrS4mGgMCPVhLtHMVbz0Ng=; b=SEgJyLLGOfNfv6pvs/+XEj6u6HFH6FU5b/B59OAZJ8eWiXcOHaoHlIQ2xJUtt1NlEN ClBNXwzi+JSl4jdpMqLZSNxOuYSkQAiEP8KROmWhjbmjocUBnVZfFLf0BP9/HPVjgTIH 2T+YIl0pcxfxelSnfqdbApmF+UciOmqC3YVYgBOARG2ltKw0ZMPrT9dwCYLAyEhxCkUD I9BMuEZNdHiMBfg1LferzK+k6mwEI8fezmxDoG8Fl9R//fSXtBlageUdhqyJ9JcW819u q19bGPlog2S8laliKnSl3oOM7g1v85NaZykFsdXOCRGtk8vFw7u8PUVj7QyggjykxhGx wO4Q== X-Gm-Message-State: AHYfb5i6HF2Vh8ipgzf30IBrlG/Zhr1ksw8IX/Ku5O5yLvAhY1NLBzZf PqtrmEUMw+mb0hqo X-Received: by 10.28.9.72 with SMTP id 69mr2277345wmj.154.1503331396449; Mon, 21 Aug 2017 09:03:16 -0700 (PDT) Received: from localhost.localdomain ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id 63sm8120063wra.30.2017.08.21.09.03.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Aug 2017 09:03:15 -0700 (PDT) From: Jerome Brunet To: Ulf Hansson , Kevin Hilman , Carlo Caione Subject: [PATCH v2 10/16] mmc: meson-gx: work around clk-stop issue Date: Mon, 21 Aug 2017 18:02:55 +0200 Message-Id: <20170821160301.21899-11-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170821160301.21899-1-jbrunet@baylibre.com> References: <20170821160301.21899-1-jbrunet@baylibre.com> X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-amlogic@lists.infradead.org, linux-mmc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Jerome Brunet MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP It seems that the mmc clock is also used and required, somehow, by the controller it self. It is shown during init, when writing to CFG while the divider is set to 0 will crash the SoC. During voltage switch, the controller may crash and the card may then fail to exit busy state if the clock is stopped. To avoid this, it is best to keep the clock running for the controller, except during rate change. However, we still need to be able to gate the clock out of the SoC. Let's use the pinmux for this, and fallback to gpio mode (pulled-down) when we need to gate the clock Reviewed-by: Kevin Hilman Signed-off-by: Jerome Brunet --- drivers/mmc/host/meson-gx-mmc.c | 74 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 0d3416dae8cf..c37e31dc709e 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -137,6 +137,10 @@ struct meson_host { struct clk *mmc_clk; unsigned long req_rate; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_clk_gate; + unsigned int bounce_buf_size; void *bounce_buf; dma_addr_t bounce_dma_addr; @@ -272,6 +276,42 @@ static bool meson_mmc_timing_is_ddr(struct mmc_ios *ios) return false; } +/* + * Gating the clock on this controller is tricky. It seems the mmc clock + * is also used by the controller. It may crash during some operation if the + * clock is stopped. The safest thing to do, whenever possible, is to keep + * clock running at stop it at the pad using the pinmux. + */ +static void meson_mmc_clk_gate(struct meson_host *host) +{ + u32 cfg; + + if (host->pins_clk_gate) { + pinctrl_select_state(host->pinctrl, host->pins_clk_gate); + } else { + /* + * If the pinmux is not provided - default to the classic and + * unsafe method + */ + cfg = readl(host->regs + SD_EMMC_CFG); + cfg |= CFG_STOP_CLOCK; + writel(cfg, host->regs + SD_EMMC_CFG); + } +} + +static void meson_mmc_clk_ungate(struct meson_host *host) +{ + u32 cfg; + + if (host->pins_clk_gate) + pinctrl_select_state(host->pinctrl, host->pins_default); + + /* Make sure the clock is not stopped in the controller */ + cfg = readl(host->regs + SD_EMMC_CFG); + cfg &= ~CFG_STOP_CLOCK; + writel(cfg, host->regs + SD_EMMC_CFG); +} + static int meson_mmc_clk_set(struct meson_host *host, struct mmc_ios *ios) { struct mmc_host *mmc = host->mmc; @@ -288,9 +328,7 @@ static int meson_mmc_clk_set(struct meson_host *host, struct mmc_ios *ios) return 0; /* stop clock */ - cfg = readl(host->regs + SD_EMMC_CFG); - cfg |= CFG_STOP_CLOCK; - writel(cfg, host->regs + SD_EMMC_CFG); + meson_mmc_clk_gate(host); host->req_rate = 0; if (!rate) { @@ -299,6 +337,11 @@ static int meson_mmc_clk_set(struct meson_host *host, struct mmc_ios *ios) return 0; } + /* Stop the clock during rate change to avoid glitches */ + cfg = readl(host->regs + SD_EMMC_CFG); + cfg |= CFG_STOP_CLOCK; + writel(cfg, host->regs + SD_EMMC_CFG); + ret = clk_set_rate(host->mmc_clk, rate); if (ret) { dev_err(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n", @@ -318,9 +361,7 @@ static int meson_mmc_clk_set(struct meson_host *host, struct mmc_ios *ios) dev_dbg(host->dev, "requested rate was %u\n", ios->clock); /* (re)start clock */ - cfg = readl(host->regs + SD_EMMC_CFG); - cfg &= ~CFG_STOP_CLOCK; - writel(cfg, host->regs + SD_EMMC_CFG); + meson_mmc_clk_ungate(host); return 0; } @@ -932,6 +973,27 @@ static int meson_mmc_probe(struct platform_device *pdev) goto free_host; } + host->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(host->pinctrl)) { + ret = PTR_ERR(host->pinctrl); + goto free_host; + } + + host->pins_default = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_DEFAULT); + if (IS_ERR(host->pins_default)) { + ret = PTR_ERR(host->pins_default); + goto free_host; + } + + host->pins_clk_gate = pinctrl_lookup_state(host->pinctrl, + "clk-gate"); + if (IS_ERR(host->pins_clk_gate)) { + dev_warn(&pdev->dev, + "can't get clk-gate pinctrl, using clk_stop bit\n"); + host->pins_clk_gate = NULL; + } + host->core_clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(host->core_clk)) { ret = PTR_ERR(host->core_clk);