From 1a2e75e750eae9994291623c76fb719a943d361c Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 27 Jun 2024 14:51:37 -0400 Subject: [PATCH] Fixes for 6.9 Signed-off-by: Sasha Levin --- ...i-lantiq-restore-reset-gpio-polarity.patch | 73 +++++++++++++++ ...ate-prescaler-with-a-division-instea.patch | 77 ++++++++++++++++ ...for-settings-using-period-uint32_max.patch | 89 +++++++++++++++++++ ...e-precision-of-calculation-in-.apply.patch | 64 +++++++++++++ ...m32-refuse-too-small-period-requests.patch | 46 ++++++++++ queue-6.9/series | 5 ++ 6 files changed, 354 insertions(+) create mode 100644 queue-6.9/mips-pci-lantiq-restore-reset-gpio-polarity.patch create mode 100644 queue-6.9/pwm-stm32-calculate-prescaler-with-a-division-instea.patch create mode 100644 queue-6.9/pwm-stm32-fix-for-settings-using-period-uint32_max.patch create mode 100644 queue-6.9/pwm-stm32-improve-precision-of-calculation-in-.apply.patch create mode 100644 queue-6.9/pwm-stm32-refuse-too-small-period-requests.patch diff --git a/queue-6.9/mips-pci-lantiq-restore-reset-gpio-polarity.patch b/queue-6.9/mips-pci-lantiq-restore-reset-gpio-polarity.patch new file mode 100644 index 00000000000..61f61491f27 --- /dev/null +++ b/queue-6.9/mips-pci-lantiq-restore-reset-gpio-polarity.patch @@ -0,0 +1,73 @@ +From 88411c94960d96e1e1c379f9fe0e8f637c0b9a00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jun 2024 11:04:00 +0200 +Subject: MIPS: pci: lantiq: restore reset gpio polarity + +From: Martin Schiller + +[ Upstream commit 277a0363120276645ae598d8d5fea7265e076ae9 ] + +Commit 90c2d2eb7ab5 ("MIPS: pci: lantiq: switch to using gpiod API") not +only switched to the gpiod API, but also inverted / changed the polarity +of the GPIO. + +According to the PCI specification, the RST# pin is an active-low +signal. However, most of the device trees that have been widely used for +a long time (mainly in the openWrt project) define this GPIO as +active-high and the old driver code inverted the signal internally. + +Apparently there are actually boards where the reset gpio must be +operated inverted. For this reason, we cannot use the GPIOD_OUT_LOW/HIGH +flag for initialization. Instead, we must explicitly set the gpio to +value 1 in order to take into account any "GPIO_ACTIVE_LOW" flag that +may have been set. + +In order to remain compatible with all these existing device trees, we +should therefore keep the logic as it was before the commit. + +Fixes: 90c2d2eb7ab5 ("MIPS: pci: lantiq: switch to using gpiod API") +Cc: stable@vger.kernel.org +Signed-off-by: Martin Schiller +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + arch/mips/pci/pci-lantiq.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c +index 68a8cefed420b..0844db34022e4 100644 +--- a/arch/mips/pci/pci-lantiq.c ++++ b/arch/mips/pci/pci-lantiq.c +@@ -124,14 +124,14 @@ static int ltq_pci_startup(struct platform_device *pdev) + clk_disable(clk_external); + + /* setup reset gpio used by pci */ +- reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", +- GPIOD_OUT_LOW); ++ reset_gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_ASIS); + error = PTR_ERR_OR_ZERO(reset_gpio); + if (error) { + dev_err(&pdev->dev, "failed to request gpio: %d\n", error); + return error; + } + gpiod_set_consumer_name(reset_gpio, "pci_reset"); ++ gpiod_direction_output(reset_gpio, 1); + + /* enable auto-switching between PCI and EBU */ + ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); +@@ -194,10 +194,10 @@ static int ltq_pci_startup(struct platform_device *pdev) + + /* toggle reset pin */ + if (reset_gpio) { +- gpiod_set_value_cansleep(reset_gpio, 1); ++ gpiod_set_value_cansleep(reset_gpio, 0); + wmb(); + mdelay(1); +- gpiod_set_value_cansleep(reset_gpio, 0); ++ gpiod_set_value_cansleep(reset_gpio, 1); + } + return 0; + } +-- +2.43.0 + diff --git a/queue-6.9/pwm-stm32-calculate-prescaler-with-a-division-instea.patch b/queue-6.9/pwm-stm32-calculate-prescaler-with-a-division-instea.patch new file mode 100644 index 00000000000..d628dc98858 --- /dev/null +++ b/queue-6.9/pwm-stm32-calculate-prescaler-with-a-division-instea.patch @@ -0,0 +1,77 @@ +From 44ca2eb625f4693b99d63a97bd906660d3bc16b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Mar 2024 22:52:16 +0100 +Subject: pwm: stm32: Calculate prescaler with a division instead of a loop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 8002fbeef1e469b2c397d5cd2940e37b32a17849 ] + +Instead of looping over increasing values for the prescaler and testing +if it's big enough, calculate the value using a single division. + +Link: https://lore.kernel.org/r/498a44b313a6c0a84ccddd03cd67aadaaaf7daf2.1710711976.git.u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Stable-dep-of: c45fcf46ca23 ("pwm: stm32: Refuse too small period requests") +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-stm32.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c +index 27fcc90504f67..1c8911353b81d 100644 +--- a/drivers/pwm/pwm-stm32.c ++++ b/drivers/pwm/pwm-stm32.c +@@ -311,29 +311,33 @@ 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, + u64 duty_ns, u64 period_ns) + { +- unsigned long long prd, div, dty; +- unsigned int prescaler = 0; ++ unsigned long long prd, dty; ++ unsigned long long prescaler; + u32 ccmr, mask, shift; + + /* + * .probe() asserted that clk_get_rate() is not bigger than 1 GHz, so +- * this won't overflow. ++ * the calculations here won't overflow. ++ * First we need to find the minimal value for prescaler such that ++ * ++ * period_ns * clkrate ++ * ------------------------------ ++ * NSEC_PER_SEC * (prescaler + 1) ++ * ++ * isn't bigger than max_arr. + */ +- div = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk), +- NSEC_PER_SEC); +- prd = div; +- +- while (div > priv->max_arr) { +- prescaler++; +- div = prd; +- do_div(div, prescaler + 1); +- } + +- prd = div; ++ prescaler = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk), ++ (u64)NSEC_PER_SEC * priv->max_arr); ++ if (prescaler > 0) ++ prescaler -= 1; + + if (prescaler > MAX_TIM_PSC) + return -EINVAL; + ++ prd = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk), ++ (u64)NSEC_PER_SEC * (prescaler + 1)); ++ + /* + * All channels share the same prescaler and counter so when two + * channels are active at the same time we can't change them +-- +2.43.0 + diff --git a/queue-6.9/pwm-stm32-fix-for-settings-using-period-uint32_max.patch b/queue-6.9/pwm-stm32-fix-for-settings-using-period-uint32_max.patch new file mode 100644 index 00000000000..ff9830a1739 --- /dev/null +++ b/queue-6.9/pwm-stm32-fix-for-settings-using-period-uint32_max.patch @@ -0,0 +1,89 @@ +From 00fb789a41beba8c6654a8b319ab479d9263bb53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Mar 2024 22:52:15 +0100 +Subject: pwm: stm32: Fix for settings using period > UINT32_MAX +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ 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@pengutronix.de +Signed-off-by: Uwe Kleine-König +Stable-dep-of: c45fcf46ca23 ("pwm: stm32: Refuse too small period requests") +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-stm32.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +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. */ +-- +2.43.0 + diff --git a/queue-6.9/pwm-stm32-improve-precision-of-calculation-in-.apply.patch b/queue-6.9/pwm-stm32-improve-precision-of-calculation-in-.apply.patch new file mode 100644 index 00000000000..22dd456b942 --- /dev/null +++ b/queue-6.9/pwm-stm32-improve-precision-of-calculation-in-.apply.patch @@ -0,0 +1,64 @@ +From e910bcd4d018e3f4b0f49efd8e10b11703b5ef58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Mar 2024 22:52:14 +0100 +Subject: pwm: stm32: Improve precision of calculation in .apply() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit e419617847b688799a91126eb6c94b936bfb35ff ] + +While mathematically it's ok to calculate the number of cyles for the +duty cycle as: + + duty_cycles = period_cycles * duty_ns / period_ns + +this doesn't always give the right result when doing integer math. This +is best demonstrated using an example: With the input clock running at +208877930 Hz a request for duty_cycle = 383 ns and period = 49996 ns +results in + + period_cycles = clkrate * period_ns / NSEC_PER_SEC = 10443.06098828 + +Now calculating duty_cycles with the above formula gives: + + duty_cycles = 10443.06098828 * 383 / 49996 = 80.00024719 + +However with period_cycle truncated to an integer results in: + + duty_cycles = 10443 * 383 / 49996 = 79.99977998239859 + +So while a value of (a little more than) 80 would be the right result, +only 79 is used here. The problem here is that 14443 is a rounded result +that should better not be used to do further math. So to fix that use +the exact formular similar to how period_cycles is calculated. + +Link: https://lore.kernel.org/r/7628ecd8a7538aa5a7397f0fc4199a077168e8a6.1710711976.git.u.kleine-koenig@pengutronix.de +Signed-off-by: Uwe Kleine-König +Stable-dep-of: c45fcf46ca23 ("pwm: stm32: Refuse too small period requests") +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-stm32.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c +index 0c028d17c0752..d50194ad24b1c 100644 +--- a/drivers/pwm/pwm-stm32.c ++++ b/drivers/pwm/pwm-stm32.c +@@ -351,8 +351,9 @@ 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 = prd * duty_ns; +- do_div(dty, period_ns); ++ dty = (unsigned long long)clk_get_rate(priv->clk) * duty_ns; ++ do_div(dty, prescaler + 1); ++ do_div(dty, NSEC_PER_SEC); + + regmap_write(priv->regmap, TIM_CCR1 + 4 * ch, dty); + +-- +2.43.0 + diff --git a/queue-6.9/pwm-stm32-refuse-too-small-period-requests.patch b/queue-6.9/pwm-stm32-refuse-too-small-period-requests.patch new file mode 100644 index 00000000000..e3dbf8a99d3 --- /dev/null +++ b/queue-6.9/pwm-stm32-refuse-too-small-period-requests.patch @@ -0,0 +1,46 @@ +From cdf1762592f778dbfec99a8f9c9cc6740b4ffc94 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jun 2024 16:37:12 +0200 +Subject: pwm: stm32: Refuse too small period requests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit c45fcf46ca2368dafe7e5c513a711a6f0f974308 ] + +If period_ns is small, prd might well become 0. Catch that case because +otherwise with + + regmap_write(priv->regmap, TIM_ARR, prd - 1); + +a few lines down quite a big period is configured. + +Fixes: 7edf7369205b ("pwm: Add driver for STM32 plaftorm") +Cc: stable@vger.kernel.org +Reviewed-by: Trevor Gamblin +Signed-off-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/b86f62f099983646f97eeb6bfc0117bb2d0c340d.1718979150.git.u.kleine-koenig@baylibre.com +Signed-off-by: Uwe Kleine-König +Signed-off-by: Sasha Levin +--- + drivers/pwm/pwm-stm32.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c +index 1c8911353b81d..a8a1075f932df 100644 +--- a/drivers/pwm/pwm-stm32.c ++++ b/drivers/pwm/pwm-stm32.c +@@ -337,6 +337,8 @@ static int stm32_pwm_config(struct stm32_pwm *priv, unsigned int ch, + + prd = mul_u64_u64_div_u64(period_ns, clk_get_rate(priv->clk), + (u64)NSEC_PER_SEC * (prescaler + 1)); ++ if (!prd) ++ return -EINVAL; + + /* + * All channels share the same prescaler and counter so when two +-- +2.43.0 + diff --git a/queue-6.9/series b/queue-6.9/series index 6ac918fd039..932a2a6d3c3 100644 --- a/queue-6.9/series +++ b/queue-6.9/series @@ -7,3 +7,8 @@ pinctrl-rockchip-fix-pinmux-bits-for-rk3328-gpio2-b-.patch pinctrl-rockchip-fix-pinmux-bits-for-rk3328-gpio3-b-.patch pinctrl-rockchip-use-dedicated-pinctrl-type-for-rk33.patch pinctrl-rockchip-fix-pinmux-reset-in-rockchip_pmx_se.patch +mips-pci-lantiq-restore-reset-gpio-polarity.patch +pwm-stm32-improve-precision-of-calculation-in-.apply.patch +pwm-stm32-fix-for-settings-using-period-uint32_max.patch +pwm-stm32-calculate-prescaler-with-a-division-instea.patch +pwm-stm32-refuse-too-small-period-requests.patch -- 2.47.3