Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/clk-divider.c
26278 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 long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
435
unsigned long *prate)
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_round_rate(hw, rate, prate, divider->table,
447
divider->width, divider->flags,
448
val);
449
}
450
451
return divider_round_rate(hw, rate, prate, divider->table,
452
divider->width, divider->flags);
453
}
454
455
static int clk_divider_determine_rate(struct clk_hw *hw,
456
struct clk_rate_request *req)
457
{
458
struct clk_divider *divider = to_clk_divider(hw);
459
460
/* if read only, just return current value */
461
if (divider->flags & CLK_DIVIDER_READ_ONLY) {
462
u32 val;
463
464
val = clk_div_readl(divider) >> divider->shift;
465
val &= clk_div_mask(divider->width);
466
467
return divider_ro_determine_rate(hw, req, divider->table,
468
divider->width,
469
divider->flags, val);
470
}
471
472
return divider_determine_rate(hw, req, divider->table, divider->width,
473
divider->flags);
474
}
475
476
int divider_get_val(unsigned long rate, unsigned long parent_rate,
477
const struct clk_div_table *table, u8 width,
478
unsigned long flags)
479
{
480
unsigned int div, value;
481
482
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
483
484
if (!_is_valid_div(table, div, flags))
485
return -EINVAL;
486
487
value = _get_val(table, div, flags, width);
488
489
return min_t(unsigned int, value, clk_div_mask(width));
490
}
491
EXPORT_SYMBOL_GPL(divider_get_val);
492
493
static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
494
unsigned long parent_rate)
495
{
496
struct clk_divider *divider = to_clk_divider(hw);
497
int value;
498
unsigned long flags = 0;
499
u32 val;
500
501
value = divider_get_val(rate, parent_rate, divider->table,
502
divider->width, divider->flags);
503
if (value < 0)
504
return value;
505
506
if (divider->lock)
507
spin_lock_irqsave(divider->lock, flags);
508
else
509
__acquire(divider->lock);
510
511
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
512
val = clk_div_mask(divider->width) << (divider->shift + 16);
513
} else {
514
val = clk_div_readl(divider);
515
val &= ~(clk_div_mask(divider->width) << divider->shift);
516
}
517
val |= (u32)value << divider->shift;
518
clk_div_writel(divider, val);
519
520
if (divider->lock)
521
spin_unlock_irqrestore(divider->lock, flags);
522
else
523
__release(divider->lock);
524
525
return 0;
526
}
527
528
const struct clk_ops clk_divider_ops = {
529
.recalc_rate = clk_divider_recalc_rate,
530
.round_rate = clk_divider_round_rate,
531
.determine_rate = clk_divider_determine_rate,
532
.set_rate = clk_divider_set_rate,
533
};
534
EXPORT_SYMBOL_GPL(clk_divider_ops);
535
536
const struct clk_ops clk_divider_ro_ops = {
537
.recalc_rate = clk_divider_recalc_rate,
538
.round_rate = clk_divider_round_rate,
539
.determine_rate = clk_divider_determine_rate,
540
};
541
EXPORT_SYMBOL_GPL(clk_divider_ro_ops);
542
543
struct clk_hw *__clk_hw_register_divider(struct device *dev,
544
struct device_node *np, const char *name,
545
const char *parent_name, const struct clk_hw *parent_hw,
546
const struct clk_parent_data *parent_data, unsigned long flags,
547
void __iomem *reg, u8 shift, u8 width,
548
unsigned long clk_divider_flags,
549
const struct clk_div_table *table, spinlock_t *lock)
550
{
551
struct clk_divider *div;
552
struct clk_hw *hw;
553
struct clk_init_data init = {};
554
int ret;
555
556
if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
557
if (width + shift > 16) {
558
pr_warn("divider value exceeds LOWORD field\n");
559
return ERR_PTR(-EINVAL);
560
}
561
}
562
563
/* allocate the divider */
564
div = kzalloc(sizeof(*div), GFP_KERNEL);
565
if (!div)
566
return ERR_PTR(-ENOMEM);
567
568
init.name = name;
569
if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
570
init.ops = &clk_divider_ro_ops;
571
else
572
init.ops = &clk_divider_ops;
573
init.flags = flags;
574
init.parent_names = parent_name ? &parent_name : NULL;
575
init.parent_hws = parent_hw ? &parent_hw : NULL;
576
init.parent_data = parent_data;
577
if (parent_name || parent_hw || parent_data)
578
init.num_parents = 1;
579
else
580
init.num_parents = 0;
581
582
/* struct clk_divider assignments */
583
div->reg = reg;
584
div->shift = shift;
585
div->width = width;
586
div->flags = clk_divider_flags;
587
div->lock = lock;
588
div->hw.init = &init;
589
div->table = table;
590
591
/* register the clock */
592
hw = &div->hw;
593
ret = clk_hw_register(dev, hw);
594
if (ret) {
595
kfree(div);
596
hw = ERR_PTR(ret);
597
}
598
599
return hw;
600
}
601
EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
602
603
/**
604
* clk_register_divider_table - register a table based divider clock with
605
* the clock framework
606
* @dev: device registering this clock
607
* @name: name of this clock
608
* @parent_name: name of clock's parent
609
* @flags: framework-specific flags
610
* @reg: register address to adjust divider
611
* @shift: number of bits to shift the bitfield
612
* @width: width of the bitfield
613
* @clk_divider_flags: divider-specific flags for this clock
614
* @table: array of divider/value pairs ending with a div set to 0
615
* @lock: shared register lock for this clock
616
*/
617
struct clk *clk_register_divider_table(struct device *dev, const char *name,
618
const char *parent_name, unsigned long flags,
619
void __iomem *reg, u8 shift, u8 width,
620
unsigned long clk_divider_flags,
621
const struct clk_div_table *table, spinlock_t *lock)
622
{
623
struct clk_hw *hw;
624
625
hw = __clk_hw_register_divider(dev, NULL, name, parent_name, NULL,
626
NULL, flags, reg, shift, width, clk_divider_flags,
627
table, lock);
628
if (IS_ERR(hw))
629
return ERR_CAST(hw);
630
return hw->clk;
631
}
632
EXPORT_SYMBOL_GPL(clk_register_divider_table);
633
634
void clk_unregister_divider(struct clk *clk)
635
{
636
struct clk_divider *div;
637
struct clk_hw *hw;
638
639
hw = __clk_get_hw(clk);
640
if (!hw)
641
return;
642
643
div = to_clk_divider(hw);
644
645
clk_unregister(clk);
646
kfree(div);
647
}
648
EXPORT_SYMBOL_GPL(clk_unregister_divider);
649
650
/**
651
* clk_hw_unregister_divider - unregister a clk divider
652
* @hw: hardware-specific clock data to unregister
653
*/
654
void clk_hw_unregister_divider(struct clk_hw *hw)
655
{
656
struct clk_divider *div;
657
658
div = to_clk_divider(hw);
659
660
clk_hw_unregister(hw);
661
kfree(div);
662
}
663
EXPORT_SYMBOL_GPL(clk_hw_unregister_divider);
664
665
static void devm_clk_hw_release_divider(struct device *dev, void *res)
666
{
667
clk_hw_unregister_divider(*(struct clk_hw **)res);
668
}
669
670
struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
671
struct device_node *np, const char *name,
672
const char *parent_name, const struct clk_hw *parent_hw,
673
const struct clk_parent_data *parent_data, unsigned long flags,
674
void __iomem *reg, u8 shift, u8 width,
675
unsigned long clk_divider_flags,
676
const struct clk_div_table *table, spinlock_t *lock)
677
{
678
struct clk_hw **ptr, *hw;
679
680
ptr = devres_alloc(devm_clk_hw_release_divider, sizeof(*ptr), GFP_KERNEL);
681
if (!ptr)
682
return ERR_PTR(-ENOMEM);
683
684
hw = __clk_hw_register_divider(dev, np, name, parent_name, parent_hw,
685
parent_data, flags, reg, shift, width,
686
clk_divider_flags, table, lock);
687
688
if (!IS_ERR(hw)) {
689
*ptr = hw;
690
devres_add(dev, ptr);
691
} else {
692
devres_free(ptr);
693
}
694
695
return hw;
696
}
697
EXPORT_SYMBOL_GPL(__devm_clk_hw_register_divider);
698
699