From d982dcdc4e64eb1881df44b0035a8268bf1ab067 Mon Sep 17 00:00:00 2001 From: Koen Beel Date: Fri, 15 Jul 2011 17:39:00 -0400 Subject: mmc: mxs-mmc: fix clock rate setting Fix clock rate setting in the mxs-mmc driver. Previously, if div2 was 0 then the value for TIMING_CLOCK_RATE would have been 255 instead of 0. The limits for div1 (TIMING_CLOCK_DIVIDE) and div2 (TIMING_CLOCK_RATE+1) were also not correctly defined. Can easily be reproduced on mx23evk: default clock for high speed sdio cards is 50 MHz. With a SSP_CLK of 28.8 MHz default), this resulted in an actual clock rate of about 56 kHz. Tested on mx23evk. Signed-off-by: Koen Beel Reviewed-by: Wolfram Sang Signed-off-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'drivers/mmc/host/mxs-mmc.c') 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) static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) { - unsigned int ssp_rate, bit_rate; - u32 div1, div2; + unsigned int ssp_clk, ssp_sck; + u32 clock_divide, clock_rate; u32 val; - ssp_rate = clk_get_rate(host->clk); + ssp_clk = clk_get_rate(host->clk); - for (div1 = 2; div1 < 254; div1 += 2) { - div2 = ssp_rate / rate / div1; - if (div2 < 0x100) + for (clock_divide = 2; clock_divide <= 254; clock_divide += 2) { + clock_rate = DIV_ROUND_UP(ssp_clk, rate * clock_divide); + clock_rate = (clock_rate > 0) ? clock_rate - 1 : 0; + if (clock_rate <= 255) break; } - if (div1 >= 254) { + if (clock_divide > 254) { dev_err(mmc_dev(host->mmc), "%s: cannot set clock to %d\n", __func__, rate); return; } - if (div2 == 0) - bit_rate = ssp_rate / div1; - else - bit_rate = ssp_rate / div1 / div2; + ssp_sck = ssp_clk / clock_divide / (1 + clock_rate); val = readl(host->base + HW_SSP_TIMING); val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); - val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE); - val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE); + val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE); + val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE); writel(val, host->base + HW_SSP_TIMING); - host->clk_rate = bit_rate; + host->clk_rate = ssp_sck; dev_dbg(mmc_dev(host->mmc), - "%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n", - __func__, div1, div2, ssp_rate, bit_rate, rate); + "%s: clock_divide %d, clock_rate %d, ssp_clk %d, rate_actual %d, rate_requested %d\n", + __func__, clock_divide, clock_rate, ssp_clk, ssp_sck, rate); } static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -- cgit v1.2.3