diff options
Diffstat (limited to 'drivers/mmc/host/mxs-mmc.c')
-rw-r--r-- | drivers/mmc/host/mxs-mmc.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 99d39a6a1032..d513d47364d0 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
@@ -564,40 +564,38 @@ static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
564 | 564 | ||
565 | static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) | 565 | static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) |
566 | { | 566 | { |
567 | unsigned int ssp_rate, bit_rate; | 567 | unsigned int ssp_clk, ssp_sck; |
568 | u32 div1, div2; | 568 | u32 clock_divide, clock_rate; |
569 | u32 val; | 569 | u32 val; |
570 | 570 | ||
571 | ssp_rate = clk_get_rate(host->clk); | 571 | ssp_clk = clk_get_rate(host->clk); |
572 | 572 | ||
573 | for (div1 = 2; div1 < 254; div1 += 2) { | 573 | for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) { |
574 | div2 = ssp_rate / rate / div1; | 574 | clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide); |
575 | if (div2 < 0x100) | 575 | clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0; |
576 | if (clock_rate <= 255) | ||
576 | break; | 577 | break; |
577 | } | 578 | } |
578 | 579 | ||
579 | if (div1 >= 254) { | 580 | if (clock_divide > 254) { |
580 | dev_err(mmc_dev(host->mmc), | 581 | dev_err(mmc_dev(host->mmc), |
581 | "%s: cannot set clock to %d\n", __func__, rate); | 582 | "%s: cannot set clock to %d\n", __func__, rate); |
582 | return; | 583 | return; |
583 | } | 584 | } |
584 | 585 | ||
585 | if (div2 == 0) | 586 | ssp_sck = ssp_clk / clock_divide / (1 + clock_rate); |
586 | bit_rate = ssp_rate / div1; | ||
587 | else | ||
588 | bit_rate = ssp_rate / div1 / div2; | ||
589 | 587 | ||
590 | val = readl(host->base + HW_SSP_TIMING); | 588 | val = readl(host->base + HW_SSP_TIMING); |
591 | val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); | 589 | val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); |
592 | val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE); | 590 | val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE); |
593 | val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE); | 591 | val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE); |
594 | writel(val, host->base + HW_SSP_TIMING); | 592 | writel(val, host->base + HW_SSP_TIMING); |
595 | 593 | ||
596 | host->clk_rate = bit_rate; | 594 | host->clk_rate = ssp_sck; |
597 | 595 | ||
598 | dev_dbg(mmc_dev(host->mmc), | 596 | dev_dbg(mmc_dev(host->mmc), |
599 | "%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n", | 597 | "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n", |
600 | __func__, div1, div2, ssp_rate, bit_rate, rate); | 598 | __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate); |
601 | } | 599 | } |
602 | 600 | ||
603 | static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 601 | static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |