1bb150645SManivannan Sadhasivam // SPDX-License-Identifier: GPL-2.0+
2bb150645SManivannan Sadhasivam //
3bb150645SManivannan Sadhasivam // OWL composite clock driver
4bb150645SManivannan Sadhasivam //
5bb150645SManivannan Sadhasivam // Copyright (c) 2014 Actions Semi Inc.
6bb150645SManivannan Sadhasivam // Author: David Liu <liuwei@actions-semi.com>
7bb150645SManivannan Sadhasivam //
8bb150645SManivannan Sadhasivam // Copyright (c) 2018 Linaro Ltd.
9bb150645SManivannan Sadhasivam // Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
10bb150645SManivannan Sadhasivam
11bb150645SManivannan Sadhasivam #include <linux/clk-provider.h>
12bb150645SManivannan Sadhasivam #include <linux/regmap.h>
13bb150645SManivannan Sadhasivam
14bb150645SManivannan Sadhasivam #include "owl-composite.h"
15bb150645SManivannan Sadhasivam
owl_comp_get_parent(struct clk_hw * hw)16bb150645SManivannan Sadhasivam static u8 owl_comp_get_parent(struct clk_hw *hw)
17bb150645SManivannan Sadhasivam {
18bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
19bb150645SManivannan Sadhasivam
20bb150645SManivannan Sadhasivam return owl_mux_helper_get_parent(&comp->common, &comp->mux_hw);
21bb150645SManivannan Sadhasivam }
22bb150645SManivannan Sadhasivam
owl_comp_set_parent(struct clk_hw * hw,u8 index)23bb150645SManivannan Sadhasivam static int owl_comp_set_parent(struct clk_hw *hw, u8 index)
24bb150645SManivannan Sadhasivam {
25bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
26bb150645SManivannan Sadhasivam
27bb150645SManivannan Sadhasivam return owl_mux_helper_set_parent(&comp->common, &comp->mux_hw, index);
28bb150645SManivannan Sadhasivam }
29bb150645SManivannan Sadhasivam
owl_comp_disable(struct clk_hw * hw)30bb150645SManivannan Sadhasivam static void owl_comp_disable(struct clk_hw *hw)
31bb150645SManivannan Sadhasivam {
32bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
33bb150645SManivannan Sadhasivam struct owl_clk_common *common = &comp->common;
34bb150645SManivannan Sadhasivam
35bb150645SManivannan Sadhasivam owl_gate_set(common, &comp->gate_hw, false);
36bb150645SManivannan Sadhasivam }
37bb150645SManivannan Sadhasivam
owl_comp_enable(struct clk_hw * hw)38bb150645SManivannan Sadhasivam static int owl_comp_enable(struct clk_hw *hw)
39bb150645SManivannan Sadhasivam {
40bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
41bb150645SManivannan Sadhasivam struct owl_clk_common *common = &comp->common;
42bb150645SManivannan Sadhasivam
43bb150645SManivannan Sadhasivam owl_gate_set(common, &comp->gate_hw, true);
44bb150645SManivannan Sadhasivam
45bb150645SManivannan Sadhasivam return 0;
46bb150645SManivannan Sadhasivam }
47bb150645SManivannan Sadhasivam
owl_comp_is_enabled(struct clk_hw * hw)48bb150645SManivannan Sadhasivam static int owl_comp_is_enabled(struct clk_hw *hw)
49bb150645SManivannan Sadhasivam {
50bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
51bb150645SManivannan Sadhasivam struct owl_clk_common *common = &comp->common;
52bb150645SManivannan Sadhasivam
53bb150645SManivannan Sadhasivam return owl_gate_clk_is_enabled(common, &comp->gate_hw);
54bb150645SManivannan Sadhasivam }
55bb150645SManivannan Sadhasivam
owl_comp_div_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)5644077406SMaxime Ripard static int owl_comp_div_determine_rate(struct clk_hw *hw,
5744077406SMaxime Ripard struct clk_rate_request *req)
58bb150645SManivannan Sadhasivam {
59bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
6044077406SMaxime Ripard long rate;
61bb150645SManivannan Sadhasivam
6244077406SMaxime Ripard rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
6344077406SMaxime Ripard req->rate, &req->best_parent_rate);
6444077406SMaxime Ripard if (rate < 0)
6544077406SMaxime Ripard return rate;
6644077406SMaxime Ripard
6744077406SMaxime Ripard req->rate = rate;
6844077406SMaxime Ripard return 0;
69bb150645SManivannan Sadhasivam }
70bb150645SManivannan Sadhasivam
owl_comp_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)71bb150645SManivannan Sadhasivam static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw,
72bb150645SManivannan Sadhasivam unsigned long parent_rate)
73bb150645SManivannan Sadhasivam {
74bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
75bb150645SManivannan Sadhasivam
76bb150645SManivannan Sadhasivam return owl_divider_helper_recalc_rate(&comp->common, &comp->rate.div_hw,
77bb150645SManivannan Sadhasivam parent_rate);
78bb150645SManivannan Sadhasivam }
79bb150645SManivannan Sadhasivam
owl_comp_div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)80bb150645SManivannan Sadhasivam static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate,
81bb150645SManivannan Sadhasivam unsigned long parent_rate)
82bb150645SManivannan Sadhasivam {
83bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
84bb150645SManivannan Sadhasivam
85bb150645SManivannan Sadhasivam return owl_divider_helper_set_rate(&comp->common, &comp->rate.div_hw,
86bb150645SManivannan Sadhasivam rate, parent_rate);
87bb150645SManivannan Sadhasivam }
88bb150645SManivannan Sadhasivam
owl_comp_fact_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)89*939b61f6SMaxime Ripard static int owl_comp_fact_determine_rate(struct clk_hw *hw,
90*939b61f6SMaxime Ripard struct clk_rate_request *req)
91bb150645SManivannan Sadhasivam {
92bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
93*939b61f6SMaxime Ripard long rate;
94bb150645SManivannan Sadhasivam
95*939b61f6SMaxime Ripard rate = owl_factor_helper_round_rate(&comp->common,
96bb150645SManivannan Sadhasivam &comp->rate.factor_hw,
97*939b61f6SMaxime Ripard req->rate, &req->best_parent_rate);
98*939b61f6SMaxime Ripard if (rate < 0)
99*939b61f6SMaxime Ripard return rate;
100*939b61f6SMaxime Ripard
101*939b61f6SMaxime Ripard req->rate = rate;
102*939b61f6SMaxime Ripard return 0;
103bb150645SManivannan Sadhasivam }
104bb150645SManivannan Sadhasivam
owl_comp_fact_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)105bb150645SManivannan Sadhasivam static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw,
106bb150645SManivannan Sadhasivam unsigned long parent_rate)
107bb150645SManivannan Sadhasivam {
108bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
109bb150645SManivannan Sadhasivam
110bb150645SManivannan Sadhasivam return owl_factor_helper_recalc_rate(&comp->common,
111bb150645SManivannan Sadhasivam &comp->rate.factor_hw,
112bb150645SManivannan Sadhasivam parent_rate);
113bb150645SManivannan Sadhasivam }
114bb150645SManivannan Sadhasivam
owl_comp_fact_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)115bb150645SManivannan Sadhasivam static int owl_comp_fact_set_rate(struct clk_hw *hw, unsigned long rate,
116bb150645SManivannan Sadhasivam unsigned long parent_rate)
117bb150645SManivannan Sadhasivam {
118bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
119bb150645SManivannan Sadhasivam
120bb150645SManivannan Sadhasivam return owl_factor_helper_set_rate(&comp->common,
121bb150645SManivannan Sadhasivam &comp->rate.factor_hw,
122bb150645SManivannan Sadhasivam rate, parent_rate);
123bb150645SManivannan Sadhasivam }
124bb150645SManivannan Sadhasivam
owl_comp_fix_fact_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)125bb150645SManivannan Sadhasivam static long owl_comp_fix_fact_round_rate(struct clk_hw *hw, unsigned long rate,
126bb150645SManivannan Sadhasivam unsigned long *parent_rate)
127bb150645SManivannan Sadhasivam {
128bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
129bb150645SManivannan Sadhasivam struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
130bb150645SManivannan Sadhasivam
131bb150645SManivannan Sadhasivam return comp->fix_fact_ops->round_rate(&fix_fact_hw->hw, rate, parent_rate);
132bb150645SManivannan Sadhasivam }
133bb150645SManivannan Sadhasivam
owl_comp_fix_fact_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)134bb150645SManivannan Sadhasivam static unsigned long owl_comp_fix_fact_recalc_rate(struct clk_hw *hw,
135bb150645SManivannan Sadhasivam unsigned long parent_rate)
136bb150645SManivannan Sadhasivam {
137bb150645SManivannan Sadhasivam struct owl_composite *comp = hw_to_owl_comp(hw);
138bb150645SManivannan Sadhasivam struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
139bb150645SManivannan Sadhasivam
140bb150645SManivannan Sadhasivam return comp->fix_fact_ops->recalc_rate(&fix_fact_hw->hw, parent_rate);
141bb150645SManivannan Sadhasivam
142bb150645SManivannan Sadhasivam }
143bb150645SManivannan Sadhasivam
owl_comp_fix_fact_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)144bb150645SManivannan Sadhasivam static int owl_comp_fix_fact_set_rate(struct clk_hw *hw, unsigned long rate,
145bb150645SManivannan Sadhasivam unsigned long parent_rate)
146bb150645SManivannan Sadhasivam {
147bb150645SManivannan Sadhasivam /*
148bb150645SManivannan Sadhasivam * We must report success but we can do so unconditionally because
149bb150645SManivannan Sadhasivam * owl_comp_fix_fact_round_rate returns values that ensure this call is
150bb150645SManivannan Sadhasivam * a nop.
151bb150645SManivannan Sadhasivam */
152bb150645SManivannan Sadhasivam
153bb150645SManivannan Sadhasivam return 0;
154bb150645SManivannan Sadhasivam }
155bb150645SManivannan Sadhasivam
156bb150645SManivannan Sadhasivam const struct clk_ops owl_comp_div_ops = {
157bb150645SManivannan Sadhasivam /* mux_ops */
158bb150645SManivannan Sadhasivam .get_parent = owl_comp_get_parent,
159bb150645SManivannan Sadhasivam .set_parent = owl_comp_set_parent,
160bb150645SManivannan Sadhasivam
161bb150645SManivannan Sadhasivam /* gate_ops */
162bb150645SManivannan Sadhasivam .disable = owl_comp_disable,
163bb150645SManivannan Sadhasivam .enable = owl_comp_enable,
164bb150645SManivannan Sadhasivam .is_enabled = owl_comp_is_enabled,
165bb150645SManivannan Sadhasivam
166bb150645SManivannan Sadhasivam /* div_ops */
16744077406SMaxime Ripard .determine_rate = owl_comp_div_determine_rate,
168bb150645SManivannan Sadhasivam .recalc_rate = owl_comp_div_recalc_rate,
169bb150645SManivannan Sadhasivam .set_rate = owl_comp_div_set_rate,
170bb150645SManivannan Sadhasivam };
171bb150645SManivannan Sadhasivam
172bb150645SManivannan Sadhasivam
173bb150645SManivannan Sadhasivam const struct clk_ops owl_comp_fact_ops = {
174bb150645SManivannan Sadhasivam /* mux_ops */
175bb150645SManivannan Sadhasivam .get_parent = owl_comp_get_parent,
176bb150645SManivannan Sadhasivam .set_parent = owl_comp_set_parent,
177bb150645SManivannan Sadhasivam
178bb150645SManivannan Sadhasivam /* gate_ops */
179bb150645SManivannan Sadhasivam .disable = owl_comp_disable,
180bb150645SManivannan Sadhasivam .enable = owl_comp_enable,
181bb150645SManivannan Sadhasivam .is_enabled = owl_comp_is_enabled,
182bb150645SManivannan Sadhasivam
183bb150645SManivannan Sadhasivam /* fact_ops */
184*939b61f6SMaxime Ripard .determine_rate = owl_comp_fact_determine_rate,
185bb150645SManivannan Sadhasivam .recalc_rate = owl_comp_fact_recalc_rate,
186bb150645SManivannan Sadhasivam .set_rate = owl_comp_fact_set_rate,
187bb150645SManivannan Sadhasivam };
188bb150645SManivannan Sadhasivam
189bb150645SManivannan Sadhasivam const struct clk_ops owl_comp_fix_fact_ops = {
190bb150645SManivannan Sadhasivam /* gate_ops */
191bb150645SManivannan Sadhasivam .disable = owl_comp_disable,
192bb150645SManivannan Sadhasivam .enable = owl_comp_enable,
193bb150645SManivannan Sadhasivam .is_enabled = owl_comp_is_enabled,
194bb150645SManivannan Sadhasivam
195bb150645SManivannan Sadhasivam /* fix_fact_ops */
196bb150645SManivannan Sadhasivam .round_rate = owl_comp_fix_fact_round_rate,
197bb150645SManivannan Sadhasivam .recalc_rate = owl_comp_fix_fact_recalc_rate,
198bb150645SManivannan Sadhasivam .set_rate = owl_comp_fix_fact_set_rate,
199bb150645SManivannan Sadhasivam };
200bb150645SManivannan Sadhasivam
201bb150645SManivannan Sadhasivam
202bb150645SManivannan Sadhasivam const struct clk_ops owl_comp_pass_ops = {
203bb150645SManivannan Sadhasivam /* mux_ops */
2043876e2d7SMaxime Ripard .determine_rate = clk_hw_determine_rate_no_reparent,
205bb150645SManivannan Sadhasivam .get_parent = owl_comp_get_parent,
206bb150645SManivannan Sadhasivam .set_parent = owl_comp_set_parent,
207bb150645SManivannan Sadhasivam
208bb150645SManivannan Sadhasivam /* gate_ops */
209bb150645SManivannan Sadhasivam .disable = owl_comp_disable,
210bb150645SManivannan Sadhasivam .enable = owl_comp_enable,
211bb150645SManivannan Sadhasivam .is_enabled = owl_comp_is_enabled,
212bb150645SManivannan Sadhasivam };
213