diff options
Diffstat (limited to 'drivers/clk/shmobile/clk-div6.c')
-rw-r--r-- | drivers/clk/shmobile/clk-div6.c | 18 |
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) | |||
54 | static void cpg_div6_clock_disable(struct clk_hw *hw) | 54 | static 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 | ||
65 | static int cpg_div6_clock_is_enabled(struct clk_hw *hw) | 72 | static 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 | } |