aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/st/clk-flexgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/st/clk-flexgen.c')
-rw-r--r--drivers/clk/st/clk-flexgen.c39
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}