Patch "pwm: stm32: Fix for settings using period > UINT32_MAX" has been added to the 6.9-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    pwm: stm32: Fix for settings using period > UINT32_MAX

to the 6.9-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     pwm-stm32-fix-for-settings-using-period-uint32_max.patch
and it can be found in the queue-6.9 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 00fb789a41beba8c6654a8b319ab479d9263bb53
Author: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
Date:   Sun Mar 17 22:52:15 2024 +0100

    pwm: stm32: Fix for settings using period > UINT32_MAX
    
    [ Upstream commit d44d635635a7192c773a75e674a8590a163e879e ]
    
    stm32_pwm_config() took the duty_cycle and period values with the type
    int, however stm32_pwm_apply() passed u64 values there. Expand the
    function parameters to u64 to not discard relevant bits and adapt the
    calculations to the wider type.
    
    To ensure the calculations won't overflow, check in .probe() the input
    clk doesn't run faster than 1 GHz.
    
    Link: https://lore.kernel.org/r/06b4a650a608d0887d934c1b2b8919e0f78e4db2.1710711976.git.u.kleine-koenig@xxxxxxxxxxxxxx
    Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx>
    Stable-dep-of: c45fcf46ca23 ("pwm: stm32: Refuse too small period requests")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index d50194ad24b1c..27fcc90504f67 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -309,16 +309,18 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
 }
 
 static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
-			    int duty_ns, int period_ns)
+			    u64 duty_ns, u64 period_ns)
 {
 	unsigned long long prd, div, dty;
 	unsigned int prescaler = 0;
 	u32 ccmr, mask, shift;
 
-	/* Period and prescaler values depends on clock rate */
-	div = (unsigned long long)clk_get_rate(priv->clk) * period_ns;
-
-	do_div(div, NSEC_PER_SEC);
+	/*
+	 * .probe() asserted that clk_get_rate() is not bigger than 1 GHz, so
+	 * this won't overflow.
+	 */
+	div = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk),
+				  NSEC_PER_SEC);
 	prd = div;
 
 	while (div > priv->max_arr) {
@@ -351,9 +353,8 @@ static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch,
 	regmap_set_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE);
 
 	/* Calculate the duty cycles */
-	dty = (unsigned long long)clk_get_rate(priv->clk) * duty_ns;
-	do_div(dty, prescaler + 1);
-	do_div(dty, NSEC_PER_SEC);
+	dty = mul_u64_u64_div_u64(duty_ns, clk_get_rate(priv->clk),
+				  (u64)NSEC_PER_SEC * (prescaler + 1));
 
 	regmap_write(priv->regmap, TIM_CCR1 + 4 * ch, dty);
 
@@ -657,6 +658,17 @@ static int stm32_pwm_probe(struct platform_device *pdev)
 
 	stm32_pwm_detect_complementary(priv);
 
+	ret = devm_clk_rate_exclusive_get(dev, priv->clk);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to lock clock\n");
+
+	/*
+	 * With the clk running with not more than 1 GHz the calculations in
+	 * .apply() won't overflow.
+	 */
+	if (clk_get_rate(priv->clk) > 1000000000)
+		return dev_err_probe(dev, -EINVAL, "Failed to lock clock\n");
+
 	chip->ops = &stm32pwm_ops;
 
 	/* Initialize clock refcount to number of enabled PWM channels. */




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux