From patchwork Fri Aug 4 17:43:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 109447 Delivered-To: patch@linaro.org Received: by 10.140.101.6 with SMTP id t6csp2475372qge; Fri, 4 Aug 2017 10:45:17 -0700 (PDT) X-Received: by 10.99.149.6 with SMTP id p6mr3104539pgd.412.1501868717467; Fri, 04 Aug 2017 10:45:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1501868717; cv=none; d=google.com; s=arc-20160816; b=Txb8+Ly7nwIbF8vIm8y8y9qjfG2ZUM1tetMaEaLYNBr654+eMo2Gv1teQaKkhJpShW 3iCuwcp652UGGGB8VmkuaakvuWsYsXUv8S8oFbIAip8sPvUgLpwuotXW8kxpfKvQ6s1p 1Q0Nd1QgRL0Q1vnKpzwYccBBsx8SgkmNQIUpCd07Mmnw2zpHhvuXu9zK6IEt3ZuMAupc YnfWDDvdBmZpoH+ZM3b7Zn7WiSucL/Q29YBnEyC+9LTPVvEdBbE2RmXNn19FS88gwsTk nt7ng0gSvPGkK31xESRpVsI3wajZ8+iCK9DwRSAVC0frR7q9Gy2Sv5tTFNeS6psMqQ13 7hkw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=aXSsxtzj86v1KcEcxpTUl3XG7ximZhw4N1xAHRIzeiY=; b=dEXBQfGiUookOYVXRfpaKFV232aje/cGC81VmcGCUtIHb1ml6oYNfUE9HTvR2v7Vob sWBzoxswP+kS+Sd12v9EkkFLAAC76x0aiiseU/8o+TnAg24rJuY4uKnn9WlSSiTb4DjR 88GzPiAnwv31+F72PCid/yZupd1zpGg7HONfcU73A+V8Gv/dcQN2cQITzwErf5pAg1lc 0T/ouTGMHIsnKXw/ymZdpwociO/7ZpaLIw1DGgaB7xo15jO+W4UlgueDiT5hdp7cAvbP CcUcNa4QtSb64B3ZTyV0M/XiIv75e0mtlTgvAMYTUEoTdLzp3Ot+XiuqiuBLb5P+8dfP MP9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.b=BtquizK8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d16si1472606plj.104.2017.08.04.10.45.17; Fri, 04 Aug 2017 10:45:17 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.b=BtquizK8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753285AbdHDRpO (ORCPT + 25 others); Fri, 4 Aug 2017 13:45:14 -0400 Received: from mail-wr0-f181.google.com ([209.85.128.181]:38488 "EHLO mail-wr0-f181.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753209AbdHDRoT (ORCPT ); Fri, 4 Aug 2017 13:44:19 -0400 Received: by mail-wr0-f181.google.com with SMTP id f21so19228821wrf.5 for ; Fri, 04 Aug 2017 10:44: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=aXSsxtzj86v1KcEcxpTUl3XG7ximZhw4N1xAHRIzeiY=; b=BtquizK8tYjasMgXia1WkvmsUNDYhR5DX3iu5t/qIXfjX1aWaG+o4YXBWEJxhlDoZo wPvy5tvT0vGXtnkdgEVBBxcRn2OiBd7qM3EVsLX1DnPzbigh1Lqs43+FQUT8AHZ4Z19c CTFV0bgWp9Wg89pSicXR+6yQCDupzijN54ck76yBbmr0j3NIqPneUYxUxp1ybYz3k6bt IckaQxlU1cBvdDut0Jp9mQQnLIY/v9gN9cEIWrEB4/zgoO5MKnOgpyjkG0APOqHjYKoY 9EAun9VLkg+gI8W2J5cWIfJ7afGIOP2DBYXay+b0XzywZDNWxkZDcBMIqugwSffpnTWP IpvA== 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=aXSsxtzj86v1KcEcxpTUl3XG7ximZhw4N1xAHRIzeiY=; b=Gl+DEUa5WRbYFFb32tMhXJp3Z/xtFbxRTPriAphLe6OZkiu12jxslAkvLZcx/4a680 7i2uNNWf6ByUEHOJu1x4vGRFfRvlSV8oG7dhuaFbYKEWFX3MVVHAw3SBXp6jV5HrKsi2 X83JKQccopD5LVDmiznHo+2AzPny3me2pzf2A0RpANmPOyzpYTcVvX2rrXUNwnmrgBr/ m/YqzeZhJkdi1TNkU414aHryPPzNDojp9+wpaF0IN8yh407pFNU+FklnoRPl7k2QDd7P Gjcvu8HLFlxWtGGj5aPSRSf4KBS5eHUe25VxZTu1Bp/s/Tv/wZA6qhbq3aUBfDyW5qDp 405Q== X-Gm-Message-State: AIVw112YOCuo1TGhlFgRR696sGfx3u+MVfsfKnoz5G3wneGYFCfu/9sg Edwz6FzRiFGhULSw X-Received: by 10.223.139.216 with SMTP id w24mr2255177wra.206.1501868657761; Fri, 04 Aug 2017 10:44:17 -0700 (PDT) Received: from localhost.localdomain (cag06-3-82-243-161-21.fbx.proxad.net. [82.243.161.21]) by smtp.googlemail.com with ESMTPSA id p17sm996082wma.45.2017.08.04.10.44.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 04 Aug 2017 10:44:17 -0700 (PDT) From: Jerome Brunet To: Ulf Hansson , Kevin Hilman , Carlo Caione Cc: Jerome Brunet , linux-mmc@vger.kernel.org, linux-amlogic@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 13/14] mmc: meson-gx: work around clk-stop issue Date: Fri, 4 Aug 2017 19:43:52 +0200 Message-Id: <20170804174353.16486-14-jbrunet@baylibre.com> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170804174353.16486-1-jbrunet@baylibre.com> References: <20170804174353.16486-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org It seems that the signal 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 Signed-off-by: Jerome Brunet --- drivers/mmc/host/meson-gx-mmc.c | 74 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 6 deletions(-) -- 2.9.4 diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index f973278a3f8d..e991c9e452ab 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -145,6 +145,10 @@ struct meson_host { struct clk *signal_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; @@ -308,6 +312,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 signal 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; @@ -324,9 +364,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) { @@ -335,6 +373,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->signal_clk, rate); if (ret) { dev_err(host->dev, "Unable to set cfg_div_clk to %lu. ret=%d\n", @@ -354,9 +397,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; } @@ -1037,6 +1078,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);