diff options
author | Tomasz Figa <tomasz.figa@gmail.com> | 2014-01-11 16:39:02 -0500 |
---|---|---|
committer | Chris Ball <chris@printf.net> | 2014-03-03 10:23:18 -0500 |
commit | 6eb28bdcb27249ca9981fb063d3f2485fd344500 (patch) | |
tree | 689d84356e6e9e9b3f8d44c5ff745d3bb8891b48 /drivers/mmc/host/sdhci-s3c.c | |
parent | 8880a4a526340335403696f30daf4e05a413f3bd (diff) |
mmc: sdhci-s3c: Cache bus clock rates
To fix scheduling while atomic happening in sdhci_s3c_set_clock() caused
by calling clk_get_rate() that might sleep, this patch modifies the
driver to cache rates of all bus clocks at probe time and then only use
those cache values.
Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Jaehoon Chung <jh80.chung@samsung.com>
Acked-by; Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Chris Ball <chris@printf.net>
Diffstat (limited to 'drivers/mmc/host/sdhci-s3c.c')
-rw-r--r-- | drivers/mmc/host/sdhci-s3c.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 52770d58cc47..9b783915b02a 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -57,6 +57,7 @@ struct sdhci_s3c { | |||
57 | 57 | ||
58 | struct clk *clk_io; | 58 | struct clk *clk_io; |
59 | struct clk *clk_bus[MAX_BUS_CLK]; | 59 | struct clk *clk_bus[MAX_BUS_CLK]; |
60 | unsigned long clk_rates[MAX_BUS_CLK]; | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | /** | 63 | /** |
@@ -158,7 +159,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
158 | return wanted - rate; | 159 | return wanted - rate; |
159 | } | 160 | } |
160 | 161 | ||
161 | rate = clk_get_rate(clksrc); | 162 | rate = ourhost->clk_rates[src]; |
162 | 163 | ||
163 | for (shift = 0; shift < 8; ++shift) { | 164 | for (shift = 0; shift < 8; ++shift) { |
164 | if ((rate >> shift) <= wanted) | 165 | if ((rate >> shift) <= wanted) |
@@ -215,7 +216,7 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
215 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | 216 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); |
216 | 217 | ||
217 | ourhost->cur_clk = best_src; | 218 | ourhost->cur_clk = best_src; |
218 | host->max_clk = clk_get_rate(clk); | 219 | host->max_clk = ourhost->clk_rates[best_src]; |
219 | 220 | ||
220 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); | 221 | ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2); |
221 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; | 222 | ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK; |
@@ -583,8 +584,10 @@ static int sdhci_s3c_probe(struct platform_device *pdev) | |||
583 | */ | 584 | */ |
584 | sc->cur_clk = ptr; | 585 | sc->cur_clk = ptr; |
585 | 586 | ||
587 | sc->clk_rates[ptr] = clk_get_rate(sc->clk_bus[ptr]); | ||
588 | |||
586 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", | 589 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", |
587 | ptr, name, clk_get_rate(clk)); | 590 | ptr, name, sc->clk_rates[ptr]); |
588 | } | 591 | } |
589 | 592 | ||
590 | if (clks == 0) { | 593 | if (clks == 0) { |