2 * Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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
32 Allwinner clocks formula :
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)
56 const char *parent_name;
57 uint64_t default_freq;
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
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
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 */
92 uint32_t flags; /* Flags */
102 static inline uint32_t
103 aw_clk_get_factor(uint32_t val, struct aw_clk_factor *factor)
108 if (factor->flags & AW_CLK_FACTOR_HAS_COND) {
109 cond = (val & factor->cond_mask) >> factor->cond_shift;
110 if (cond != factor->cond_value)
114 if (factor->flags & AW_CLK_FACTOR_FIXED)
115 return (factor->value);
117 factor_val = (val & factor->mask) >> factor->shift;
118 if (factor_val == 0 && (factor->flags & AW_CLK_FACTOR_ZERO_IS_ONE))
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))
129 static inline uint32_t
130 aw_clk_factor_get_max(struct aw_clk_factor *factor)
134 if (factor->flags & AW_CLK_FACTOR_FIXED)
136 else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
137 max = 1 << ((1 << factor->width) - 1);
139 max = (1 << factor->width);
145 static inline uint32_t
146 aw_clk_factor_get_min(struct aw_clk_factor *factor)
150 if (factor->flags & AW_CLK_FACTOR_FIXED)
152 else if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
154 else if (factor->flags & AW_CLK_FACTOR_MIN_VALUE)
155 min = factor->min_value;
162 static inline uint32_t
163 aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
167 if (factor->flags & AW_CLK_FACTOR_FIXED)
168 return (factor->value);
170 if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
172 else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) {
173 for (val = 0; raw != 1; val++)
175 } else if (factor->flags & AW_CLK_FACTOR_MAX_VALUE)
176 val = factor->max_value;
183 #define CCU_RESET(idx, o, s) \
189 #define CCU_GATE(idx, clkname, pname, o, s) \
192 .parent_name = pname, \
197 #define NKMP_CLK(_clkname, _id, _name, _pnames, \
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, \
204 _lock, _lock_retries, \
206 static struct aw_clk_nkmp_def _clkname = { \
210 .parent_names = _pnames, \
211 .parent_cnt = nitems(_pnames), \
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, \
236 #define NKMP_CLK_WITH_MUX(_clkname, \
237 _id, _name, _pnames, \
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, \
246 static struct aw_clk_nkmp_def _clkname = { \
250 .parent_names = _pnames, \
251 .parent_cnt = nitems(_pnames), \
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, \
278 #define NKMP_CLK_WITH_UPDATE(_clkname, \
279 _id, _name, _pnames, \
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, \
286 _lock, _lock_retries, \
289 static struct aw_clk_nkmp_def _clkname = { \
293 .parent_names = _pnames, \
294 .parent_cnt = nitems(_pnames), \
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, \
320 #define FRAC_CLK(_clkname, _id, _name, _pnames, \
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 = { \
331 .parent_names = _pnames, \
332 .parent_cnt = nitems(_pnames), \
333 .flags = CLK_NODE_GLITCH_FREE, \
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, \
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, \
356 #define M_CLK(_clkname, _id, _name, _pnames, \
358 _mshift, _mwidth, _mvalue, _mflags, \
359 _mux_shift, _mux_width, \
362 static struct aw_clk_m_def _clkname = { \
366 .parent_names = _pnames, \
367 .parent_cnt = nitems(_pnames), \
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, \
380 #define NM_CLK(_clkname, _id, _name, _pnames, \
382 _nshift, _nwidth, _nvalue, _nflags, \
383 _mshift, _mwidth, _mvalue, _mflags, \
384 _mux_shift, _mux_width, \
387 static struct aw_clk_nm_def _clkname = { \
391 .parent_names = _pnames, \
392 .parent_cnt = nitems(_pnames), \
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, \
409 #define NMM_CLK(_clkname, _id, _name, _pnames, \
411 _nshift, _nwidth, _nvalue, _nflags, \
412 _m0shift, _m0width, _m0value, _m0flags, \
413 _m1shift, _m1width, _m1value, _m1flags, \
415 _lock, _lock_retries, \
417 static struct aw_clk_nmm_def _clkname = { \
421 .parent_names = _pnames, \
422 .parent_cnt = nitems(_pnames), \
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, \
443 #define NP_CLK(_clkname, _id, _name, _pnames, \
445 _nshift, _nwidth, _nvalue, _nflags, \
446 _pshift, _pwidth, _pvalue, _pflags, \
448 _lock, _lock_retries, \
450 static struct aw_clk_np_def _clkname = { \
454 .parent_names = _pnames, \
455 .parent_cnt = nitems(_pnames), \
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, \
472 #define PREDIV_CLK(_clkname, _id, _name, _pnames, \
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 = { \
482 .parent_names = _pnames, \
483 .parent_cnt = nitems(_pnames), \
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, \
501 #define PREDIV_CLK_WITH_MASK(_clkname, _id, _name, _pnames, \
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 = { \
511 .parent_names = _pnames, \
512 .parent_cnt = nitems(_pnames), \
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, \
531 #define MIPI_CLK(_clkname, _id, _name, _pnames, \
533 _kshift, _kwidth, _kflags, _kmin, \
536 _gate_shift, _lock_shift) \
537 static struct aw_clk_mipi_def _clkname = { \
541 .parent_names = _pnames, \
542 .parent_cnt = nitems(_pnames) \
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, \
557 #define MUX_CLK(_clkname, _id, _name, _pnames, \
558 _offset, _shift, _width) \
559 static struct clk_mux_def _clkname = { \
563 .parent_names = _pnames, \
564 .parent_cnt = nitems(_pnames) \
571 #define DIV_CLK(_clkname, _id, _name, _pnames, \
573 _i_shift, _i_width, \
574 _div_flags, _div_table) \
575 static struct clk_div_def _clkname = { \
579 .parent_names = _pnames, \
580 .parent_cnt = nitems(_pnames) \
583 .i_shift = _i_shift, \
584 .i_width = _i_width, \
585 .div_flags = _div_flags, \
586 .div_table = _div_table, \
589 #define FIXED_CLK(_clkname, _id, _name, _pnames, \
590 _freq, _mult, _div, _flags) \
591 static struct clk_fixed_def _clkname = { \
595 .parent_names = _pnames, \
601 .fixed_flags = _flags, \
604 #endif /* __AW_CLK_H__ */