From: sashiko-bot@kernel.org
To: "Long Zhao" <longzhao@ambarella.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
linux-clk@vger.kernel.org
Subject: Re: [PATCH v3 4/6] clk: ambarella: add CV75 CCU driver
Date: Thu, 13 Aug 2026 10:10:06 +0000 [thread overview]
Message-ID: <20260813101007.1745F1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260813-cv75-v3-a-v3-4-cfdd20b1b4dd@ambarella.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] VCO range iteration underflows and corrupts the PLL CTRL3 register if `fvco_mhz` evaluates to 0.
- [High] `amb_pll_calc_params` omits the feedback and output dividers (`fsdiv` and `fsout`) when determining parameters, resulting in drastically incorrect clock frequencies.
- [High] Division by zero kernel panic in `amb_pll_calc_params()` when the parent clock rate is zero.
- [Medium] Setting the rate of a non-ONE_BASED divider to 0 permanently disables the clock due to an incorrect mask.
- [Medium] `amb_pll_determine_rate` unnecessarily restricts integer PLL rates to multiples of `parent_rate / 2`.
- [Low] Passing a 64-bit divisor to `DIV_ROUND_CLOSEST_ULL` causes a build failure on 32-bit architectures.
--
--- Patch [4]: [PATCH v3 4/6] clk: ambarella: add CV75 CCU driver ---
commit 434160130974a0a15aae2d546aa85876cbc1fe59
Author: Long Zhao <longzhao@ambarella.com>
clk: ambarella: add CV75 CCU driver
Add the Ambarella CV75 clock driver covering the core PLL and the
UART0 / AHB / APB clocks needed for early console bring-up.
> diff --git a/drivers/clk/ambarella/ccu_mux_div.c b/drivers/clk/ambarella/ccu_mux_div.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/clk/ambarella/ccu_mux_div.c
[ ... ]
> +static int amb_div_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
[ ... ]
> + if (!rate) {
> + /* Assert the reset/disable bit above the divider field. */
> + val = BIT(div->width);
> + mask = clk_div_mask(div->width + 1);
> + } else {
> + val = divider_get_val(rate, parent_rate, NULL,
> + div->width, div->flags);
> + if (val < 0)
> + return val;
> +
> + mask = (div->flags & CLK_DIVIDER_ONE_BASED) ?
> + clk_div_mask(div->width + 1) : clk_div_mask(div->width);
[Severity: Medium]
When setting the rate to 0, the driver asserts the reset/disable bit above
the divider field. When a non-zero rate is subsequently requested, this logic
uses a mask that strictly covers only the divider field.
Will this exclude the higher disable bit during the update, leaving the clock
permanently disabled?
> + }
> +
> + regmap_update_bits(div->map, div->offset, mask << div->shift,
> + val << div->shift);
[ ... ]
> diff --git a/drivers/clk/ambarella/ccu_pll.c b/drivers/clk/ambarella/ccu_pll.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/clk/ambarella/ccu_pll.c
[ ... ]
> +static int amb_pll_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + struct amb_pll *pll = to_amb_pll(hw);
> + unsigned long half_refclk = req->best_parent_rate / 2;
> +
> + if (pll->frac_mode)
> + return 0;
> +
> + if (!half_refclk)
> + return -EINVAL;
> +
> + req->rate = roundup(req->rate, half_refclk);
[Severity: Medium]
Does clamping the requested rate to a multiple of half_refclk artificially
restrict the hardware's capabilities?
Because the hardware sout divider supports ranges up to 16, it looks like it
could natively support a wide and fine-grained selection of exact integer
frequencies instead of being clamped this way.
> +
> + return 0;
> +}
> +
> +static int amb_pll_calc_params(struct amb_pll *pll, unsigned long rate,
> + unsigned long parent_rate, u32 ctrl2_val,
> + u32 *intp, u32 *sdiv, u32 *sout,
> + u32 *vcodiv, u32 *fsdiv, u32 *fsout)
> +{
[ ... ]
> + max_numerator = soc_data->vco_max_mhz;
> + max_numerator = div_u64(max_numerator * 1000000ULL, parent_rate);
[Severity: High]
In amb_pll_determine_rate(), if the PLL is in frac_mode, it returns 0
immediately without validating if half_refclk is zero:
static int amb_pll_determine_rate(...) {
...
if (pll->frac_mode)
return 0;
if (!half_refclk)
return -EINVAL;
...
}
If a zero-rate parent clock reaches amb_pll_calc_params(), will this
division by zero trigger a kernel panic?
> + max_numerator = div_u64(max_numerator, *vcodiv * *fsdiv);
> + max_numerator = min(128UL, max_numerator);
> + if (!max_numerator)
> + return -EINVAL;
> +
> + max_denominator = AMB_PLL_MAX_SOUT;
> + rate_tmp = rate;
> + rational_best_approximation(rate_tmp, parent_rate, max_numerator,
> + max_denominator, &intp_ul, &sout_ul);
[Severity: High]
The hardware frequency depends on fsdiv and fsout, but this call requests an
approximation using just rate and parent_rate.
If the hardware is left in a state where fsdiv and fsout are not identical,
will the resulting frequency be scaled incorrectly and bypass the refinement
loop?
> +
> + while (parent_rate * *fsdiv * intp_ul * *sdiv / *fsout / sout_ul >
[ ... ]
> +static int amb_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> + unsigned long parent_rate)
> +{
[ ... ]
> + old_rate = amb_pll_recalc_rate(hw, parent_rate) * pll->fix_divider;
> + rate_tmp = old_rate > rate ? 0 : rate - old_rate;
> + if (rate_tmp && pll->frac_mode) {
> + u64 dividend, divider;
> +
> + dividend = (u64)rate_tmp * sout * fsout;
> + dividend <<= 32;
> + divider = (u64)sdiv * fsdiv * parent_rate;
> + frac_val = DIV_ROUND_CLOSEST_ULL(dividend, divider);
[Severity: Low]
The divider variable evaluates to a 64-bit integer, but
DIV_ROUND_CLOSEST_ULL() invokes do_div() which expects a 32-bit divisor on
32-bit architectures.
Will this trigger a __div64_32 link failure under COMPILE_TEST?
> + regmap_write(pll->map, reg[FRAC_OFFSET], frac_val);
> + ctrl_val |= CTRL_FRAC_MODE;
> + }
> +
> + if (soc_data->pll_version >= 2) {
[ ... ]
> + } else {
> + u32 fvco_mhz, range;
> +
> + fvco_mhz = amb_pll_calc_vco(pll, parent_rate) / 1000000UL;
> + for (range = 0; range < ARRAY_SIZE(soc_data->vco_range);
> + range++) {
> + if (fvco_mhz > soc_data->vco_range[range])
> + break;
> + }
> + range = ARRAY_SIZE(soc_data->vco_range) - range - 1;
> +
> + regmap_read(pll->map, reg[CTRL3_OFFSET], &ctrl3_val);
> + ctrl3_val &= ~CTRL3_VCO_RANGE_MASK;
> + ctrl3_val |= range << 1;
[Severity: High]
If the PLL parent rate is exceptionally low (e.g., from a dummy clock),
fvco_mhz can evaluate to 0. Since 0 is not strictly greater than any range
minimum, the loop finishes at 4.
Will the subsequent calculation 4 - 4 - 1 underflow to 0xFFFFFFFF and
corrupt the CTRL3 register bits?
> + regmap_write(pll->map, reg[CTRL3_OFFSET], ctrl3_val);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260813-cv75-v3-a-v3-0-cfdd20b1b4dd@ambarella.com?part=4
next prev parent reply other threads:[~2026-08-13 10:10 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-13 9:56 [PATCH v3 0/6] Ambarella CV75: bindings, RCT clocks, and DT Long Zhao via B4 Relay
2026-08-13 9:56 ` [PATCH v3 1/6] dt-bindings: arm: add Ambarella CV75 platforms Long Zhao via B4 Relay
2026-08-13 9:56 ` [PATCH v3 2/6] dt-bindings: mfd: syscon: add Ambarella CV75 secure scratchpad Long Zhao via B4 Relay
2026-08-13 10:03 ` sashiko-bot
2026-08-13 9:56 ` [PATCH v3 3/6] dt-bindings: clock: add Ambarella CV75 RCT Long Zhao via B4 Relay
2026-08-13 10:02 ` sashiko-bot
2026-08-13 9:56 ` [PATCH v3 4/6] clk: ambarella: add CV75 CCU driver Long Zhao via B4 Relay
2026-08-13 10:10 ` sashiko-bot [this message]
2026-08-13 9:56 ` [PATCH v3 5/6] arm64: ambarella: add ARCH_AMBARELLA and CV75 EVK DT Long Zhao via B4 Relay
2026-08-13 10:07 ` sashiko-bot
2026-08-13 9:56 ` [PATCH v3 6/6] MAINTAINERS: add ARM/AMBARELLA SoC support Long Zhao via B4 Relay
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260813101007.1745F1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=linux-clk@vger.kernel.org \
--cc=longzhao@ambarella.com \
--cc=robh@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox