aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci.c
diff options
context:
space:
mode:
authorArindam Nath <arindam.nath@amd.com>2011-05-05 12:19:00 +0530
committerChris Ball <cjb@laptop.org>2011-05-24 23:53:44 -0400
commit758535c4e3cdd2b5b09565d9651aaa541aac3de8 (patch)
tree68675c722181a7d83e19830ee5b1bd50399b8d64 /drivers/mmc/host/sdhci.c
parentd6d50a15a2897d4133d536dd4343b5cf21163db3 (diff)
downloadkernel_samsung_smdk4412-758535c4e3cdd2b5b09565d9651aaa541aac3de8.zip
kernel_samsung_smdk4412-758535c4e3cdd2b5b09565d9651aaa541aac3de8.tar.gz
kernel_samsung_smdk4412-758535c4e3cdd2b5b09565d9651aaa541aac3de8.tar.bz2
mmc: sdhci: reset sdclk before setting high speed enable
As per Host Controller spec v3.00, we reset SDCLK before setting High Speed Enable, and then set it back to avoid generating clock gliches. Before enabling SDCLK again, we make sure the clock is stable, so we use sdhci_set_clock(). Tested by Zhangfei Gao with a Toshiba uhs card and general hs card, on mmp2 in SDMA mode. Signed-off-by: Arindam Nath <arindam.nath@amd.com> Reviewed-by: Philip Rakity <prakity@marvell.com> Tested-by: Philip Rakity <prakity@marvell.com> Acked-by: Zhangfei Gao <zhangfei.gao@marvell.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sdhci.c')
-rw-r--r--drivers/mmc/host/sdhci.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8072e16..409cde5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1243,13 +1243,12 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
else
ctrl &= ~SDHCI_CTRL_HISPD;
- sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
-
if (host->version >= SDHCI_SPEC_300) {
u16 ctrl_2;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if (!(ctrl_2 & SDHCI_CTRL_PRESET_VAL_ENABLE)) {
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
/*
* We only need to set Driver Strength if the
* preset value enable is not set.
@@ -1261,8 +1260,30 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C;
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+ } else {
+ /*
+ * According to SDHC Spec v3.00, if the Preset Value
+ * Enable in the Host Control 2 register is set, we
+ * need to reset SD Clock Enable before changing High
+ * Speed Enable to avoid generating clock gliches.
+ */
+ u16 clk;
+ unsigned int clock;
+
+ /* Reset SD Clock Enable */
+ clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+ clk &= ~SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+
+ /* Re-enable SD Clock */
+ clock = host->clock;
+ host->clock = 0;
+ sdhci_set_clock(host, clock);
}
- }
+ } else
+ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
/*
* Some (ENE) controllers go apeshit on some ios operation,