Lines Matching full:pll
3 * drivers/media/i2c/ccs-pll.c
5 * Generic MIPI CCS/SMIA/SMIA++ PLL calculator
17 #include "ccs-pll.h"
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()
95 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL || in print_pll()
108 if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) || in print_pll()
123 pll->pixel_rate_pixel_array); 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()
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
162 pll_fr = &pll->op_fr; in check_fr_bounds()
165 pll_fr = &pll->vt_fr; 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()
205 pll_bk = &pll->op_bk; in check_bk_bounds()
208 pll_bk = &pll->vt_bk; 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()
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()
252 struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr, in ccs_pll_find_vt_sys_div() argument
292 struct ccs_pll *pll, u32 mul, u32 div) in __ccs_pll_calculate_vt_tree() argument
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()
303 pll->ext_clk_freq_hz / pll_fr->pre_pll_clk_div; in __ccs_pll_calculate_vt_tree()
316 dev_dbg(dev, "pll multiplier %u too high\n", in __ccs_pll_calculate_vt_tree()
330 ccs_pll_find_vt_sys_div(dev, lim, pll, pll_fr, vt_div, vt_div, in __ccs_pll_calculate_vt_tree()
375 pll->pixel_rate_pixel_array = in __ccs_pll_calculate_vt_tree()
376 pll_bk->pix_clk_freq_hz * pll->vt_lanes; in __ccs_pll_calculate_vt_tree()
383 struct ccs_pll *pll) in ccs_pll_calculate_vt_tree() argument
386 struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; in ccs_pll_calculate_vt_tree()
391 pre_div = gcd(pll->pixel_rate_csi, in ccs_pll_calculate_vt_tree()
392 pll->ext_clk_freq_hz * pll->vt_lanes); in ccs_pll_calculate_vt_tree()
393 pre_mul = pll->pixel_rate_csi / pre_div; in ccs_pll_calculate_vt_tree()
394 pre_div = pll->ext_clk_freq_hz * pll->vt_lanes / pre_div; in ccs_pll_calculate_vt_tree()
396 /* Make sure PLL input frequency is within limits */ in ccs_pll_calculate_vt_tree()
399 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate_vt_tree()
403 pll->ext_clk_freq_hz / in ccs_pll_calculate_vt_tree()
405 if (!(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER)) in ccs_pll_calculate_vt_tree()
414 (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : in ccs_pll_calculate_vt_tree()
426 rval = __ccs_pll_calculate_vt_tree(dev, lim, pll, in ccs_pll_calculate_vt_tree()
431 rval = check_fr_bounds(dev, lim, pll, PLL_VT); in ccs_pll_calculate_vt_tree()
435 rval = check_bk_bounds(dev, lim, pll, PLL_VT); in ccs_pll_calculate_vt_tree()
448 struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr, in ccs_pll_calculate_vt() argument
458 if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) in ccs_pll_calculate_vt()
465 if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING)) { in ccs_pll_calculate_vt()
468 * pll->vt_lanes * phy_const / pll->op_lanes in ccs_pll_calculate_vt()
469 / (PHY_CONST_DIV << op_pix_ddr(pll->flags)); in ccs_pll_calculate_vt()
479 / pll->binning_horizontal) in ccs_pll_calculate_vt()
480 vt_op_binning_div = pll->binning_horizontal; in ccs_pll_calculate_vt()
496 dev_dbg(dev, "scale_m: %u\n", pll->scale_m); in ccs_pll_calculate_vt()
498 DIV_ROUND_UP(pll->bits_per_pixel in ccs_pll_calculate_vt()
499 * op_pll_bk->sys_clk_div * pll->scale_n in ccs_pll_calculate_vt()
500 * pll->vt_lanes * phy_const, in ccs_pll_calculate_vt()
501 (pll->flags & in ccs_pll_calculate_vt()
503 pll->csi2.lanes : 1) in ccs_pll_calculate_vt()
504 * vt_op_binning_div * pll->scale_m in ccs_pll_calculate_vt()
505 * PHY_CONST_DIV << op_pix_ddr(pll->flags)); in ccs_pll_calculate_vt()
527 ccs_pll_find_vt_sys_div(dev, lim, pll, pll_fr, min_vt_div, in ccs_pll_calculate_vt()
569 pll->vt_bk.sys_clk_div = DIV_ROUND_UP(vt_div, best_pix_div); in ccs_pll_calculate_vt()
570 pll->vt_bk.pix_clk_div = best_pix_div; in ccs_pll_calculate_vt()
572 pll->vt_bk.sys_clk_freq_hz = in ccs_pll_calculate_vt()
573 pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; in ccs_pll_calculate_vt()
574 pll->vt_bk.pix_clk_freq_hz = in ccs_pll_calculate_vt()
575 pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div; in ccs_pll_calculate_vt()
578 pll->pixel_rate_pixel_array = in ccs_pll_calculate_vt()
579 pll->vt_bk.pix_clk_freq_hz * pll->vt_lanes; in ccs_pll_calculate_vt()
583 * Heuristically guess the PLL tree for a given common multiplier and
587 * @mul is the PLL multiplier and @div is the common divisor
588 * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
597 struct ccs_pll *pll, struct ccs_pll_branch_fr *op_pll_fr, in ccs_pll_calculate_op() argument
618 /* Don't go above max pll multiplier. */ in ccs_pll_calculate_op()
622 /* Don't go above max pll op frequency. */ in ccs_pll_calculate_op()
627 / (pll->ext_clk_freq_hz / in ccs_pll_calculate_op()
644 pll->ext_clk_freq_hz / in ccs_pll_calculate_op()
679 op_pll_fr->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz in ccs_pll_calculate_op()
685 if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) in ccs_pll_calculate_op()
687 (pll->bits_per_pixel in ccs_pll_calculate_op()
688 * pll->op_lanes * (phy_const << op_sys_ddr(pll->flags)) in ccs_pll_calculate_op()
689 / PHY_CONST_DIV / pll->csi2.lanes / l) in ccs_pll_calculate_op()
690 >> op_pix_ddr(pll->flags); in ccs_pll_calculate_op()
693 (pll->bits_per_pixel in ccs_pll_calculate_op()
694 * (phy_const << op_sys_ddr(pll->flags)) in ccs_pll_calculate_op()
695 / PHY_CONST_DIV / l) >> op_pix_ddr(pll->flags); in ccs_pll_calculate_op()
698 (op_sys_clk_freq_hz_sdr >> op_pix_ddr(pll->flags)) in ccs_pll_calculate_op()
701 op_sys_clk_freq_hz_sdr >> op_sys_ddr(pll->flags); in ccs_pll_calculate_op()
709 struct ccs_pll *pll) in ccs_pll_calculate() argument
715 bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY; in ccs_pll_calculate()
721 u32 l = (!pll->op_bits_per_lane || in ccs_pll_calculate()
722 pll->op_bits_per_lane >= pll->bits_per_pixel) ? 1 : 2; in ccs_pll_calculate()
726 if (!(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL)) { in ccs_pll_calculate()
727 pll->op_lanes = 1; in ccs_pll_calculate()
728 pll->vt_lanes = 1; in ccs_pll_calculate()
731 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { in ccs_pll_calculate()
734 op_pll_fr = &pll->op_fr; in ccs_pll_calculate()
735 op_pll_bk = &pll->op_bk; in ccs_pll_calculate()
736 } else if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { in ccs_pll_calculate()
738 * If there's no OP PLL at all, use the VT values in ccs_pll_calculate()
740 * the PLL calculation. in ccs_pll_calculate()
744 op_pll_fr = &pll->vt_fr; in ccs_pll_calculate()
745 op_pll_bk = &pll->vt_bk; in ccs_pll_calculate()
749 op_pll_fr = &pll->vt_fr; in ccs_pll_calculate()
750 op_pll_bk = &pll->op_bk; in ccs_pll_calculate()
753 if (!pll->op_lanes || !pll->vt_lanes || !pll->bits_per_pixel || in ccs_pll_calculate()
754 !pll->ext_clk_freq_hz || !pll->link_freq || !pll->scale_m || in ccs_pll_calculate()
766 if (!(pll->flags & CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV) && in ccs_pll_calculate()
767 (pll->bits_per_pixel * pll->op_lanes) % in ccs_pll_calculate()
768 (pll->csi2.lanes * l << op_pix_ddr(pll->flags))) { in ccs_pll_calculate()
770 pll->bits_per_pixel, pll->op_lanes, pll->csi2.lanes, l); in ccs_pll_calculate()
774 dev_dbg(dev, "vt_lanes: %u\n", pll->vt_lanes); in ccs_pll_calculate()
775 dev_dbg(dev, "op_lanes: %u\n", pll->op_lanes); in ccs_pll_calculate()
777 dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal, in ccs_pll_calculate()
778 pll->binning_vertical); in ccs_pll_calculate()
780 switch (pll->bus_type) { in ccs_pll_calculate()
783 op_sys_clk_freq_hz_sdr = pll->link_freq * 2 in ccs_pll_calculate()
784 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? in ccs_pll_calculate()
785 1 : pll->csi2.lanes); in ccs_pll_calculate()
791 pll->pixel_rate_csi = in ccs_pll_calculate()
793 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? in ccs_pll_calculate()
794 pll->csi2.lanes : 1) * PHY_CONST_DIV, in ccs_pll_calculate()
795 phy_const * pll->bits_per_pixel * l); in ccs_pll_calculate()
797 /* Figure out limits for OP pre-pll divider based on extclk */ in ccs_pll_calculate()
802 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate()
807 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate()
809 dev_dbg(dev, "pre-pll check: min / max op_pre_pll_clk_div: %u / %u\n", in ccs_pll_calculate()
813 pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)); in ccs_pll_calculate()
815 div = (pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)) / i; in ccs_pll_calculate()
824 pll->ext_clk_freq_hz)))); in ccs_pll_calculate()
825 if (!(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER)) in ccs_pll_calculate()
833 (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : in ccs_pll_calculate()
835 rval = ccs_pll_calculate_op(dev, lim, op_lim_fr, op_lim_bk, pll, in ccs_pll_calculate()
842 rval = check_fr_bounds(dev, lim, pll, in ccs_pll_calculate()
843 pll->flags & CCS_PLL_FLAG_DUAL_PLL ? in ccs_pll_calculate()
848 rval = check_bk_bounds(dev, lim, pll, PLL_OP); in ccs_pll_calculate()
852 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) in ccs_pll_calculate()
855 ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr, in ccs_pll_calculate()
858 rval = check_bk_bounds(dev, lim, pll, PLL_VT); in ccs_pll_calculate()
861 rval = check_ext_bounds(dev, pll); in ccs_pll_calculate()
874 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { in ccs_pll_calculate()
875 rval = ccs_pll_calculate_vt_tree(dev, lim, pll); in ccs_pll_calculate()
881 print_pll(dev, pll); in ccs_pll_calculate()
888 MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ PLL calculator");