]>
Commit | Line | Data |
---|---|---|
76414229 GKH |
1 | From 16681037e75ce08f2980ac5dbb03414429c7a55d Mon Sep 17 00:00:00 2001 |
2 | From: Anssi Hannula <anssi.hannula@bitwise.fi> | |
3 | Date: Mon, 13 Feb 2017 14:06:10 +0200 | |
4 | Subject: mmc: sdhci-of-arasan: fix incorrect timeout clock | |
5 | ||
6 | From: Anssi Hannula <anssi.hannula@bitwise.fi> | |
7 | ||
8 | commit 16681037e75ce08f2980ac5dbb03414429c7a55d upstream. | |
9 | ||
10 | sdhci_arasan_get_timeout_clock() divides the frequency it has with (1 << | |
11 | (13 + divisor)). | |
12 | ||
13 | However, the divisor is not some Arasan-specific value, but instead is | |
14 | just the Data Timeout Counter Value from the SDHCI Timeout Control | |
15 | Register. | |
16 | ||
17 | Applying it here like this is wrong as the sdhci driver already takes | |
18 | that value into account when calculating timeouts, and in fact it *sets* | |
19 | that register value based on how long a timeout is wanted. | |
20 | ||
21 | Additionally, sdhci core interprets the .get_timeout_clock callback | |
22 | return value as if it were read from hardware registers, i.e. the unit | |
23 | should be kHz or MHz depending on SDHCI_TIMEOUT_CLK_UNIT capability bit. | |
24 | This bit is set at least on the tested Zynq-7000 SoC. | |
25 | ||
26 | With the tested hardware (SDHCI_TIMEOUT_CLK_UNIT set) this results in | |
27 | too high a timeout clock rate being reported, causing the core to use | |
28 | longer-than-needed timeouts. Additionally, on a partitioned MMC | |
29 | (therefore having erase_group_def bit set) mmc_calc_max_discard() | |
30 | disables discard support as it looks like controller does not support | |
31 | the long timeouts needed for that. | |
32 | ||
33 | Do not apply the extra divisor and return the timeout clock in the | |
34 | expected unit. | |
35 | ||
36 | Tested with a Zynq-7000 SoC and a partitioned Toshiba THGBMAG5A1JBAWR | |
37 | eMMC card. | |
38 | ||
39 | Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi> | |
40 | Fixes: e3ec3a3d11ad ("mmc: arasan: Add driver for Arasan SDHCI") | |
41 | Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> | |
42 | Signed-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 | } |