diff options
author | Emilio López <emilio@elopez.com.ar> | 2013-09-14 20:37:59 -0400 |
---|---|---|
committer | Maxime Ripard <maxime.ripard@free-electrons.com> | 2013-11-10 05:39:07 -0500 |
commit | 107f3198fd2c5902b9cc54c86a0c86f815c173e2 (patch) | |
tree | 60dc1d889efaf68e77b6c18126a99fcc9ae6eff9 | |
parent | 272b98c6455f00884f0350f775c5342358ebb73f (diff) |
clk: composite: .determine_rate support
This commit adds .determine_rate support to the composite clock. It will
use the .determine_rate callback from the rate component if available,
and fall back on the mux component otherwise. This allows composite
clocks to enjoy the benefits of automatic clock reparenting.
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
-rw-r--r-- | drivers/clk/clk-composite.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index a33f46f20a41..753d0b784762 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c | |||
@@ -55,6 +55,30 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, | |||
55 | return rate_ops->recalc_rate(rate_hw, parent_rate); | 55 | return rate_ops->recalc_rate(rate_hw, parent_rate); |
56 | } | 56 | } |
57 | 57 | ||
58 | static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
59 | unsigned long *best_parent_rate, | ||
60 | struct clk **best_parent_p) | ||
61 | { | ||
62 | struct clk_composite *composite = to_clk_composite(hw); | ||
63 | const struct clk_ops *rate_ops = composite->rate_ops; | ||
64 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
65 | struct clk_hw *rate_hw = composite->rate_hw; | ||
66 | struct clk_hw *mux_hw = composite->mux_hw; | ||
67 | |||
68 | if (rate_hw && rate_ops && rate_ops->determine_rate) { | ||
69 | rate_hw->clk = hw->clk; | ||
70 | return rate_ops->determine_rate(rate_hw, rate, best_parent_rate, | ||
71 | best_parent_p); | ||
72 | } else if (mux_hw && mux_ops && mux_ops->determine_rate) { | ||
73 | mux_hw->clk = hw->clk; | ||
74 | return mux_ops->determine_rate(rate_hw, rate, best_parent_rate, | ||
75 | best_parent_p); | ||
76 | } else { | ||
77 | pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n"); | ||
78 | return 0; | ||
79 | } | ||
80 | } | ||
81 | |||
58 | static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, | 82 | static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, |
59 | unsigned long *prate) | 83 | unsigned long *prate) |
60 | { | 84 | { |
@@ -147,6 +171,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
147 | composite->mux_ops = mux_ops; | 171 | composite->mux_ops = mux_ops; |
148 | clk_composite_ops->get_parent = clk_composite_get_parent; | 172 | clk_composite_ops->get_parent = clk_composite_get_parent; |
149 | clk_composite_ops->set_parent = clk_composite_set_parent; | 173 | clk_composite_ops->set_parent = clk_composite_set_parent; |
174 | if (mux_ops->determine_rate) | ||
175 | clk_composite_ops->determine_rate = clk_composite_determine_rate; | ||
150 | } | 176 | } |
151 | 177 | ||
152 | if (rate_hw && rate_ops) { | 178 | if (rate_hw && rate_ops) { |
@@ -170,6 +196,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name, | |||
170 | composite->rate_hw = rate_hw; | 196 | composite->rate_hw = rate_hw; |
171 | composite->rate_ops = rate_ops; | 197 | composite->rate_ops = rate_ops; |
172 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; | 198 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; |
199 | if (rate_ops->determine_rate) | ||
200 | clk_composite_ops->determine_rate = clk_composite_determine_rate; | ||
173 | } | 201 | } |
174 | 202 | ||
175 | if (gate_hw && gate_ops) { | 203 | if (gate_hw && gate_ops) { |