summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/ccs-pll.c
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@linux.intel.com>2020-09-15 11:37:32 +0300
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-12-07 18:01:45 +0300
commitf25d3962ac8f23ab4871cef1d79e10a8c34f7908 (patch)
tree7f47f57d153abb8c22f5b9979e266f6ca2df0c0c /drivers/media/i2c/ccs-pll.c
parentfadfe88441fcf67a15acd0fe47785f89d93782ff (diff)
downloadlinux-f25d3962ac8f23ab4871cef1d79e10a8c34f7908.tar.xz
media: ccs-pll: Rework bounds checks
Refactor bounds checks so that the caller can decide what to check. This allows doing the checks early, when the values are available. This also adds front OP PLL configuration and limits. Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/media/i2c/ccs-pll.c')
-rw-r--r--drivers/media/i2c/ccs-pll.c148
1 files changed, 91 insertions, 57 deletions
diff --git a/drivers/media/i2c/ccs-pll.c b/drivers/media/i2c/ccs-pll.c
index 43735f6d0bb2..a6443589b948 100644
--- a/drivers/media/i2c/ccs-pll.c
+++ b/drivers/media/i2c/ccs-pll.c
@@ -46,12 +46,14 @@ static inline uint32_t one_or_more(uint32_t a)
}
static int bounds_check(struct device *dev, uint32_t val,
- uint32_t min, uint32_t max, char *str)
+ uint32_t min, uint32_t max, const char *prefix,
+ char *str)
{
if (val >= min && val <= max)
return 0;
- dev_dbg(dev, "%s out of bounds: %d (%d--%d)\n", str, val, min, max);
+ dev_dbg(dev, "%s_%s out of bounds: %d (%d--%d)\n", prefix,
+ str, val, min, max);
return -EINVAL;
}
@@ -81,7 +83,7 @@ static void print_pll(struct device *dev, struct ccs_pll *pll)
unsigned int which;
} branches[] = {
{ &pll->vt_fr, &pll->vt_bk, PLL_VT },
- { NULL, &pll->op_bk, PLL_OP }
+ { &pll->op_fr, &pll->op_bk, PLL_OP }
}, *br;
unsigned int i;
@@ -127,68 +129,90 @@ static void print_pll(struct device *dev, struct ccs_pll *pll)
pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : "");
}
-static int check_all_bounds(struct device *dev,
- const struct ccs_pll_limits *lim,
- const struct ccs_pll_branch_limits_fr *op_lim_fr,
- const struct ccs_pll_branch_limits_bk *op_lim_bk,
- struct ccs_pll *pll,
- struct ccs_pll_branch_fr *op_pll_fr,
- struct ccs_pll_branch_bk *op_pll_bk)
+static int check_fr_bounds(struct device *dev,
+ const struct ccs_pll_limits *lim,
+ struct ccs_pll *pll, unsigned int which)
{
+ const struct ccs_pll_branch_limits_fr *lim_fr;
+ struct ccs_pll_branch_fr *pll_fr;
+ const char *s = pll_string(which);
int rval;
- rval = bounds_check(dev, op_pll_fr->pll_ip_clk_freq_hz,
- op_lim_fr->min_pll_ip_clk_freq_hz,
- op_lim_fr->max_pll_ip_clk_freq_hz,
- "pll_ip_clk_freq_hz");
- if (!rval)
- rval = bounds_check(
- dev, op_pll_fr->pll_multiplier,
- op_lim_fr->min_pll_multiplier,
- op_lim_fr->max_pll_multiplier, "pll_multiplier");
- if (!rval)
- rval = bounds_check(
- dev, op_pll_fr->pll_op_clk_freq_hz,
- op_lim_fr->min_pll_op_clk_freq_hz,
- op_lim_fr->max_pll_op_clk_freq_hz, "pll_op_clk_freq_hz");
+ if (which == PLL_OP) {
+ lim_fr = &lim->op_fr;
+ pll_fr = &pll->op_fr;
+ } else {
+ lim_fr = &lim->vt_fr;
+ pll_fr = &pll->vt_fr;
+ }
+
+ rval = bounds_check(dev, pll_fr->pre_pll_clk_div,
+ lim_fr->min_pre_pll_clk_div,
+ lim_fr->max_pre_pll_clk_div, s, "pre_pll_clk_div");
+
if (!rval)
- rval = bounds_check(
- dev, op_pll_bk->sys_clk_div,
- op_lim_bk->min_sys_clk_div, op_lim_bk->max_sys_clk_div,
- "op_sys_clk_div");
+ rval = bounds_check(dev, pll_fr->pll_ip_clk_freq_hz,
+ lim_fr->min_pll_ip_clk_freq_hz,
+ lim_fr->max_pll_ip_clk_freq_hz,
+ s, "pll_ip_clk_freq_hz");
if (!rval)
- rval = bounds_check(
- dev, op_pll_bk->sys_clk_freq_hz,
- op_lim_bk->min_sys_clk_freq_hz,
- op_lim_bk->max_sys_clk_freq_hz,
- "op_sys_clk_freq_hz");
+ rval = bounds_check(dev, pll_fr->pll_multiplier,
+ lim_fr->min_pll_multiplier,
+ lim_fr->max_pll_multiplier,
+ s, "pll_multiplier");
if (!rval)
- rval = bounds_check(
- dev, op_pll_bk->pix_clk_freq_hz,
- op_lim_bk->min_pix_clk_freq_hz,
- op_lim_bk->max_pix_clk_freq_hz,
- "op_pix_clk_freq_hz");
+ rval = bounds_check(dev, pll_fr->pll_op_clk_freq_hz,
+ lim_fr->min_pll_op_clk_freq_hz,
+ lim_fr->max_pll_op_clk_freq_hz,
+ s, "pll_op_clk_freq_hz");
- /*
- * If there are no OP clocks, the VT clocks are contained in
- * the OP clock struct.
- */
- if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)
- return rval;
+ return rval;
+}
+
+static int check_bk_bounds(struct device *dev,
+ const struct ccs_pll_limits *lim,
+ struct ccs_pll *pll, unsigned int which)
+{
+ const struct ccs_pll_branch_limits_bk *lim_bk;
+ struct ccs_pll_branch_bk *pll_bk;
+ const char *s = pll_string(which);
+ int rval;
+
+ if (which == PLL_OP) {
+ if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)
+ return 0;
+ lim_bk = &lim->op_bk;
+ pll_bk = &pll->op_bk;
+ } else {
+ lim_bk = &lim->vt_bk;
+ pll_bk = &pll->vt_bk;
+ }
+
+ rval = bounds_check(dev, pll_bk->sys_clk_div,
+ lim_bk->min_sys_clk_div,
+ lim_bk->max_sys_clk_div, s, "op_sys_clk_div");
+ if (!rval)
+ rval = bounds_check(dev, pll_bk->sys_clk_freq_hz,
+ lim_bk->min_sys_clk_freq_hz,
+ lim_bk->max_sys_clk_freq_hz,
+ s, "sys_clk_freq_hz");
if (!rval)
- rval = bounds_check(
- dev, pll->vt_bk.sys_clk_freq_hz,
- lim->vt_bk.min_sys_clk_freq_hz,
- lim->vt_bk.max_sys_clk_freq_hz,
- "vt_sys_clk_freq_hz");
+ rval = bounds_check(dev, pll_bk->sys_clk_div,
+ lim_bk->min_sys_clk_div,
+ lim_bk->max_sys_clk_div,
+ s, "sys_clk_div");
if (!rval)
- rval = bounds_check(
- dev, pll->vt_bk.pix_clk_freq_hz,
- lim->vt_bk.min_pix_clk_freq_hz,
- lim->vt_bk.max_pix_clk_freq_hz,
- "vt_pix_clk_freq_hz");
+ rval = bounds_check(dev, pll_bk->pix_clk_freq_hz,
+ lim_bk->min_pix_clk_freq_hz,
+ lim_bk->max_pix_clk_freq_hz,
+ s, "pix_clk_freq_hz");
+
+ return rval;
+}
+static int check_ext_bounds(struct device *dev, struct ccs_pll *pll)
+{
if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING) &&
pll->pixel_rate_pixel_array > pll->pixel_rate_csi) {
dev_dbg(dev, "device does not support derating\n");
@@ -201,7 +225,7 @@ static int check_all_bounds(struct device *dev,
return -EINVAL;
}
- return rval;
+ return 0;
}
#define CPHY_CONST 7
@@ -610,11 +634,21 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
if (rval)
continue;
+ rval = check_fr_bounds(dev, lim, pll, PLL_VT);
+ if (rval)
+ continue;
+
+ rval = check_bk_bounds(dev, lim, pll, PLL_OP);
+ if (rval)
+ continue;
+
ccs_pll_calculate_vt(dev, lim, op_lim_bk, pll, op_pll_fr,
op_pll_bk, cphy, phy_const);
- rval = check_all_bounds(dev, lim, op_lim_fr, op_lim_bk, pll,
- op_pll_fr, op_pll_bk);
+ rval = check_bk_bounds(dev, lim, pll, PLL_VT);
+ if (rval)
+ continue;
+ rval = check_ext_bounds(dev, pll);
if (rval)
continue;