diff options
Diffstat (limited to 'drivers/clk/st/clk-flexgen.c')
-rw-r--r-- | drivers/clk/st/clk-flexgen.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 2282cef9f2ff..bf12a25eb3a2 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c | |||
@@ -37,8 +37,8 @@ static int flexgen_enable(struct clk_hw *hw) | |||
37 | struct clk_hw *pgate_hw = &flexgen->pgate.hw; | 37 | struct clk_hw *pgate_hw = &flexgen->pgate.hw; |
38 | struct clk_hw *fgate_hw = &flexgen->fgate.hw; | 38 | struct clk_hw *fgate_hw = &flexgen->fgate.hw; |
39 | 39 | ||
40 | pgate_hw->clk = hw->clk; | 40 | __clk_hw_set_clk(pgate_hw, hw); |
41 | fgate_hw->clk = hw->clk; | 41 | __clk_hw_set_clk(fgate_hw, hw); |
42 | 42 | ||
43 | clk_gate_ops.enable(pgate_hw); | 43 | clk_gate_ops.enable(pgate_hw); |
44 | 44 | ||
@@ -54,7 +54,7 @@ static void flexgen_disable(struct clk_hw *hw) | |||
54 | struct clk_hw *fgate_hw = &flexgen->fgate.hw; | 54 | struct clk_hw *fgate_hw = &flexgen->fgate.hw; |
55 | 55 | ||
56 | /* disable only the final gate */ | 56 | /* disable only the final gate */ |
57 | fgate_hw->clk = hw->clk; | 57 | __clk_hw_set_clk(fgate_hw, hw); |
58 | 58 | ||
59 | clk_gate_ops.disable(fgate_hw); | 59 | clk_gate_ops.disable(fgate_hw); |
60 | 60 | ||
@@ -66,7 +66,7 @@ static int flexgen_is_enabled(struct clk_hw *hw) | |||
66 | struct flexgen *flexgen = to_flexgen(hw); | 66 | struct flexgen *flexgen = to_flexgen(hw); |
67 | struct clk_hw *fgate_hw = &flexgen->fgate.hw; | 67 | struct clk_hw *fgate_hw = &flexgen->fgate.hw; |
68 | 68 | ||
69 | fgate_hw->clk = hw->clk; | 69 | __clk_hw_set_clk(fgate_hw, hw); |
70 | 70 | ||
71 | if (!clk_gate_ops.is_enabled(fgate_hw)) | 71 | if (!clk_gate_ops.is_enabled(fgate_hw)) |
72 | return 0; | 72 | return 0; |
@@ -79,7 +79,7 @@ static u8 flexgen_get_parent(struct clk_hw *hw) | |||
79 | struct flexgen *flexgen = to_flexgen(hw); | 79 | struct flexgen *flexgen = to_flexgen(hw); |
80 | struct clk_hw *mux_hw = &flexgen->mux.hw; | 80 | struct clk_hw *mux_hw = &flexgen->mux.hw; |
81 | 81 | ||
82 | mux_hw->clk = hw->clk; | 82 | __clk_hw_set_clk(mux_hw, hw); |
83 | 83 | ||
84 | return clk_mux_ops.get_parent(mux_hw); | 84 | return clk_mux_ops.get_parent(mux_hw); |
85 | } | 85 | } |
@@ -89,7 +89,7 @@ static int flexgen_set_parent(struct clk_hw *hw, u8 index) | |||
89 | struct flexgen *flexgen = to_flexgen(hw); | 89 | struct flexgen *flexgen = to_flexgen(hw); |
90 | struct clk_hw *mux_hw = &flexgen->mux.hw; | 90 | struct clk_hw *mux_hw = &flexgen->mux.hw; |
91 | 91 | ||
92 | mux_hw->clk = hw->clk; | 92 | __clk_hw_set_clk(mux_hw, hw); |
93 | 93 | ||
94 | return clk_mux_ops.set_parent(mux_hw, index); | 94 | return clk_mux_ops.set_parent(mux_hw, index); |
95 | } | 95 | } |
@@ -124,8 +124,8 @@ unsigned long flexgen_recalc_rate(struct clk_hw *hw, | |||
124 | struct clk_hw *fdiv_hw = &flexgen->fdiv.hw; | 124 | struct clk_hw *fdiv_hw = &flexgen->fdiv.hw; |
125 | unsigned long mid_rate; | 125 | unsigned long mid_rate; |
126 | 126 | ||
127 | pdiv_hw->clk = hw->clk; | 127 | __clk_hw_set_clk(pdiv_hw, hw); |
128 | fdiv_hw->clk = hw->clk; | 128 | __clk_hw_set_clk(fdiv_hw, hw); |
129 | 129 | ||
130 | mid_rate = clk_divider_ops.recalc_rate(pdiv_hw, parent_rate); | 130 | mid_rate = clk_divider_ops.recalc_rate(pdiv_hw, parent_rate); |
131 | 131 | ||
@@ -138,16 +138,27 @@ static int flexgen_set_rate(struct clk_hw *hw, unsigned long rate, | |||
138 | struct flexgen *flexgen = to_flexgen(hw); | 138 | struct flexgen *flexgen = to_flexgen(hw); |
139 | struct clk_hw *pdiv_hw = &flexgen->pdiv.hw; | 139 | struct clk_hw *pdiv_hw = &flexgen->pdiv.hw; |
140 | struct clk_hw *fdiv_hw = &flexgen->fdiv.hw; | 140 | struct clk_hw *fdiv_hw = &flexgen->fdiv.hw; |
141 | unsigned long primary_div = 0; | 141 | unsigned long div = 0; |
142 | int ret = 0; | 142 | int ret = 0; |
143 | 143 | ||
144 | pdiv_hw->clk = hw->clk; | 144 | __clk_hw_set_clk(pdiv_hw, hw); |
145 | fdiv_hw->clk = hw->clk; | 145 | __clk_hw_set_clk(fdiv_hw, hw); |
146 | 146 | ||
147 | primary_div = clk_best_div(parent_rate, rate); | 147 | div = clk_best_div(parent_rate, rate); |
148 | 148 | ||
149 | clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate); | 149 | /* |
150 | ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * primary_div); | 150 | * pdiv is mainly targeted for low freq results, while fdiv |
151 | * should be used for div <= 64. The other way round can | ||
152 | * lead to 'duty cycle' issues. | ||
153 | */ | ||
154 | |||
155 | if (div <= 64) { | ||
156 | clk_divider_ops.set_rate(pdiv_hw, parent_rate, parent_rate); | ||
157 | ret = clk_divider_ops.set_rate(fdiv_hw, rate, rate * div); | ||
158 | } else { | ||
159 | clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate); | ||
160 | ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * div); | ||
161 | } | ||
151 | 162 | ||
152 | return ret; | 163 | return ret; |
153 | } | 164 | } |