diff options
author | Sahitya Tummala <stummala@codeaurora.org> | 2013-06-10 16:32:51 +0530 |
---|---|---|
committer | Subhash Jadavani <subhashj@codeaurora.org> | 2016-05-27 10:28:42 -0700 |
commit | a467484ee963486ba9b527c6ca2dafd0f3b34eda (patch) | |
tree | 594febf80ea801744da82fd8233b5da4703960f9 /drivers/mmc | |
parent | b2f263c3ea2f0dd31343b10b6df5b46f0cddb7f4 (diff) |
mmc: sdhci-msm: calculate timeout value based on the base clock
The driver currently uses fixed timeout value from capabilities
register (bit 5-0) to calculate the timeout which is advertized
as 50MHz. But the driver uses SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK
and controls the base clock (MCLK) directly. So during card
initialization, the frequency would be 400KHz but still timeout
is calculated at 50MHz which is wrong. This patch fixes this by
using the current base clock frequency to calculate the timeout.
The controller internally multiplies the timeout control register
value by 4 with the assumption that driver always uses fixed
timeout clock value from capabilities register. Add a quirk
SDHCI_QUIRK2_DIVIDE_TOUT_BY_4 to avoid this multiplicaiton in
case base clock is used for timeout calculation.
CRs-fixed: 498159
Change-Id: I503fd16132bf17e590239997d6970b9b730d4202
Signed-off-by: Sahitya Tummala <stummala@codeaurora.org>
[subhashj@codeaurora.org: fixed minor merge conflict]
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/sdhci-msm.c | 3 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 10 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 13 |
3 files changed, 25 insertions, 1 deletions
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index ed64d1846d61..9cac755d36e2 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -2261,6 +2261,9 @@ static int sdhci_msm_probe(struct platform_device *pdev) host->quirks2 |= SDHCI_QUIRK2_BROKEN_PRESET_VALUE; host->quirks2 |= SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT; + if (host->quirks2 & SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK) + host->quirks2 |= SDHCI_QUIRK2_DIVIDE_TOUT_BY_4; + host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n", host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 176cc39e6dd5..de0bcb9149d2 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -670,6 +670,7 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) u8 count; struct mmc_data *data = cmd->data; unsigned target_timeout, current_timeout; + u32 curr_clk = 0; /* In KHz */ /* * If the host controller provides us with an incorrect timeout @@ -704,7 +705,14 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd) * (1) / (2) > 2^6 */ count = 0; - current_timeout = (1 << 13) * 1000 / host->timeout_clk; + if (host->quirks2 & SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK) { + curr_clk = host->clock / 1000; + if (host->quirks2 & SDHCI_QUIRK2_DIVIDE_TOUT_BY_4) + curr_clk /= 4; + current_timeout = (1 << 13) * 1000 / curr_clk; + } else { + current_timeout = (1 << 13) * 1000 / host->timeout_clk; + } while (current_timeout < target_timeout) { count++; current_timeout <<= 1; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 4335837f7c17..1a39c46439c5 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -458,6 +458,19 @@ struct sdhci_host { * specification. */ #define SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT (1<<23) +/* + * This is applicable for controllers that advertize timeout clock + * value in capabilities register (bit 5-0) as just 50MHz whereas the + * base clock frequency is 200MHz. So, the controller internally + * multiplies the value in timeout control register by 4 with the + * assumption that driver always uses fixed timeout clock value from + * capabilities register to calculate the timeout. But when the driver + * uses SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK base clock frequency is directly + * controller by driver and it's rate varies upto max. 200MHz. This new quirk + * will be used in such cases to avoid controller mulplication when timeout is + * calculated based on the base clock. + */ +#define SDHCI_QUIRK2_DIVIDE_TOUT_BY_4 (1 << 23) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ |