2 * Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 Allwinner clocks formula :
49 Clock Source/Divider N/Divider M
50 Clock Source/Divider N/Divider M/2
51 Clock Source*N/(Divider M+1)/(Divider P+1)
57 const char *parent_name;
58 uint64_t default_freq;
62 #define AW_CLK_HAS_GATE 0x0001
63 #define AW_CLK_HAS_LOCK 0x0002
64 #define AW_CLK_HAS_MUX 0x0004
65 #define AW_CLK_REPARENT 0x0008
66 #define AW_CLK_SCALE_CHANGE 0x0010
67 #define AW_CLK_HAS_UPDATE 0x0040
68 #define AW_CLK_HAS_PREDIV 0x0080
69 #define AW_CLK_SET_PARENT 0x0100
71 #define AW_CLK_FACTOR_POWER_OF_TWO 0x0001
72 #define AW_CLK_FACTOR_ZERO_BASED 0x0002
73 #define AW_CLK_FACTOR_HAS_COND 0x0004
74 #define AW_CLK_FACTOR_FIXED 0x0008
75 #define AW_CLK_FACTOR_ZERO_IS_ONE 0x0010
76 #define AW_CLK_FACTOR_MIN_VALUE 0x0020
77 #define AW_CLK_FACTOR_MAX_VALUE 0x0040
79 struct aw_clk_factor {
80 uint32_t shift; /* Shift bits for the factor */
81 uint32_t mask; /* Mask to get the factor, will be override by the clk methods */
82 uint32_t width; /* Number of bits for the factor */
83 uint32_t value; /* Fixed value, depends on AW_CLK_FACTOR_FIXED */
93 uint32_t flags; /* Flags */
103 static inline uint32_t
104 aw_clk_get_factor(uint32_t val, struct aw_clk_factor *factor)
109 if (factor->flags & AW_CLK_FACTOR_HAS_COND) {
110 cond = (val & factor->cond_mask) >> factor->cond_shift;
111 if (cond != factor->cond_value)
115 if (factor->flags & AW_CLK_FACTOR_FIXED)
116 return (factor->value);
118 factor_val = (val & factor->mask) >> factor->shift;
119 if (factor_val == 0 && (factor->flags & AW_CLK_FACTOR_ZERO_IS_ONE))
122 if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
123 factor_val = 1 << factor_val;
124 else if (!(factor->flags & AW_CLK_FACTOR_ZERO_BASED))
130 static inline uint32_t
131 aw_clk_factor_get_max(struct aw_clk_factor *factor)
135 if (factor->flags & AW_CLK_FACTOR_FIXED)
137 else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
138 max = 1 << ((1 << factor->width) - 1);
140 max = (1 << factor->width);
146 static inline uint32_t
147 aw_clk_factor_get_min(struct aw_clk_factor *factor)
151 if (factor->flags & AW_CLK_FACTOR_FIXED)
153 else if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
155 else if (factor->flags & AW_CLK_FACTOR_MIN_VALUE)
156 min = factor->min_value;
163 static inline uint32_t
164 aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
168 if (factor->flags & AW_CLK_FACTOR_FIXED)
169 return (factor->value);
171 if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
173 else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) {
174 for (val = 0; raw != 1; val++)
176 } else if (factor->flags & AW_CLK_FACTOR_MAX_VALUE)
177 val = factor->max_value;
184 #define CCU_RESET(idx, o, s) \
190 #define CCU_GATE(idx, clkname, pname, o, s) \
193 .parent_name = pname, \
198 #define NKMP_CLK(_clkname, _id, _name, _pnames, \
200 _n_shift, _n_width, _n_value, _n_flags, \
201 _k_shift, _k_width, _k_value, _k_flags, \
202 _m_shift, _m_width, _m_value, _m_flags, \
203 _p_shift, _p_width, _p_value, _p_flags, \
205 _lock, _lock_retries, \
207 static struct aw_clk_nkmp_def _clkname = { \
211 .parent_names = _pnames, \
212 .parent_cnt = nitems(_pnames), \
215 .n.shift = _n_shift, \
216 .n.width = _n_width, \
217 .n.value = _n_value, \
218 .n.flags = _n_flags, \
219 .k.shift = _k_shift, \
220 .k.width = _k_width, \
221 .k.value = _k_value, \
222 .k.flags = _k_flags, \
223 .m.shift = _m_shift, \
224 .m.width = _m_width, \
225 .m.value = _m_value, \
226 .m.flags = _m_flags, \
227 .p.shift = _p_shift, \
228 .p.width = _p_width, \
229 .p.value = _p_value, \
230 .p.flags = _p_flags, \
231 .gate_shift = _gate, \
232 .lock_shift = _lock, \
233 .lock_retries = _lock_retries, \
237 #define NKMP_CLK_WITH_MUX(_clkname, \
238 _id, _name, _pnames, \
240 _n_shift, _n_width, _n_value, _n_flags, \
241 _k_shift, _k_width, _k_value, _k_flags, \
242 _m_shift, _m_width, _m_value, _m_flags, \
243 _p_shift, _p_width, _p_value, _p_flags, \
244 _mux_shift, _mux_width, _gate, \
245 _lock, _lock_retries, \
247 static struct aw_clk_nkmp_def _clkname = { \
251 .parent_names = _pnames, \
252 .parent_cnt = nitems(_pnames), \
255 .n.shift = _n_shift, \
256 .n.width = _n_width, \
257 .n.value = _n_value, \
258 .n.flags = _n_flags, \
259 .k.shift = _k_shift, \
260 .k.width = _k_width, \
261 .k.value = _k_value, \
262 .k.flags = _k_flags, \
263 .m.shift = _m_shift, \
264 .m.width = _m_width, \
265 .m.value = _m_value, \
266 .m.flags = _m_flags, \
267 .p.shift = _p_shift, \
268 .p.width = _p_width, \
269 .p.value = _p_value, \
270 .p.flags = _p_flags, \
271 .mux_shift = _mux_shift, \
272 .mux_width = _mux_width, \
273 .gate_shift = _gate, \
274 .lock_shift = _lock, \
275 .lock_retries = _lock_retries, \
279 #define NKMP_CLK_WITH_UPDATE(_clkname, \
280 _id, _name, _pnames, \
282 _n_shift, _n_width, _n_value, _n_flags, \
283 _k_shift, _k_width, _k_value, _k_flags, \
284 _m_shift, _m_width, _m_value, _m_flags, \
285 _p_shift, _p_width, _p_value, _p_flags, \
287 _lock, _lock_retries, \
290 static struct aw_clk_nkmp_def _clkname = { \
294 .parent_names = _pnames, \
295 .parent_cnt = nitems(_pnames), \
298 .n.shift = _n_shift, \
299 .n.width = _n_width, \
300 .n.value = _n_value, \
301 .n.flags = _n_flags, \
302 .k.shift = _k_shift, \
303 .k.width = _k_width, \
304 .k.value = _k_value, \
305 .k.flags = _k_flags, \
306 .m.shift = _m_shift, \
307 .m.width = _m_width, \
308 .m.value = _m_value, \
309 .m.flags = _m_flags, \
310 .p.shift = _p_shift, \
311 .p.width = _p_width, \
312 .p.value = _p_value, \
313 .p.flags = _p_flags, \
314 .gate_shift = _gate, \
315 .lock_shift = _lock, \
316 .lock_retries = _lock_retries, \
317 .update_shift = _update, \
318 .flags = _flags | AW_CLK_HAS_UPDATE, \
321 #define FRAC_CLK(_clkname, _id, _name, _pnames, \
323 _nshift, _nwidth, _nvalue, _nflags, \
324 _mshift, _mwidth, _mvalue, _mflags, \
325 _gate_shift, _lock_shift,_lock_retries, \
326 _flags, _freq0, _freq1, _mode_sel, _freq_sel, \
327 _min_freq, _max_freq) \
328 static struct aw_clk_frac_def _clkname = { \
332 .parent_names = _pnames, \
333 .parent_cnt = nitems(_pnames), \
334 .flags = CLK_NODE_GLITCH_FREE, \
337 .n.shift = _nshift, \
338 .n.width = _nwidth, \
339 .n.value = _nvalue, \
340 .n.flags = _nflags, \
341 .m.shift = _mshift, \
342 .m.width = _mwidth, \
343 .m.value = _mvalue, \
344 .m.flags = _mflags, \
345 .gate_shift = _gate_shift, \
346 .lock_shift = _lock_shift, \
347 .lock_retries = _lock_retries, \
349 .frac.freq0 = _freq0, \
350 .frac.freq1 = _freq1, \
351 .frac.mode_sel = _mode_sel, \
352 .frac.freq_sel = _freq_sel, \
353 .min_freq = _min_freq, \
354 .max_freq = _max_freq, \
357 #define M_CLK(_clkname, _id, _name, _pnames, \
359 _mshift, _mwidth, _mvalue, _mflags, \
360 _mux_shift, _mux_width, \
363 static struct aw_clk_m_def _clkname = { \
367 .parent_names = _pnames, \
368 .parent_cnt = nitems(_pnames), \
371 .mux_shift = _mux_shift, \
372 .m.shift = _mshift, \
373 .m.width = _mwidth, \
374 .m.value = _mvalue, \
375 .m.flags = _mflags, \
376 .mux_width = _mux_width, \
377 .gate_shift = _gate_shift, \
381 #define NM_CLK(_clkname, _id, _name, _pnames, \
383 _nshift, _nwidth, _nvalue, _nflags, \
384 _mshift, _mwidth, _mvalue, _mflags, \
385 _mux_shift, _mux_width, \
388 static struct aw_clk_nm_def _clkname = { \
392 .parent_names = _pnames, \
393 .parent_cnt = nitems(_pnames), \
396 .n.shift = _nshift, \
397 .n.width = _nwidth, \
398 .n.value = _nvalue, \
399 .n.flags = _nflags, \
400 .mux_shift = _mux_shift, \
401 .m.shift = _mshift, \
402 .m.width = _mwidth, \
403 .m.value = _mvalue, \
404 .m.flags = _mflags, \
405 .mux_width = _mux_width, \
406 .gate_shift = _gate_shift, \
410 #define NMM_CLK(_clkname, _id, _name, _pnames, \
412 _nshift, _nwidth, _nvalue, _nflags, \
413 _m0shift, _m0width, _m0value, _m0flags, \
414 _m1shift, _m1width, _m1value, _m1flags, \
416 _lock, _lock_retries, \
418 static struct aw_clk_nmm_def _clkname = { \
422 .parent_names = _pnames, \
423 .parent_cnt = nitems(_pnames), \
426 .n.shift = _nshift, \
427 .n.width = _nwidth, \
428 .n.value = _nvalue, \
429 .n.flags = _nflags, \
430 .m0.shift = _m0shift, \
431 .m0.width = _m0width, \
432 .m0.value = _m0value, \
433 .m0.flags = _m0flags, \
434 .m1.shift = _m1shift, \
435 .m1.width = _m1width, \
436 .m1.value = _m1value, \
437 .m1.flags = _m1flags, \
438 .gate_shift = _gate_shift, \
439 .lock_shift = _lock, \
440 .lock_retries = _lock_retries, \
444 #define NP_CLK(_clkname, _id, _name, _pnames, \
446 _nshift, _nwidth, _nvalue, _nflags, \
447 _pshift, _pwidth, _pvalue, _pflags, \
449 _lock, _lock_retries, \
451 static struct aw_clk_np_def _clkname = { \
455 .parent_names = _pnames, \
456 .parent_cnt = nitems(_pnames), \
459 .n.shift = _nshift, \
460 .n.width = _nwidth, \
461 .n.value = _nvalue, \
462 .n.flags = _nflags, \
463 .p.shift = _pshift, \
464 .p.width = _pwidth, \
465 .p.value = _pvalue, \
466 .p.flags = _pflags, \
467 .gate_shift = _gate_shift, \
468 .lock_shift = _lock, \
469 .lock_retries = _lock_retries, \
473 #define PREDIV_CLK(_clkname, _id, _name, _pnames, \
475 _mux_shift, _mux_width, \
476 _div_shift, _div_width, _div_value, _div_flags, \
477 _prediv_shift, _prediv_width, _prediv_value, _prediv_flags, \
478 _prediv_cond_shift, _prediv_cond_width, _prediv_cond_value) \
479 static struct aw_clk_prediv_mux_def _clkname = { \
483 .parent_names = _pnames, \
484 .parent_cnt = nitems(_pnames), \
487 .mux_shift = _mux_shift, \
488 .mux_width = _mux_width, \
489 .div.shift = _div_shift, \
490 .div.width = _div_width, \
491 .div.value = _div_value, \
492 .div.flags = _div_flags, \
493 .prediv.shift = _prediv_shift, \
494 .prediv.width = _prediv_width, \
495 .prediv.value = _prediv_value, \
496 .prediv.flags = _prediv_flags, \
497 .prediv.cond_shift = _prediv_cond_shift, \
498 .prediv.cond_width = _prediv_cond_width, \
499 .prediv.cond_value = _prediv_cond_value, \
502 #define PREDIV_CLK_WITH_MASK(_clkname, _id, _name, _pnames, \
504 _mux_shift, _mux_width, \
505 _div_shift, _div_width, _div_value, _div_flags, \
506 _prediv_shift, _prediv_width, _prediv_value, _prediv_flags, \
507 _prediv_cond_mask, _prediv_cond_value) \
508 static struct aw_clk_prediv_mux_def _clkname = { \
512 .parent_names = _pnames, \
513 .parent_cnt = nitems(_pnames), \
516 .mux_shift = _mux_shift, \
517 .mux_width = _mux_width, \
518 .div.shift = _div_shift, \
519 .div.width = _div_width, \
520 .div.value = _div_value, \
521 .div.flags = _div_flags, \
522 .prediv.shift = _prediv_shift, \
523 .prediv.width = _prediv_width, \
524 .prediv.value = _prediv_value, \
525 .prediv.flags = _prediv_flags, \
526 .prediv.cond_shift = 0, \
527 .prediv.cond_width = 0, \
528 .prediv.cond_mask = _prediv_cond_mask, \
529 .prediv.cond_value = _prediv_cond_value, \
532 #define MIPI_CLK(_clkname, _id, _name, _pnames, \
534 _kshift, _kwidth, _kflags, _kmin, \
537 _gate_shift, _lock_shift) \
538 static struct aw_clk_mipi_def _clkname = { \
542 .parent_names = _pnames, \
543 .parent_cnt = nitems(_pnames) \
546 .k.shift = _kshift, \
547 .k.width = _kwidth, \
548 .k.flags = _kflags, \
549 .k.min_value = _kmin, \
550 .m.shift = _mshift, \
551 .m.width = _mwidth, \
552 .n.shift = _nshift, \
553 .n.width = _nwidth, \
554 .gate_shift = _gate_shift, \
555 .lock_shift = _lock_shift, \
558 #define MUX_CLK(_clkname, _id, _name, _pnames, \
559 _offset, _shift, _width) \
560 static struct clk_mux_def _clkname = { \
564 .parent_names = _pnames, \
565 .parent_cnt = nitems(_pnames) \
572 #define DIV_CLK(_clkname, _id, _name, _pnames, \
574 _i_shift, _i_width, \
575 _div_flags, _div_table) \
576 static struct clk_div_def _clkname = { \
580 .parent_names = _pnames, \
581 .parent_cnt = nitems(_pnames) \
584 .i_shift = _i_shift, \
585 .i_width = _i_width, \
586 .div_flags = _div_flags, \
587 .div_table = _div_table, \
590 #define FIXED_CLK(_clkname, _id, _name, _pnames, \
591 _freq, _mult, _div, _flags) \
592 static struct clk_fixed_def _clkname = { \
596 .parent_names = _pnames, \
602 .fixed_flags = _flags, \
605 #endif /* __AW_CLK_H__ */