30
30
31
31
#define to_clk_divider (_hw ) container_of(_hw, struct clk_divider, hw)
32
32
33
- #define div_mask (d ) ((1 << ((d)-> width)) - 1)
33
+ #define div_mask (width ) ((1 << (width)) - 1)
34
34
35
35
static unsigned int _get_table_maxdiv (const struct clk_div_table * table )
36
36
{
@@ -54,15 +54,16 @@ static unsigned int _get_table_mindiv(const struct clk_div_table *table)
54
54
return mindiv ;
55
55
}
56
56
57
- static unsigned int _get_maxdiv (struct clk_divider * divider )
57
+ static unsigned int _get_maxdiv (const struct clk_div_table * table , u8 width ,
58
+ unsigned long flags )
58
59
{
59
- if (divider -> flags & CLK_DIVIDER_ONE_BASED )
60
- return div_mask (divider );
61
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO )
62
- return 1 << div_mask (divider );
63
- if (divider -> table )
64
- return _get_table_maxdiv (divider -> table );
65
- return div_mask (divider ) + 1 ;
60
+ if (flags & CLK_DIVIDER_ONE_BASED )
61
+ return div_mask (width );
62
+ if (flags & CLK_DIVIDER_POWER_OF_TWO )
63
+ return 1 << div_mask (width );
64
+ if (table )
65
+ return _get_table_maxdiv (table );
66
+ return div_mask (width ) + 1 ;
66
67
}
67
68
68
69
static unsigned int _get_table_div (const struct clk_div_table * table ,
@@ -76,14 +77,15 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
76
77
return 0 ;
77
78
}
78
79
79
- static unsigned int _get_div (struct clk_divider * divider , unsigned int val )
80
+ static unsigned int _get_div (const struct clk_div_table * table ,
81
+ unsigned int val , unsigned long flags )
80
82
{
81
- if (divider -> flags & CLK_DIVIDER_ONE_BASED )
83
+ if (flags & CLK_DIVIDER_ONE_BASED )
82
84
return val ;
83
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO )
85
+ if (flags & CLK_DIVIDER_POWER_OF_TWO )
84
86
return 1 << val ;
85
- if (divider -> table )
86
- return _get_table_div (divider -> table , val );
87
+ if (table )
88
+ return _get_table_div (table , val );
87
89
return val + 1 ;
88
90
}
89
91
@@ -98,36 +100,49 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
98
100
return 0 ;
99
101
}
100
102
101
- static unsigned int _get_val (struct clk_divider * divider , unsigned int div )
103
+ static unsigned int _get_val (const struct clk_div_table * table ,
104
+ unsigned int div , unsigned long flags )
102
105
{
103
- if (divider -> flags & CLK_DIVIDER_ONE_BASED )
106
+ if (flags & CLK_DIVIDER_ONE_BASED )
104
107
return div ;
105
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO )
108
+ if (flags & CLK_DIVIDER_POWER_OF_TWO )
106
109
return __ffs (div );
107
- if (divider -> table )
108
- return _get_table_val (divider -> table , div );
110
+ if (table )
111
+ return _get_table_val (table , div );
109
112
return div - 1 ;
110
113
}
111
114
112
- static unsigned long clk_divider_recalc_rate (struct clk_hw * hw ,
113
- unsigned long parent_rate )
115
+ unsigned long divider_recalc_rate (struct clk_hw * hw , unsigned long parent_rate ,
116
+ unsigned int val ,
117
+ const struct clk_div_table * table ,
118
+ unsigned long flags )
114
119
{
115
- struct clk_divider * divider = to_clk_divider (hw );
116
- unsigned int div , val ;
120
+ unsigned int div ;
117
121
118
- val = clk_readl (divider -> reg ) >> divider -> shift ;
119
- val &= div_mask (divider );
120
-
121
- div = _get_div (divider , val );
122
+ div = _get_div (table , val , flags );
122
123
if (!div ) {
123
- WARN (!(divider -> flags & CLK_DIVIDER_ALLOW_ZERO ),
124
+ WARN (!(flags & CLK_DIVIDER_ALLOW_ZERO ),
124
125
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n" ,
125
126
__clk_get_name (hw -> clk ));
126
127
return parent_rate ;
127
128
}
128
129
129
130
return DIV_ROUND_UP (parent_rate , div );
130
131
}
132
+ EXPORT_SYMBOL_GPL (divider_recalc_rate );
133
+
134
+ static unsigned long clk_divider_recalc_rate (struct clk_hw * hw ,
135
+ unsigned long parent_rate )
136
+ {
137
+ struct clk_divider * divider = to_clk_divider (hw );
138
+ unsigned int val ;
139
+
140
+ val = clk_readl (divider -> reg ) >> divider -> shift ;
141
+ val &= div_mask (divider -> width );
142
+
143
+ return divider_recalc_rate (hw , parent_rate , val , divider -> table ,
144
+ divider -> flags );
145
+ }
131
146
132
147
/*
133
148
* The reverse of DIV_ROUND_UP: The maximum number which
@@ -146,12 +161,13 @@ static bool _is_valid_table_div(const struct clk_div_table *table,
146
161
return false;
147
162
}
148
163
149
- static bool _is_valid_div (struct clk_divider * divider , unsigned int div )
164
+ static bool _is_valid_div (const struct clk_div_table * table , unsigned int div ,
165
+ unsigned long flags )
150
166
{
151
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO )
167
+ if (flags & CLK_DIVIDER_POWER_OF_TWO )
152
168
return is_power_of_2 (div );
153
- if (divider -> table )
154
- return _is_valid_table_div (divider -> table , div );
169
+ if (table )
170
+ return _is_valid_table_div (table , div );
155
171
return true;
156
172
}
157
173
@@ -191,91 +207,88 @@ static int _round_down_table(const struct clk_div_table *table, int div)
191
207
return down ;
192
208
}
193
209
194
- static int _div_round_up (struct clk_divider * divider ,
195
- unsigned long parent_rate , unsigned long rate )
210
+ static int _div_round_up (const struct clk_div_table * table ,
211
+ unsigned long parent_rate , unsigned long rate ,
212
+ unsigned long flags )
196
213
{
197
214
int div = DIV_ROUND_UP (parent_rate , rate );
198
215
199
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO )
216
+ if (flags & CLK_DIVIDER_POWER_OF_TWO )
200
217
div = __roundup_pow_of_two (div );
201
- if (divider -> table )
202
- div = _round_up_table (divider -> table , div );
218
+ if (table )
219
+ div = _round_up_table (table , div );
203
220
204
221
return div ;
205
222
}
206
223
207
- static int _div_round_closest (struct clk_divider * divider ,
208
- unsigned long parent_rate , unsigned long rate )
224
+ static int _div_round_closest (const struct clk_div_table * table ,
225
+ unsigned long parent_rate , unsigned long rate ,
226
+ unsigned long flags )
209
227
{
210
228
int up , down , div ;
211
229
212
230
up = down = div = DIV_ROUND_CLOSEST (parent_rate , rate );
213
231
214
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO ) {
232
+ if (flags & CLK_DIVIDER_POWER_OF_TWO ) {
215
233
up = __roundup_pow_of_two (div );
216
234
down = __rounddown_pow_of_two (div );
217
- } else if (divider -> table ) {
218
- up = _round_up_table (divider -> table , div );
219
- down = _round_down_table (divider -> table , div );
235
+ } else if (table ) {
236
+ up = _round_up_table (table , div );
237
+ down = _round_down_table (table , div );
220
238
}
221
239
222
240
return (up - div ) <= (div - down ) ? up : down ;
223
241
}
224
242
225
- static int _div_round (struct clk_divider * divider , unsigned long parent_rate ,
226
- unsigned long rate )
243
+ static int _div_round (const struct clk_div_table * table ,
244
+ unsigned long parent_rate , unsigned long rate ,
245
+ unsigned long flags )
227
246
{
228
- if (divider -> flags & CLK_DIVIDER_ROUND_CLOSEST )
229
- return _div_round_closest (divider , parent_rate , rate );
247
+ if (flags & CLK_DIVIDER_ROUND_CLOSEST )
248
+ return _div_round_closest (table , parent_rate , rate , flags );
230
249
231
- return _div_round_up (divider , parent_rate , rate );
250
+ return _div_round_up (table , parent_rate , rate , flags );
232
251
}
233
252
234
- static bool _is_best_div (struct clk_divider * divider ,
235
- unsigned long rate , unsigned long now , unsigned long best )
253
+ static bool _is_best_div (unsigned long rate , unsigned long now ,
254
+ unsigned long best , unsigned long flags )
236
255
{
237
- if (divider -> flags & CLK_DIVIDER_ROUND_CLOSEST )
256
+ if (flags & CLK_DIVIDER_ROUND_CLOSEST )
238
257
return abs (rate - now ) < abs (rate - best );
239
258
240
259
return now <= rate && now > best ;
241
260
}
242
261
243
- static int _next_div (struct clk_divider * divider , int div )
262
+ static int _next_div (const struct clk_div_table * table , int div ,
263
+ unsigned long flags )
244
264
{
245
265
div ++ ;
246
266
247
- if (divider -> flags & CLK_DIVIDER_POWER_OF_TWO )
267
+ if (flags & CLK_DIVIDER_POWER_OF_TWO )
248
268
return __roundup_pow_of_two (div );
249
- if (divider -> table )
250
- return _round_up_table (divider -> table , div );
269
+ if (table )
270
+ return _round_up_table (table , div );
251
271
252
272
return div ;
253
273
}
254
274
255
275
static int clk_divider_bestdiv (struct clk_hw * hw , unsigned long rate ,
256
- unsigned long * best_parent_rate )
276
+ unsigned long * best_parent_rate ,
277
+ const struct clk_div_table * table , u8 width ,
278
+ unsigned long flags )
257
279
{
258
- struct clk_divider * divider = to_clk_divider (hw );
259
280
int i , bestdiv = 0 ;
260
281
unsigned long parent_rate , best = 0 , now , maxdiv ;
261
282
unsigned long parent_rate_saved = * best_parent_rate ;
262
283
263
284
if (!rate )
264
285
rate = 1 ;
265
286
266
- /* if read only, just return current value */
267
- if (divider -> flags & CLK_DIVIDER_READ_ONLY ) {
268
- bestdiv = readl (divider -> reg ) >> divider -> shift ;
269
- bestdiv &= div_mask (divider );
270
- bestdiv = _get_div (divider , bestdiv );
271
- return bestdiv ;
272
- }
273
-
274
- maxdiv = _get_maxdiv (divider );
287
+ maxdiv = _get_maxdiv (table , width , flags );
275
288
276
289
if (!(__clk_get_flags (hw -> clk ) & CLK_SET_RATE_PARENT )) {
277
290
parent_rate = * best_parent_rate ;
278
- bestdiv = _div_round (divider , parent_rate , rate );
291
+ bestdiv = _div_round (table , parent_rate , rate , flags );
279
292
bestdiv = bestdiv == 0 ? 1 : bestdiv ;
280
293
bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv ;
281
294
return bestdiv ;
@@ -287,8 +300,8 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
287
300
*/
288
301
maxdiv = min (ULONG_MAX / rate , maxdiv );
289
302
290
- for (i = 1 ; i <= maxdiv ; i = _next_div (divider , i )) {
291
- if (!_is_valid_div (divider , i ))
303
+ for (i = 1 ; i <= maxdiv ; i = _next_div (table , i , flags )) {
304
+ if (!_is_valid_div (table , i , flags ))
292
305
continue ;
293
306
if (rate * i == parent_rate_saved ) {
294
307
/*
@@ -302,56 +315,87 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
302
315
parent_rate = __clk_round_rate (__clk_get_parent (hw -> clk ),
303
316
MULT_ROUND_UP (rate , i ));
304
317
now = DIV_ROUND_UP (parent_rate , i );
305
- if (_is_best_div (divider , rate , now , best )) {
318
+ if (_is_best_div (rate , now , best , flags )) {
306
319
bestdiv = i ;
307
320
best = now ;
308
321
* best_parent_rate = parent_rate ;
309
322
}
310
323
}
311
324
312
325
if (!bestdiv ) {
313
- bestdiv = _get_maxdiv (divider );
326
+ bestdiv = _get_maxdiv (table , width , flags );
314
327
* best_parent_rate = __clk_round_rate (__clk_get_parent (hw -> clk ), 1 );
315
328
}
316
329
317
330
return bestdiv ;
318
331
}
319
332
320
- static long clk_divider_round_rate (struct clk_hw * hw , unsigned long rate ,
321
- unsigned long * prate )
333
+ long divider_round_rate (struct clk_hw * hw , unsigned long rate ,
334
+ unsigned long * prate , const struct clk_div_table * table ,
335
+ u8 width , unsigned long flags )
322
336
{
323
337
int div ;
324
- div = clk_divider_bestdiv (hw , rate , prate );
338
+
339
+ div = clk_divider_bestdiv (hw , rate , prate , table , width , flags );
325
340
326
341
return DIV_ROUND_UP (* prate , div );
327
342
}
343
+ EXPORT_SYMBOL_GPL (divider_round_rate );
328
344
329
- static int clk_divider_set_rate (struct clk_hw * hw , unsigned long rate ,
330
- unsigned long parent_rate )
345
+ static long clk_divider_round_rate (struct clk_hw * hw , unsigned long rate ,
346
+ unsigned long * prate )
331
347
{
332
348
struct clk_divider * divider = to_clk_divider (hw );
349
+ int bestdiv ;
350
+
351
+ /* if read only, just return current value */
352
+ if (divider -> flags & CLK_DIVIDER_READ_ONLY ) {
353
+ bestdiv = readl (divider -> reg ) >> divider -> shift ;
354
+ bestdiv &= div_mask (divider -> width );
355
+ bestdiv = _get_div (divider -> table , bestdiv , divider -> flags );
356
+ return bestdiv ;
357
+ }
358
+
359
+ return divider_round_rate (hw , rate , prate , divider -> table ,
360
+ divider -> width , divider -> flags );
361
+ }
362
+
363
+ int divider_get_val (unsigned long rate , unsigned long parent_rate ,
364
+ const struct clk_div_table * table , u8 width ,
365
+ unsigned long flags )
366
+ {
333
367
unsigned int div , value ;
334
- unsigned long flags = 0 ;
335
- u32 val ;
336
368
337
369
div = DIV_ROUND_UP (parent_rate , rate );
338
370
339
- if (!_is_valid_div (divider , div ))
371
+ if (!_is_valid_div (table , div , flags ))
340
372
return - EINVAL ;
341
373
342
- value = _get_val (divider , div );
374
+ value = _get_val (table , div , flags );
375
+
376
+ return min_t (unsigned int , value , div_mask (width ));
377
+ }
378
+ EXPORT_SYMBOL_GPL (divider_get_val );
379
+
380
+ static int clk_divider_set_rate (struct clk_hw * hw , unsigned long rate ,
381
+ unsigned long parent_rate )
382
+ {
383
+ struct clk_divider * divider = to_clk_divider (hw );
384
+ unsigned int value ;
385
+ unsigned long flags = 0 ;
386
+ u32 val ;
343
387
344
- if ( value > div_mask ( divider ))
345
- value = div_mask ( divider );
388
+ value = divider_get_val ( rate , parent_rate , divider -> table ,
389
+ divider -> width , divider -> flags );
346
390
347
391
if (divider -> lock )
348
392
spin_lock_irqsave (divider -> lock , flags );
349
393
350
394
if (divider -> flags & CLK_DIVIDER_HIWORD_MASK ) {
351
- val = div_mask (divider ) << (divider -> shift + 16 );
395
+ val = div_mask (divider -> width ) << (divider -> shift + 16 );
352
396
} else {
353
397
val = clk_readl (divider -> reg );
354
- val &= ~(div_mask (divider ) << divider -> shift );
398
+ val &= ~(div_mask (divider -> width ) << divider -> shift );
355
399
}
356
400
val |= value << divider -> shift ;
357
401
clk_writel (val , divider -> reg );
0 commit comments