aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/sdhci-s3c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host/sdhci-s3c.c')
-rw-r--r--drivers/mmc/host/sdhci-s3c.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index a7710f557849..17203586305c 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -130,6 +130,15 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
130 if (!clksrc) 130 if (!clksrc)
131 return UINT_MAX; 131 return UINT_MAX;
132 132
133 /*
134 * Clock divider's step is different as 1 from that of host controller
135 * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
136 */
137 if (ourhost->pdata->clk_type) {
138 rate = clk_round_rate(clksrc, wanted);
139 return wanted - rate;
140 }
141
133 rate = clk_get_rate(clksrc); 142 rate = clk_get_rate(clksrc);
134 143
135 for (div = 1; div < 256; div *= 2) { 144 for (div = 1; div < 256; div *= 2) {
@@ -232,6 +241,42 @@ static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host)
232 return min; 241 return min;
233} 242}
234 243
244/* sdhci_cmu_get_max_clk - callback to get maximum clock frequency.*/
245static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host)
246{
247 struct sdhci_s3c *ourhost = to_s3c(host);
248
249 return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX);
250}
251
252/* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */
253static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host)
254{
255 struct sdhci_s3c *ourhost = to_s3c(host);
256
257 /*
258 * initial clock can be in the frequency range of
259 * 100KHz-400KHz, so we set it as max value.
260 */
261 return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000);
262}
263
264/* sdhci_cmu_set_clock - callback on clock change.*/
265static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
266{
267 struct sdhci_s3c *ourhost = to_s3c(host);
268
269 /* don't bother if the clock is going off */
270 if (clock == 0)
271 return;
272
273 sdhci_s3c_set_clock(host, clock);
274
275 clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
276
277 host->clock = clock;
278}
279
235static struct sdhci_ops sdhci_s3c_ops = { 280static struct sdhci_ops sdhci_s3c_ops = {
236 .get_max_clock = sdhci_s3c_get_max_clk, 281 .get_max_clock = sdhci_s3c_get_max_clk,
237 .set_clock = sdhci_s3c_set_clock, 282 .set_clock = sdhci_s3c_set_clock,
@@ -361,6 +406,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
361 406
362 clks++; 407 clks++;
363 sc->clk_bus[ptr] = clk; 408 sc->clk_bus[ptr] = clk;
409
410 /*
411 * save current clock index to know which clock bus
412 * is used later in overriding functions.
413 */
414 sc->cur_clk = ptr;
415
364 clk_enable(clk); 416 clk_enable(clk);
365 417
366 dev_info(dev, "clock source %d: %s (%ld Hz)\n", 418 dev_info(dev, "clock source %d: %s (%ld Hz)\n",
@@ -427,6 +479,16 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
427 /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ 479 /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */
428 host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; 480 host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
429 481
482 /*
483 * If controller does not have internal clock divider,
484 * we can use overriding functions instead of default.
485 */
486 if (pdata->clk_type) {
487 sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
488 sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
489 sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
490 }
491
430 /* It supports additional host capabilities if needed */ 492 /* It supports additional host capabilities if needed */
431 if (pdata->host_caps) 493 if (pdata->host_caps)
432 host->mmc->caps |= pdata->host_caps; 494 host->mmc->caps |= pdata->host_caps;