aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/shmobile/clk-div6.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/shmobile/clk-div6.c')
-rw-r--r--drivers/clk/shmobile/clk-div6.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/clk/shmobile/clk-div6.c b/drivers/clk/shmobile/clk-div6.c
index 639241e31e03..036a692c7219 100644
--- a/drivers/clk/shmobile/clk-div6.c
+++ b/drivers/clk/shmobile/clk-div6.c
@@ -54,12 +54,19 @@ static int cpg_div6_clock_enable(struct clk_hw *hw)
54static void cpg_div6_clock_disable(struct clk_hw *hw) 54static void cpg_div6_clock_disable(struct clk_hw *hw)
55{ 55{
56 struct div6_clock *clock = to_div6_clock(hw); 56 struct div6_clock *clock = to_div6_clock(hw);
57 u32 val;
57 58
58 /* DIV6 clocks require the divisor field to be non-zero when stopping 59 val = clk_readl(clock->reg);
59 * the clock. 60 val |= CPG_DIV6_CKSTP;
61 /*
62 * DIV6 clocks require the divisor field to be non-zero when stopping
63 * the clock. However, some clocks (e.g. ZB on sh73a0) fail to be
64 * re-enabled later if the divisor field is changed when stopping the
65 * clock
60 */ 66 */
61 clk_writel(clk_readl(clock->reg) | CPG_DIV6_CKSTP | CPG_DIV6_DIV_MASK, 67 if (!(val & CPG_DIV6_DIV_MASK))
62 clock->reg); 68 val |= CPG_DIV6_DIV_MASK;
69 clk_writel(val, clock->reg);
63} 70}
64 71
65static int cpg_div6_clock_is_enabled(struct clk_hw *hw) 72static int cpg_div6_clock_is_enabled(struct clk_hw *hw)
@@ -83,6 +90,9 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
83{ 90{
84 unsigned int div; 91 unsigned int div;
85 92
93 if (!rate)
94 rate = 1;
95
86 div = DIV_ROUND_CLOSEST(parent_rate, rate); 96 div = DIV_ROUND_CLOSEST(parent_rate, rate);
87 return clamp_t(unsigned int, div, 1, 64); 97 return clamp_t(unsigned int, div, 1, 64);
88} 98}