Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/clk/allwinner/aw_clk.h
39536 views
1
/*-
2
* Copyright (c) 2017 Emmanuel Vadot <[email protected]>
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
*
13
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
18
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
20
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
* SUCH DAMAGE.
24
*/
25
26
#ifndef __AW_CLK_H__
27
#define __AW_CLK_H__
28
29
/*
30
Allwinner clocks formula :
31
32
PLLs:
33
34
(24MHz*N*K)/(M*P)
35
(24MHz*N)/(M*P)
36
(24MHz*N*2)/M
37
(24MHz*N)/M
38
(24MHz*N*K)/M
39
(24MHz*N*K/2)
40
(24MHz*N)/M
41
(24MHz*N*K/2)
42
(24MHz*N)/M
43
44
Periph clocks:
45
46
Clock Source/Divider N/Divider M
47
Clock Source/Divider N/Divider M/2
48
Clock Source*N/(Divider M+1)/(Divider P+1)
49
50
*/
51
52
struct aw_clk_init {
53
const char *name;
54
const char *parent_name;
55
uint64_t default_freq;
56
bool enable;
57
};
58
59
#define AW_CLK_HAS_GATE 0x0001
60
#define AW_CLK_HAS_LOCK 0x0002
61
#define AW_CLK_HAS_MUX 0x0004
62
#define AW_CLK_REPARENT 0x0008
63
#define AW_CLK_SCALE_CHANGE 0x0010
64
#define AW_CLK_HAS_UPDATE 0x0040
65
#define AW_CLK_HAS_PREDIV 0x0080
66
#define AW_CLK_SET_PARENT 0x0100
67
68
#define AW_CLK_FACTOR_POWER_OF_TWO 0x0001
69
#define AW_CLK_FACTOR_ZERO_BASED 0x0002
70
#define AW_CLK_FACTOR_HAS_COND 0x0004
71
#define AW_CLK_FACTOR_FIXED 0x0008
72
#define AW_CLK_FACTOR_ZERO_IS_ONE 0x0010
73
#define AW_CLK_FACTOR_MIN_VALUE 0x0020
74
#define AW_CLK_FACTOR_MAX_VALUE 0x0040
75
76
struct aw_clk_factor {
77
uint32_t shift; /* Shift bits for the factor */
78
uint32_t mask; /* Mask to get the factor, will be override by the clk methods */
79
uint32_t width; /* Number of bits for the factor */
80
uint32_t value; /* Fixed value, depends on AW_CLK_FACTOR_FIXED */
81
82
uint32_t cond_shift;
83
uint32_t cond_mask;
84
uint32_t cond_width;
85
uint32_t cond_value;
86
87
uint32_t min_value;
88
uint32_t max_value;
89
90
uint32_t flags; /* Flags */
91
};
92
93
struct aw_clk_frac {
94
uint64_t freq0;
95
uint64_t freq1;
96
uint32_t mode_sel;
97
uint32_t freq_sel;
98
};
99
100
static inline uint32_t
101
aw_clk_get_factor(uint32_t val, struct aw_clk_factor *factor)
102
{
103
uint32_t factor_val;
104
uint32_t cond;
105
106
if (factor->flags & AW_CLK_FACTOR_HAS_COND) {
107
cond = (val & factor->cond_mask) >> factor->cond_shift;
108
if (cond != factor->cond_value)
109
return (1);
110
}
111
112
if (factor->flags & AW_CLK_FACTOR_FIXED)
113
return (factor->value);
114
115
factor_val = (val & factor->mask) >> factor->shift;
116
if (factor_val == 0 && (factor->flags & AW_CLK_FACTOR_ZERO_IS_ONE))
117
factor_val = 1;
118
119
if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
120
factor_val = 1 << factor_val;
121
else if (!(factor->flags & AW_CLK_FACTOR_ZERO_BASED))
122
factor_val += 1;
123
124
return (factor_val);
125
}
126
127
static inline uint32_t
128
aw_clk_factor_get_max(struct aw_clk_factor *factor)
129
{
130
uint32_t max;
131
132
if (factor->flags & AW_CLK_FACTOR_FIXED)
133
max = factor->value;
134
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
135
max = 1 << ((1 << factor->width) - 1);
136
else {
137
max = (1 << factor->width);
138
}
139
140
return (max);
141
}
142
143
static inline uint32_t
144
aw_clk_factor_get_min(struct aw_clk_factor *factor)
145
{
146
uint32_t min;
147
148
if (factor->flags & AW_CLK_FACTOR_FIXED)
149
min = factor->value;
150
else if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
151
min = 0;
152
else if (factor->flags & AW_CLK_FACTOR_MIN_VALUE)
153
min = factor->min_value;
154
else
155
min = 1;
156
157
return (min);
158
}
159
160
static inline uint32_t
161
aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
162
{
163
uint32_t val;
164
165
if (factor->flags & AW_CLK_FACTOR_FIXED)
166
return (factor->value);
167
168
if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
169
val = raw;
170
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) {
171
for (val = 0; raw != 1; val++)
172
raw >>= 1;
173
} else if (factor->flags & AW_CLK_FACTOR_MAX_VALUE)
174
val = factor->max_value;
175
else
176
val = raw - 1;
177
178
return (val);
179
}
180
181
#define CCU_RESET(idx, o, s) \
182
[idx] = { \
183
.offset = o, \
184
.shift = s, \
185
},
186
187
#define CCU_GATE(idx, clkname, pname, o, s) \
188
[idx] = { \
189
.name = clkname, \
190
.parent_name = pname, \
191
.offset = o, \
192
.shift = s, \
193
},
194
195
#define NKMP_CLK(_clkname, _id, _name, _pnames, \
196
_offset, \
197
_n_shift, _n_width, _n_value, _n_flags, \
198
_k_shift, _k_width, _k_value, _k_flags, \
199
_m_shift, _m_width, _m_value, _m_flags, \
200
_p_shift, _p_width, _p_value, _p_flags, \
201
_gate, \
202
_lock, _lock_retries, \
203
_flags) \
204
static struct aw_clk_nkmp_def _clkname = { \
205
.clkdef = { \
206
.id = _id, \
207
.name = _name, \
208
.parent_names = _pnames, \
209
.parent_cnt = nitems(_pnames), \
210
}, \
211
.offset = _offset, \
212
.n.shift = _n_shift, \
213
.n.width = _n_width, \
214
.n.value = _n_value, \
215
.n.flags = _n_flags, \
216
.k.shift = _k_shift, \
217
.k.width = _k_width, \
218
.k.value = _k_value, \
219
.k.flags = _k_flags, \
220
.m.shift = _m_shift, \
221
.m.width = _m_width, \
222
.m.value = _m_value, \
223
.m.flags = _m_flags, \
224
.p.shift = _p_shift, \
225
.p.width = _p_width, \
226
.p.value = _p_value, \
227
.p.flags = _p_flags, \
228
.gate_shift = _gate, \
229
.lock_shift = _lock, \
230
.lock_retries = _lock_retries, \
231
.flags = _flags, \
232
}
233
234
#define NKMP_CLK_WITH_MUX(_clkname, \
235
_id, _name, _pnames, \
236
_offset, \
237
_n_shift, _n_width, _n_value, _n_flags, \
238
_k_shift, _k_width, _k_value, _k_flags, \
239
_m_shift, _m_width, _m_value, _m_flags, \
240
_p_shift, _p_width, _p_value, _p_flags, \
241
_mux_shift, _mux_width, _gate, \
242
_lock, _lock_retries, \
243
_flags) \
244
static struct aw_clk_nkmp_def _clkname = { \
245
.clkdef = { \
246
.id = _id, \
247
.name = _name, \
248
.parent_names = _pnames, \
249
.parent_cnt = nitems(_pnames), \
250
}, \
251
.offset = _offset, \
252
.n.shift = _n_shift, \
253
.n.width = _n_width, \
254
.n.value = _n_value, \
255
.n.flags = _n_flags, \
256
.k.shift = _k_shift, \
257
.k.width = _k_width, \
258
.k.value = _k_value, \
259
.k.flags = _k_flags, \
260
.m.shift = _m_shift, \
261
.m.width = _m_width, \
262
.m.value = _m_value, \
263
.m.flags = _m_flags, \
264
.p.shift = _p_shift, \
265
.p.width = _p_width, \
266
.p.value = _p_value, \
267
.p.flags = _p_flags, \
268
.mux_shift = _mux_shift, \
269
.mux_width = _mux_width, \
270
.gate_shift = _gate, \
271
.lock_shift = _lock, \
272
.lock_retries = _lock_retries, \
273
.flags = _flags, \
274
}
275
276
#define NKMP_CLK_WITH_UPDATE(_clkname, \
277
_id, _name, _pnames, \
278
_offset, \
279
_n_shift, _n_width, _n_value, _n_flags, \
280
_k_shift, _k_width, _k_value, _k_flags, \
281
_m_shift, _m_width, _m_value, _m_flags, \
282
_p_shift, _p_width, _p_value, _p_flags, \
283
_gate, \
284
_lock, _lock_retries, \
285
_update, \
286
_flags) \
287
static struct aw_clk_nkmp_def _clkname = { \
288
.clkdef = { \
289
.id = _id, \
290
.name = _name, \
291
.parent_names = _pnames, \
292
.parent_cnt = nitems(_pnames), \
293
}, \
294
.offset = _offset, \
295
.n.shift = _n_shift, \
296
.n.width = _n_width, \
297
.n.value = _n_value, \
298
.n.flags = _n_flags, \
299
.k.shift = _k_shift, \
300
.k.width = _k_width, \
301
.k.value = _k_value, \
302
.k.flags = _k_flags, \
303
.m.shift = _m_shift, \
304
.m.width = _m_width, \
305
.m.value = _m_value, \
306
.m.flags = _m_flags, \
307
.p.shift = _p_shift, \
308
.p.width = _p_width, \
309
.p.value = _p_value, \
310
.p.flags = _p_flags, \
311
.gate_shift = _gate, \
312
.lock_shift = _lock, \
313
.lock_retries = _lock_retries, \
314
.update_shift = _update, \
315
.flags = _flags | AW_CLK_HAS_UPDATE, \
316
}
317
318
#define FRAC_CLK(_clkname, _id, _name, _pnames, \
319
_offset, \
320
_nshift, _nwidth, _nvalue, _nflags, \
321
_mshift, _mwidth, _mvalue, _mflags, \
322
_gate_shift, _lock_shift,_lock_retries, \
323
_flags, _freq0, _freq1, _mode_sel, _freq_sel, \
324
_min_freq, _max_freq) \
325
static struct aw_clk_frac_def _clkname = { \
326
.clkdef = { \
327
.id = _id, \
328
.name = _name, \
329
.parent_names = _pnames, \
330
.parent_cnt = nitems(_pnames), \
331
.flags = CLK_NODE_GLITCH_FREE, \
332
}, \
333
.offset = _offset, \
334
.n.shift = _nshift, \
335
.n.width = _nwidth, \
336
.n.value = _nvalue, \
337
.n.flags = _nflags, \
338
.m.shift = _mshift, \
339
.m.width = _mwidth, \
340
.m.value = _mvalue, \
341
.m.flags = _mflags, \
342
.gate_shift = _gate_shift, \
343
.lock_shift = _lock_shift, \
344
.lock_retries = _lock_retries, \
345
.flags = _flags, \
346
.frac.freq0 = _freq0, \
347
.frac.freq1 = _freq1, \
348
.frac.mode_sel = _mode_sel, \
349
.frac.freq_sel = _freq_sel, \
350
.min_freq = _min_freq, \
351
.max_freq = _max_freq, \
352
}
353
354
#define M_CLK(_clkname, _id, _name, _pnames, \
355
_offset, \
356
_mshift, _mwidth, _mvalue, _mflags, \
357
_mux_shift, _mux_width, \
358
_gate_shift, \
359
_flags) \
360
static struct aw_clk_m_def _clkname = { \
361
.clkdef = { \
362
.id = _id, \
363
.name = _name, \
364
.parent_names = _pnames, \
365
.parent_cnt = nitems(_pnames), \
366
}, \
367
.offset = _offset, \
368
.mux_shift = _mux_shift, \
369
.m.shift = _mshift, \
370
.m.width = _mwidth, \
371
.m.value = _mvalue, \
372
.m.flags = _mflags, \
373
.mux_width = _mux_width, \
374
.gate_shift = _gate_shift, \
375
.flags = _flags, \
376
}
377
378
#define NM_CLK(_clkname, _id, _name, _pnames, \
379
_offset, \
380
_nshift, _nwidth, _nvalue, _nflags, \
381
_mshift, _mwidth, _mvalue, _mflags, \
382
_mux_shift, _mux_width, \
383
_gate_shift, \
384
_flags) \
385
static struct aw_clk_nm_def _clkname = { \
386
.clkdef = { \
387
.id = _id, \
388
.name = _name, \
389
.parent_names = _pnames, \
390
.parent_cnt = nitems(_pnames), \
391
}, \
392
.offset = _offset, \
393
.n.shift = _nshift, \
394
.n.width = _nwidth, \
395
.n.value = _nvalue, \
396
.n.flags = _nflags, \
397
.mux_shift = _mux_shift, \
398
.m.shift = _mshift, \
399
.m.width = _mwidth, \
400
.m.value = _mvalue, \
401
.m.flags = _mflags, \
402
.mux_width = _mux_width, \
403
.gate_shift = _gate_shift, \
404
.flags = _flags, \
405
}
406
407
#define NMM_CLK(_clkname, _id, _name, _pnames, \
408
_offset, \
409
_nshift, _nwidth, _nvalue, _nflags, \
410
_m0shift, _m0width, _m0value, _m0flags, \
411
_m1shift, _m1width, _m1value, _m1flags, \
412
_gate_shift, \
413
_lock, _lock_retries, \
414
_flags) \
415
static struct aw_clk_nmm_def _clkname = { \
416
.clkdef = { \
417
.id = _id, \
418
.name = _name, \
419
.parent_names = _pnames, \
420
.parent_cnt = nitems(_pnames), \
421
}, \
422
.offset = _offset, \
423
.n.shift = _nshift, \
424
.n.width = _nwidth, \
425
.n.value = _nvalue, \
426
.n.flags = _nflags, \
427
.m0.shift = _m0shift, \
428
.m0.width = _m0width, \
429
.m0.value = _m0value, \
430
.m0.flags = _m0flags, \
431
.m1.shift = _m1shift, \
432
.m1.width = _m1width, \
433
.m1.value = _m1value, \
434
.m1.flags = _m1flags, \
435
.gate_shift = _gate_shift, \
436
.lock_shift = _lock, \
437
.lock_retries = _lock_retries, \
438
.flags = _flags, \
439
}
440
441
#define NP_CLK(_clkname, _id, _name, _pnames, \
442
_offset, \
443
_nshift, _nwidth, _nvalue, _nflags, \
444
_pshift, _pwidth, _pvalue, _pflags, \
445
_gate_shift, \
446
_lock, _lock_retries, \
447
_flags) \
448
static struct aw_clk_np_def _clkname = { \
449
.clkdef = { \
450
.id = _id, \
451
.name = _name, \
452
.parent_names = _pnames, \
453
.parent_cnt = nitems(_pnames), \
454
}, \
455
.offset = _offset, \
456
.n.shift = _nshift, \
457
.n.width = _nwidth, \
458
.n.value = _nvalue, \
459
.n.flags = _nflags, \
460
.p.shift = _pshift, \
461
.p.width = _pwidth, \
462
.p.value = _pvalue, \
463
.p.flags = _pflags, \
464
.gate_shift = _gate_shift, \
465
.lock_shift = _lock, \
466
.lock_retries = _lock_retries, \
467
.flags = _flags, \
468
}
469
470
#define PREDIV_CLK(_clkname, _id, _name, _pnames, \
471
_offset, \
472
_mux_shift, _mux_width, \
473
_div_shift, _div_width, _div_value, _div_flags, \
474
_prediv_shift, _prediv_width, _prediv_value, _prediv_flags, \
475
_prediv_cond_shift, _prediv_cond_width, _prediv_cond_value) \
476
static struct aw_clk_prediv_mux_def _clkname = { \
477
.clkdef = { \
478
.id = _id, \
479
.name = _name, \
480
.parent_names = _pnames, \
481
.parent_cnt = nitems(_pnames), \
482
}, \
483
.offset = _offset, \
484
.mux_shift = _mux_shift, \
485
.mux_width = _mux_width, \
486
.div.shift = _div_shift, \
487
.div.width = _div_width, \
488
.div.value = _div_value, \
489
.div.flags = _div_flags, \
490
.prediv.shift = _prediv_shift, \
491
.prediv.width = _prediv_width, \
492
.prediv.value = _prediv_value, \
493
.prediv.flags = _prediv_flags, \
494
.prediv.cond_shift = _prediv_cond_shift, \
495
.prediv.cond_width = _prediv_cond_width, \
496
.prediv.cond_value = _prediv_cond_value, \
497
}
498
499
#define PREDIV_CLK_WITH_MASK(_clkname, _id, _name, _pnames, \
500
_offset, \
501
_mux_shift, _mux_width, \
502
_div_shift, _div_width, _div_value, _div_flags, \
503
_prediv_shift, _prediv_width, _prediv_value, _prediv_flags, \
504
_prediv_cond_mask, _prediv_cond_value) \
505
static struct aw_clk_prediv_mux_def _clkname = { \
506
.clkdef = { \
507
.id = _id, \
508
.name = _name, \
509
.parent_names = _pnames, \
510
.parent_cnt = nitems(_pnames), \
511
}, \
512
.offset = _offset, \
513
.mux_shift = _mux_shift, \
514
.mux_width = _mux_width, \
515
.div.shift = _div_shift, \
516
.div.width = _div_width, \
517
.div.value = _div_value, \
518
.div.flags = _div_flags, \
519
.prediv.shift = _prediv_shift, \
520
.prediv.width = _prediv_width, \
521
.prediv.value = _prediv_value, \
522
.prediv.flags = _prediv_flags, \
523
.prediv.cond_shift = 0, \
524
.prediv.cond_width = 0, \
525
.prediv.cond_mask = _prediv_cond_mask, \
526
.prediv.cond_value = _prediv_cond_value, \
527
}
528
529
#define MIPI_CLK(_clkname, _id, _name, _pnames, \
530
_offset, \
531
_kshift, _kwidth, _kflags, _kmin, \
532
_mshift, _mwidth, \
533
_nshift, _nwidth, \
534
_gate_shift, _lock_shift) \
535
static struct aw_clk_mipi_def _clkname = { \
536
.clkdef = { \
537
.id = _id, \
538
.name = _name, \
539
.parent_names = _pnames, \
540
.parent_cnt = nitems(_pnames) \
541
}, \
542
.offset = _offset, \
543
.k.shift = _kshift, \
544
.k.width = _kwidth, \
545
.k.flags = _kflags, \
546
.k.min_value = _kmin, \
547
.m.shift = _mshift, \
548
.m.width = _mwidth, \
549
.n.shift = _nshift, \
550
.n.width = _nwidth, \
551
.gate_shift = _gate_shift, \
552
.lock_shift = _lock_shift, \
553
}
554
555
#define MUX_CLK(_clkname, _id, _name, _pnames, \
556
_offset, _shift, _width) \
557
static struct clk_mux_def _clkname = { \
558
.clkdef = { \
559
.id = _id, \
560
.name = _name, \
561
.parent_names = _pnames, \
562
.parent_cnt = nitems(_pnames) \
563
}, \
564
.offset = _offset, \
565
.shift = _shift, \
566
.width = _width, \
567
}
568
569
#define DIV_CLK(_clkname, _id, _name, _pnames, \
570
_offset, \
571
_i_shift, _i_width, \
572
_div_flags, _div_table) \
573
static struct clk_div_def _clkname = { \
574
.clkdef = { \
575
.id = _id, \
576
.name = _name, \
577
.parent_names = _pnames, \
578
.parent_cnt = nitems(_pnames) \
579
}, \
580
.offset = _offset, \
581
.i_shift = _i_shift, \
582
.i_width = _i_width, \
583
.div_flags = _div_flags, \
584
.div_table = _div_table, \
585
}
586
587
#define FIXED_CLK(_clkname, _id, _name, _pnames, \
588
_freq, _mult, _div, _flags) \
589
static struct clk_fixed_def _clkname = { \
590
.clkdef = { \
591
.id = _id, \
592
.name = _name, \
593
.parent_names = _pnames, \
594
.parent_cnt = 1, \
595
}, \
596
.freq = _freq, \
597
.mult = _mult, \
598
.div = _div, \
599
.fixed_flags = _flags, \
600
}
601
602
#endif /* __AW_CLK_H__ */
603
604