summaryrefslogtreecommitdiffstats
path: root/drivers/clk/st
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/st')
-rw-r--r--drivers/clk/st/clk-flexgen.c39
-rw-r--r--drivers/clk/st/clkgen-mux.c14
2 files changed, 32 insertions, 21 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)
struct clk_hw *pgate_hw = &flexgen->pgate.hw;
struct clk_hw *fgate_hw = &flexgen->fgate.hw;
- pgate_hw->clk = hw->clk;
- fgate_hw->clk = hw->clk;
+ __clk_hw_set_clk(pgate_hw, hw);
+ __clk_hw_set_clk(fgate_hw, hw);
clk_gate_ops.enable(pgate_hw);
@@ -54,7 +54,7 @@ static void flexgen_disable(struct clk_hw *hw)
struct clk_hw *fgate_hw = &flexgen->fgate.hw;
/* disable only the final gate */
- fgate_hw->clk = hw->clk;
+ __clk_hw_set_clk(fgate_hw, hw);
clk_gate_ops.disable(fgate_hw);
@@ -66,7 +66,7 @@ static int flexgen_is_enabled(struct clk_hw *hw)
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *fgate_hw = &flexgen->fgate.hw;
- fgate_hw->clk = hw->clk;
+ __clk_hw_set_clk(fgate_hw, hw);
if (!clk_gate_ops.is_enabled(fgate_hw))
return 0;
@@ -79,7 +79,7 @@ static u8 flexgen_get_parent(struct clk_hw *hw)
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *mux_hw = &flexgen->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return clk_mux_ops.get_parent(mux_hw);
}
@@ -89,7 +89,7 @@ static int flexgen_set_parent(struct clk_hw *hw, u8 index)
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *mux_hw = &flexgen->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return clk_mux_ops.set_parent(mux_hw, index);
}
@@ -124,8 +124,8 @@ unsigned long flexgen_recalc_rate(struct clk_hw *hw,
struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
unsigned long mid_rate;
- pdiv_hw->clk = hw->clk;
- fdiv_hw->clk = hw->clk;
+ __clk_hw_set_clk(pdiv_hw, hw);
+ __clk_hw_set_clk(fdiv_hw, hw);
mid_rate = clk_divider_ops.recalc_rate(pdiv_hw, parent_rate);
@@ -138,16 +138,27 @@ static int flexgen_set_rate(struct clk_hw *hw, unsigned long rate,
struct flexgen *flexgen = to_flexgen(hw);
struct clk_hw *pdiv_hw = &flexgen->pdiv.hw;
struct clk_hw *fdiv_hw = &flexgen->fdiv.hw;
- unsigned long primary_div = 0;
+ unsigned long div = 0;
int ret = 0;
- pdiv_hw->clk = hw->clk;
- fdiv_hw->clk = hw->clk;
+ __clk_hw_set_clk(pdiv_hw, hw);
+ __clk_hw_set_clk(fdiv_hw, hw);
- primary_div = clk_best_div(parent_rate, rate);
+ div = clk_best_div(parent_rate, rate);
- clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate);
- ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * primary_div);
+ /*
+ * pdiv is mainly targeted for low freq results, while fdiv
+ * should be used for div <= 64. The other way round can
+ * lead to 'duty cycle' issues.
+ */
+
+ if (div <= 64) {
+ clk_divider_ops.set_rate(pdiv_hw, parent_rate, parent_rate);
+ ret = clk_divider_ops.set_rate(fdiv_hw, rate, rate * div);
+ } else {
+ clk_divider_ops.set_rate(fdiv_hw, parent_rate, parent_rate);
+ ret = clk_divider_ops.set_rate(pdiv_hw, rate, rate * div);
+ }
return ret;
}
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c
index 79dc40b5cc68..9a15ec344a85 100644
--- a/drivers/clk/st/clkgen-mux.c
+++ b/drivers/clk/st/clkgen-mux.c
@@ -94,7 +94,7 @@ static int clkgena_divmux_enable(struct clk_hw *hw)
unsigned long timeout;
int ret = 0;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
ret = clk_mux_ops.set_parent(mux_hw, genamux->muxsel);
if (ret)
@@ -116,7 +116,7 @@ static void clkgena_divmux_disable(struct clk_hw *hw)
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
clk_mux_ops.set_parent(mux_hw, CKGAX_CLKOPSRC_SWITCH_OFF);
}
@@ -126,7 +126,7 @@ static int clkgena_divmux_is_enabled(struct clk_hw *hw)
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
return (s8)clk_mux_ops.get_parent(mux_hw) > 0;
}
@@ -136,7 +136,7 @@ u8 clkgena_divmux_get_parent(struct clk_hw *hw)
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *mux_hw = &genamux->mux.hw;
- mux_hw->clk = hw->clk;
+ __clk_hw_set_clk(mux_hw, hw);
genamux->muxsel = clk_mux_ops.get_parent(mux_hw);
if ((s8)genamux->muxsel < 0) {
@@ -174,7 +174,7 @@ unsigned long clkgena_divmux_recalc_rate(struct clk_hw *hw,
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return clk_divider_ops.recalc_rate(div_hw, parent_rate);
}
@@ -185,7 +185,7 @@ static int clkgena_divmux_set_rate(struct clk_hw *hw, unsigned long rate,
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return clk_divider_ops.set_rate(div_hw, rate, parent_rate);
}
@@ -196,7 +196,7 @@ static long clkgena_divmux_round_rate(struct clk_hw *hw, unsigned long rate,
struct clkgena_divmux *genamux = to_clkgena_divmux(hw);
struct clk_hw *div_hw = &genamux->div[genamux->muxsel].hw;
- div_hw->clk = hw->clk;
+ __clk_hw_set_clk(div_hw, hw);
return clk_divider_ops.round_rate(div_hw, rate, prate);
}