summaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-esdhc-imx.c
diff options
context:
space:
mode:
authorDong Aisheng2013-09-13 13:11:32 +0200
committerChris Ball2013-09-26 13:57:12 +0200
commitd31fc00a71b4f3a52d23c5a995ccd63e50a2c877 (patch)
tree01abef4ac1da7dffe7230d458badafabce7b834a /drivers/mmc/host/sdhci-esdhc-imx.c
parentmmc: sdhci: allow platform access of sdhci_send_command (diff)
downloadkernel-qcow2-linux-d31fc00a71b4f3a52d23c5a995ccd63e50a2c877.tar.gz
kernel-qcow2-linux-d31fc00a71b4f3a52d23c5a995ccd63e50a2c877.tar.xz
kernel-qcow2-linux-d31fc00a71b4f3a52d23c5a995ccd63e50a2c877.zip
mmc: sdhci-esdhc: move common esdhc_set_clock to platform driver
We need a lot of imx6 specific things into common esdhc_set_clock for support SD3.0 and eMMC DDR mode which is not needed for power pc platforms, so esdhc_set_clock seems not so common anymore. Instead of keeping add platform specfics things into this common API, we choose to move that code into platform driver itself to handle. This can also exclude the dependency between imx and power pc on this headfile and is easy for maintain in the future. Signed-off-by: Dong Aisheng <b29396@freescale.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/sdhci-esdhc-imx.c')
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index abc8cf01e6e3..67eaec92e333 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -409,8 +409,39 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
-
- esdhc_set_clock(host, clock, clk_get_rate(pltfm_host->clk));
+ unsigned int host_clock = clk_get_rate(pltfm_host->clk);
+ int pre_div = 2;
+ int div = 1;
+ u32 temp;
+
+ if (clock == 0)
+ goto out;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | ESDHC_CLOCK_MASK);
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+
+ while (host_clock / pre_div / 16 > clock && pre_div < 256)
+ pre_div *= 2;
+
+ while (host_clock / pre_div / div > clock && div < 16)
+ div++;
+
+ dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n",
+ clock, host_clock / pre_div / div);
+
+ pre_div >>= 1;
+ div--;
+
+ temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
+ temp |= (ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
+ | (div << ESDHC_DIVIDER_SHIFT)
+ | (pre_div << ESDHC_PREDIV_SHIFT));
+ sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+ mdelay(1);
+out:
+ host->clock = clock;
}
static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)