gpio: mvebu: pwm fixes and improvements
v2 cover gpio: mvebu: pwm fixes and improvements
This series adds a few related fixes to the pwm .apply and .get_state callbacks.
The first patch was originally part of the series adding Armada 8K/7K pwm support. I split it out to a separate series following review comments from Uwe Kleine-König who spotted a few more issues. There is no dependency between this and the Armada 8K/7K series.
v2:
Address Uwe Kleine-König comments.
* Improve patch 1/5 summary line
* Add more information to patch 1/5 description
* Add more information to patch 2/5 description
* Don't round period/duty_cycle up in .apply (patch 3/5)
* Expand the comment in path 5/5 based on RMK's analysis of hardware behaviour
* Add Uwe's Reviewed-by tags
Baruch Siach (5):
gpio: mvebu: fix pwm .get_state period calculation
gpio: mvebu: improve pwm period calculation accuracy
gpio: mvebu: make pwm .get_state closer to idempotent
gpio: mvebu: don't limit pwm period/duty_cycle to UINT_MAX
gpio: mvebu: document zero pwm duty cycle limitation
drivers/gpio/gpio-mvebu.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-)
Signature · 1 line
2.29.2
PATCH v2 1/5 gpio: mvebu: fix pwm .get_state period calculation
The period is the sum of on and off values. That is, calculate period as
($on + $off) / clkrate
instead of
$off / clkrate - $on / clkrate
that makes no sense.
--- drivers/gpio/gpio-mvebu.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
drivers/gpio/gpio-mvebu.c +8 -11
@@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,else state->duty_cycle =1 ; + val = (unsigned long long ) u;/* on duration */ regmap_read (mvpwm->regs,mvebu_pwmreg_blink_off_duration (mvpwm), &u); - val = (unsigned long long ) u *NSEC_PER_SEC ; + val += (unsigned long long ) u;/* period = on + off duration */ + val *=NSEC_PER_SEC ;do_div (val, mvpwm->clk_rate); -if (val < state->duty_cycle) { +if (val >UINT_MAX ) + state->period =UINT_MAX ; +else if (val) + state->period = val; +else state->period =1 ; - }else { - val -= state->duty_cycle; -if (val >UINT_MAX ) - state->period =UINT_MAX ; -else if (val) - state->period = val; -else - state->period =1 ; - }regmap_read (mvchip->regs,GPIO_BLINK_EN_OFF + mvchip->offset, &u);if (u)
Signature · 1 line
2.29.2
Re: [PATCH v2 1/5] gpio: mvebu: fix pwm .get_state period calculation
Quoted 6 lines · Baruch Siach
The period is the sum of on and off values. That is, calculate period as
($on + $off) / clkrate
instead of
Quoted 7 lines
$off / clkrate - $on / clkrate
that makes no sense.
Reported-by Russell King <[email protected]>Fixes 757642f9a584e ("gpio: mvebu: Add limited PWM support")Signed-off-by Baruch Siach <[email protected]>
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | https://www.pengutronix.de/ |
Re: [PATCH v2 1/5] gpio: mvebu: fix pwm .get_state period calculation
In reply to Baruch SiachQuoted 8 lines · Baruch Siach
The period is the sum of on and off values. That is, calculate period as
($on + $off) / clkrate
instead of
$off / clkrate - $on / clkrate
Quoted 8 lines
that makes no sense.
Reported-by Russell King <[email protected]>Fixes 757642f9a584e ("gpio: mvebu: Add limited PWM support")Signed-off-by Baruch Siach <[email protected]>--- drivers/gpio/gpio-mvebu.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-)
PATCH v2 2/5 gpio: mvebu: improve pwm period calculation accuracy
In reply to Baruch SiachChange 'off' register value calculation from
$off = (period - duty_cycle) * clkrate / NSEC_PER_SEC
to
$off = (period * clkrate / NSEC_PER_SEC) - $on
That is, divide the full period value to reduce rounding error.
--- drivers/gpio/gpio-mvebu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpio/gpio-mvebu.c +2 -2
@@ -715,9 +715,9 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,else on =1 ; - val = (unsigned long long ) mvpwm->clk_rate * - (state->period - state->duty_cycle); + val = (unsigned long long ) mvpwm->clk_rate * state->period;do_div (val,NSEC_PER_SEC ); + val -= on;if (val >UINT_MAX )return -EINVAL ;if (val)
Signature · 1 line
2.29.2
PATCH v2 3/5 gpio: mvebu: make pwm .get_state closer to idempotent
In reply to Baruch SiachRound up the result of division in period/duty_cycle calculation to make the result closer to idempotent.
--- drivers/gpio/gpio-mvebu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpio/gpio-mvebu.c +2 -2
@@ -668,7 +668,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,regmap_read (mvpwm->regs,mvebu_pwmreg_blink_on_duration (mvpwm), &u); val = (unsigned long long ) u *NSEC_PER_SEC ; -do_div (val, mvpwm->clk_rate); + val =DIV_ROUND_UP_ULL (val, mvpwm->clk_rate);if (val >UINT_MAX ) state->duty_cycle =UINT_MAX ;else if (val)
@@ -680,7 +680,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,regmap_read (mvpwm->regs,mvebu_pwmreg_blink_off_duration (mvpwm), &u); val += (unsigned long long ) u;/* period = on + off duration */ val *=NSEC_PER_SEC ; -do_div (val, mvpwm->clk_rate); + val =DIV_ROUND_UP_ULL (val, mvpwm->clk_rate);if (val >UINT_MAX ) state->period =UINT_MAX ;else if (val)
Signature · 1 line
2.29.2
Re: [PATCH v2 3/5] gpio: mvebu: make pwm .get_state closer to idempotent
Quoted 2 lines · Baruch Siach
Round up the result of division in period/duty_cycle calculation to make the result closer to idempotent.
Maybe:
Round up the divisions in .get_state() to make applying the read out configuration idempotent in most cases as .apply rounds down.
Quoted 2 lines
Reported-by Uwe Kleine-König <[email protected]>Signed-off-by Baruch Siach <[email protected]>
Other than that:
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | https://www.pengutronix.de/ |
PATCH v2 4/5 gpio: mvebu: don't limit pwm period/duty_cycle to UINT_MAX
In reply to Baruch SiachPWM on/off registers are limited to UINT_MAX. However the state period and duty_cycle fields are ns values of type u64. There is no reason to limit them to UINT_MAX.
--- drivers/gpio/gpio-mvebu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
drivers/gpio/gpio-mvebu.c +2 -6
@@ -669,9 +669,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,regmap_read (mvpwm->regs,mvebu_pwmreg_blink_on_duration (mvpwm), &u); val = (unsigned long long ) u *NSEC_PER_SEC ; val =DIV_ROUND_UP_ULL (val, mvpwm->clk_rate); -if (val >UINT_MAX ) - state->duty_cycle =UINT_MAX ; -else if (val) +if (val) state->duty_cycle = val;else state->duty_cycle =1 ;
@@ -681,9 +679,7 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, val += (unsigned long long ) u;/* period = on + off duration */ val *=NSEC_PER_SEC ; val =DIV_ROUND_UP_ULL (val, mvpwm->clk_rate); -if (val >UINT_MAX ) - state->period =UINT_MAX ; -else if (val) +if (val) state->period = val;else state->period =1 ;
Signature · 1 line
2.29.2
PATCH v2 5/5 gpio: mvebu: document zero pwm duty cycle limitation
In reply to Baruch SiachAdd a comment on why the code never sets on/off registers to zero.
--- drivers/gpio/gpio-mvebu.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpio/gpio-mvebu.c +4 -0
@@ -706,6 +706,10 @@ static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,do_div (val,NSEC_PER_SEC );if (val >UINT_MAX )return -EINVAL ; +/* +* Zero on/off values don't work as expected. Experimentation shows +* that zero value is treated as 2^32. This behavior is not documented. +*/ if (val) on = val;else
Signature · 1 line
2.29.2
Quoted 7 lines · Baruch Siach
This series adds a few related fixes to the pwm .apply and .get_state callbacks.
The first patch was originally part of the series adding Armada 8K/7K pwm support. I split it out to a separate series following review comments from Uwe Kleine-König who spotted a few more issues. There is no dependency between this and the Armada 8K/7K series.
This version looks really good and +/- minor tweaks as indicated by Uwe:
Yours,
Linus Walleij
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Hello Linus,
Quoted 5 lines · Linus Walleij
Quoted 3 lines · Baruch Siach
This series adds a few related fixes to the pwm .apply and .get_state callbacks.
Quoted 8 lines
Quoted 4 lines
The first patch was originally part of the series adding Armada 8K/7K pwm support. I split it out to a separate series following review comments from Uwe Kleine-König who spotted a few more issues. There is no dependency between this and the Armada 8K/7K series.
This version looks really good and +/- minor tweaks as indicated by Uwe:
Reviewed-by Linus Walleij <[email protected]>
The most recent version of this series is v4.
Best regards
Uwe
Signature · 2 lines
Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | https://www.pengutronix.de/ |
_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel