28
28
* @hw: handle between common and hardware-specific interfaces
29
29
* @reg: IO-remapped register
30
30
* @div: divisor value (1-64)
31
- * @src_shift: Shift to access the register bits to select the parent clock
32
- * @src_width: Number of register bits to select the parent clock (may be 0)
31
+ * @src_mask: Bitmask covering the register bits to select the parent clock
33
32
* @nb: Notifier block to save/restore clock state for system resume
34
33
* @parents: Array to map from valid parent clocks indices to hardware indices
35
34
*/
36
35
struct div6_clock {
37
36
struct clk_hw hw ;
38
37
void __iomem * reg ;
39
38
unsigned int div ;
40
- u32 src_shift ;
41
- u32 src_width ;
39
+ u32 src_mask ;
42
40
struct notifier_block nb ;
43
41
u8 parents [];
44
42
};
@@ -99,15 +97,52 @@ static unsigned int cpg_div6_clock_calc_div(unsigned long rate,
99
97
rate = 1 ;
100
98
101
99
div = DIV_ROUND_CLOSEST (parent_rate , rate );
102
- return clamp_t ( unsigned int , div , 1 , 64 );
100
+ return clamp ( div , 1U , 64U );
103
101
}
104
102
105
- static long cpg_div6_clock_round_rate (struct clk_hw * hw , unsigned long rate ,
106
- unsigned long * parent_rate )
103
+ static int cpg_div6_clock_determine_rate (struct clk_hw * hw ,
104
+ struct clk_rate_request * req )
107
105
{
108
- unsigned int div = cpg_div6_clock_calc_div (rate , * parent_rate );
106
+ unsigned long prate , calc_rate , diff , best_rate , best_prate ;
107
+ unsigned int num_parents = clk_hw_get_num_parents (hw );
108
+ struct clk_hw * parent , * best_parent = NULL ;
109
+ unsigned int i , min_div , max_div , div ;
110
+ unsigned long min_diff = ULONG_MAX ;
111
+
112
+ for (i = 0 ; i < num_parents ; i ++ ) {
113
+ parent = clk_hw_get_parent_by_index (hw , i );
114
+ if (!parent )
115
+ continue ;
116
+
117
+ prate = clk_hw_get_rate (parent );
118
+ if (!prate )
119
+ continue ;
120
+
121
+ min_div = max (DIV_ROUND_UP (prate , req -> max_rate ), 1UL );
122
+ max_div = req -> min_rate ? min (prate / req -> min_rate , 64UL ) : 64 ;
123
+ if (max_div < min_div )
124
+ continue ;
125
+
126
+ div = cpg_div6_clock_calc_div (req -> rate , prate );
127
+ div = clamp (div , min_div , max_div );
128
+ calc_rate = prate / div ;
129
+ diff = calc_rate > req -> rate ? calc_rate - req -> rate
130
+ : req -> rate - calc_rate ;
131
+ if (diff < min_diff ) {
132
+ best_rate = calc_rate ;
133
+ best_parent = parent ;
134
+ best_prate = prate ;
135
+ min_diff = diff ;
136
+ }
137
+ }
138
+
139
+ if (!best_parent )
140
+ return - EINVAL ;
109
141
110
- return * parent_rate / div ;
142
+ req -> best_parent_rate = best_prate ;
143
+ req -> best_parent_hw = best_parent ;
144
+ req -> rate = best_rate ;
145
+ return 0 ;
111
146
}
112
147
113
148
static int cpg_div6_clock_set_rate (struct clk_hw * hw , unsigned long rate ,
@@ -133,11 +168,11 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
133
168
unsigned int i ;
134
169
u8 hw_index ;
135
170
136
- if (clock -> src_width == 0 )
171
+ if (clock -> src_mask == 0 )
137
172
return 0 ;
138
173
139
- hw_index = (readl (clock -> reg ) >> clock -> src_shift ) &
140
- ( BIT ( clock -> src_width ) - 1 );
174
+ hw_index = (readl (clock -> reg ) & clock -> src_mask ) >>
175
+ __ffs ( clock -> src_mask );
141
176
for (i = 0 ; i < clk_hw_get_num_parents (hw ); i ++ ) {
142
177
if (clock -> parents [i ] == hw_index )
143
178
return i ;
@@ -151,18 +186,13 @@ static u8 cpg_div6_clock_get_parent(struct clk_hw *hw)
151
186
static int cpg_div6_clock_set_parent (struct clk_hw * hw , u8 index )
152
187
{
153
188
struct div6_clock * clock = to_div6_clock (hw );
154
- u8 hw_index ;
155
- u32 mask ;
189
+ u32 src ;
156
190
157
191
if (index >= clk_hw_get_num_parents (hw ))
158
192
return - EINVAL ;
159
193
160
- mask = ~((BIT (clock -> src_width ) - 1 ) << clock -> src_shift );
161
- hw_index = clock -> parents [index ];
162
-
163
- writel ((readl (clock -> reg ) & mask ) | (hw_index << clock -> src_shift ),
164
- clock -> reg );
165
-
194
+ src = clock -> parents [index ] << __ffs (clock -> src_mask );
195
+ writel ((readl (clock -> reg ) & ~clock -> src_mask ) | src , clock -> reg );
166
196
return 0 ;
167
197
}
168
198
@@ -173,7 +203,7 @@ static const struct clk_ops cpg_div6_clock_ops = {
173
203
.get_parent = cpg_div6_clock_get_parent ,
174
204
.set_parent = cpg_div6_clock_set_parent ,
175
205
.recalc_rate = cpg_div6_clock_recalc_rate ,
176
- .round_rate = cpg_div6_clock_round_rate ,
206
+ .determine_rate = cpg_div6_clock_determine_rate ,
177
207
.set_rate = cpg_div6_clock_set_rate ,
178
208
};
179
209
@@ -236,17 +266,15 @@ struct clk * __init cpg_div6_register(const char *name,
236
266
switch (num_parents ) {
237
267
case 1 :
238
268
/* fixed parent clock */
239
- clock -> src_shift = clock -> src_width = 0 ;
269
+ clock -> src_mask = 0 ;
240
270
break ;
241
271
case 4 :
242
272
/* clock with EXSRC bits 6-7 */
243
- clock -> src_shift = 6 ;
244
- clock -> src_width = 2 ;
273
+ clock -> src_mask = GENMASK (7 , 6 );
245
274
break ;
246
275
case 8 :
247
276
/* VCLK with EXSRC bits 12-14 */
248
- clock -> src_shift = 12 ;
249
- clock -> src_width = 3 ;
277
+ clock -> src_mask = GENMASK (14 , 12 );
250
278
break ;
251
279
default :
252
280
pr_err ("%s: invalid number of parents for DIV6 clock %s\n" ,
0 commit comments