Lines Matching +full:pll +full:- +full:out
1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/media/i2c/ccs-pll.c
5 * Generic MIPI CCS/SMIA/SMIA++ PLL calculator
8 * Copyright (C) 2011--2012 Nokia Corporation
17 #include "ccs-pll.h"
55 dev_dbg(dev, "%s_%s out of bounds: %d (%d--%d)\n", prefix, in bounds_check()
58 return -EINVAL; in bounds_check()
78 static void print_pll(struct device *dev, struct ccs_pll *pll) in print_pll() argument
85 { &pll->vt_fr, &pll->vt_bk, PLL_VT }, in print_pll()
86 { &pll->op_fr, &pll->op_bk, PLL_OP } in print_pll()
90 dev_dbg(dev, "ext_clk_freq_hz\t\t%u\n", pll->ext_clk_freq_hz); in print_pll()
93 const char *s = pll_string(br->which); in print_pll()
95 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL || in print_pll()
96 br->which == PLL_VT) { in print_pll()
98 br->fr->pre_pll_clk_div); in print_pll()
100 br->fr->pll_multiplier); in print_pll()
103 br->fr->pll_ip_clk_freq_hz); in print_pll()
105 br->fr->pll_op_clk_freq_hz); in print_pll()
108 if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) || in print_pll()
109 br->which == PLL_VT) { in print_pll()
111 br->bk->sys_clk_div); in print_pll()
113 br->bk->pix_clk_div); in print_pll()
116 br->bk->sys_clk_freq_hz); in print_pll()
118 br->bk->pix_clk_freq_hz); in print_pll()
123 pll->pixel_rate_pixel_array); in print_pll()
124 dev_dbg(dev, "pixel rate on CSI-2 bus:\t%u\n", in print_pll()
125 pll->pixel_rate_csi); in print_pll()
128 pll->flags & PLL_FL(LANE_SPEED_MODEL) ? " lane-speed" : "", in print_pll()
129 pll->flags & PLL_FL(LINK_DECOUPLED) ? " link-decoupled" : "", in print_pll()
130 pll->flags & PLL_FL(EXT_IP_PLL_DIVIDER) ? in print_pll()
131 " ext-ip-pll-divider" : "", in print_pll()
132 pll->flags & PLL_FL(FLEXIBLE_OP_PIX_CLK_DIV) ? in print_pll()
133 " flexible-op-pix-div" : "", in print_pll()
134 pll->flags & PLL_FL(FIFO_DERATING) ? " fifo-derating" : "", in print_pll()
135 pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : "", in print_pll()
136 pll->flags & PLL_FL(DUAL_PLL) ? " dual-pll" : "", in print_pll()
137 pll->flags & PLL_FL(OP_SYS_DDR) ? " op-sys-ddr" : "", in print_pll()
138 pll->flags & PLL_FL(OP_PIX_DDR) ? " op-pix-ddr" : ""); in print_pll()
153 struct ccs_pll *pll, unsigned int which) in check_fr_bounds() argument
161 lim_fr = &lim->op_fr; in check_fr_bounds()
162 pll_fr = &pll->op_fr; in check_fr_bounds()
164 lim_fr = &lim->vt_fr; in check_fr_bounds()
165 pll_fr = &pll->vt_fr; in check_fr_bounds()
168 rval = bounds_check(dev, pll_fr->pre_pll_clk_div, in check_fr_bounds()
169 lim_fr->min_pre_pll_clk_div, in check_fr_bounds()
170 lim_fr->max_pre_pll_clk_div, s, "pre_pll_clk_div"); in check_fr_bounds()
173 rval = bounds_check(dev, pll_fr->pll_ip_clk_freq_hz, in check_fr_bounds()
174 lim_fr->min_pll_ip_clk_freq_hz, in check_fr_bounds()
175 lim_fr->max_pll_ip_clk_freq_hz, in check_fr_bounds()
178 rval = bounds_check(dev, pll_fr->pll_multiplier, in check_fr_bounds()
179 lim_fr->min_pll_multiplier, in check_fr_bounds()
180 lim_fr->max_pll_multiplier, in check_fr_bounds()
183 rval = bounds_check(dev, pll_fr->pll_op_clk_freq_hz, in check_fr_bounds()
184 lim_fr->min_pll_op_clk_freq_hz, in check_fr_bounds()
185 lim_fr->max_pll_op_clk_freq_hz, in check_fr_bounds()
193 struct ccs_pll *pll, unsigned int which) in check_bk_bounds() argument
201 if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) in check_bk_bounds()
204 lim_bk = &lim->op_bk; in check_bk_bounds()
205 pll_bk = &pll->op_bk; in check_bk_bounds()
207 lim_bk = &lim->vt_bk; in check_bk_bounds()
208 pll_bk = &pll->vt_bk; in check_bk_bounds()
211 rval = bounds_check(dev, pll_bk->sys_clk_div, in check_bk_bounds()
212 lim_bk->min_sys_clk_div, in check_bk_bounds()
213 lim_bk->max_sys_clk_div, s, "op_sys_clk_div"); in check_bk_bounds()
215 rval = bounds_check(dev, pll_bk->sys_clk_freq_hz, in check_bk_bounds()
216 lim_bk->min_sys_clk_freq_hz, in check_bk_bounds()
217 lim_bk->max_sys_clk_freq_hz, in check_bk_bounds()
220 rval = bounds_check(dev, pll_bk->sys_clk_div, in check_bk_bounds()
221 lim_bk->min_sys_clk_div, in check_bk_bounds()
222 lim_bk->max_sys_clk_div, in check_bk_bounds()
225 rval = bounds_check(dev, pll_bk->pix_clk_freq_hz, in check_bk_bounds()
226 lim_bk->min_pix_clk_freq_hz, in check_bk_bounds()
227 lim_bk->max_pix_clk_freq_hz, in check_bk_bounds()
233 static int check_ext_bounds(struct device *dev, struct ccs_pll *pll) in check_ext_bounds() argument
235 if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING) && in check_ext_bounds()
236 pll->pixel_rate_pixel_array > pll->pixel_rate_csi) { in check_ext_bounds()
238 return -EINVAL; in check_ext_bounds()
241 if (!(pll->flags & CCS_PLL_FLAG_FIFO_OVERRATING) && in check_ext_bounds()
242 pll->pixel_rate_pixel_array < pll->pixel_rate_csi) { in check_ext_bounds()
244 return -EINVAL; in check_ext_bounds()
252 struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr, in ccs_pll_find_vt_sys_div() argument
260 *min_sys_div = lim->vt_bk.min_sys_clk_div; in ccs_pll_find_vt_sys_div()
264 lim->vt_bk.max_pix_clk_div)); in ccs_pll_find_vt_sys_div()
267 pll_fr->pll_op_clk_freq_hz in ccs_pll_find_vt_sys_div()
268 / lim->vt_bk.max_sys_clk_freq_hz); in ccs_pll_find_vt_sys_div()
273 *max_sys_div = lim->vt_bk.max_sys_clk_div; in ccs_pll_find_vt_sys_div()
277 lim->vt_bk.min_pix_clk_div)); in ccs_pll_find_vt_sys_div()
280 DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, in ccs_pll_find_vt_sys_div()
281 lim->vt_bk.min_pix_clk_freq_hz)); in ccs_pll_find_vt_sys_div()
292 struct ccs_pll *pll, u32 mul, u32 div) in __ccs_pll_calculate_vt_tree() argument
294 const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr; in __ccs_pll_calculate_vt_tree()
295 const struct ccs_pll_branch_limits_bk *lim_bk = &lim->vt_bk; in __ccs_pll_calculate_vt_tree()
296 struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; in __ccs_pll_calculate_vt_tree()
297 struct ccs_pll_branch_bk *pll_bk = &pll->vt_bk; in __ccs_pll_calculate_vt_tree()
299 u16 best_pix_div = SHRT_MAX >> 1, best_div = lim_bk->max_sys_clk_div; in __ccs_pll_calculate_vt_tree()
302 pll_fr->pll_ip_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
303 pll->ext_clk_freq_hz / pll_fr->pre_pll_clk_div; in __ccs_pll_calculate_vt_tree()
305 dev_dbg(dev, "vt_pll_ip_clk_freq_hz %u\n", pll_fr->pll_ip_clk_freq_hz); in __ccs_pll_calculate_vt_tree()
307 more_mul = one_or_more(DIV_ROUND_UP(lim_fr->min_pll_op_clk_freq_hz, in __ccs_pll_calculate_vt_tree()
308 pll_fr->pll_ip_clk_freq_hz * mul)); in __ccs_pll_calculate_vt_tree()
311 more_mul *= DIV_ROUND_UP(lim_fr->min_pll_multiplier, mul * more_mul); in __ccs_pll_calculate_vt_tree()
314 pll_fr->pll_multiplier = mul * more_mul; in __ccs_pll_calculate_vt_tree()
316 if (pll_fr->pll_multiplier * pll_fr->pll_ip_clk_freq_hz > in __ccs_pll_calculate_vt_tree()
317 lim_fr->max_pll_op_clk_freq_hz) in __ccs_pll_calculate_vt_tree()
318 return -EINVAL; in __ccs_pll_calculate_vt_tree()
320 pll_fr->pll_op_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
321 pll_fr->pll_ip_clk_freq_hz * pll_fr->pll_multiplier; in __ccs_pll_calculate_vt_tree()
325 ccs_pll_find_vt_sys_div(dev, lim, pll, pll_fr, vt_div, vt_div, in __ccs_pll_calculate_vt_tree()
333 sys_div += 2 - (sys_div & 1)) { in __ccs_pll_calculate_vt_tree()
341 if (pix_div < lim_bk->min_pix_clk_div || in __ccs_pll_calculate_vt_tree()
342 pix_div > lim_bk->max_pix_clk_div) { in __ccs_pll_calculate_vt_tree()
344 "pix_div %u too small or too big (%u--%u)\n", in __ccs_pll_calculate_vt_tree()
346 lim_bk->min_pix_clk_div, in __ccs_pll_calculate_vt_tree()
347 lim_bk->max_pix_clk_div); in __ccs_pll_calculate_vt_tree()
360 return -EINVAL; in __ccs_pll_calculate_vt_tree()
362 pll_bk->sys_clk_div = best_div / best_pix_div; in __ccs_pll_calculate_vt_tree()
363 pll_bk->pix_clk_div = best_pix_div; in __ccs_pll_calculate_vt_tree()
365 pll_bk->sys_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
366 pll_fr->pll_op_clk_freq_hz / pll_bk->sys_clk_div; in __ccs_pll_calculate_vt_tree()
367 pll_bk->pix_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
368 pll_bk->sys_clk_freq_hz / pll_bk->pix_clk_div; in __ccs_pll_calculate_vt_tree()
370 pll->pixel_rate_pixel_array = in __ccs_pll_calculate_vt_tree()
371 pll_bk->pix_clk_freq_hz * pll->vt_lanes; in __ccs_pll_calculate_vt_tree()
378 struct ccs_pll *pll) in ccs_pll_calculate_vt_tree() argument
380 const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr; in ccs_pll_calculate_vt_tree()
381 struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; in ccs_pll_calculate_vt_tree()
382 u16 min_pre_pll_clk_div = lim_fr->min_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
383 u16 max_pre_pll_clk_div = lim_fr->max_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
386 pre_div = gcd(pll->pixel_rate_csi, in ccs_pll_calculate_vt_tree()
387 pll->ext_clk_freq_hz * pll->vt_lanes); in ccs_pll_calculate_vt_tree()
388 pre_mul = pll->pixel_rate_csi / pre_div; in ccs_pll_calculate_vt_tree()
389 pre_div = pll->ext_clk_freq_hz * pll->vt_lanes / pre_div; in ccs_pll_calculate_vt_tree()
391 /* Make sure PLL input frequency is within limits */ in ccs_pll_calculate_vt_tree()
394 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate_vt_tree()
395 lim_fr->min_pll_ip_clk_freq_hz)); in ccs_pll_calculate_vt_tree()
398 pll->ext_clk_freq_hz / in ccs_pll_calculate_vt_tree()
399 lim_fr->max_pll_ip_clk_freq_hz); in ccs_pll_calculate_vt_tree()
404 for (pll_fr->pre_pll_clk_div = min_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
405 pll_fr->pre_pll_clk_div <= max_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
406 pll_fr->pre_pll_clk_div += in ccs_pll_calculate_vt_tree()
407 (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : in ccs_pll_calculate_vt_tree()
408 2 - (pll_fr->pre_pll_clk_div & 1)) { in ccs_pll_calculate_vt_tree()
412 div = gcd(pre_mul * pll_fr->pre_pll_clk_div, pre_div); in ccs_pll_calculate_vt_tree()
413 mul = pre_mul * pll_fr->pre_pll_clk_div / div; in ccs_pll_calculate_vt_tree()
416 dev_dbg(dev, "vt pre-div/mul/div: %u,%u,%u\n", in ccs_pll_calculate_vt_tree()
417 pll_fr->pre_pll_clk_div, mul, div); in ccs_pll_calculate_vt_tree()
419 rval = __ccs_pll_calculate_vt_tree(dev, lim, pll, in ccs_pll_calculate_vt_tree()
424 rval = check_fr_bounds(dev, lim, pll, PLL_VT); in ccs_pll_calculate_vt_tree()
428 rval = check_bk_bounds(dev, lim, pll, PLL_VT); in ccs_pll_calculate_vt_tree()
435 return -EINVAL; in ccs_pll_calculate_vt_tree()
441 struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr, in ccs_pll_calculate_vt() argument
451 if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) in ccs_pll_calculate_vt()
455 * Find out whether a sensor supports derating. If it does not, VT and in ccs_pll_calculate_vt()
458 if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING)) { in ccs_pll_calculate_vt()
460 op_pll_bk->sys_clk_div * op_pll_bk->pix_clk_div in ccs_pll_calculate_vt()
461 * pll->vt_lanes * phy_const / pll->op_lanes in ccs_pll_calculate_vt()
462 / (PHY_CONST_DIV << op_pix_ddr(pll->flags)); in ccs_pll_calculate_vt()
467 * found out using this formula. The ones doing this digitally in ccs_pll_calculate_vt()
471 if (lim->min_line_length_pck_bin > lim->min_line_length_pck in ccs_pll_calculate_vt()
472 / pll->binning_horizontal) in ccs_pll_calculate_vt()
473 vt_op_binning_div = pll->binning_horizontal; in ccs_pll_calculate_vt()
483 * enough to accommodate the CSI-2 sync codes. in ccs_pll_calculate_vt()
489 dev_dbg(dev, "scale_m: %u\n", pll->scale_m); in ccs_pll_calculate_vt()
491 DIV_ROUND_UP(pll->bits_per_pixel in ccs_pll_calculate_vt()
492 * op_pll_bk->sys_clk_div * pll->scale_n in ccs_pll_calculate_vt()
493 * pll->vt_lanes * phy_const, in ccs_pll_calculate_vt()
494 (pll->flags & in ccs_pll_calculate_vt()
496 pll->csi2.lanes : 1) in ccs_pll_calculate_vt()
497 * vt_op_binning_div * pll->scale_m in ccs_pll_calculate_vt()
498 * PHY_CONST_DIV << op_pix_ddr(pll->flags)); in ccs_pll_calculate_vt()
504 DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, in ccs_pll_calculate_vt()
505 lim->vt_bk.max_pix_clk_freq_hz)); in ccs_pll_calculate_vt()
508 min_vt_div = max_t(u16, min_vt_div, lim->vt_bk.min_pix_clk_div in ccs_pll_calculate_vt()
509 * lim->vt_bk.min_sys_clk_div); in ccs_pll_calculate_vt()
512 max_vt_div = lim->vt_bk.max_sys_clk_div * lim->vt_bk.max_pix_clk_div; in ccs_pll_calculate_vt()
515 DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, in ccs_pll_calculate_vt()
516 lim->vt_bk.min_pix_clk_freq_hz)); in ccs_pll_calculate_vt()
520 ccs_pll_find_vt_sys_div(dev, lim, pll, pll_fr, min_vt_div, in ccs_pll_calculate_vt()
532 sys_div += 2 - (sys_div & 1)) { in ccs_pll_calculate_vt()
538 if (pix_div < lim->vt_bk.min_pix_clk_div in ccs_pll_calculate_vt()
539 || pix_div > lim->vt_bk.max_pix_clk_div) { in ccs_pll_calculate_vt()
541 "pix_div %u too small or too big (%u--%u)\n", in ccs_pll_calculate_vt()
543 lim->vt_bk.min_pix_clk_div, in ccs_pll_calculate_vt()
544 lim->vt_bk.max_pix_clk_div); in ccs_pll_calculate_vt()
554 /* Bail out if we've already found the best value. */ in ccs_pll_calculate_vt()
562 pll->vt_bk.sys_clk_div = DIV_ROUND_UP(vt_div, best_pix_div); in ccs_pll_calculate_vt()
563 pll->vt_bk.pix_clk_div = best_pix_div; in ccs_pll_calculate_vt()
565 pll->vt_bk.sys_clk_freq_hz = in ccs_pll_calculate_vt()
566 pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; in ccs_pll_calculate_vt()
567 pll->vt_bk.pix_clk_freq_hz = in ccs_pll_calculate_vt()
568 pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div; in ccs_pll_calculate_vt()
571 pll->pixel_rate_pixel_array = in ccs_pll_calculate_vt()
572 pll->vt_bk.pix_clk_freq_hz * pll->vt_lanes; in ccs_pll_calculate_vt()
576 * Heuristically guess the PLL tree for a given common multiplier and
580 * @mul is the PLL multiplier and @div is the common divisor
581 * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
590 struct ccs_pll *pll, struct ccs_pll_branch_fr *op_pll_fr, in ccs_pll_calculate_op() argument
609 dev_dbg(dev, "op_pre_pll_clk_div %u\n", op_pll_fr->pre_pll_clk_div); in ccs_pll_calculate_op()
611 /* Don't go above max pll multiplier. */ in ccs_pll_calculate_op()
612 more_mul_max = op_lim_fr->max_pll_multiplier / mul; in ccs_pll_calculate_op()
615 /* Don't go above max pll op frequency. */ in ccs_pll_calculate_op()
619 op_lim_fr->max_pll_op_clk_freq_hz in ccs_pll_calculate_op()
620 / (pll->ext_clk_freq_hz / in ccs_pll_calculate_op()
621 op_pll_fr->pre_pll_clk_div * mul)); in ccs_pll_calculate_op()
626 op_lim_bk->max_sys_clk_div * op_pll_fr->pre_pll_clk_div in ccs_pll_calculate_op()
631 more_mul_max = min(more_mul_max, op_lim_fr->max_pll_multiplier / mul); in ccs_pll_calculate_op()
636 more_mul_min = DIV_ROUND_UP(op_lim_fr->min_pll_op_clk_freq_hz, in ccs_pll_calculate_op()
637 pll->ext_clk_freq_hz / in ccs_pll_calculate_op()
638 op_pll_fr->pre_pll_clk_div * mul); in ccs_pll_calculate_op()
643 DIV_ROUND_UP(op_lim_fr->min_pll_multiplier, mul)); in ccs_pll_calculate_op()
650 return -EINVAL; in ccs_pll_calculate_op()
653 more_mul_factor = lcm(div, op_pll_fr->pre_pll_clk_div) / div; in ccs_pll_calculate_op()
655 more_mul_factor = lcm(more_mul_factor, op_lim_bk->min_sys_clk_div); in ccs_pll_calculate_op()
665 return -EINVAL; in ccs_pll_calculate_op()
668 op_pll_fr->pll_multiplier = mul * i; in ccs_pll_calculate_op()
669 op_pll_bk->sys_clk_div = div * i / op_pll_fr->pre_pll_clk_div; in ccs_pll_calculate_op()
670 dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll_bk->sys_clk_div); in ccs_pll_calculate_op()
672 op_pll_fr->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz in ccs_pll_calculate_op()
673 / op_pll_fr->pre_pll_clk_div; in ccs_pll_calculate_op()
675 op_pll_fr->pll_op_clk_freq_hz = op_pll_fr->pll_ip_clk_freq_hz in ccs_pll_calculate_op()
676 * op_pll_fr->pll_multiplier; in ccs_pll_calculate_op()
678 if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) in ccs_pll_calculate_op()
679 op_pll_bk->pix_clk_div = in ccs_pll_calculate_op()
680 (pll->bits_per_pixel in ccs_pll_calculate_op()
681 * pll->op_lanes * (phy_const << op_sys_ddr(pll->flags)) in ccs_pll_calculate_op()
682 / PHY_CONST_DIV / pll->csi2.lanes / l) in ccs_pll_calculate_op()
683 >> op_pix_ddr(pll->flags); in ccs_pll_calculate_op()
685 op_pll_bk->pix_clk_div = in ccs_pll_calculate_op()
686 (pll->bits_per_pixel in ccs_pll_calculate_op()
687 * (phy_const << op_sys_ddr(pll->flags)) in ccs_pll_calculate_op()
688 / PHY_CONST_DIV / l) >> op_pix_ddr(pll->flags); in ccs_pll_calculate_op()
690 op_pll_bk->pix_clk_freq_hz = in ccs_pll_calculate_op()
691 (op_sys_clk_freq_hz_sdr >> op_pix_ddr(pll->flags)) in ccs_pll_calculate_op()
692 / op_pll_bk->pix_clk_div; in ccs_pll_calculate_op()
693 op_pll_bk->sys_clk_freq_hz = in ccs_pll_calculate_op()
694 op_sys_clk_freq_hz_sdr >> op_sys_ddr(pll->flags); in ccs_pll_calculate_op()
696 dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll_bk->pix_clk_div); in ccs_pll_calculate_op()
702 struct ccs_pll *pll) in ccs_pll_calculate() argument
708 bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY; in ccs_pll_calculate()
714 u32 l = (!pll->op_bits_per_lane || in ccs_pll_calculate()
715 pll->op_bits_per_lane >= pll->bits_per_pixel) ? 1 : 2; in ccs_pll_calculate()
717 int rval = -EINVAL; in ccs_pll_calculate()
719 if (!(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL)) { in ccs_pll_calculate()
720 pll->op_lanes = 1; in ccs_pll_calculate()
721 pll->vt_lanes = 1; in ccs_pll_calculate()
724 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { in ccs_pll_calculate()
725 op_lim_fr = &lim->op_fr; in ccs_pll_calculate()
726 op_lim_bk = &lim->op_bk; in ccs_pll_calculate()
727 op_pll_fr = &pll->op_fr; in ccs_pll_calculate()
728 op_pll_bk = &pll->op_bk; in ccs_pll_calculate()
729 } else if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { in ccs_pll_calculate()
731 * If there's no OP PLL at all, use the VT values in ccs_pll_calculate()
733 * the PLL calculation. in ccs_pll_calculate()
735 op_lim_fr = &lim->vt_fr; in ccs_pll_calculate()
736 op_lim_bk = &lim->vt_bk; in ccs_pll_calculate()
737 op_pll_fr = &pll->vt_fr; in ccs_pll_calculate()
738 op_pll_bk = &pll->vt_bk; in ccs_pll_calculate()
740 op_lim_fr = &lim->vt_fr; in ccs_pll_calculate()
741 op_lim_bk = &lim->op_bk; in ccs_pll_calculate()
742 op_pll_fr = &pll->vt_fr; in ccs_pll_calculate()
743 op_pll_bk = &pll->op_bk; in ccs_pll_calculate()
746 if (!pll->op_lanes || !pll->vt_lanes || !pll->bits_per_pixel || in ccs_pll_calculate()
747 !pll->ext_clk_freq_hz || !pll->link_freq || !pll->scale_m || in ccs_pll_calculate()
748 !op_lim_fr->min_pll_ip_clk_freq_hz || in ccs_pll_calculate()
749 !op_lim_fr->max_pll_ip_clk_freq_hz || in ccs_pll_calculate()
750 !op_lim_fr->min_pll_op_clk_freq_hz || in ccs_pll_calculate()
751 !op_lim_fr->max_pll_op_clk_freq_hz || in ccs_pll_calculate()
752 !op_lim_bk->max_sys_clk_div || !op_lim_fr->max_pll_multiplier) in ccs_pll_calculate()
753 return -EINVAL; in ccs_pll_calculate()
756 * Make sure op_pix_clk_div will be integer --- unless flexible in ccs_pll_calculate()
759 if (!(pll->flags & CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV) && in ccs_pll_calculate()
760 (pll->bits_per_pixel * pll->op_lanes) % in ccs_pll_calculate()
761 (pll->csi2.lanes * l << op_pix_ddr(pll->flags))) { in ccs_pll_calculate()
763 pll->bits_per_pixel, pll->op_lanes, pll->csi2.lanes, l); in ccs_pll_calculate()
764 return -EINVAL; in ccs_pll_calculate()
767 dev_dbg(dev, "vt_lanes: %u\n", pll->vt_lanes); in ccs_pll_calculate()
768 dev_dbg(dev, "op_lanes: %u\n", pll->op_lanes); in ccs_pll_calculate()
770 dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal, in ccs_pll_calculate()
771 pll->binning_vertical); in ccs_pll_calculate()
773 switch (pll->bus_type) { in ccs_pll_calculate()
776 op_sys_clk_freq_hz_sdr = pll->link_freq * 2 in ccs_pll_calculate()
777 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? in ccs_pll_calculate()
778 1 : pll->csi2.lanes); in ccs_pll_calculate()
781 return -EINVAL; in ccs_pll_calculate()
784 pll->pixel_rate_csi = in ccs_pll_calculate()
786 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? in ccs_pll_calculate()
787 pll->csi2.lanes : 1) * PHY_CONST_DIV, in ccs_pll_calculate()
788 phy_const * pll->bits_per_pixel * l); in ccs_pll_calculate()
790 /* Figure out limits for OP pre-pll divider based on extclk */ in ccs_pll_calculate()
792 op_lim_fr->min_pre_pll_clk_div, op_lim_fr->max_pre_pll_clk_div); in ccs_pll_calculate()
794 min_t(u16, op_lim_fr->max_pre_pll_clk_div, in ccs_pll_calculate()
795 clk_div_even(pll->ext_clk_freq_hz / in ccs_pll_calculate()
796 op_lim_fr->min_pll_ip_clk_freq_hz)); in ccs_pll_calculate()
798 max_t(u16, op_lim_fr->min_pre_pll_clk_div, in ccs_pll_calculate()
800 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate()
801 op_lim_fr->max_pll_ip_clk_freq_hz))); in ccs_pll_calculate()
802 dev_dbg(dev, "pre-pll check: min / max op_pre_pll_clk_div: %u / %u\n", in ccs_pll_calculate()
806 pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)); in ccs_pll_calculate()
808 div = (pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)) / i; in ccs_pll_calculate()
816 DIV_ROUND_UP(op_lim_fr->max_pll_op_clk_freq_hz, in ccs_pll_calculate()
817 pll->ext_clk_freq_hz)))); in ccs_pll_calculate()
821 for (op_pll_fr->pre_pll_clk_div = min_op_pre_pll_clk_div; in ccs_pll_calculate()
822 op_pll_fr->pre_pll_clk_div <= max_op_pre_pll_clk_div; in ccs_pll_calculate()
823 op_pll_fr->pre_pll_clk_div += in ccs_pll_calculate()
824 (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : in ccs_pll_calculate()
825 2 - (op_pll_fr->pre_pll_clk_div & 1)) { in ccs_pll_calculate()
826 rval = ccs_pll_calculate_op(dev, lim, op_lim_fr, op_lim_bk, pll, in ccs_pll_calculate()
833 rval = check_fr_bounds(dev, lim, pll, in ccs_pll_calculate()
834 pll->flags & CCS_PLL_FLAG_DUAL_PLL ? in ccs_pll_calculate()
839 rval = check_bk_bounds(dev, lim, pll, PLL_OP); in ccs_pll_calculate()
843 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) in ccs_pll_calculate()
846 ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, in ccs_pll_calculate()
849 rval = check_bk_bounds(dev, lim, pll, PLL_VT); in ccs_pll_calculate()
852 rval = check_ext_bounds(dev, pll); in ccs_pll_calculate()
865 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { in ccs_pll_calculate()
866 rval = ccs_pll_calculate_vt_tree(dev, lim, pll); in ccs_pll_calculate()
872 print_pll(dev, pll); in ccs_pll_calculate()
879 MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ PLL calculator");