* [PATCH 1/6] pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
@ 2025-04-05 9:27 ` Uwe Kleine-König
2025-04-07 12:52 ` Trevor Gamblin
2025-04-05 9:27 ` [PATCH 2/6] pwm: stm32: Search an appropriate duty_cycle if period cannot be modified Uwe Kleine-König
` (5 subsequent siblings)
6 siblings, 1 reply; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-05 9:27 UTC (permalink / raw)
To: linux-pwm; +Cc: linux-kernel
Waveform parameters are supposed to be rounded down to the next value
possible for the hardware. However when a requested value is too small,
.round_waveform_tohw() is supposed to pick the next bigger value and
return 1. Let pwm_set_waveform() behave in the same way.
This creates consistency between pwm_set_waveform_might_sleep() with
exact=false and pwm_round_waveform_might_sleep() +
pwm_set_waveform_might_sleep() with exact=true.
The PWM_DEBUG rounding check has to be adapted to only trigger if no
uprounding happend.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/pwm/core.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index a40c511e0096..0387bd838487 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -322,7 +322,7 @@ static int __pwm_set_waveform(struct pwm_device *pwm,
const struct pwm_ops *ops = chip->ops;
char wfhw[WFHWSIZE];
struct pwm_waveform wf_rounded;
- int err;
+ int err, ret_tohw;
BUG_ON(WFHWSIZE < ops->sizeof_wfhw);
@@ -332,16 +332,16 @@ static int __pwm_set_waveform(struct pwm_device *pwm,
if (!pwm_wf_valid(wf))
return -EINVAL;
- err = __pwm_round_waveform_tohw(chip, pwm, wf, &wfhw);
- if (err)
- return err;
+ ret_tohw = __pwm_round_waveform_tohw(chip, pwm, wf, &wfhw);
+ if (ret_tohw < 0)
+ return ret_tohw;
if ((IS_ENABLED(CONFIG_PWM_DEBUG) || exact) && wf->period_length_ns) {
err = __pwm_round_waveform_fromhw(chip, pwm, &wfhw, &wf_rounded);
if (err)
return err;
- if (IS_ENABLED(CONFIG_PWM_DEBUG) && !pwm_check_rounding(wf, &wf_rounded))
+ if (IS_ENABLED(CONFIG_PWM_DEBUG) && ret_tohw == 0 && !pwm_check_rounding(wf, &wf_rounded))
dev_err(&chip->dev, "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu]\n",
wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns,
wf_rounded.duty_length_ns, wf_rounded.period_length_ns, wf_rounded.duty_offset_ns);
@@ -382,7 +382,8 @@ static int __pwm_set_waveform(struct pwm_device *pwm,
wf_rounded.duty_length_ns, wf_rounded.period_length_ns, wf_rounded.duty_offset_ns,
wf_set.duty_length_ns, wf_set.period_length_ns, wf_set.duty_offset_ns);
}
- return 0;
+
+ return ret_tohw;
}
/**
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 1/6] pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up
2025-04-05 9:27 ` [PATCH 1/6] pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up Uwe Kleine-König
@ 2025-04-07 12:52 ` Trevor Gamblin
0 siblings, 0 replies; 13+ messages in thread
From: Trevor Gamblin @ 2025-04-07 12:52 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm; +Cc: linux-kernel
On 2025-04-05 05:27, Uwe Kleine-König wrote:
> Waveform parameters are supposed to be rounded down to the next value
> possible for the hardware. However when a requested value is too small,
> .round_waveform_tohw() is supposed to pick the next bigger value and
> return 1. Let pwm_set_waveform() behave in the same way.
>
> This creates consistency between pwm_set_waveform_might_sleep() with
> exact=false and pwm_round_waveform_might_sleep() +
> pwm_set_waveform_might_sleep() with exact=true.
>
> The PWM_DEBUG rounding check has to be adapted to only trigger if no
> uprounding happend.
>
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Tested-by: Trevor Gamblin <tgamblin@baylibre.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 2/6] pwm: stm32: Search an appropriate duty_cycle if period cannot be modified
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
2025-04-05 9:27 ` [PATCH 1/6] pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up Uwe Kleine-König
@ 2025-04-05 9:27 ` Uwe Kleine-König
2025-04-05 9:27 ` [PATCH 3/6] pwm: stm32: Don't open-code TIM_CCER_CCxE() Uwe Kleine-König
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-05 9:27 UTC (permalink / raw)
To: linux-pwm
Cc: Fabrice Gasnier, Maxime Coquelin, Alexandre Torgue, linux-stm32,
linux-arm-kernel, linux-kernel
If another channel is already enabled period must not be modified. If
the requested period is smaller than this unchangable period the driver
is still supposed to search a duty_cycle according to the usual rounding
rules.
So don't set the duty_cycle to 0 but continue to determine an
appropriate value for ccr.
Fixes: deaba9cff809 ("pwm: stm32: Implementation of the waveform callbacks")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/pwm/pwm-stm32.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index a59de4de18b6..ec2c05c9ee7a 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -103,22 +103,16 @@ static int stm32_pwm_round_waveform_tohw(struct pwm_chip *chip,
if (ret)
goto out;
- /*
- * calculate the best value for ARR for the given PSC, refuse if
- * the resulting period gets bigger than the requested one.
- */
arr = mul_u64_u64_div_u64(wf->period_length_ns, rate,
(u64)NSEC_PER_SEC * (wfhw->psc + 1));
if (arr <= wfhw->arr) {
/*
- * requested period is small than the currently
+ * requested period is smaller than the currently
* configured and unchangable period, report back the smallest
- * possible period, i.e. the current state; Initialize
- * ccr to anything valid.
+ * possible period, i.e. the current state and return 1
+ * to indicate the wrong rounding direction.
*/
- wfhw->ccr = 0;
ret = 1;
- goto out;
}
} else {
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 3/6] pwm: stm32: Don't open-code TIM_CCER_CCxE()
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
2025-04-05 9:27 ` [PATCH 1/6] pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up Uwe Kleine-König
2025-04-05 9:27 ` [PATCH 2/6] pwm: stm32: Search an appropriate duty_cycle if period cannot be modified Uwe Kleine-König
@ 2025-04-05 9:27 ` Uwe Kleine-König
2025-04-05 9:27 ` [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks Uwe Kleine-König
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-05 9:27 UTC (permalink / raw)
To: linux-pwm
Cc: Fabrice Gasnier, Maxime Coquelin, Alexandre Torgue, linux-stm32,
linux-arm-kernel, linux-kernel
Instead of manually calculating the offset of the channels CCxE bit,
make use of the TIM_CCER_CCxE macro.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/pwm/pwm-stm32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index ec2c05c9ee7a..c6625f51a199 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -88,7 +88,7 @@ static int stm32_pwm_round_waveform_tohw(struct pwm_chip *chip,
rate = clk_get_rate(priv->clk);
- if (active_channels(priv) & ~(1 << ch * 4)) {
+ if (active_channels(priv) & ~TIM_CCER_CCxE(ch + 1)) {
u64 arr;
/*
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
` (2 preceding siblings ...)
2025-04-05 9:27 ` [PATCH 3/6] pwm: stm32: Don't open-code TIM_CCER_CCxE() Uwe Kleine-König
@ 2025-04-05 9:27 ` Uwe Kleine-König
2025-04-05 22:15 ` kernel test robot
2025-04-06 4:58 ` kernel test robot
2025-04-05 9:27 ` [PATCH 5/6] pwm: axi-pwmgen: Let .round_waveform_tohw() signal when request was rounded up Uwe Kleine-König
` (2 subsequent siblings)
6 siblings, 2 replies; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-05 9:27 UTC (permalink / raw)
To: linux-pwm
Cc: Fabrice Gasnier, Maxime Coquelin, Alexandre Torgue, linux-stm32,
linux-arm-kernel, linux-kernel
When you're interested in the actual register settings the driver
chooses or interprets you want to see them also for calls that hit
corner cases.
Make sure that all calls to stm32_pwm_round_waveform_tohw() and
stm32_pwm_round_waveform_fromhw() emit the debug message about the
register settings.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/pwm/pwm-stm32.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index c6625f51a199..dca5d09d80b9 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -180,11 +180,11 @@ static int stm32_pwm_round_waveform_tohw(struct pwm_chip *chip,
wfhw->ccr = min_t(u64, ccr, wfhw->arr + 1);
+out:
dev_dbg(&chip->dev, "pwm#%u: %lld/%lld [+%lld] @%lu -> CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x\n",
pwm->hwpwm, wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns,
rate, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr);
-out:
clk_disable(priv->clk);
return ret;
@@ -236,17 +236,16 @@ static int stm32_pwm_round_waveform_fromhw(struct pwm_chip *chip,
wf->duty_length_ns = ccr_ns;
wf->duty_offset_ns = 0;
}
-
- dev_dbg(&chip->dev, "pwm#%u: CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x @%lu -> %lld/%lld [+%lld]\n",
- pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
- wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns);
-
} else {
*wf = (struct pwm_waveform){
.period_length_ns = 0,
};
}
+ dev_dbg(&chip->dev, "pwm#%u: CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x @%lu -> %lld/%lld [+%lld]\n",
+ pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
+ wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns);
+
return 0;
}
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks
2025-04-05 9:27 ` [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks Uwe Kleine-König
@ 2025-04-05 22:15 ` kernel test robot
2025-04-06 4:58 ` kernel test robot
1 sibling, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-04-05 22:15 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm
Cc: oe-kbuild-all, Fabrice Gasnier, Maxime Coquelin, Alexandre Torgue,
linux-stm32, linux-arm-kernel, linux-kernel
Hi Uwe,
kernel test robot noticed the following build errors:
[auto build test ERROR on e48e99b6edf41c69c5528aa7ffb2daf3c59ee105]
url: https://github.com/intel-lab-lkp/linux/commits/Uwe-Kleine-K-nig/pwm-Let-pwm_set_waveform-succeed-even-if-lowlevel-driver-rounded-up/20250405-173024
base: e48e99b6edf41c69c5528aa7ffb2daf3c59ee105
patch link: https://lore.kernel.org/r/fe154e79319da5ff4159cdc71201a9d3b395e491.1743844730.git.u.kleine-koenig%40baylibre.com
patch subject: [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks
config: arm-randconfig-004-20250406 (https://download.01.org/0day-ci/archive/20250406/202504060517.dHXuUANs-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 10.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250406/202504060517.dHXuUANs-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202504060517.dHXuUANs-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from include/linux/device.h:15,
from include/linux/dmaengine.h:8,
from include/linux/mfd/stm32-timers.h:11,
from drivers/pwm/pwm-stm32.c:12:
drivers/pwm/pwm-stm32.c: In function 'stm32_pwm_round_waveform_fromhw':
>> drivers/pwm/pwm-stm32.c:246:60: error: 'rate' undeclared (first use in this function)
246 | pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
| ^~~~
include/linux/dev_printk.h:139:35: note: in definition of macro 'dev_no_printk'
139 | _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
| ^~~~~~~~~~~
drivers/pwm/pwm-stm32.c:245:2: note: in expansion of macro 'dev_dbg'
245 | dev_dbg(&chip->dev, "pwm#%u: CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x @%lu -> %lld/%lld [+%lld]\n",
| ^~~~~~~
drivers/pwm/pwm-stm32.c:246:60: note: each undeclared identifier is reported only once for each function it appears in
246 | pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
| ^~~~
include/linux/dev_printk.h:139:35: note: in definition of macro 'dev_no_printk'
139 | _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
| ^~~~~~~~~~~
drivers/pwm/pwm-stm32.c:245:2: note: in expansion of macro 'dev_dbg'
245 | dev_dbg(&chip->dev, "pwm#%u: CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x @%lu -> %lld/%lld [+%lld]\n",
| ^~~~~~~
vim +/rate +246 drivers/pwm/pwm-stm32.c
208
209 static int stm32_pwm_round_waveform_fromhw(struct pwm_chip *chip,
210 struct pwm_device *pwm,
211 const void *_wfhw,
212 struct pwm_waveform *wf)
213 {
214 const struct stm32_pwm_waveform *wfhw = _wfhw;
215 struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
216 unsigned int ch = pwm->hwpwm;
217
218 if (wfhw->ccer & TIM_CCER_CCxE(ch + 1)) {
219 unsigned long rate = clk_get_rate(priv->clk);
220 u64 ccr_ns;
221
222 /* The result doesn't overflow for rate >= 15259 */
223 wf->period_length_ns = stm32_pwm_mul_u64_u64_div_u64_roundup(((u64)wfhw->psc + 1) * (wfhw->arr + 1),
224 NSEC_PER_SEC, rate);
225
226 ccr_ns = stm32_pwm_mul_u64_u64_div_u64_roundup(((u64)wfhw->psc + 1) * wfhw->ccr,
227 NSEC_PER_SEC, rate);
228
229 if (wfhw->ccer & TIM_CCER_CCxP(ch + 1)) {
230 wf->duty_length_ns =
231 stm32_pwm_mul_u64_u64_div_u64_roundup(((u64)wfhw->psc + 1) * (wfhw->arr + 1 - wfhw->ccr),
232 NSEC_PER_SEC, rate);
233
234 wf->duty_offset_ns = ccr_ns;
235 } else {
236 wf->duty_length_ns = ccr_ns;
237 wf->duty_offset_ns = 0;
238 }
239 } else {
240 *wf = (struct pwm_waveform){
241 .period_length_ns = 0,
242 };
243 }
244
245 dev_dbg(&chip->dev, "pwm#%u: CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x @%lu -> %lld/%lld [+%lld]\n",
> 246 pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
247 wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns);
248
249 return 0;
250 }
251
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks
2025-04-05 9:27 ` [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks Uwe Kleine-König
2025-04-05 22:15 ` kernel test robot
@ 2025-04-06 4:58 ` kernel test robot
1 sibling, 0 replies; 13+ messages in thread
From: kernel test robot @ 2025-04-06 4:58 UTC (permalink / raw)
To: Uwe Kleine-König, linux-pwm
Cc: llvm, oe-kbuild-all, Fabrice Gasnier, Maxime Coquelin,
Alexandre Torgue, linux-stm32, linux-arm-kernel, linux-kernel
Hi Uwe,
kernel test robot noticed the following build errors:
[auto build test ERROR on e48e99b6edf41c69c5528aa7ffb2daf3c59ee105]
url: https://github.com/intel-lab-lkp/linux/commits/Uwe-Kleine-K-nig/pwm-Let-pwm_set_waveform-succeed-even-if-lowlevel-driver-rounded-up/20250405-173024
base: e48e99b6edf41c69c5528aa7ffb2daf3c59ee105
patch link: https://lore.kernel.org/r/fe154e79319da5ff4159cdc71201a9d3b395e491.1743844730.git.u.kleine-koenig%40baylibre.com
patch subject: [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks
config: x86_64-buildonly-randconfig-001-20250406 (https://download.01.org/0day-ci/archive/20250406/202504061207.97zbNPvV-lkp@intel.com/config)
compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250406/202504061207.97zbNPvV-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202504061207.97zbNPvV-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/pwm/pwm-stm32.c:246:60: error: use of undeclared identifier 'rate'
246 | pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
| ^
1 error generated.
vim +/rate +246 drivers/pwm/pwm-stm32.c
208
209 static int stm32_pwm_round_waveform_fromhw(struct pwm_chip *chip,
210 struct pwm_device *pwm,
211 const void *_wfhw,
212 struct pwm_waveform *wf)
213 {
214 const struct stm32_pwm_waveform *wfhw = _wfhw;
215 struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
216 unsigned int ch = pwm->hwpwm;
217
218 if (wfhw->ccer & TIM_CCER_CCxE(ch + 1)) {
219 unsigned long rate = clk_get_rate(priv->clk);
220 u64 ccr_ns;
221
222 /* The result doesn't overflow for rate >= 15259 */
223 wf->period_length_ns = stm32_pwm_mul_u64_u64_div_u64_roundup(((u64)wfhw->psc + 1) * (wfhw->arr + 1),
224 NSEC_PER_SEC, rate);
225
226 ccr_ns = stm32_pwm_mul_u64_u64_div_u64_roundup(((u64)wfhw->psc + 1) * wfhw->ccr,
227 NSEC_PER_SEC, rate);
228
229 if (wfhw->ccer & TIM_CCER_CCxP(ch + 1)) {
230 wf->duty_length_ns =
231 stm32_pwm_mul_u64_u64_div_u64_roundup(((u64)wfhw->psc + 1) * (wfhw->arr + 1 - wfhw->ccr),
232 NSEC_PER_SEC, rate);
233
234 wf->duty_offset_ns = ccr_ns;
235 } else {
236 wf->duty_length_ns = ccr_ns;
237 wf->duty_offset_ns = 0;
238 }
239 } else {
240 *wf = (struct pwm_waveform){
241 .period_length_ns = 0,
242 };
243 }
244
245 dev_dbg(&chip->dev, "pwm#%u: CCER: %08x, PSC: %08x, ARR: %08x, CCR: %08x @%lu -> %lld/%lld [+%lld]\n",
> 246 pwm->hwpwm, wfhw->ccer, wfhw->psc, wfhw->arr, wfhw->ccr, rate,
247 wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns);
248
249 return 0;
250 }
251
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 5/6] pwm: axi-pwmgen: Let .round_waveform_tohw() signal when request was rounded up
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
` (3 preceding siblings ...)
2025-04-05 9:27 ` [PATCH 4/6] pwm: stm32: Emit debug output also for corner cases of the rounding callbacks Uwe Kleine-König
@ 2025-04-05 9:27 ` Uwe Kleine-König
2025-04-07 12:52 ` Trevor Gamblin
2025-04-05 9:27 ` [PATCH 6/6] pwm: Do stricter return value checking for .round_waveform_tohw() Uwe Kleine-König
2025-04-07 10:24 ` [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
6 siblings, 1 reply; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-05 9:27 UTC (permalink / raw)
To: linux-pwm; +Cc: Michael Hennerich, Nuno Sá, Trevor Gamblin, linux-kernel
The .round_waveform_tohw() is supposed to return 1 if the requested
waveform cannot be implemented by rounding down all parameters. Also
adapt the corresponding comment to better describe why the implemented
procedure is right.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/pwm/pwm-axi-pwmgen.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/pwm/pwm-axi-pwmgen.c b/drivers/pwm/pwm-axi-pwmgen.c
index 4259a0db9ff4..4337c8f5acf0 100644
--- a/drivers/pwm/pwm-axi-pwmgen.c
+++ b/drivers/pwm/pwm-axi-pwmgen.c
@@ -75,6 +75,7 @@ static int axi_pwmgen_round_waveform_tohw(struct pwm_chip *chip,
{
struct axi_pwmgen_waveform *wfhw = _wfhw;
struct axi_pwmgen_ddata *ddata = axi_pwmgen_ddata_from_chip(chip);
+ int ret = 0;
if (wf->period_length_ns == 0) {
*wfhw = (struct axi_pwmgen_waveform){
@@ -91,12 +92,15 @@ static int axi_pwmgen_round_waveform_tohw(struct pwm_chip *chip,
if (wfhw->period_cnt == 0) {
/*
* The specified period is too short for the hardware.
- * Let's round .duty_cycle down to 0 to get a (somewhat)
- * valid result.
+ * So round up .period_cnt to 1 (i.e. the smallest
+ * possible period). With .duty_cycle and .duty_offset
+ * being less than or equal to .period, their rounded
+ * value must be 0.
*/
wfhw->period_cnt = 1;
wfhw->duty_cycle_cnt = 0;
wfhw->duty_offset_cnt = 0;
+ ret = 1;
} else {
wfhw->duty_cycle_cnt = min_t(u64,
mul_u64_u32_div(wf->duty_length_ns, ddata->clk_rate_hz, NSEC_PER_SEC),
@@ -111,7 +115,7 @@ static int axi_pwmgen_round_waveform_tohw(struct pwm_chip *chip,
pwm->hwpwm, wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns,
ddata->clk_rate_hz, wfhw->period_cnt, wfhw->duty_cycle_cnt, wfhw->duty_offset_cnt);
- return 0;
+ return ret;
}
static int axi_pwmgen_round_waveform_fromhw(struct pwm_chip *chip, struct pwm_device *pwm,
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 6/6] pwm: Do stricter return value checking for .round_waveform_tohw()
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
` (4 preceding siblings ...)
2025-04-05 9:27 ` [PATCH 5/6] pwm: axi-pwmgen: Let .round_waveform_tohw() signal when request was rounded up Uwe Kleine-König
@ 2025-04-05 9:27 ` Uwe Kleine-König
2025-04-07 10:24 ` [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
6 siblings, 0 replies; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-05 9:27 UTC (permalink / raw)
To: linux-pwm; +Cc: linux-kernel
The .round_waveform_tohw() is supposed to return 0 if the request could
be rounded down to match the hardware capabilities and return 1 if
rounding down wasn't possible.
Expand the PWM_DEBUG check to not only assert proper downrounding if 0
was returned but also check that it was actually rounded up when the
callback signalled uprounding.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/pwm/core.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 0387bd838487..1a9d497f5cfe 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -270,10 +270,10 @@ int pwm_round_waveform_might_sleep(struct pwm_device *pwm, struct pwm_waveform *
wf_req.duty_length_ns, wf_req.period_length_ns, wf_req.duty_offset_ns, ret_tohw);
if (IS_ENABLED(CONFIG_PWM_DEBUG) &&
- ret_tohw == 0 && !pwm_check_rounding(&wf_req, wf))
- dev_err(&chip->dev, "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu]\n",
+ (ret_tohw == 0) != pwm_check_rounding(&wf_req, wf))
+ dev_err(&chip->dev, "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu], ret: %d\n",
wf_req.duty_length_ns, wf_req.period_length_ns, wf_req.duty_offset_ns,
- wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns);
+ wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns, ret_tohw);
return ret_tohw;
}
@@ -341,10 +341,10 @@ static int __pwm_set_waveform(struct pwm_device *pwm,
if (err)
return err;
- if (IS_ENABLED(CONFIG_PWM_DEBUG) && ret_tohw == 0 && !pwm_check_rounding(wf, &wf_rounded))
- dev_err(&chip->dev, "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu]\n",
+ if (IS_ENABLED(CONFIG_PWM_DEBUG) && (ret_tohw == 0) != pwm_check_rounding(wf, &wf_rounded))
+ dev_err(&chip->dev, "Wrong rounding: requested %llu/%llu [+%llu], result %llu/%llu [+%llu], ret: %d\n",
wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns,
- wf_rounded.duty_length_ns, wf_rounded.period_length_ns, wf_rounded.duty_offset_ns);
+ wf_rounded.duty_length_ns, wf_rounded.period_length_ns, wf_rounded.duty_offset_ns, ret_tohw);
if (exact && pwmwfcmp(wf, &wf_rounded)) {
dev_dbg(&chip->dev, "Requested no rounding, but %llu/%llu [+%llu] -> %llu/%llu [+%llu]\n",
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH 0/6] pwm: Some fixes preparing chardev support
2025-04-05 9:27 [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
` (5 preceding siblings ...)
2025-04-05 9:27 ` [PATCH 6/6] pwm: Do stricter return value checking for .round_waveform_tohw() Uwe Kleine-König
@ 2025-04-07 10:24 ` Uwe Kleine-König
2025-04-07 15:16 ` Uwe Kleine-König
6 siblings, 1 reply; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-07 10:24 UTC (permalink / raw)
To: linux-pwm
Cc: linux-kernel, Fabrice Gasnier, Maxime Coquelin, Alexandre Torgue,
linux-stm32, linux-arm-kernel, Michael Hennerich, Nuno Sá,
Trevor Gamblin
[-- Attachment #1: Type: text/plain, Size: 1310 bytes --]
On Sat, Apr 05, 2025 at 11:27:11AM +0200, Uwe Kleine-König wrote:
> Hello,
>
> while working on character device support for PWMs I found a few
> inconsistencies that are fixed in this series. After that I plan to work
> on getting the character device support into shape to get it into
> mainline, too.
>
> While some of these patches qualify as fixes I think there is no urge to
> get them into 6.15, but given there is a bunch of such changes I might
> send them to all together to Linus for inclusion to 6.15.
>
> Best regards
> Uwe
>
> Uwe Kleine-König (6):
> pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up
> pwm: stm32: Search an appropriate duty_cycle if period cannot be
> modified
> pwm: stm32: Don't open-code TIM_CCER_CCxE()
> pwm: stm32: Emit debug output also for corner cases of the rounding
> callbacks
> pwm: axi-pwmgen: Let .round_waveform_tohw() signal when request was
> rounded up
> pwm: Do stricter return value checking for .round_waveform_tohw()
I applied patches #1, #2 and #5 to
https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git pwm/fixes
I still havn't made up my mind about trying to get these into v6.15, but
at least they should be included in next for now.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH 0/6] pwm: Some fixes preparing chardev support
2025-04-07 10:24 ` [PATCH 0/6] pwm: Some fixes preparing chardev support Uwe Kleine-König
@ 2025-04-07 15:16 ` Uwe Kleine-König
0 siblings, 0 replies; 13+ messages in thread
From: Uwe Kleine-König @ 2025-04-07 15:16 UTC (permalink / raw)
To: linux-pwm
Cc: linux-kernel, Fabrice Gasnier, Maxime Coquelin, Alexandre Torgue,
linux-stm32, linux-arm-kernel, Michael Hennerich, Nuno Sá,
Trevor Gamblin
[-- Attachment #1: Type: text/plain, Size: 2148 bytes --]
On Mon, Apr 07, 2025 at 12:24:31PM +0200, Uwe Kleine-König wrote:
> On Sat, Apr 05, 2025 at 11:27:11AM +0200, Uwe Kleine-König wrote:
> > Hello,
> >
> > while working on character device support for PWMs I found a few
> > inconsistencies that are fixed in this series. After that I plan to work
> > on getting the character device support into shape to get it into
> > mainline, too.
> >
> > While some of these patches qualify as fixes I think there is no urge to
> > get them into 6.15, but given there is a bunch of such changes I might
> > send them to all together to Linus for inclusion to 6.15.
> >
> > Best regards
> > Uwe
> >
> > Uwe Kleine-König (6):
> > pwm: Let pwm_set_waveform() succeed even if lowlevel driver rounded up
> > pwm: stm32: Search an appropriate duty_cycle if period cannot be
> > modified
> > pwm: stm32: Don't open-code TIM_CCER_CCxE()
> > pwm: stm32: Emit debug output also for corner cases of the rounding
> > callbacks
> > pwm: axi-pwmgen: Let .round_waveform_tohw() signal when request was
> > rounded up
> > pwm: Do stricter return value checking for .round_waveform_tohw()
>
> I applied patches #1, #2 and #5 to
> https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git pwm/fixes
And patches #3, #4 and #6 applied to
https://git.kernel.org/pub/scm/linux/kernel/git/ukleinek/linux.git pwm/for-next
with
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index dca5d09d80b9..4b148f0afeb9 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -213,10 +213,10 @@ static int stm32_pwm_round_waveform_fromhw(struct pwm_chip *chip,
{
const struct stm32_pwm_waveform *wfhw = _wfhw;
struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
+ unsigned long rate = clk_get_rate(priv->clk);
unsigned int ch = pwm->hwpwm;
if (wfhw->ccer & TIM_CCER_CCxE(ch + 1)) {
- unsigned long rate = clk_get_rate(priv->clk);
u64 ccr_ns;
/* The result doesn't overflow for rate >= 15259 */
squashed into #4 to fix the build failure that the 0day robot reported
in this thread.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply related [flat|nested] 13+ messages in thread