diff mbox series

[v2] pwm: bcm2835: improve precision of pwm

Message ID 20190603090058.qd3tbiffmdgqm34d@gofer.mess.org
State Accepted
Headers show
Series [v2] pwm: bcm2835: improve precision of pwm | expand

Commit Message

Sean Young June 3, 2019, 9 a.m. UTC
If sending IR with carrier of 455kHz using the pwm-ir-tx driver, the
carrier ends up being 476kHz. The clock is set to bcm2835-pwm with a
rate of 10MHz.

A carrier of 455kHz has a period of 2198ns, but the arithmetic truncates
this to 2100ns rather than 2200ns. So, use DIV_ROUND_CLOSEST() to reduce
rounding errors, and we have a much more accurate carrier of 454.5kHz.

Reported-by: Andreas Christ <andreas@christ-faesch.ch>
Signed-off-by: Sean Young <sean@mess.org>
---
 drivers/pwm/pwm-bcm2835.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Stefan Wahren June 11, 2019, 7:09 p.m. UTC | #1
Am 03.06.19 um 11:00 schrieb Sean Young:
> If sending IR with carrier of 455kHz using the pwm-ir-tx driver, the
> carrier ends up being 476kHz. The clock is set to bcm2835-pwm with a
> rate of 10MHz.
>
> A carrier of 455kHz has a period of 2198ns, but the arithmetic truncates
> this to 2100ns rather than 2200ns. So, use DIV_ROUND_CLOSEST() to reduce
> rounding errors, and we have a much more accurate carrier of 454.5kHz.
>
> Reported-by: Andreas Christ <andreas@christ-faesch.ch>
> Signed-off-by: Sean Young <sean@mess.org>

Acked-by: Stefan Wahren <wahrenst@gmx.net>

Thanks
Stefan Wahren June 19, 2019, 5:21 a.m. UTC | #2
Am 03.06.19 um 11:00 schrieb Sean Young:
> If sending IR with carrier of 455kHz using the pwm-ir-tx driver, the
> carrier ends up being 476kHz. The clock is set to bcm2835-pwm with a
> rate of 10MHz.
>
> A carrier of 455kHz has a period of 2198ns, but the arithmetic truncates
> this to 2100ns rather than 2200ns. So, use DIV_ROUND_CLOSEST() to reduce
> rounding errors, and we have a much more accurate carrier of 454.5kHz.
>
> Reported-by: Andreas Christ <andreas@christ-faesch.ch>
> Signed-off-by: Sean Young <sean@mess.org>
Acked-by: Stefan Wahren <wahrenst@gmx.de>
Uwe Kleine-König June 19, 2019, 7:22 a.m. UTC | #3
Hallo Stefan,

On Wed, Jun 19, 2019 at 07:21:43AM +0200, Stefan Wahren wrote:
> Am 03.06.19 um 11:00 schrieb Sean Young:
> > If sending IR with carrier of 455kHz using the pwm-ir-tx driver, the
> > carrier ends up being 476kHz. The clock is set to bcm2835-pwm with a
> > rate of 10MHz.
> >
> > A carrier of 455kHz has a period of 2198ns, but the arithmetic truncates
> > this to 2100ns rather than 2200ns. So, use DIV_ROUND_CLOSEST() to reduce
> > rounding errors, and we have a much more accurate carrier of 454.5kHz.
> >
> > Reported-by: Andreas Christ <andreas@christ-faesch.ch>
> > Signed-off-by: Sean Young <sean@mess.org>
> Acked-by: Stefan Wahren <wahrenst@gmx.de>

you already acked that with a slightly different mail address a week
ago. Was this intended?

Best regards
Uwe
Stefan Wahren June 19, 2019, 7:29 a.m. UTC | #4
Hi Uwe,

On 19.06.19 09:22, Uwe Kleine-König wrote:
> Hallo Stefan,
>
> On Wed, Jun 19, 2019 at 07:21:43AM +0200, Stefan Wahren wrote:
>> Am 03.06.19 um 11:00 schrieb Sean Young:
>>> If sending IR with carrier of 455kHz using the pwm-ir-tx driver, the
>>> carrier ends up being 476kHz. The clock is set to bcm2835-pwm with a
>>> rate of 10MHz.
>>>
>>> A carrier of 455kHz has a period of 2198ns, but the arithmetic truncates
>>> this to 2100ns rather than 2200ns. So, use DIV_ROUND_CLOSEST() to reduce
>>> rounding errors, and we have a much more accurate carrier of 454.5kHz.
>>>
>>> Reported-by: Andreas Christ <andreas@christ-faesch.ch>
>>> Signed-off-by: Sean Young <sean@mess.org>
>> Acked-by: Stefan Wahren <wahrenst@gmx.de>
> you already acked that with a slightly different mail address a week
> ago. Was this intended?

thanks. Please ignore this email this was a typo. The correct domain was
gmx.net.

Stefan

>
> Best regards
> Uwe
>
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-bcm2835.c b/drivers/pwm/pwm-bcm2835.c
index 5652f461d994..f6fe0b922e1e 100644
--- a/drivers/pwm/pwm-bcm2835.c
+++ b/drivers/pwm/pwm-bcm2835.c
@@ -70,7 +70,7 @@  static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 		return -EINVAL;
 	}
 
-	scaler = NSEC_PER_SEC / rate;
+	scaler = DIV_ROUND_CLOSEST(NSEC_PER_SEC, rate);
 
 	if (period_ns <= MIN_PERIOD) {
 		dev_err(pc->dev, "period %d not supported, minimum %d\n",
@@ -78,8 +78,10 @@  static int bcm2835_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 		return -EINVAL;
 	}
 
-	writel(duty_ns / scaler, pc->base + DUTY(pwm->hwpwm));
-	writel(period_ns / scaler, pc->base + PERIOD(pwm->hwpwm));
+	writel(DIV_ROUND_CLOSEST(duty_ns, scaler),
+	       pc->base + DUTY(pwm->hwpwm));
+	writel(DIV_ROUND_CLOSEST(period_ns, scaler),
+	       pc->base + PERIOD(pwm->hwpwm));
 
 	return 0;
 }