diff options
-rw-r--r-- | arch/arm/mach-shmobile/clock-sh73a0.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c index d05cf9039788..d9fd0336b910 100644 --- a/arch/arm/mach-shmobile/clock-sh73a0.c +++ b/arch/arm/mach-shmobile/clock-sh73a0.c | |||
@@ -257,7 +257,7 @@ static struct clk twd_clk = { | |||
257 | .ops = &twd_clk_ops, | 257 | .ops = &twd_clk_ops, |
258 | }; | 258 | }; |
259 | 259 | ||
260 | static struct sh_clk_ops zclk_ops; | 260 | static struct sh_clk_ops zclk_ops, kicker_ops; |
261 | static const struct sh_clk_ops *div4_clk_ops; | 261 | static const struct sh_clk_ops *div4_clk_ops; |
262 | 262 | ||
263 | static int zclk_set_rate(struct clk *clk, unsigned long rate) | 263 | static int zclk_set_rate(struct clk *clk, unsigned long rate) |
@@ -324,18 +324,32 @@ static unsigned long zclk_recalc(struct clk *clk) | |||
324 | return clk_get_rate(clk->parent); | 324 | return clk_get_rate(clk->parent); |
325 | } | 325 | } |
326 | 326 | ||
327 | static void zclk_extend(void) | 327 | static int kicker_set_rate(struct clk *clk, unsigned long rate) |
328 | { | 328 | { |
329 | div4_clk_ops = div4_clks[DIV4_Z].ops; | 329 | if (__raw_readl(FRQCRB) & (1 << 31)) |
330 | return -EBUSY; | ||
331 | |||
332 | return div4_clk_ops->set_rate(clk, rate); | ||
333 | } | ||
334 | |||
335 | static void div4_clk_extend(void) | ||
336 | { | ||
337 | int i; | ||
338 | |||
339 | div4_clk_ops = div4_clks[0].ops; | ||
330 | 340 | ||
341 | /* Add a kicker-busy check before changing the rate */ | ||
342 | kicker_ops = *div4_clk_ops; | ||
331 | /* We extend the DIV4 clock with a 1:1 pass-through case */ | 343 | /* We extend the DIV4 clock with a 1:1 pass-through case */ |
332 | zclk_ops = *div4_clk_ops; | 344 | zclk_ops = *div4_clk_ops; |
333 | 345 | ||
346 | kicker_ops.set_rate = kicker_set_rate; | ||
334 | zclk_ops.set_rate = zclk_set_rate; | 347 | zclk_ops.set_rate = zclk_set_rate; |
335 | zclk_ops.round_rate = zclk_round_rate; | 348 | zclk_ops.round_rate = zclk_round_rate; |
336 | zclk_ops.recalc = zclk_recalc; | 349 | zclk_ops.recalc = zclk_recalc; |
337 | 350 | ||
338 | div4_clks[DIV4_Z].ops = &zclk_ops; | 351 | for (i = 0; i < DIV4_NR; i++) |
352 | div4_clks[i].ops = i == DIV4_Z ? &zclk_ops : &kicker_ops; | ||
339 | } | 353 | } |
340 | 354 | ||
341 | enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1, | 355 | enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1, |
@@ -697,7 +711,7 @@ void __init sh73a0_clock_init(void) | |||
697 | if (!ret) { | 711 | if (!ret) { |
698 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); | 712 | ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); |
699 | if (!ret) | 713 | if (!ret) |
700 | zclk_extend(); | 714 | div4_clk_extend(); |
701 | } | 715 | } |
702 | 716 | ||
703 | if (!ret) | 717 | if (!ret) |