Re: [PATCH 3/3] clk: tegra: dfll: Get the voltage step of range-based regulators

From: Mikko Perttunen

Date: Mon Nov 02 2026 - 03:31:54 EST


On Thursday, October 29, 2026 6:33 PM Patrick Fischer via B4 Relay wrote:
> From: Patrick Fischer <admin@xxxxxxxxxxxxxxxxxx>
>
> get_alignment_from_regulator() takes the voltage step from
> regulator_get_linear_step(), which returns desc->uV_step. Regulators
> described by linear ranges, such as the SMPS of the TI Palmas PMIC,
> leave uV_step at 0.
>
> With a step of 0, round_cvb_voltage() returns 0 for every OPP, which is
> then clamped to min_millivolts, so all CPU OPPs get the same voltage.
> The I2C LUT is broken as well: find_vdd_map_entry_exact() and
> find_vdd_map_entry_min() divide by the step, and on ARMv7 with hardware
> division the result is 0, so selector 0 matches every voltage. The LUT
> ends up with a single entry and the DFLL never changes vdd_cpu.
>
> This affects boards that run the DFLL in I2C mode with a Palmas SMPS as
> vdd_cpu. In mainline these are the Xiaomi Mi Pad (Tegra124, since v6.19)
> and the Asus Transformer Pad TF701T (Tegra114, DFLL enabled for v7.4).
> The AS3722 and MAX77621 used by the other DFLL boards report a linear
> step, and the PWM mode does not use the regulator.
>
> On a Tegra Note 7 (Tegra114, TPS65913) all 16 CPU OPPs are at 1000 mV
> and vdd_cpu stays at the 1.10 V left by the bootloader. The CPU runs at
> about 1.34 GHz whatever cpufreq requests. With this patch the OPPs range
> from 1000 mV to 1270 mV, the LUT holds the 1000 mV to 1270 mV selectors
> and the DFLL follows cpufreq up to 1708.5 MHz.
>
> If the regulator reports no linear step, use the smallest step between
> the voltages that are usable on the board. Fail the probe if there is
> none instead of running with a step of 0.
>
> Fixes: b3cf8d069505 ("clk: tegra: dfll: CVB calculation alignment with the regulator")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Patrick Fischer <admin@xxxxxxxxxxxxxxxxxx>
> ---
> drivers/clk/tegra/clk-tegra124-dfll-fcpu.c | 26 ++++++++++++++++++++++++++
> 1 file changed, 26 insertions(+)
>
> diff --git a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
> index 457a77c5bb62..5bdea4775076 100644
> --- a/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
> +++ b/drivers/clk/tegra/clk-tegra124-dfll-fcpu.c
> @@ -642,6 +642,7 @@ static int get_alignment_from_regulator(struct device *dev,
> struct rail_alignment *align)
> {
> struct regulator *reg = regulator_get(dev, "vdd-cpu");
> + int i, n_voltages, uv, prev_uv = 0;
>
> if (IS_ERR(reg))
> return PTR_ERR(reg);
> @@ -649,8 +650,33 @@ static int get_alignment_from_regulator(struct device *dev,
> align->offset_uv = regulator_list_voltage(reg, 0);
> align->step_uv = regulator_get_linear_step(reg);
>
> + /*
> + * Regulators described by linear ranges (e.g. the Palmas SMPS) don't
> + * report a linear step. Use the smallest step between the voltages
> + * that are usable on this board instead.
> + */
> + if (!align->step_uv) {
> + n_voltages = regulator_count_voltages(reg);
> + for (i = 0; i < n_voltages; i++) {
> + uv = regulator_list_voltage(reg, i);
> + if (uv <= 0)
> + continue;
> +
> + if (prev_uv && uv > prev_uv &&
> + (!align->step_uv || uv - prev_uv < align->step_uv))
> + align->step_uv = uv - prev_uv;
> +
> + prev_uv = uv;
> + }
> + }
> +

I think this is a bit of a kludge that happens to work on Palmas but not
necessarily every other regulator. However, all Tegra114 devices there
will ever be already exist, so it's probably fine.

Reviewed-by: Mikko Perttunen <mperttunen@xxxxxxxxxx>

> regulator_put(reg);
>
> + if (!align->step_uv) {
> + dev_err(dev, "failed to get vdd-cpu voltage step\n");
> + return -EINVAL;
> + }
> +
> return 0;
> }
>
>
> --
> 2.56.0
>
>
>