From patchwork Mon Feb 13 12:06:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anssi Hannula X-Patchwork-Id: 9569431 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 37F1E60572 for ; Mon, 13 Feb 2017 12:07:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 42EE4212BE for ; Mon, 13 Feb 2017 12:07:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 37C4525404; Mon, 13 Feb 2017 12:07:23 +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.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI 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 92907212BE for ; Mon, 13 Feb 2017 12:07:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753007AbdBMMHO (ORCPT ); Mon, 13 Feb 2017 07:07:14 -0500 Received: from mail.bitwise.fi ([109.204.228.163]:39183 "EHLO mail.bitwise.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752999AbdBMMHN (ORCPT ); Mon, 13 Feb 2017 07:07:13 -0500 Received: from localhost (localhost [127.0.0.1]) by mail.bitwise.fi (Postfix) with ESMTP id 9E39E6037B; Mon, 13 Feb 2017 14:07:06 +0200 (EET) X-Virus-Scanned: Debian amavisd-new at mail.bitwise.fi Received: from mail.bitwise.fi ([127.0.0.1]) by localhost (mail.bitwise.fi [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id bxC696dJPtpb; Mon, 13 Feb 2017 14:07:03 +0200 (EET) Received: from localhost.sec.bitwise.fi (fw1.dmz.bitwise.fi [192.168.69.1]) (using TLSv1 with cipher ECDHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: anssiha) by mail.bitwise.fi (Postfix) with ESMTPSA id 7FD4160218; Mon, 13 Feb 2017 14:07:03 +0200 (EET) From: Anssi Hannula To: Adrian Hunter Cc: linux-mmc@vger.kernel.org, stable@vger.kernel.org Subject: [PATCH] mmc: sdhci-of-arasan: fix incorrect timeout clock Date: Mon, 13 Feb 2017 14:06:10 +0200 Message-Id: <20170213120610.1385-1-anssi.hannula@bitwise.fi> X-Mailer: git-send-email 2.8.3 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 sdhci_arasan_get_timeout_clock() divides the frequency it has with (1 << (13 + divisor)). However, the divisor is not some Arasan-specific value, but instead is just the Data Timeout Counter Value from the SDHCI Timeout Control Register. Applying it here like this is wrong as the sdhci driver already takes that value into account when calculating timeouts, and in fact it *sets* that register value based on how long a timeout is wanted. Additionally, sdhci core interprets the .get_timeout_clock callback return value as if it were read from hardware registers, i.e. the unit should be kHz or MHz depending on SDHCI_TIMEOUT_CLK_UNIT capability bit. This bit is set at least on the tested Zynq-7000 SoC. With the tested hardware (SDHCI_TIMEOUT_CLK_UNIT set) this results in too high a timeout clock rate being reported, causing the core to use longer-than-needed timeouts. Additionally, on a partitioned MMC (therefore having erase_group_def bit set) mmc_calc_max_discard() disables discard support as it looks like controller does not support the long timeouts needed for that. Do not apply the extra divisor and return the timeout clock in the expected unit. Tested with a Zynq-7000 SoC and a partitioned Toshiba THGBMAG5A1JBAWR eMMC card. Signed-off-by: Anssi Hannula Fixes: e3ec3a3d11ad ("mmc: arasan: Add driver for Arasan SDHCI") Cc: --- The .get_timeout_clock situation seems rather messy altogether, but I wasn't sure which direction to take it to and it is probably best to have that separate from this bugfix, anyway, so I kept the scope limited. drivers/mmc/host/sdhci-of-arasan.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 410a55b..1cfd7f9 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -28,13 +28,9 @@ #include "sdhci-pltfm.h" #include -#define SDHCI_ARASAN_CLK_CTRL_OFFSET 0x2c #define SDHCI_ARASAN_VENDOR_REGISTER 0x78 #define VENDOR_ENHANCED_STROBE BIT(0) -#define CLK_CTRL_TIMEOUT_SHIFT 16 -#define CLK_CTRL_TIMEOUT_MASK (0xf << CLK_CTRL_TIMEOUT_SHIFT) -#define CLK_CTRL_TIMEOUT_MIN_EXP 13 #define PHY_CLK_TOO_SLOW_HZ 400000 @@ -163,15 +159,15 @@ static int sdhci_arasan_syscon_write(struct sdhci_host *host, static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host) { - u32 div; unsigned long freq; struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET); - div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT; + /* SDHCI timeout clock is in kHz */ + freq = DIV_ROUND_UP(clk_get_rate(pltfm_host->clk), 1000); - freq = clk_get_rate(pltfm_host->clk); - freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div); + /* or in MHz */ + if (host->caps & SDHCI_TIMEOUT_CLK_UNIT) + freq = DIV_ROUND_UP(freq, 1000); return freq; }