Patch "[PATCH 068/135] pwm: lpc32xx: fix and simplify duty cycle and period" has been added to the 4.4-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
[PATCH 068/135] pwm: lpc32xx: fix and simplify duty cycle and period
to the 4.4-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:
0068-pwm-lpc32xx-fix-and-simplify-duty-cycle-and-period-c.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
923f8ee01265e83f788fa96898a9b7befbf83b59Mon Sep 17 00:00:00 2001
From: Vladimir Zapolskiy <[email protected]>
Date: Sun, 6 Dec 2015 13:32:01 +0200
Subject: [PATCH 068/135] pwm: lpc32xx: fix and simplify duty cycle and period
calculations
[ Upstream commit 5a9fc9c666d5d759699cf5495bda85f1da0d747e ]
The change fixes a problem, if duty_ns is too small in comparison to period_ns (as a valid corner case duty_ns is 0 ns), then due to PWM_DUTY() macro applied on a value the result is overflowed over 8 bits, and instead of the highest bitfield duty cycle value 0xff the invalid duty cycle bitfield value 0x00 is written.
For reference the LPC32xx spec defines PWMx_DUTY bitfield description is this way and it seems to be correct:
[Low]/[High] = [PWM_DUTY]/[256-PWM_DUTY], where 0 < PWM_DUTY <= 255.
In addition according to my oscilloscope measurements LPC32xx PWM is "tristate" in sense that it produces a wave with floating min/max voltage levels for different duty cycle values, for corner cases:
PWM_DUTY == 0x01 => signal is in range from -1.05v to 0v
....
PWM_DUTY == 0x80 => signal is in range from -0.75v to +0.75v
....
PWM_DUTY == 0xff => signal is in range from 0v to +1.05v
PWM_DUTY == 0x00 => signal is around 0v, PWM is off
Due to this peculiarity on very long period ranges (less than 1KHz) and odd pre-divider values PWM generated wave does not remind a clock shape signal, but rather a heartbit shape signal with positive and negative peaks, so I would recommend to use high-speed HCLK clock as a PWM parent clock and avoid using RTC clock as a parent.
The change corrects PWM output in corner cases and prevents any possible overflows in calculation of values for PWM_DUTY and PWM_RELOADV bitfields, thus helper macro definitions may be removed.
--- drivers/pwm/pwm-lpc32xx.c | 51 ++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 33 deletions(-)
drivers/pwm/pwm-lpc32xx.c +18 -33
@@ -24,9 +24,7 @@ struct lpc32xx_pwm_chip {void __iomem *base; }; -#define PWM_ENABLE (1 << 31) -#define PWM_RELOADV (x) (((x) & 0xFF) << 8) -#define PWM_DUTY (x) ((x) & 0xFF) +#define PWM_ENABLE BIT(31)#define to_lpc32xx_pwm_chip (_chip) \ container_of(_chip, struct lpc32xx_pwm_chip, chip)
@@ -38,40 +36,27 @@ static int lpc32xx_pwm_config(struct pwmunsigned long long c;int period_cycles, duty_cycles;u32 val; + c =clk_get_rate (lpc32xx->clk); - c =clk_get_rate (lpc32xx->clk) /256 ; - c = c * period_ns; -do_div (c,NSEC_PER_SEC ); - -/* Handle high and low extremes */ -if (c ==0 ) - c =1 ; -if (c >255 ) - c =0 ;/* 0 set division by 256 */ - period_cycles = c; - -/* The duty-cycle value is as follows: -* -* DUTY-CYCLE HIGH LEVEL -* 1 99.9% -* 25 90.0% -* 128 50.0% -* 220 10.0% -* 255 0.1% -* 0 0.0% -* -* In other words, the register value is duty-cycle % 256 with -* duty-cycle in the range 1-256. -*/ - c =256 * duty_ns; -do_div (c, period_ns); -if (c >255 ) - c =255 ; - duty_cycles =256 - c; +/* The highest acceptable divisor is 256, which is represented by 0 */ + period_cycles =div64_u64 (c * period_ns, + (unsigned long long )NSEC_PER_SEC *256 ); +if (!period_cycles) + period_cycles =1 ; +if (period_cycles >255 ) + period_cycles =0 ; + +/* Compute 256 x #duty/period value and care for corner cases */ + duty_cycles =div64_u64 ((unsigned long long )(period_ns - duty_ns) *256 , + period_ns); +if (!duty_cycles) + duty_cycles =1 ; +if (duty_cycles >255 ) + duty_cycles =255 ; val =readl (lpc32xx->base + (pwm->hwpwm <<2 )); val &= ~0xFFFF ; - val |=PWM_RELOADV (period_cycles) |PWM_DUTY (duty_cycles); + val |= (period_cycles <<8 ) | duty_cycles;writel (val, lpc32xx->base + (pwm->hwpwm <<2 ));return 0 ;
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/0067-pwm-lpc32xx-correct-number-of-PWM-channels-from-2-to.patch queue-4.4/0068-pwm-lpc32xx-fix-and-simplify-duty-cycle-and-period-c.patch