]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.10.7/mmc-sdhci-of-arasan-fix-incorrect-timeout-clock.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.10.7 / mmc-sdhci-of-arasan-fix-incorrect-timeout-clock.patch
CommitLineData
76414229
GKH
1From 16681037e75ce08f2980ac5dbb03414429c7a55d Mon Sep 17 00:00:00 2001
2From: Anssi Hannula <anssi.hannula@bitwise.fi>
3Date: Mon, 13 Feb 2017 14:06:10 +0200
4Subject: mmc: sdhci-of-arasan: fix incorrect timeout clock
5
6From: Anssi Hannula <anssi.hannula@bitwise.fi>
7
8commit 16681037e75ce08f2980ac5dbb03414429c7a55d upstream.
9
10sdhci_arasan_get_timeout_clock() divides the frequency it has with (1 <<
11(13 + divisor)).
12
13However, the divisor is not some Arasan-specific value, but instead is
14just the Data Timeout Counter Value from the SDHCI Timeout Control
15Register.
16
17Applying it here like this is wrong as the sdhci driver already takes
18that value into account when calculating timeouts, and in fact it *sets*
19that register value based on how long a timeout is wanted.
20
21Additionally, sdhci core interprets the .get_timeout_clock callback
22return value as if it were read from hardware registers, i.e. the unit
23should be kHz or MHz depending on SDHCI_TIMEOUT_CLK_UNIT capability bit.
24This bit is set at least on the tested Zynq-7000 SoC.
25
26With the tested hardware (SDHCI_TIMEOUT_CLK_UNIT set) this results in
27too high a timeout clock rate being reported, causing the core to use
28longer-than-needed timeouts. Additionally, on a partitioned MMC
29(therefore having erase_group_def bit set) mmc_calc_max_discard()
30disables discard support as it looks like controller does not support
31the long timeouts needed for that.
32
33Do not apply the extra divisor and return the timeout clock in the
34expected unit.
35
36Tested with a Zynq-7000 SoC and a partitioned Toshiba THGBMAG5A1JBAWR
37eMMC card.
38
39Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
40Fixes: e3ec3a3d11ad ("mmc: arasan: Add driver for Arasan SDHCI")
41Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
42Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
43
44---
45 drivers/mmc/host/sdhci-of-arasan.c | 14 +++++---------
46 1 file changed, 5 insertions(+), 9 deletions(-)
47
48--- a/drivers/mmc/host/sdhci-of-arasan.c
49+++ b/drivers/mmc/host/sdhci-of-arasan.c
50@@ -28,13 +28,9 @@
51 #include "sdhci-pltfm.h"
52 #include <linux/of.h>
53
54-#define SDHCI_ARASAN_CLK_CTRL_OFFSET 0x2c
55 #define SDHCI_ARASAN_VENDOR_REGISTER 0x78
56
57 #define VENDOR_ENHANCED_STROBE BIT(0)
58-#define CLK_CTRL_TIMEOUT_SHIFT 16
59-#define CLK_CTRL_TIMEOUT_MASK (0xf << CLK_CTRL_TIMEOUT_SHIFT)
60-#define CLK_CTRL_TIMEOUT_MIN_EXP 13
61
62 #define PHY_CLK_TOO_SLOW_HZ 400000
63
64@@ -163,15 +159,15 @@ static int sdhci_arasan_syscon_write(str
65
66 static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)
67 {
68- u32 div;
69 unsigned long freq;
70 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
71
72- div = readl(host->ioaddr + SDHCI_ARASAN_CLK_CTRL_OFFSET);
73- div = (div & CLK_CTRL_TIMEOUT_MASK) >> CLK_CTRL_TIMEOUT_SHIFT;
74+ /* SDHCI timeout clock is in kHz */
75+ freq = DIV_ROUND_UP(clk_get_rate(pltfm_host->clk), 1000);
76
77- freq = clk_get_rate(pltfm_host->clk);
78- freq /= 1 << (CLK_CTRL_TIMEOUT_MIN_EXP + div);
79+ /* or in MHz */
80+ if (host->caps & SDHCI_TIMEOUT_CLK_UNIT)
81+ freq = DIV_ROUND_UP(freq, 1000);
82
83 return freq;
84 }