Lines Matching +full:divider +full:- +full:int +full:- +full:0
4 * SPDX-License-Identifier: Apache-2.0
46 for (i = 0; i <= CLKOUT_MAX; i++) { in litex_clk_regs_addr_init()
66 …* https://github.com/Digilent/Zybo-hdmi-out/blob/b991fff6e964420ae3c00c3dbee52f2ad748b3ba/sdk/disp…
75 0b0001011111,
76 0b0001010111,
77 0b0001111011,
78 0b0001011011,
79 0b0001101011,
80 0b0001110011,
81 0b0001110011,
82 0b0001110011,
83 0b0001110011,
84 0b0001001011,
85 0b0001001011,
86 0b0001001011,
87 0b0010110011,
88 0b0001010011,
89 0b0001010011,
90 0b0001010011,
91 0b0001010011,
92 0b0001010011,
93 0b0001010011,
94 0b0001010011,
95 0b0001010011,
96 0b0001010011,
97 0b0001010011,
98 0b0001100011,
99 0b0001100011,
100 0b0001100011,
101 0b0001100011,
102 0b0001100011,
103 0b0001100011,
104 0b0001100011,
105 0b0001100011,
106 0b0001100011,
107 0b0001100011,
108 0b0001100011,
109 0b0001100011,
110 0b0001100011,
111 0b0001100011,
112 0b0010010011,
113 0b0010010011,
114 0b0010010011,
115 0b0010010011,
116 0b0010010011,
117 0b0010010011,
118 0b0010010011,
119 0b0010010011,
120 0b0010010011,
121 0b0010010011,
122 0b0010100011,
123 0b0010100011,
124 0b0010100011,
125 0b0010100011,
126 0b0010100011,
127 0b0010100011,
128 0b0010100011,
129 0b0010100011,
130 0b0010100011,
131 0b0010100011,
132 0b0010100011,
133 0b0010100011,
134 0b0010100011,
135 0b0010100011,
136 0b0010100011,
137 0b0010100011,
138 0b0010100011
143 0b0011000110111110100011111010010000000001,
144 0b0011000110111110100011111010010000000001,
145 0b0100001000111110100011111010010000000001,
146 0b0101101011111110100011111010010000000001,
147 0b0111001110111110100011111010010000000001,
148 0b1000110001111110100011111010010000000001,
149 0b1001110011111110100011111010010000000001,
150 0b1011010110111110100011111010010000000001,
151 0b1100111001111110100011111010010000000001,
152 0b1110011100111110100011111010010000000001,
153 0b1111111111111000010011111010010000000001,
154 0b1111111111110011100111111010010000000001,
155 0b1111111111101110111011111010010000000001,
156 0b1111111111101011110011111010010000000001,
157 0b1111111111101000101011111010010000000001,
158 0b1111111111100111000111111010010000000001,
159 0b1111111111100011111111111010010000000001,
160 0b1111111111100010011011111010010000000001,
161 0b1111111111100000110111111010010000000001,
162 0b1111111111011111010011111010010000000001,
163 0b1111111111011101101111111010010000000001,
164 0b1111111111011100001011111010010000000001,
165 0b1111111111011010100111111010010000000001,
166 0b1111111111011001000011111010010000000001,
167 0b1111111111011001000011111010010000000001,
168 0b1111111111010111011111111010010000000001,
169 0b1111111111010101111011111010010000000001,
170 0b1111111111010101111011111010010000000001,
171 0b1111111111010100010111111010010000000001,
172 0b1111111111010100010111111010010000000001,
173 0b1111111111010010110011111010010000000001,
174 0b1111111111010010110011111010010000000001,
175 0b1111111111010010110011111010010000000001,
176 0b1111111111010001001111111010010000000001,
177 0b1111111111010001001111111010010000000001,
178 0b1111111111010001001111111010010000000001,
179 0b1111111111001111101011111010010000000001,
180 0b1111111111001111101011111010010000000001,
181 0b1111111111001111101011111010010000000001,
182 0b1111111111001111101011111010010000000001,
183 0b1111111111001111101011111010010000000001,
184 0b1111111111001111101011111010010000000001,
185 0b1111111111001111101011111010010000000001,
186 0b1111111111001111101011111010010000000001,
187 0b1111111111001111101011111010010000000001,
188 0b1111111111001111101011111010010000000001,
189 0b1111111111001111101011111010010000000001,
190 0b1111111111001111101011111010010000000001,
191 0b1111111111001111101011111010010000000001,
192 0b1111111111001111101011111010010000000001,
193 0b1111111111001111101011111010010000000001,
194 0b1111111111001111101011111010010000000001,
195 0b1111111111001111101011111010010000000001,
196 0b1111111111001111101011111010010000000001,
197 0b1111111111001111101011111010010000000001,
198 0b1111111111001111101011111010010000000001,
199 0b1111111111001111101011111010010000000001,
200 0b1111111111001111101011111010010000000001,
201 0b1111111111001111101011111010010000000001,
202 0b1111111111001111101011111010010000000001,
203 0b1111111111001111101011111010010000000001,
204 0b1111111111001111101011111010010000000001,
205 0b1111111111001111101011111010010000000001,
206 0b1111111111001111101011111010010000000001
213 return litex_clk_filter_table[glob_mul - 1]; in litex_clk_lookup_filter()
219 return litex_clk_lock_table[glob_mul - 1]; in litex_clk_lookup_lock()
234 int assert = (1 << (drp[reg].size * BITS_PER_BYTE)) - 1; in litex_clk_assert_reg()
244 static int litex_clk_wait(uint32_t reg) in litex_clk_wait()
251 timeout = ldev->timeout.lock; in litex_clk_wait()
253 timeout = ldev->timeout.drdy; in litex_clk_wait()
257 timeout--; in litex_clk_wait()
260 if (timeout == 0) { in litex_clk_wait()
261 LOG_WRN("Timeout occured when waiting for the register: 0x%x", reg); in litex_clk_wait()
262 return -ETIME; in litex_clk_wait()
264 return 0; in litex_clk_wait()
268 static int litex_clk_get_DO(uint8_t clk_reg_addr, uint16_t *res) in litex_clk_get_DO()
270 int ret; in litex_clk_get_DO()
277 if (ret != 0) { in litex_clk_get_DO()
283 return 0; in litex_clk_get_DO()
286 /* Get global divider and multiplier values and update global config */
287 static int litex_clk_update_global_config(void) in litex_clk_update_global_config()
289 int ret; in litex_clk_update_global_config()
294 if (ret != 0) { in litex_clk_update_global_config()
298 if (ret != 0) { in litex_clk_update_global_config()
303 ldev->g_config.mul = 1; in litex_clk_update_global_config()
308 if (ret != 0) { in litex_clk_update_global_config()
313 ldev->g_config.mul = low_time + high_time; in litex_clk_update_global_config()
317 ldev->g_config.div = 1; in litex_clk_update_global_config()
321 ldev->g_config.div = low_time + high_time; in litex_clk_update_global_config()
324 return 0; in litex_clk_update_global_config()
343 f = litex_clk_calc_global_frequency(ldev->g_config.mul, in litex_clk_get_real_global_frequency()
344 ldev->g_config.div); in litex_clk_get_real_global_frequency()
345 ldev->g_config.freq = f; in litex_clk_get_real_global_frequency()
346 ldev->ts_g_config.div = ldev->g_config.div; in litex_clk_get_real_global_frequency()
347 ldev->ts_g_config.mul = ldev->g_config.mul; in litex_clk_get_real_global_frequency()
348 ldev->ts_g_config.freq = ldev->g_config.freq; in litex_clk_get_real_global_frequency()
354 static int litex_clk_get_clkout_divider(struct litex_clk_clkout *lcko, in litex_clk_get_clkout_divider()
355 uint32_t *divider, uint32_t *fract_cnt) in litex_clk_get_clkout_divider() argument
358 int ret; in litex_clk_get_clkout_divider()
360 uint8_t clkout_nr = lcko->id; in litex_clk_get_clkout_divider()
364 if (ret != 0) { in litex_clk_get_clkout_divider()
368 if (ret != 0) { in litex_clk_get_clkout_divider()
374 *divider = low_time + high_time; in litex_clk_get_clkout_divider()
377 return 0; in litex_clk_get_clkout_divider()
386 int ret; in litex_clk_check_DO()
389 if (ret != 0) { in litex_clk_check_DO()
392 LOG_DBG("%s: 0x%x", reg_name, *res); in litex_clk_check_DO()
431 for (i = 0; i < ldev->nclkout; i++) { in litex_clk_print_all_regs()
439 LOG_DBG("CLKOUT%d DUMP:", lcko->id); in litex_clk_print_params()
442 lcko->def.freq, lcko->def.duty.num, in litex_clk_print_params()
443 lcko->def.duty.den, lcko->def.phase); in litex_clk_print_params()
446 lcko->ts_config.div, lcko->ts_config.freq, in litex_clk_print_params()
447 lcko->ts_config.duty.num, lcko->ts_config.duty.den, in litex_clk_print_params()
448 lcko->ts_config.phase, lcko->config.period_off); in litex_clk_print_params()
451 lcko->config.div, lcko->config.freq, in litex_clk_print_params()
452 lcko->config.duty.num, lcko->config.duty.den, in litex_clk_print_params()
453 lcko->config.phase, lcko->config.period_off); in litex_clk_print_params()
456 lcko->div.edge, lcko->div.high_time, in litex_clk_print_params()
457 lcko->div.low_time, lcko->div.no_cnt); in litex_clk_print_params()
460 lcko->frac.frac, lcko->frac.frac_en, lcko->frac.frac_wf_f, in litex_clk_print_params()
461 lcko->frac.frac_wf_r, lcko->frac.phase_mux_f); in litex_clk_print_params()
464 lcko->phase.delay_time, lcko->phase.phase_mux, lcko->phase.mx); in litex_clk_print_params()
473 ldev->ts_g_config.freq, ldev->ts_g_config.mul, in litex_clk_print_all_params()
474 ldev->ts_g_config.div); in litex_clk_print_all_params()
477 ldev->g_config.freq, ldev->g_config.mul, ldev->g_config.div); in litex_clk_print_all_params()
478 for (c = 0; c < ldev->nclkout; c++) { in litex_clk_print_all_params()
479 litex_clk_print_params(&ldev->clkouts[c]); in litex_clk_print_all_params()
497 static int litex_clk_set_DI(uint16_t DI_val) in litex_clk_set_DI()
499 int ret; in litex_clk_set_DI()
512 * by selecting 1 or 0 on desired specific mask positions
517 static int litex_clk_change_value(uint16_t mask, uint16_t bitset, in litex_clk_change_value()
521 int ret; in litex_clk_change_value()
526 if (ret != 0) { in litex_clk_change_value()
531 if (ret != 0) { in litex_clk_change_value()
536 LOG_DBG("set 0x%x under: 0x%x", DI_val, clk_reg_addr); in litex_clk_change_value()
549 * by selecting 1 or 0 on desired specific mask positions
553 static int litex_clk_set_clock(uint8_t clkout_nr, uint16_t mask_reg1, in litex_clk_set_clock()
558 int ret; in litex_clk_set_clock()
563 if (ret != 0) { in litex_clk_set_clock()
570 if (ret != 0) { in litex_clk_set_clock()
575 return 0; in litex_clk_set_clock()
578 /* Set global divider for all CLKOUTs */
579 static int litex_clk_set_divreg(void) in litex_clk_set_divreg()
581 int ret; in litex_clk_set_divreg()
582 uint8_t no_cnt = 0, edge = 0, ht = 0, lt = 0, in litex_clk_set_divreg()
583 div = ldev->ts_g_config.div; in litex_clk_set_divreg()
584 uint16_t bitset = 0; in litex_clk_set_divreg()
603 if (ret != 0) { in litex_clk_set_divreg()
607 ldev->g_config.div = div; in litex_clk_set_divreg()
608 LOG_DBG("Global divider set to %u", div); in litex_clk_set_divreg()
610 return 0; in litex_clk_set_divreg()
614 static int litex_clk_set_mulreg(void) in litex_clk_set_mulreg()
616 int ret; in litex_clk_set_mulreg()
617 uint8_t no_cnt = 0, edge = 0, ht = 0, lt = 0, in litex_clk_set_mulreg()
618 mul = ldev->ts_g_config.mul; in litex_clk_set_mulreg()
619 uint16_t bitset1 = 0; in litex_clk_set_mulreg()
636 if (ret != 0) { in litex_clk_set_mulreg()
646 if (ret != 0) { in litex_clk_set_mulreg()
651 ldev->g_config.mul = mul; in litex_clk_set_mulreg()
654 return 0; in litex_clk_set_mulreg()
657 static int litex_clk_set_filt(void) in litex_clk_set_filt()
661 int ret; in litex_clk_set_filt()
663 mul = ldev->g_config.mul; in litex_clk_set_filt()
670 filt_reg = (((filt >> 9) & 0x1) << 15) | in litex_clk_set_filt()
671 (((filt >> 7) & 0x3) << 11) | in litex_clk_set_filt()
672 (((filt >> 6) & 0x1) << 8); in litex_clk_set_filt()
674 if (ret != 0) { in litex_clk_set_filt()
678 filt_reg = (((filt >> 5) & 0x1) << 15) | in litex_clk_set_filt()
679 (((filt >> 3) & 0x3) << 11) | in litex_clk_set_filt()
680 (((filt >> 1) & 0x3) << 7) | in litex_clk_set_filt()
681 (((filt) & 0x1) << 4); in litex_clk_set_filt()
687 static int litex_clk_set_lock(void) in litex_clk_set_lock()
692 int ret; in litex_clk_set_lock()
694 mul = ldev->g_config.mul; in litex_clk_set_lock()
701 lock_reg = (lock >> 20) & 0x3FF; in litex_clk_set_lock()
703 if (ret != 0) { in litex_clk_set_lock()
707 lock_reg = (((lock >> 30) & 0x1F) << 10) | in litex_clk_set_lock()
708 (lock & 0x3FF); in litex_clk_set_lock()
710 if (ret != 0) { in litex_clk_set_lock()
714 lock_reg = (((lock >> 35) & 0x1F) << 10) | in litex_clk_set_lock()
715 ((lock >> 10) & 0x3FF); in litex_clk_set_lock()
721 /* Set all multiplier-related regs: mul, filt and lock regs */
722 static int litex_clk_set_mul(void) in litex_clk_set_mul()
724 int ret; in litex_clk_set_mul()
727 if (ret != 0) { in litex_clk_set_mul()
731 if (ret != 0) { in litex_clk_set_mul()
738 static int litex_clk_set_both_globs(void) in litex_clk_set_both_globs()
745 int ret; in litex_clk_set_both_globs()
747 /* div-first case */ in litex_clk_set_both_globs()
749 ldev->g_config.mul, in litex_clk_set_both_globs()
750 ldev->ts_g_config.div); in litex_clk_set_both_globs()
751 if (vco_freq > ldev->vco.max || vco_freq < ldev->vco.min) { in litex_clk_set_both_globs()
752 /* div-first not safe */ in litex_clk_set_both_globs()
754 ldev->ts_g_config.mul, in litex_clk_set_both_globs()
755 ldev->g_config.div); in litex_clk_set_both_globs()
756 if (vco_freq > ldev->vco.max || vco_freq < ldev->vco.min) { in litex_clk_set_both_globs()
757 /* mul-first not safe */ in litex_clk_set_both_globs()
760 if (ret != -ETIME && ret != 0) { in litex_clk_set_both_globs()
762 } else if (ret == -ETIME) { in litex_clk_set_both_globs()
763 ldev->g_config.div = ldev->ts_g_config.div; in litex_clk_set_both_globs()
764 LOG_DBG("Global divider set to %u", in litex_clk_set_both_globs()
765 ldev->g_config.div); in litex_clk_set_both_globs()
768 if (ret != 0) { in litex_clk_set_both_globs()
772 /* mul-first safe */ in litex_clk_set_both_globs()
774 if (ret != 0) { in litex_clk_set_both_globs()
778 if (ret != 0) { in litex_clk_set_both_globs()
783 /* div-first safe */ in litex_clk_set_both_globs()
785 if (ret != 0) { in litex_clk_set_both_globs()
789 if (ret != 0) { in litex_clk_set_both_globs()
793 return 0; in litex_clk_set_both_globs()
796 /* Set global divider, multiplier, filt and lock values */
797 static int litex_clk_set_globs(void) in litex_clk_set_globs()
799 int ret; in litex_clk_set_globs()
800 uint8_t set_div = 0, in litex_clk_set_globs()
801 set_mul = 0; in litex_clk_set_globs()
803 set_div = ldev->ts_g_config.div != ldev->g_config.div; in litex_clk_set_globs()
804 set_mul = ldev->ts_g_config.mul != ldev->g_config.mul; in litex_clk_set_globs()
809 if (ret != 0) { in litex_clk_set_globs()
813 /* set divider only */ in litex_clk_set_globs()
815 if (ret != 0) { in litex_clk_set_globs()
821 if (ret != 0) { in litex_clk_set_globs()
825 ldev->g_config.freq = ldev->ts_g_config.freq; in litex_clk_set_globs()
827 return 0; in litex_clk_set_globs()
844 int litex_clk_get_duty_cycle(struct litex_clk_clkout *lcko, in litex_clk_get_duty_cycle()
848 int ret; in litex_clk_get_duty_cycle()
849 uint32_t divider; in litex_clk_get_duty_cycle() local
853 clkout_nr = lcko->id; in litex_clk_get_duty_cycle()
854 /* Check if divider is off */ in litex_clk_get_duty_cycle()
856 if (ret != 0) { in litex_clk_get_duty_cycle()
865 /* get duty 50% when divider is off or fractional is enabled */ in litex_clk_get_duty_cycle()
867 duty->num = 1; in litex_clk_get_duty_cycle()
868 duty->den = 2; in litex_clk_get_duty_cycle()
869 return 0; in litex_clk_get_duty_cycle()
873 if (ret != 0) { in litex_clk_get_duty_cycle()
877 divider = clkout_reg1 & HL_TIME_MASK; in litex_clk_get_duty_cycle()
879 divider += high_time; in litex_clk_get_duty_cycle()
882 duty->num = high_time * 10 + edge * 5; in litex_clk_get_duty_cycle()
883 duty->den = (divider + edge) * 10; in litex_clk_get_duty_cycle()
885 return 0; in litex_clk_get_duty_cycle()
893 ht = duty->num; in litex_clk_calc_duty_percent()
894 div = duty->den; in litex_clk_calc_duty_percent()
901 static int litex_clk_calc_duty_normal(struct litex_clk_clkout *lcko, in litex_clk_calc_duty_normal()
902 int calc_new) in litex_clk_calc_duty_normal()
905 int delta_d; in litex_clk_calc_duty_normal()
908 divider = lcko->config.div; in litex_clk_calc_duty_normal() local
909 int err; in litex_clk_calc_duty_normal()
912 duty = lcko->ts_config.duty; in litex_clk_calc_duty_normal()
915 if (err != 0) { in litex_clk_calc_duty_normal()
923 ht_aprox = high_duty * divider; in litex_clk_calc_duty_normal()
927 (divider * 100) - ht_aprox) { in litex_clk_calc_duty_normal()
928 return -EINVAL; in litex_clk_calc_duty_normal()
931 /* to prevent high_time == 0 or low_time == 0 */ in litex_clk_calc_duty_normal()
932 for (high_time_it = 1; high_time_it < divider; high_time_it++) { in litex_clk_calc_duty_normal()
933 for (edge_it = 0; edge_it < 2; edge_it++) { in litex_clk_calc_duty_normal()
935 divider; in litex_clk_calc_duty_normal()
936 delta_d = synth_duty - high_duty; in litex_clk_calc_duty_normal()
939 if (delta_d < min_d && (divider - high_time_it) <= in litex_clk_calc_duty_normal()
942 lcko->div.high_time = high_time_it; in litex_clk_calc_duty_normal()
943 lcko->div.low_time = divider - high_time_it; in litex_clk_calc_duty_normal()
944 lcko->div.edge = edge_it; in litex_clk_calc_duty_normal()
945 lcko->config.duty.num = high_time_it * 100 + 50 in litex_clk_calc_duty_normal()
947 lcko->config.duty.den = divider * 100; in litex_clk_calc_duty_normal()
955 lcko->frac.frac_wf_f = 0; in litex_clk_calc_duty_normal()
956 lcko->frac.frac_wf_r = 0; in litex_clk_calc_duty_normal()
958 return 0; in litex_clk_calc_duty_normal()
961 /* Calculates duty high_time for given divider and ratio */
962 static inline int litex_clk_calc_duty_high_time(struct clk_duty *duty, in litex_clk_calc_duty_high_time()
963 uint32_t divider) in litex_clk_calc_duty_high_time() argument
967 high_duty = litex_clk_calc_duty_percent(duty) * divider; in litex_clk_calc_duty_high_time()
973 static int litex_clk_set_duty_cycle(struct litex_clk_clkout *lcko, in litex_clk_set_duty_cycle()
976 int ret; in litex_clk_set_duty_cycle()
978 uint8_t clkout_nr = lcko->id, in litex_clk_set_duty_cycle()
979 *edge = &lcko->div.edge, in litex_clk_set_duty_cycle()
980 *high_time = &lcko->div.high_time, in litex_clk_set_duty_cycle()
982 *low_time = &lcko->div.low_time; in litex_clk_set_duty_cycle()
984 if (lcko->frac.frac == 0) { in litex_clk_set_duty_cycle()
985 lcko->ts_config.duty = *duty; in litex_clk_set_duty_cycle()
987 lcko->id, duty->num, duty->den); in litex_clk_set_duty_cycle()
989 if (ret != 0) { in litex_clk_set_duty_cycle()
995 LOG_ERR("CLKOUT%d: cannot set duty cycle when fractional divider enabled", in litex_clk_set_duty_cycle()
997 return -EACCES; in litex_clk_set_duty_cycle()
1004 LOG_DBG("SET DUTY CYCLE: e:%u ht:%u lt:%u\nbitset1: 0x%x bitset2: 0x%x", in litex_clk_set_duty_cycle()
1009 if (ret != 0) { in litex_clk_set_duty_cycle()
1013 LOG_INF("CLKOUT%d: set duty: %d%%", lcko->id, in litex_clk_set_duty_cycle()
1014 litex_clk_calc_duty_percent(&lcko->config.duty)); in litex_clk_set_duty_cycle()
1015 return 0; in litex_clk_set_duty_cycle()
1023 static int litex_clk_calc_phase_normal(struct litex_clk_clkout *lcko) in litex_clk_calc_phase_normal()
1027 *period_off = &lcko->ts_config.period_off; in litex_clk_calc_phase_normal()
1028 uint8_t divider = lcko->config.div; in litex_clk_calc_phase_normal() local
1035 clkout_period = global_period * divider; in litex_clk_calc_phase_normal()
1037 if (lcko->ts_config.phase != 0) { in litex_clk_calc_phase_normal()
1038 int synth_phase, delta_p, min_p, p_o; in litex_clk_calc_phase_normal()
1044 return -EINVAL; in litex_clk_calc_phase_normal()
1049 /* Delay_time: (0-63) */ in litex_clk_calc_phase_normal()
1050 for (delay = 0; delay <= DELAY_TIME_MAX; delay++) { in litex_clk_calc_phase_normal()
1051 /* phase_mux: (0-7) */ in litex_clk_calc_phase_normal()
1052 for (p_m = 0; p_m <= PHASE_MUX_MAX; p_m++) { in litex_clk_calc_phase_normal()
1056 delta_p = synth_phase - p_o; in litex_clk_calc_phase_normal()
1060 lcko->phase.phase_mux = p_m; in litex_clk_calc_phase_normal()
1061 lcko->phase.delay_time = delay; in litex_clk_calc_phase_normal()
1062 lcko->config.period_off = synth_phase; in litex_clk_calc_phase_normal()
1068 lcko->phase.phase_mux = 0; in litex_clk_calc_phase_normal()
1069 lcko->phase.delay_time = 0; in litex_clk_calc_phase_normal()
1075 lcko->frac.phase_mux_f = 0; in litex_clk_calc_phase_normal()
1077 return 0; in litex_clk_calc_phase_normal()
1081 static int litex_clk_prepare_phase(struct litex_clk_clkout *lcko) in litex_clk_prepare_phase()
1083 int *phase = &lcko->ts_config.phase; in litex_clk_prepare_phase()
1087 if (*phase < 0) { in litex_clk_prepare_phase()
1091 lcko->ts_config.period_off = ((*phase * 10000) / 360); in litex_clk_prepare_phase()
1093 return 0; in litex_clk_prepare_phase()
1097 static int litex_clk_calc_phase(struct litex_clk_clkout *lcko) in litex_clk_calc_phase()
1104 /* Returns phase-specific values of given clock output */
1105 static int litex_clk_get_phase_data(struct litex_clk_clkout *lcko, in litex_clk_get_phase_data()
1109 int ret; in litex_clk_get_phase_data()
1111 uint8_t clkout_nr = lcko->id; in litex_clk_get_phase_data()
1114 if (ret != 0) { in litex_clk_get_phase_data()
1118 if (ret != 0) { in litex_clk_get_phase_data()
1125 return 0; in litex_clk_get_phase_data()
1129 int litex_clk_get_phase(struct litex_clk_clkout *lcko) in litex_clk_get_phase()
1132 uint32_t divider = 0, fract_cnt, post_glob_div_f, in litex_clk_get_phase() local
1134 uint8_t phase_mux = 0, delay_time = 0; in litex_clk_get_phase()
1135 int err = 0; in litex_clk_get_phase()
1138 err = litex_clk_get_clkout_divider(lcko, ÷r, &fract_cnt); in litex_clk_get_phase()
1139 if (err != 0) { in litex_clk_get_phase()
1148 clkout_period = global_period * divider; in litex_clk_get_phase()
1162 int litex_clk_get_phase_deg(struct litex_clk_clkout *lcko) in litex_clk_get_phase_deg()
1170 clkout_period *= lcko->config.div; in litex_clk_get_phase_deg()
1172 buff = lcko->config.period_off * 1000 / clkout_period; in litex_clk_get_phase_deg()
1176 return (int)buff; in litex_clk_get_phase_deg()
1179 int litex_clk_set_phase(struct litex_clk_clkout *lcko, int degrees) in litex_clk_set_phase()
1181 int ret; in litex_clk_set_phase()
1183 uint8_t *phase_mux = &lcko->phase.phase_mux, in litex_clk_set_phase()
1184 *delay_time = &lcko->phase.delay_time, in litex_clk_set_phase()
1185 clkout_nr = lcko->id; in litex_clk_set_phase()
1187 lcko->ts_config.phase = degrees; in litex_clk_set_phase()
1189 LOG_DBG("CLKOUT%d: setting phase: %u deg", lcko->id, degrees); in litex_clk_set_phase()
1192 if (ret != 0) { in litex_clk_set_phase()
1203 if (ret != 0) { in litex_clk_set_phase()
1206 lcko->config.phase = litex_clk_get_phase_deg(lcko); in litex_clk_set_phase()
1207 LOG_INF("CLKOUT%d: set phase: %d deg", lcko->id, lcko->config.phase); in litex_clk_set_phase()
1208 LOG_DBG("SET PHASE: pm:%u dt:%u\nbitset1: 0x%x bitset2: 0x%x", in litex_clk_set_phase()
1211 return 0; in litex_clk_set_phase()
1221 uint64_t f = litex_clk_calc_global_frequency(ldev->ts_g_config.mul, in litex_clk_calc_rate()
1222 ldev->ts_g_config.div); in litex_clk_calc_rate()
1224 f /= lcko->config.div; in litex_clk_calc_rate()
1231 * and base above 0. Used for calculating scaling factor for
1237 int ret = 1; in litex_clk_pow()
1239 while (exp--) { in litex_clk_pow()
1247 static int litex_clk_calc_clkout_params(struct litex_clk_clkout *lcko, in litex_clk_calc_clkout_params()
1250 int delta_f; in litex_clk_calc_clkout_params()
1251 uint64_t m, clk_freq = 0; in litex_clk_calc_clkout_params()
1254 if (lcko->margin.exp) { in litex_clk_calc_clkout_params()
1255 margin = litex_clk_pow(10, lcko->margin.exp); in litex_clk_calc_clkout_params()
1258 lcko->div.no_cnt = 0; in litex_clk_calc_clkout_params()
1260 for (d = lcko->clkout_div.min; d <= lcko->clkout_div.max; d++) { in litex_clk_calc_clkout_params()
1263 m = lcko->ts_config.freq * lcko->margin.m; in litex_clk_calc_clkout_params()
1265 if (lcko->margin.exp) { in litex_clk_calc_clkout_params()
1269 delta_f = clk_freq - lcko->ts_config.freq; in litex_clk_calc_clkout_params()
1272 lcko->config.freq = (uint32_t)clk_freq; in litex_clk_calc_clkout_params()
1273 if (lcko->config.div != d) { in litex_clk_calc_clkout_params()
1274 ldev->update_clkout[lcko->id] = 1; in litex_clk_calc_clkout_params()
1276 lcko->config.div = d; in litex_clk_calc_clkout_params()
1278 lcko->ts_config.div = d; in litex_clk_calc_clkout_params()
1279 /* we are not using fractional divider */ in litex_clk_calc_clkout_params()
1280 lcko->frac.frac_en = 0; in litex_clk_calc_clkout_params()
1281 lcko->frac.frac = 0; in litex_clk_calc_clkout_params()
1283 lcko->div.no_cnt = 1; in litex_clk_calc_clkout_params()
1286 lcko->id, lcko->config.freq, lcko->config.div, in litex_clk_calc_clkout_params()
1287 ldev->ts_g_config.div, ldev->ts_g_config.mul); in litex_clk_calc_clkout_params()
1296 static int litex_clk_calc_all_clkout_params(uint64_t vco_freq) in litex_clk_calc_all_clkout_params()
1301 for (c = 0; c < ldev->nclkout; c++) { in litex_clk_calc_all_clkout_params()
1302 lcko = &ldev->clkouts[c]; in litex_clk_calc_all_clkout_params()
1311 static int litex_clk_calc_all_params(void) in litex_clk_calc_all_params()
1314 uint64_t vco_freq = 0; in litex_clk_calc_all_params()
1316 for (div = ldev->divclk.min; div <= ldev->divclk.max; div++) { in litex_clk_calc_all_params()
1317 ldev->ts_g_config.div = div; in litex_clk_calc_all_params()
1318 for (mul = ldev->clkfbout.max; mul >= ldev->clkfbout.min; in litex_clk_calc_all_params()
1319 mul--) { in litex_clk_calc_all_params()
1320 int below, above, all_valid = true; in litex_clk_calc_all_params()
1324 below = vco_freq < (ldev->vco.min in litex_clk_calc_all_params()
1325 * (1 + ldev->vco_margin)); in litex_clk_calc_all_params()
1326 above = vco_freq > (ldev->vco.max in litex_clk_calc_all_params()
1327 * (1 - ldev->vco_margin)); in litex_clk_calc_all_params()
1333 ldev->ts_g_config.mul = mul; in litex_clk_calc_all_params()
1334 ldev->ts_g_config.freq = vco_freq; in litex_clk_calc_all_params()
1336 ldev->ts_g_config.freq, in litex_clk_calc_all_params()
1337 ldev->ts_g_config.div, in litex_clk_calc_all_params()
1338 ldev->ts_g_config.mul); in litex_clk_calc_all_params()
1339 return 0; in litex_clk_calc_all_params()
1345 return -ENOTSUP; in litex_clk_calc_all_params()
1348 int litex_clk_check_rate_range(struct litex_clk_clkout *lcko, uint32_t rate) in litex_clk_check_rate_range()
1353 m = rate * lcko->margin.m; in litex_clk_check_rate_range()
1354 if (lcko->margin.exp) { in litex_clk_check_rate_range()
1355 margin = litex_clk_pow(10, lcko->margin.exp); in litex_clk_check_rate_range()
1358 max = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC * (uint64_t)ldev->clkfbout.max; in litex_clk_check_rate_range()
1359 div = ldev->divclk.min * lcko->clkout_div.min; in litex_clk_check_rate_range()
1363 min = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC * ldev->clkfbout.min; in litex_clk_check_rate_range()
1364 div = ldev->divclk.max * lcko->clkout_div.max; in litex_clk_check_rate_range()
1368 min = 0; in litex_clk_check_rate_range()
1370 min -= m; in litex_clk_check_rate_range()
1374 return -EINVAL; in litex_clk_check_rate_range()
1376 return 0; in litex_clk_check_rate_range()
1382 int ret; in litex_clk_round_rate()
1385 if (ret != 0) { in litex_clk_round_rate()
1386 return -EINVAL; in litex_clk_round_rate()
1389 lcko->ts_config.freq = rate; in litex_clk_round_rate()
1392 if (ret != 0) { in litex_clk_round_rate()
1399 int litex_clk_write_rate(struct litex_clk_clkout *lcko) in litex_clk_write_rate()
1401 int ret; in litex_clk_write_rate()
1403 uint8_t *divider = &lcko->config.div, in litex_clk_write_rate() local
1404 *edge = &lcko->div.edge, in litex_clk_write_rate()
1405 *high_time = &lcko->div.high_time, in litex_clk_write_rate()
1406 *low_time = &lcko->div.low_time, in litex_clk_write_rate()
1407 *no_cnt = &lcko->div.no_cnt, in litex_clk_write_rate()
1408 *frac = &lcko->frac.frac, in litex_clk_write_rate()
1409 *frac_en = &lcko->frac.frac_en, in litex_clk_write_rate()
1410 *frac_wf_r = &lcko->frac.frac_wf_r; in litex_clk_write_rate()
1421 LOG_DBG("SET RATE: div:%u f:%u fwfr:%u fen:%u nc:%u e:%u ht:%u lt:%u\nbitset1: 0x%x bitset2: 0x%x", in litex_clk_write_rate()
1422 *divider, *frac, *frac_wf_r, *frac_en, in litex_clk_write_rate()
1425 ret = litex_clk_set_clock(lcko->id, REG1_FREQ_MASK, bitset1, in litex_clk_write_rate()
1427 if (ret != 0) { in litex_clk_write_rate()
1431 ldev->update_clkout[lcko->id] = 0; in litex_clk_write_rate()
1433 return 0; in litex_clk_write_rate()
1436 int litex_clk_update_clkouts(void) in litex_clk_update_clkouts()
1439 int ret; in litex_clk_update_clkouts()
1442 for (c = 0; c < ldev->nclkout; c++) { in litex_clk_update_clkouts()
1443 if (ldev->update_clkout[c]) { in litex_clk_update_clkouts()
1444 lcko = &ldev->clkouts[c]; in litex_clk_update_clkouts()
1446 if (ret != 0) { in litex_clk_update_clkouts()
1450 if (ret != 0) { in litex_clk_update_clkouts()
1454 lcko->id, lcko->ts_config.freq, in litex_clk_update_clkouts()
1455 lcko->config.freq); in litex_clk_update_clkouts()
1459 return 0; in litex_clk_update_clkouts()
1462 int litex_clk_set_rate(struct litex_clk_clkout *lcko, unsigned long rate) in litex_clk_set_rate()
1464 int ret; in litex_clk_set_rate()
1466 LOG_DBG("CLKOUT%d: setting rate: %lu", lcko->id, rate); in litex_clk_set_rate()
1468 if (ret < 0) { in litex_clk_set_rate()
1472 if (ret != 0) { in litex_clk_set_rate()
1476 if (ret != 0) { in litex_clk_set_rate()
1480 if (ret != 0) { in litex_clk_set_rate()
1483 LOG_INF("CLKOUT%d: set rate: %u HZ", lcko->id, lcko->config.freq); in litex_clk_set_rate()
1485 if (ret != 0) { in litex_clk_set_rate()
1494 return 0; in litex_clk_set_rate()
1498 static int litex_clk_set_def_clkout(int clkout_nr) in litex_clk_set_def_clkout()
1500 struct litex_clk_clkout *lcko = &ldev->clkouts[clkout_nr]; in litex_clk_set_def_clkout()
1501 int ret; in litex_clk_set_def_clkout()
1503 ret = litex_clk_set_rate(lcko, lcko->def.freq); in litex_clk_set_def_clkout()
1504 if (ret != 0) { in litex_clk_set_def_clkout()
1507 ret = litex_clk_set_duty_cycle(lcko, &lcko->def.duty); in litex_clk_set_def_clkout()
1508 if (ret != 0) { in litex_clk_set_def_clkout()
1511 return litex_clk_set_phase(lcko, lcko->def.phase); in litex_clk_set_def_clkout()
1514 static int litex_clk_set_all_def_clkouts(void) in litex_clk_set_all_def_clkouts()
1516 int c, ret; in litex_clk_set_all_def_clkouts()
1518 for (c = 0; c < ldev->nclkout; c++) { in litex_clk_set_all_def_clkouts()
1520 if (ret != 0) { in litex_clk_set_all_def_clkouts()
1524 return 0; in litex_clk_set_all_def_clkouts()
1535 static int litex_clk_get_subsys_rate(const struct device *clock, in litex_clk_get_subsys_rate()
1541 lcko = &ldev->clkouts[setup->clkout_nr]; in litex_clk_get_subsys_rate()
1544 return 0; in litex_clk_get_subsys_rate()
1553 int ret; in litex_clk_get_status()
1555 lcko = &ldev->clkouts[setup->clkout_nr]; in litex_clk_get_status()
1557 setup->rate = litex_clk_calc_rate(lcko); in litex_clk_get_status()
1559 if (ret != 0) { in litex_clk_get_status()
1562 setup->duty = litex_clk_calc_duty_percent(&duty); in litex_clk_get_status()
1563 setup->phase = litex_clk_get_phase(lcko); in litex_clk_get_status()
1568 static inline int litex_clk_on(const struct device *dev, clock_control_subsys_t sys) in litex_clk_on()
1574 int ret; in litex_clk_on()
1576 lcko = &ldev->clkouts[setup->clkout_nr]; in litex_clk_on()
1578 if (lcko->config.freq != setup->rate) { in litex_clk_on()
1579 ret = litex_clk_set_rate(lcko, setup->rate); in litex_clk_on()
1580 if (ret != 0) { in litex_clk_on()
1584 if (lcko->config.phase != setup->phase) { in litex_clk_on()
1585 ret = litex_clk_set_phase(lcko, setup->phase); in litex_clk_on()
1586 if (ret != 0) { in litex_clk_on()
1590 duty_perc = litex_clk_calc_duty_percent(&lcko->config.duty); in litex_clk_on()
1591 if (duty_perc != setup->duty) { in litex_clk_on()
1592 duty.num = setup->duty; in litex_clk_on()
1595 if (ret != 0) { in litex_clk_on()
1599 return 0; in litex_clk_on()
1602 static inline int litex_clk_off(const struct device *dev, in litex_clk_off()
1617 clkout_div->min = CLKOUT_DIVIDE_MIN; in litex_clk_dts_clkout_ranges_read()
1618 clkout_div->max = CLKOUT_DIVIDE_MAX; in litex_clk_dts_clkout_ranges_read()
1621 static int litex_clk_dts_timeout_read(struct litex_clk_timeout *timeout) in litex_clk_dts_timeout_read()
1624 timeout->lock = LOCK_TIMEOUT; in litex_clk_dts_timeout_read()
1625 if (timeout->lock < 1) { in litex_clk_dts_timeout_read()
1627 return -EINVAL; in litex_clk_dts_timeout_read()
1631 timeout->drdy = DRDY_TIMEOUT; in litex_clk_dts_timeout_read()
1632 if (timeout->drdy < 1) { in litex_clk_dts_timeout_read()
1634 return -EINVAL; in litex_clk_dts_timeout_read()
1637 return 0; in litex_clk_dts_timeout_read()
1640 static int litex_clk_dts_clkouts_read(void) in litex_clk_dts_clkouts_read()
1647 #if CLKOUT_EXIST(0) == 1 in litex_clk_dts_clkouts_read()
1648 CLKOUT_INIT(0) in litex_clk_dts_clkouts_read()
1668 return 0; in litex_clk_dts_clkouts_read()
1674 int i; in litex_clk_init_clkouts()
1676 for (i = 0; i < ldev->nclkout; i++) { in litex_clk_init_clkouts()
1677 lcko = &ldev->clkouts[i]; in litex_clk_init_clkouts()
1678 lcko->base = ldev->base; in litex_clk_init_clkouts()
1680 lcko->ts_config.freq = lcko->def.freq; in litex_clk_init_clkouts()
1681 lcko->ts_config.duty = lcko->def.duty; in litex_clk_init_clkouts()
1682 lcko->ts_config.phase = lcko->def.phase; in litex_clk_init_clkouts()
1686 static int litex_clk_dts_cnt_clocks(void) in litex_clk_dts_cnt_clocks()
1693 ldev->divclk.min = DIVCLK_DIVIDE_MIN; in litex_clk_dts_global_ranges_read()
1694 ldev->divclk.max = DIVCLK_DIVIDE_MAX; in litex_clk_dts_global_ranges_read()
1695 ldev->clkfbout.min = CLKFBOUT_MULT_MIN; in litex_clk_dts_global_ranges_read()
1696 ldev->clkfbout.max = CLKFBOUT_MULT_MAX; in litex_clk_dts_global_ranges_read()
1697 ldev->vco.min = VCO_FREQ_MIN; in litex_clk_dts_global_ranges_read()
1698 ldev->vco.max = VCO_FREQ_MAX; in litex_clk_dts_global_ranges_read()
1699 ldev->vco_margin = VCO_MARGIN; in litex_clk_dts_global_ranges_read()
1702 static int litex_clk_dts_global_read(void) in litex_clk_dts_global_read()
1704 int ret; in litex_clk_dts_global_read()
1706 ldev->nclkout = litex_clk_dts_cnt_clocks(); in litex_clk_dts_global_read()
1708 clkouts = k_malloc(sizeof(struct litex_clk_clkout) * ldev->nclkout); in litex_clk_dts_global_read()
1709 ldev->update_clkout = k_malloc(sizeof(uint8_t) * ldev->nclkout); in litex_clk_dts_global_read()
1710 if (!clkouts || !ldev->update_clkout) { in litex_clk_dts_global_read()
1712 return -ENOMEM; in litex_clk_dts_global_read()
1714 ldev->clkouts = clkouts; in litex_clk_dts_global_read()
1716 ret = litex_clk_dts_timeout_read(&ldev->timeout); in litex_clk_dts_global_read()
1717 if (ret != 0) { in litex_clk_dts_global_read()
1723 return 0; in litex_clk_dts_global_read()
1726 static int litex_clk_init_glob_clk(void) in litex_clk_init_glob_clk()
1728 int ret; in litex_clk_init_glob_clk()
1732 if (ret != 0) { in litex_clk_init_glob_clk()
1737 return 0; in litex_clk_init_glob_clk()
1739 /* Enable module, set global divider, multiplier, default clkout parameters */
1740 static int litex_clk_init(const struct device *dev) in litex_clk_init()
1742 int ret; in litex_clk_init()
1746 return -ENOMEM; in litex_clk_init()
1749 ldev->base = (uint32_t *)DRP_BASE; in litex_clk_init()
1750 if (ldev->base == NULL) { in litex_clk_init()
1751 return -EIO; in litex_clk_init()
1755 if (ret != 0) { in litex_clk_init()
1760 if (ret != 0) { in litex_clk_init()
1767 if (ret != 0) { in litex_clk_init()
1772 if (ret != 0) { in litex_clk_init()
1782 return 0; in litex_clk_init()