Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/actions/owl-composite.c
26282 views
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 <[email protected]>
7
//
8
// Copyright (c) 2018 Linaro Ltd.
9
// Author: Manivannan Sadhasivam <[email protected]>
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 int owl_comp_div_determine_rate(struct clk_hw *hw,
57
struct clk_rate_request *req)
58
{
59
struct owl_composite *comp = hw_to_owl_comp(hw);
60
long rate;
61
62
rate = owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
63
req->rate, &req->best_parent_rate);
64
if (rate < 0)
65
return rate;
66
67
req->rate = rate;
68
return 0;
69
}
70
71
static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw,
72
unsigned long parent_rate)
73
{
74
struct owl_composite *comp = hw_to_owl_comp(hw);
75
76
return owl_divider_helper_recalc_rate(&comp->common, &comp->rate.div_hw,
77
parent_rate);
78
}
79
80
static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate,
81
unsigned long parent_rate)
82
{
83
struct owl_composite *comp = hw_to_owl_comp(hw);
84
85
return owl_divider_helper_set_rate(&comp->common, &comp->rate.div_hw,
86
rate, parent_rate);
87
}
88
89
static int owl_comp_fact_determine_rate(struct clk_hw *hw,
90
struct clk_rate_request *req)
91
{
92
struct owl_composite *comp = hw_to_owl_comp(hw);
93
long rate;
94
95
rate = owl_factor_helper_round_rate(&comp->common,
96
&comp->rate.factor_hw,
97
req->rate, &req->best_parent_rate);
98
if (rate < 0)
99
return rate;
100
101
req->rate = rate;
102
return 0;
103
}
104
105
static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw,
106
unsigned long parent_rate)
107
{
108
struct owl_composite *comp = hw_to_owl_comp(hw);
109
110
return owl_factor_helper_recalc_rate(&comp->common,
111
&comp->rate.factor_hw,
112
parent_rate);
113
}
114
115
static int owl_comp_fact_set_rate(struct clk_hw *hw, unsigned long rate,
116
unsigned long parent_rate)
117
{
118
struct owl_composite *comp = hw_to_owl_comp(hw);
119
120
return owl_factor_helper_set_rate(&comp->common,
121
&comp->rate.factor_hw,
122
rate, parent_rate);
123
}
124
125
static long owl_comp_fix_fact_round_rate(struct clk_hw *hw, unsigned long rate,
126
unsigned long *parent_rate)
127
{
128
struct owl_composite *comp = hw_to_owl_comp(hw);
129
struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
130
131
return comp->fix_fact_ops->round_rate(&fix_fact_hw->hw, rate, parent_rate);
132
}
133
134
static unsigned long owl_comp_fix_fact_recalc_rate(struct clk_hw *hw,
135
unsigned long parent_rate)
136
{
137
struct owl_composite *comp = hw_to_owl_comp(hw);
138
struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
139
140
return comp->fix_fact_ops->recalc_rate(&fix_fact_hw->hw, parent_rate);
141
142
}
143
144
static int owl_comp_fix_fact_set_rate(struct clk_hw *hw, unsigned long rate,
145
unsigned long parent_rate)
146
{
147
/*
148
* We must report success but we can do so unconditionally because
149
* owl_comp_fix_fact_round_rate returns values that ensure this call is
150
* a nop.
151
*/
152
153
return 0;
154
}
155
156
const struct clk_ops owl_comp_div_ops = {
157
/* mux_ops */
158
.get_parent = owl_comp_get_parent,
159
.set_parent = owl_comp_set_parent,
160
161
/* gate_ops */
162
.disable = owl_comp_disable,
163
.enable = owl_comp_enable,
164
.is_enabled = owl_comp_is_enabled,
165
166
/* div_ops */
167
.determine_rate = owl_comp_div_determine_rate,
168
.recalc_rate = owl_comp_div_recalc_rate,
169
.set_rate = owl_comp_div_set_rate,
170
};
171
172
173
const struct clk_ops owl_comp_fact_ops = {
174
/* mux_ops */
175
.get_parent = owl_comp_get_parent,
176
.set_parent = owl_comp_set_parent,
177
178
/* gate_ops */
179
.disable = owl_comp_disable,
180
.enable = owl_comp_enable,
181
.is_enabled = owl_comp_is_enabled,
182
183
/* fact_ops */
184
.determine_rate = owl_comp_fact_determine_rate,
185
.recalc_rate = owl_comp_fact_recalc_rate,
186
.set_rate = owl_comp_fact_set_rate,
187
};
188
189
const struct clk_ops owl_comp_fix_fact_ops = {
190
/* gate_ops */
191
.disable = owl_comp_disable,
192
.enable = owl_comp_enable,
193
.is_enabled = owl_comp_is_enabled,
194
195
/* fix_fact_ops */
196
.round_rate = owl_comp_fix_fact_round_rate,
197
.recalc_rate = owl_comp_fix_fact_recalc_rate,
198
.set_rate = owl_comp_fix_fact_set_rate,
199
};
200
201
202
const struct clk_ops owl_comp_pass_ops = {
203
/* mux_ops */
204
.determine_rate = clk_hw_determine_rate_no_reparent,
205
.get_parent = owl_comp_get_parent,
206
.set_parent = owl_comp_set_parent,
207
208
/* gate_ops */
209
.disable = owl_comp_disable,
210
.enable = owl_comp_enable,
211
.is_enabled = owl_comp_is_enabled,
212
};
213
214