Thread (13 messages) 13 messages, 4 authors, 13d ago

Re: [PATCH v6 3/7] pwm: tegra: Avoid hard-coded max clock frequency

From: sashiko-bot@kernel.org
Date: 2026-07-01 03:36:11

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] dev_pm_opp_set_rate(..., ULONG_MAX) causes probe failure when the parent clock's maximum rate exceeds the DT OPP table limits.
- [High] Dropping the explicit max_frequency cap permanently locks older SoCs (num_channels > 1) to a high clock rate, severely limiting the maximum PWM period.

Pre-existing issues:
- [High] Missing pm_runtime_disable() on probe error paths and in driver remove.
--

commit 29d7ce61a02c025b3580d289a189425cd7da22aa
Author: Yi-Wei Wang [off-list ref]

pwm: tegra: Avoid hard-coded max clock frequency

The patch removes the hard-coded maximum frequency for Tegra PWM SoCs.
It updates probe to use dev_pm_opp_set_rate with ULONG_MAX to set the clock
rate based on the parent clock limits from the device tree. It also removes
the now redundant tegra194_pwm_soc configuration.
quoted hunk ↗ jump to hunk
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index f8c5495a56a66..3eef299c51f8e 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -59,9 +59,6 @@
 
 struct tegra_pwm_soc {
 	unsigned int num_channels;
-
-	/* Maximum IP frequency for given SoCs */
-	unsigned long max_frequency;
 };
 
 struct tegra_pwm_chip {
@@ -303,7 +300,7 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 		return ret;
 
 	/* Set maximum frequency of the IP */
-	ret = dev_pm_opp_set_rate(&pdev->dev, pc->soc->max_frequency);
+	ret = dev_pm_opp_set_rate(&pdev->dev, ULONG_MAX);
[Severity: High]
If the parent clock's maximum physical rate exceeds the maximum frequency
defined in the device tree OPP table, will dev_pm_opp_set_rate() fail here?

The OPP core translates ULONG_MAX using clk_round_rate() to find the absolute
maximum frequency the parent clock can physically generate. If this is higher
than the maximum frequency in the OPP table (for example, on Tegra30),
_find_freq_ceil() might fail to find a valid OPP and return -ERANGE, causing
the probe to fail.

Also, for older SoCs where num_channels > 1, tegra_pwm_config() does not
dynamically scale the clock rate.

drivers/pwm/pwm-tegra.c:tegra_pwm_config() {
    ...
    if (pc->soc->num_channels == 1) {
        ...
        err = dev_pm_opp_set_rate(pwmchip_parent(chip), required_clk_rate);
        ...
    }
    
    /* Consider precision in scale_width rate calculation */
    rate = mul_u64_u64_div_u64(pc->clk_rate, period_ns,
                               (u64)NSEC_PER_SEC * TEGRA_PWM_DEPTH);
    ...
    if (rate >> pc->soc->scale_width)
        return -EINVAL;
    ...
}

By forcing the clock to its absolute maximum frequency during probe, won't
these older SoCs be permanently locked to a high clock rate?

With a high fixed clock rate, calculating the divider (rate) for large requested
periods (like 20ms for servos) could exceed the hardware's scale_width limit,
causing legitimate config requests to fail with -EINVAL.
quoted hunk ↗ jump to hunk
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to set max frequency: %d\n", ret);
 		goto put_pm;
 	}
@@ -315,10 +312,15 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 	 * so that PWM period can be calculated more accurately.
 	 */
 	pc->clk_rate = clk_get_rate(pc->clk);
+	if (pc->clk_rate < (1 << TEGRA_PWM_DUTY_WIDTH)) {
+		dev_err(&pdev->dev, "clock maximum frequency out of range\n");
+		ret = -ERANGE;
+		goto put_pm;
[Severity: High]
This is a pre-existing issue, but does this error path leave the runtime PM
state unbalanced?

The driver calls pm_runtime_enable() earlier in tegra_pwm_probe(), but the error
handling at the put_pm label (and similarly the tegra_pwm_remove function) only
calls suspend functions without calling pm_runtime_disable():

drivers/pwm/pwm-tegra.c:tegra_pwm_probe() {
    ...
put_pm:
    pm_runtime_put_sync_suspend(&pdev->dev);
    pm_runtime_force_suspend(&pdev->dev);
    return ret;
}

Could this lead to state corruption or kernel warnings upon module reload or
device re-bind since the enable is never balanced?
+	}
 
 	/* Set minimum limit of PWM period for the IP */
 	pc->min_period_ns =
-	    (NSEC_PER_SEC / (pc->soc->max_frequency >> TEGRA_PWM_DUTY_WIDTH)) + 1;
+	    (NSEC_PER_SEC / (pc->clk_rate >> TEGRA_PWM_DUTY_WIDTH)) + 1;
 
 	pc->rst = devm_reset_control_get_exclusive(&pdev->dev, "pwm");
 	if (IS_ERR(pc->rst)) {
[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260701-t264-pwm-v6-0-2718f61f411f@nvidia.com?part=3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help