mirror of https://gitee.com/openkylin/linux.git
ARM: shmobile: sh73a0: div4 clocks must check the kick bit before changing rate
According to the datasheet, it is not allowed to change div4 clock rates if an earlier rate change operation is still in progress, as indicated by a set kick bit. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski+renesas@gmail.com> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
This commit is contained in:
parent
3b207a45f9
commit
413bfd0e67
|
@ -257,7 +257,7 @@ static struct clk twd_clk = {
|
||||||
.ops = &twd_clk_ops,
|
.ops = &twd_clk_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct sh_clk_ops zclk_ops;
|
static struct sh_clk_ops zclk_ops, kicker_ops;
|
||||||
static const struct sh_clk_ops *div4_clk_ops;
|
static const struct sh_clk_ops *div4_clk_ops;
|
||||||
|
|
||||||
static int zclk_set_rate(struct clk *clk, unsigned long rate)
|
static int zclk_set_rate(struct clk *clk, unsigned long rate)
|
||||||
|
@ -324,18 +324,32 @@ static unsigned long zclk_recalc(struct clk *clk)
|
||||||
return clk_get_rate(clk->parent);
|
return clk_get_rate(clk->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void zclk_extend(void)
|
static int kicker_set_rate(struct clk *clk, unsigned long rate)
|
||||||
{
|
{
|
||||||
div4_clk_ops = div4_clks[DIV4_Z].ops;
|
if (__raw_readl(FRQCRB) & (1 << 31))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
return div4_clk_ops->set_rate(clk, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void div4_clk_extend(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
div4_clk_ops = div4_clks[0].ops;
|
||||||
|
|
||||||
|
/* Add a kicker-busy check before changing the rate */
|
||||||
|
kicker_ops = *div4_clk_ops;
|
||||||
/* We extend the DIV4 clock with a 1:1 pass-through case */
|
/* We extend the DIV4 clock with a 1:1 pass-through case */
|
||||||
zclk_ops = *div4_clk_ops;
|
zclk_ops = *div4_clk_ops;
|
||||||
|
|
||||||
|
kicker_ops.set_rate = kicker_set_rate;
|
||||||
zclk_ops.set_rate = zclk_set_rate;
|
zclk_ops.set_rate = zclk_set_rate;
|
||||||
zclk_ops.round_rate = zclk_round_rate;
|
zclk_ops.round_rate = zclk_round_rate;
|
||||||
zclk_ops.recalc = zclk_recalc;
|
zclk_ops.recalc = zclk_recalc;
|
||||||
|
|
||||||
div4_clks[DIV4_Z].ops = &zclk_ops;
|
for (i = 0; i < DIV4_NR; i++)
|
||||||
|
div4_clks[i].ops = i == DIV4_Z ? &zclk_ops : &kicker_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
|
enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
|
||||||
|
@ -697,7 +711,7 @@ void __init sh73a0_clock_init(void)
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
|
ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
zclk_extend();
|
div4_clk_extend();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
Loading…
Reference in New Issue