Lines Matching +full:divider +full:- +full:val
4 * SPDX-License-Identifier: Apache-2.0
66 …* https://github.com/Digilent/Zybo-hdmi-out/blob/b991fff6e964420ae3c00c3dbee52f2ad748b3ba/sdk/disp…
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()
222 static inline void litex_clk_set_reg(uint32_t reg, uint32_t val) in litex_clk_set_reg() argument
224 litex_write(drp[reg].addr, drp[reg].size, val); in litex_clk_set_reg()
234 int assert = (1 << (drp[reg].size * BITS_PER_BYTE)) - 1; in litex_clk_assert_reg()
251 timeout = ldev->timeout.lock; in litex_clk_wait()
253 timeout = ldev->timeout.drdy; in litex_clk_wait()
257 timeout--; in litex_clk_wait()
262 return -ETIME; in litex_clk_wait()
286 /* Get global divider and multiplier values and update global config */
303 ldev->g_config.mul = 1; 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()
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()
355 uint32_t *divider, uint32_t *fract_cnt) in litex_clk_get_clkout_divider() argument
360 uint8_t clkout_nr = lcko->id; in litex_clk_get_clkout_divider()
374 *divider = low_time + high_time; in litex_clk_get_clkout_divider()
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()
578 /* Set global divider for all CLKOUTs */
583 div = ldev->ts_g_config.div; 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()
618 mul = ldev->ts_g_config.mul; in litex_clk_set_mulreg()
651 ldev->g_config.mul = mul; in litex_clk_set_mulreg()
663 mul = ldev->g_config.mul; in litex_clk_set_filt()
694 mul = ldev->g_config.mul; in litex_clk_set_lock()
721 /* Set all multiplier-related regs: mul, filt and lock regs */
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()
772 /* mul-first safe */ in litex_clk_set_both_globs()
783 /* div-first safe */ in litex_clk_set_both_globs()
796 /* Set global divider, multiplier, filt and lock values */
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()
813 /* set divider only */ in litex_clk_set_globs()
825 ldev->g_config.freq = ldev->ts_g_config.freq; in litex_clk_set_globs()
831 static inline uint32_t litex_round(uint32_t val, uint32_t mod) in litex_round() argument
833 if (val % mod > mod / 2) { in litex_round()
834 return val / mod + 1; in litex_round()
836 return val / mod; in litex_round()
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()
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()
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()
893 ht = duty->num; in litex_clk_calc_duty_percent()
894 div = duty->den; in litex_clk_calc_duty_percent()
908 divider = lcko->config.div; in litex_clk_calc_duty_normal() local
912 duty = lcko->ts_config.duty; 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()
932 for (high_time_it = 1; high_time_it < divider; high_time_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()
961 /* Calculates duty high_time for given divider and ratio */
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()
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()
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()
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()
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()
1044 return -EINVAL; in litex_clk_calc_phase_normal()
1049 /* Delay_time: (0-63) */ in litex_clk_calc_phase_normal()
1051 /* phase_mux: (0-7) */ 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()
1083 int *phase = &lcko->ts_config.phase; in litex_clk_prepare_phase()
1091 lcko->ts_config.period_off = ((*phase * 10000) / 360); in litex_clk_prepare_phase()
1104 /* Returns phase-specific values of given clock output */
1111 uint8_t clkout_nr = lcko->id; in litex_clk_get_phase_data()
1132 uint32_t divider = 0, fract_cnt, post_glob_div_f, in litex_clk_get_phase() local
1138 err = litex_clk_get_clkout_divider(lcko, ÷r, &fract_cnt); in litex_clk_get_phase()
1148 clkout_period = global_period * divider; in litex_clk_get_phase()
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()
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()
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()
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()
1239 while (exp--) { in litex_clk_pow()
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()
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()
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()
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()
1345 return -ENOTSUP; in litex_clk_calc_all_params()
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()
1370 min -= m; in litex_clk_check_rate_range()
1374 return -EINVAL; in litex_clk_check_rate_range()
1386 return -EINVAL; in litex_clk_round_rate()
1389 lcko->ts_config.freq = rate; in litex_clk_round_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()
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()
1431 ldev->update_clkout[lcko->id] = 0; in litex_clk_write_rate()
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()
1454 lcko->id, lcko->ts_config.freq, in litex_clk_update_clkouts()
1455 lcko->config.freq); in litex_clk_update_clkouts()
1466 LOG_DBG("CLKOUT%d: setting rate: %lu", lcko->id, rate); in litex_clk_set_rate()
1483 LOG_INF("CLKOUT%d: set rate: %u HZ", lcko->id, lcko->config.freq); in litex_clk_set_rate()
1500 struct litex_clk_clkout *lcko = &ldev->clkouts[clkout_nr]; in litex_clk_set_def_clkout()
1503 ret = litex_clk_set_rate(lcko, lcko->def.freq); in litex_clk_set_def_clkout()
1507 ret = litex_clk_set_duty_cycle(lcko, &lcko->def.duty); in litex_clk_set_def_clkout()
1511 return litex_clk_set_phase(lcko, lcko->def.phase); in litex_clk_set_def_clkout()
1518 for (c = 0; c < ldev->nclkout; c++) { in litex_clk_set_all_def_clkouts()
1541 lcko = &ldev->clkouts[setup->clkout_nr]; in litex_clk_get_subsys_rate()
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()
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()
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()
1584 if (lcko->config.phase != setup->phase) { in litex_clk_on()
1585 ret = litex_clk_set_phase(lcko, setup->phase); 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()
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()
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()
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()
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()
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()
1739 /* Enable module, set global divider, multiplier, default clkout parameters */
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()