From 3ec5f1e7747eddcd231b53c4ff96f8963f4f0332 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 6 Dec 2010 09:24:14 +0100 Subject: [PATCH] --- yaml --- r: 225779 b: refs/heads/master c: b70a67f938e4a7544ca4dea2856b88f3c47669ff h: refs/heads/master i: 225777: 4ad9ffaa9c2d43d70531465c3cc3b5c330beaf77 225775: ee5b38544506f5955d10b3b8b8e072db2c38df8d v: v3 --- [refs] | 2 +- trunk/drivers/mmc/host/mmci.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index a2bfa9628aea..bb6133d53f55 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 34177802001894e064c857cac2759f68119550cd +refs/heads/master: b70a67f938e4a7544ca4dea2856b88f3c47669ff diff --git a/trunk/drivers/mmc/host/mmci.c b/trunk/drivers/mmc/host/mmci.c index 0814b88b44d6..f67fd4f2ab48 100644 --- a/trunk/drivers/mmc/host/mmci.c +++ b/trunk/drivers/mmc/host/mmci.c @@ -51,6 +51,7 @@ static unsigned int fmax = 515633; * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when * using DMA. * @sdio: variant supports SDIO + * @st_clkdiv: true if using a ST-specific clock divider algorithm */ struct variant_data { unsigned int clkreg; @@ -61,6 +62,7 @@ struct variant_data { bool broken_blockend; bool broken_blockend_dma; bool sdio; + bool st_clkdiv; }; static struct variant_data variant_arm = { @@ -86,7 +88,9 @@ static struct variant_data variant_ux500 = { .datalength_bits = 24, .broken_blockend = true, .sdio = true, + .st_clkdiv = true, }; + /* * This must be called with host->lock held */ @@ -97,9 +101,30 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) if (desired) { if (desired >= host->mclk) { - clk = MCI_CLK_BYPASS; + /* + * The ST clock divider does not like the bypass bit, + * even though it's available. Instead the datasheet + * recommends setting the divider to zero. + */ + if (!variant->st_clkdiv) + clk = MCI_CLK_BYPASS; host->cclk = host->mclk; + } else if (variant->st_clkdiv) { + /* + * DB8500 TRM says f = mclk / (clkdiv + 2) + * => clkdiv = (mclk / f) - 2 + * Round the divider up so we don't exceed the max + * frequency + */ + clk = DIV_ROUND_UP(host->mclk, desired) - 2; + if (clk >= 256) + clk = 255; + host->cclk = host->mclk / (clk + 2); } else { + /* + * PL180 TRM says f = mclk / (2 * (clkdiv + 1)) + * => clkdiv = mclk / (2 * f) - 1 + */ clk = host->mclk / (2 * desired) - 1; if (clk >= 256) clk = 255;