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