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