Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/clk-divider.c
50386 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (C) 2011 Sascha Hauer, Pengutronix <[email protected]>
4
* Copyright (C) 2011 Richard Zhao, Linaro <[email protected]>
5
* Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <[email protected]>
6
*
7
* Adjustable divider clock implementation
8
*/
9
10
#include <linux/clk-provider.h>
11
#include <linux/device.h>
12
#include <linux/module.h>
13
#include <linux/slab.h>
14
#include <linux/io.h>
15
#include <linux/err.h>
16
#include <linux/string.h>
17
#include <linux/log2.h>
18
19
/*
20
* DOC: basic adjustable divider clock that cannot gate
21
*
22
* Traits of this clock:
23
* prepare - clk_prepare only ensures that parents are prepared
24
* enable - clk_enable only ensures that parents are enabled
25
* rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor)
26
* parent - fixed parent. No clk_set_parent support
27
*/
28
29
static inline u32 clk_div_readl(struct clk_divider *divider)
30
{
31
if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
32
return ioread32be(divider->reg);
33
34
return readl(divider->reg);
35
}
36
37
static inline void clk_div_writel(struct clk_divider *divider, u32 val)
38
{
39
if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
40
iowrite32be(val, divider->reg);
41
else
42
writel(val, divider->reg);
43
}
44
45
static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
46
u8 width)
47
{
48
unsigned int maxdiv = 0, mask = clk_div_mask(width);
49
const struct clk_div_table *clkt;
50
51
for (clkt = table; clkt->div; clkt++)
52
if (clkt->div > maxdiv && clkt->val <= mask)
53
maxdiv = clkt->div;
54
return maxdiv;
55
}
56
57
static unsigned int _get_table_mindiv(const struct clk_div_table *table)
58
{
59
unsigned int mindiv = UINT_MAX;
60
const struct clk_div_table *clkt;
61
62
for (clkt = table; clkt->div; clkt++)
63
if (clkt->div < mindiv)
64
mindiv = clkt->div;
65
return mindiv;
66
}
67
68
static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
69
unsigned long flags)
70
{
71
if (flags & CLK_DIVIDER_ONE_BASED)
72
return clk_div_mask(width);
73
if (flags & CLK_DIVIDER_POWER_OF_TWO)
74
return 1 << clk_div_mask(width);
75
if (flags & CLK_DIVIDER_EVEN_INTEGERS)
76
return 2 * (clk_div_mask(width) + 1);
77
if (table)
78
return _get_table_maxdiv(table, width);
79
return clk_div_mask(width) + 1;
80
}
81
82
static unsigned int _get_table_div(const struct clk_div_table *table,
83
unsigned int val)
84
{
85
const struct clk_div_table *clkt;
86
87
for (clkt = table; clkt->div; clkt++)
88
if (clkt->val == val)
89
return clkt->div;
90
return 0;
91
}
92
93
static unsigned int _get_div(const struct clk_div_table *table,
94
unsigned int val, unsigned long flags, u8 width)
95
{
96
if (flags & CLK_DIVIDER_ONE_BASED)
97
return val;
98
if (flags & CLK_DIVIDER_POWER_OF_TWO)
99
return 1 << val;
100
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
101
return val ? val : clk_div_mask(width) + 1;
102
if (flags & CLK_DIVIDER_EVEN_INTEGERS)
103
return 2 * (val + 1);
104
if (table)
105
return _get_table_div(table, val);
106
return val + 1;
107
}
108
109
static unsigned int _get_table_val(const struct clk_div_table *table,
110
unsigned int div)
111
{
112
const struct clk_div_table *clkt;
113
114
for (clkt = table; clkt->div; clkt++)
115
if (clkt->div == div)
116
return clkt->val;
117
return 0;
118
}
119
120
static unsigned int _get_val(const struct clk_div_table *table,
121
unsigned int div, unsigned long flags, u8 width)
122
{
123
if (flags & CLK_DIVIDER_ONE_BASED)
124
return div;
125
if (flags & CLK_DIVIDER_POWER_OF_TWO)
126
return __ffs(div);
127
if (flags & CLK_DIVIDER_MAX_AT_ZERO)
128
return (div == clk_div_mask(width) + 1) ? 0 : div;
129
if (flags & CLK_DIVIDER_EVEN_INTEGERS)
130
return (div >> 1) - 1;
131
if (table)
132
return _get_table_val(table, div);
133
return div - 1;
134
}
135
136
unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
137
unsigned int val,
138
const struct clk_div_table *table,
139
unsigned long flags, unsigned long width)
140
{
141
unsigned int div;
142
143
div = _get_div(table, val, flags, width);
144
if (!div) {
145
WARN(!(flags & CLK_DIVIDER_ALLOW_ZERO),
146
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
147
clk_hw_get_name(hw));
148
return parent_rate;
149
}
150
151
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
152
}
153
EXPORT_SYMBOL_GPL(divider_recalc_rate);
154
155
static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
156
unsigned long parent_rate)
157
{
158
struct clk_divider *divider = to_clk_divider(hw);
159
unsigned int val;
160
161
val = clk_div_readl(divider) >> divider->shift;
162
val &= clk_div_mask(divider->width);
163
164
return divider_recalc_rate(hw, parent_rate, val, divider->table,
165
divider->flags, divider->width);
166
}
167
168
static bool _is_valid_table_div(const struct clk_div_table *table,
169
unsigned int div)
170
{
171
const struct clk_div_table *clkt;
172
173
for (clkt = table; clkt->div; clkt++)
174
if (clkt->div == div)
175
return true;
176
return false;
177
}
178
179
static bool _is_valid_div(const struct clk_div_table *table, unsigned int div,
180
unsigned long flags)
181
{
182
if (flags & CLK_DIVIDER_POWER_OF_TWO)
183
return is_power_of_2(div);
184
if (table)
185
return _is_valid_table_div(table, div);
186
return true;
187
}
188
189
static int _round_up_table(const struct clk_div_table *table, int div)
190
{
191
const struct clk_div_table *clkt;
192
int up = INT_MAX;
193
194
for (clkt = table; clkt->div; clkt++) {
195
if (clkt->div == div)
196
return clkt->div;
197
else if (clkt->div < div)
198
continue;
199
200
if ((clkt->div - div) < (up - div))
201
up = clkt->div;
202
}
203
204
return up;
205
}
206
207
static int _round_down_table(const struct clk_div_table *table, int div)
208
{
209
const struct clk_div_table *clkt;
210
int down = _get_table_mindiv(table);
211
212
for (clkt = table; clkt->div; clkt++) {
213
if (clkt->div == div)
214
return clkt->div;
215
else if (clkt->div > div)
216
continue;
217
218
if ((div - clkt->div) < (div - down))
219
down = clkt->div;
220
}
221
222
return down;
223
}
224
225
static int _div_round_up(const struct clk_div_table *table,
226
unsigned long parent_rate, unsigned long rate,
227
unsigned long flags)
228
{
229
int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
230
231
if (flags & CLK_DIVIDER_POWER_OF_TWO)
232
div = __roundup_pow_of_two(div);
233
if (table)
234
div = _round_up_table(table, div);
235
236
return div;
237
}
238
239
static int _div_round_closest(const struct clk_div_table *table,
240
unsigned long parent_rate, unsigned long rate,
241
unsigned long flags)
242
{
243
int up, down;
244
unsigned long up_rate, down_rate;
245
246
up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
247
down = parent_rate / rate;
248
249
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
250
up = __roundup_pow_of_two(up);
251
down = __rounddown_pow_of_two(down);
252
} else if (table) {
253
up = _round_up_table(table, up);
254
down = _round_down_table(table, down);
255
}
256
257
up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
258
down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
259
260
return (rate - up_rate) <= (down_rate - rate) ? up : down;
261
}
262
263
static int _div_round(const struct clk_div_table *table,
264
unsigned long parent_rate, unsigned long rate,
265
unsigned long flags)
266
{
267
if (flags & CLK_DIVIDER_ROUND_CLOSEST)
268
return _div_round_closest(table, parent_rate, rate, flags);
269
270
return _div_round_up(table, parent_rate, rate, flags);
271
}
272
273
static bool _is_best_div(unsigned long rate, unsigned long now,
274
unsigned long best, unsigned long flags)
275
{
276
if (flags & CLK_DIVIDER_ROUND_CLOSEST)
277
return abs(rate - now) < abs(rate - best);
278
279
return now <= rate && now > best;
280
}
281
282
static int _next_div(const struct clk_div_table *table, int div,
283
unsigned long flags)
284
{
285
div++;
286
287
if (flags & CLK_DIVIDER_POWER_OF_TWO)
288
return __roundup_pow_of_two(div);
289
if (table)
290
return _round_up_table(table, div);
291
292
return div;
293
}
294
295
static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
296
unsigned long rate,
297
unsigned long *best_parent_rate,
298
const struct clk_div_table *table, u8 width,
299
unsigned long flags)
300
{
301
int i, bestdiv = 0;
302
unsigned long parent_rate, best = 0, now, maxdiv;
303
unsigned long parent_rate_saved = *best_parent_rate;
304
305
if (!rate)
306
rate = 1;
307
308
maxdiv = _get_maxdiv(table, width, flags);
309
310
if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
311
parent_rate = *best_parent_rate;
312
bestdiv = _div_round(table, parent_rate, rate, flags);
313
bestdiv = bestdiv == 0 ? 1 : bestdiv;
314
bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
315
return bestdiv;
316
}
317
318
/*
319
* The maximum divider we can use without overflowing
320
* unsigned long in rate * i below
321
*/
322
maxdiv = min(ULONG_MAX / rate, maxdiv);
323
324
for (i = _next_div(table, 0, flags); i <= maxdiv;
325
i = _next_div(table, i, flags)) {
326
if (rate * i == parent_rate_saved) {
327
/*
328
* It's the most ideal case if the requested rate can be
329
* divided from parent clock without needing to change
330
* parent rate, so return the divider immediately.
331
*/
332
*best_parent_rate = parent_rate_saved;
333
return i;
334
}
335
parent_rate = clk_hw_round_rate(parent, rate * i);
336
now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
337
if (_is_best_div(rate, now, best, flags)) {
338
bestdiv = i;
339
best = now;
340
*best_parent_rate = parent_rate;
341
}
342
}
343
344
if (!bestdiv) {
345
bestdiv = _get_maxdiv(table, width, flags);
346
*best_parent_rate = clk_hw_round_rate(parent, 1);
347
}
348
349
return bestdiv;
350
}
351
352
int divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req,
353
const struct clk_div_table *table, u8 width,
354
unsigned long flags)
355
{
356
int div;
357
358
div = clk_divider_bestdiv(hw, req->best_parent_hw, req->rate,
359
&req->best_parent_rate, table, width, flags);
360
361
req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div);
362
363
return 0;
364
}
365
EXPORT_SYMBOL_GPL(divider_determine_rate);
366
367
int divider_ro_determine_rate(struct clk_hw *hw, struct clk_rate_request *req,
368
const struct clk_div_table *table, u8 width,
369
unsigned long flags, unsigned int val)
370
{
371
int div;
372
373
div = _get_div(table, val, flags, width);
374
375
/* Even a read-only clock can propagate a rate change */
376
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
377
if (!req->best_parent_hw)
378
return -EINVAL;
379
380
req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw,
381
req->rate * div);
382
}
383
384
req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div);
385
386
return 0;
387
}
388
EXPORT_SYMBOL_GPL(divider_ro_determine_rate);
389
390
long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
391
unsigned long rate, unsigned long *prate,
392
const struct clk_div_table *table,
393
u8 width, unsigned long flags)
394
{
395
struct clk_rate_request req;
396
int ret;
397
398
clk_hw_init_rate_request(hw, &req, rate);
399
req.best_parent_rate = *prate;
400
req.best_parent_hw = parent;
401
402
ret = divider_determine_rate(hw, &req, table, width, flags);
403
if (ret)
404
return ret;
405
406
*prate = req.best_parent_rate;
407
408
return req.rate;
409
}
410
EXPORT_SYMBOL_GPL(divider_round_rate_parent);
411
412
long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
413
unsigned long rate, unsigned long *prate,
414
const struct clk_div_table *table, u8 width,
415
unsigned long flags, unsigned int val)
416
{
417
struct clk_rate_request req;
418
int ret;
419
420
clk_hw_init_rate_request(hw, &req, rate);
421
req.best_parent_rate = *prate;
422
req.best_parent_hw = parent;
423
424
ret = divider_ro_determine_rate(hw, &req, table, width, flags, val);
425
if (ret)
426
return ret;
427
428
*prate = req.best_parent_rate;
429
430
return req.rate;
431
}
432
EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
433
434
static int clk_divider_determine_rate(struct clk_hw *hw,
435
struct clk_rate_request *req)
436
{
437
struct clk_divider *divider = to_clk_divider(hw);
438
439
/* if read only, just return current value */
440
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
441
u32 val;
442
443
val = clk_div_readl(divider) >> divider->shift;
444
val &= clk_div_mask(divider->width);
445
446
return divider_ro_determine_rate(hw, req, divider->table,
447
divider->width,
448
divider->flags, val);
449
}
450
451
return divider_determine_rate(hw, req, divider->table, divider->width,
452
divider->flags);
453
}
454
455
int divider_get_val(unsigned long rate, unsigned long parent_rate,
456
const struct clk_div_table *table, u8 width,
457
unsigned long flags)
458
{
459
unsigned int div, value;
460
461
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
462
463
if (!_is_valid_div(table, div, flags))
464
return -EINVAL;
465
466
value = _get_val(table, div, flags, width);
467
468
return min_t(unsigned int, value, clk_div_mask(width));
469
}
470
EXPORT_SYMBOL_GPL(divider_get_val);
471
472
static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
473
unsigned long parent_rate)
474
{
475
struct clk_divider *divider = to_clk_divider(hw);
476
int value;
477
unsigned long flags = 0;
478
u32 val;
479
480
value = divider_get_val(rate, parent_rate, divider->table,
481
divider->width, divider->flags);
482
if (value < 0)
483
return value;
484
485
if (divider->lock)
486
spin_lock_irqsave(divider->lock, flags);
487
else
488
__acquire(divider->lock);
489
490
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
491
val = clk_div_mask(divider->width) << (divider->shift + 16);
492
} else {
493
val = clk_div_readl(divider);
494
val &= ~(clk_div_mask(divider->width) << divider->shift);
495
}
496
val |= (u32)value << divider->shift;
497
clk_div_writel(divider, val);
498
499
if (divider->lock)
500
spin_unlock_irqrestore(divider->lock, flags);
501
else
502
__release(divider->lock);
503
504
return 0;
505
}
506
507
const struct clk_ops clk_divider_ops = {
508
.recalc_rate = clk_divider_recalc_rate,
509
.determine_rate = clk_divider_determine_rate,
510
.set_rate = clk_divider_set_rate,
511
};
512
EXPORT_SYMBOL_GPL(clk_divider_ops);
513
514
const struct clk_ops clk_divider_ro_ops = {
515
.recalc_rate = clk_divider_recalc_rate,
516
.determine_rate = clk_divider_determine_rate,
517
};
518
EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
519
520
struct clk_hw *__clk_hw_register_divider(struct device *dev,
521
struct device_node *np, const char *name,
522
const char *parent_name, const struct clk_hw *parent_hw,
523
const struct clk_parent_data *parent_data, unsigned long flags,
524
void __iomem *reg, u8 shift, u8 width,
525
unsigned long clk_divider_flags,
526
const struct clk_div_table *table, spinlock_t *lock)
527
{
528
struct clk_divider *div;
529
struct clk_hw *hw;
530
struct clk_init_data init = {};
531
int ret;
532
533
if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
534
if (width + shift > 16) {
535
pr_warn("divider value exceeds LOWORD field\n");
536
return ERR_PTR(-EINVAL);
537
}
538
}
539
540
/* allocate the divider */
541
div = kzalloc(sizeof(*div), GFP_KERNEL);
542
if (!div)
543
return ERR_PTR(-ENOMEM);
544
545
init.name = name;
546
if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
547
init.ops = &clk_divider_ro_ops;
548
else
549
init.ops = &clk_divider_ops;
550
init.flags = flags;
551
init.parent_names = parent_name ? &parent_name : NULL;
552
init.parent_hws = parent_hw ? &parent_hw : NULL;
553
init.parent_data = parent_data;
554
if (parent_name || parent_hw || parent_data)
555
init.num_parents = 1;
556
else
557
init.num_parents = 0;
558
559
/* struct clk_divider assignments */
560
div->reg = reg;
561
div->shift = shift;
562
div->width = width;
563
div->flags = clk_divider_flags;
564
div->lock = lock;
565
div->hw.init = &init;
566
div->table = table;
567
568
/* register the clock */
569
hw = &div->hw;
570
ret = clk_hw_register(dev, hw);
571
if (ret) {
572
kfree(div);
573
hw = ERR_PTR(ret);
574
}
575
576
return hw;
577
}
578
EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
579
580
/**
581
* clk_register_divider_table - register a table based divider clock with
582
* the clock framework
583
* @dev: device registering this clock
584
* @name: name of this clock
585
* @parent_name: name of clock's parent
586
* @flags: framework-specific flags
587
* @reg: register address to adjust divider
588
* @shift: number of bits to shift the bitfield
589
* @width: width of the bitfield
590
* @clk_divider_flags: divider-specific flags for this clock
591
* @table: array of divider/value pairs ending with a div set to 0
592
* @lock: shared register lock for this clock
593
*/
594
struct clk *clk_register_divider_table(struct device *dev, const char *name,
595
const char *parent_name, unsigned long flags,
596
void __iomem *reg, u8 shift, u8 width,
597
unsigned long clk_divider_flags,
598
const struct clk_div_table *table, spinlock_t *lock)
599
{
600
struct clk_hw *hw;
601
602
hw = __clk_hw_register_divider(dev, NULL, name, parent_name, NULL,
603
NULL, flags, reg, shift, width, clk_divider_flags,
604
table, lock);
605
if (IS_ERR(hw))
606
return ERR_CAST(hw);
607
return hw->clk;
608
}
609
EXPORT_SYMBOL_GPL(clk_register_divider_table);
610
611
void clk_unregister_divider(struct clk *clk)
612
{
613
struct clk_divider *div;
614
struct clk_hw *hw;
615
616
hw = __clk_get_hw(clk);
617
if (!hw)
618
return;
619
620
div = to_clk_divider(hw);
621
622
clk_unregister(clk);
623
kfree(div);
624
}
625
EXPORT_SYMBOL_GPL(clk_unregister_divider);
626
627
/**
628
* clk_hw_unregister_divider - unregister a clk divider
629
* @hw: hardware-specific clock data to unregister
630
*/
631
void clk_hw_unregister_divider(struct clk_hw *hw)
632
{
633
struct clk_divider *div;
634
635
div = to_clk_divider(hw);
636
637
clk_hw_unregister(hw);
638
kfree(div);
639
}
640
EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);
641
642
static void devm_clk_hw_release_divider(struct device *dev, void *res)
643
{
644
clk_hw_unregister_divider(*(struct clk_hw **)res);
645
}
646
647
struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
648
struct device_node *np, const char *name,
649
const char *parent_name, const struct clk_hw *parent_hw,
650
const struct clk_parent_data *parent_data, unsigned long flags,
651
void __iomem *reg, u8 shift, u8 width,
652
unsigned long clk_divider_flags,
653
const struct clk_div_table *table, spinlock_t *lock)
654
{
655
struct clk_hw **ptr, *hw;
656
657
ptr = devres_alloc(devm_clk_hw_release_divider, sizeof(*ptr), GFP_KERNEL);
658
if (!ptr)
659
return ERR_PTR(-ENOMEM);
660
661
hw = __clk_hw_register_divider(dev, np, name, parent_name, parent_hw,
662
parent_data, flags, reg, shift, width,
663
clk_divider_flags, table, lock);
664
665
if (!IS_ERR(hw)) {
666
*ptr = hw;
667
devres_add(dev, ptr);
668
} else {
669
devres_free(ptr);
670
}
671
672
return hw;
673
}
674
EXPORT_SYMBOL_GPL(__devm_clk_hw_register_divider);
675
676