Patch "pwm: omap-dmtimer: Fix inaccurate period and duty cycle calculations" has been added to the 4.5-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
pwm: omap-dmtimer: Fix inaccurate period and duty cycle calculations
to the 4.5-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:
pwm-omap-dmtimer-fix-inaccurate-period-and-duty-cycle-calculations.patch
and it can be found in the queue-4.5 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
f8caa792261c0edded20eba2b8fcc899a1b91819Mon Sep 17 00:00:00 2001
From: David Rivshin <[email protected]>
Date: Fri, 29 Jan 2016 23:26:51 -0500
Subject: pwm: omap-dmtimer: Fix inaccurate period and duty cycle calculations
From: David Rivshin <[email protected]>
commit f8caa792261c0edded20eba2b8fcc899a1b91819 upstream.
Fix the calculation of load_value and match_value. Currently they are slightly too low, which produces a noticeably wrong PWM rate with sufficiently short periods (i.e. when 1/period approaches clk_rate/2).
Example:
clk_rate=32768Hz, period=122070ns, duty_cycle=61035ns (8192Hz/50% PWM) Correct values: load = 0xfffffffc, match = 0xfffffffd Current values: load = 0xfffffffa, match = 0xfffffffc effective PWM: period=183105ns, duty_cycle=91553ns (5461Hz/50% PWM)
--- drivers/pwm/pwm-omap-dmtimer.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
drivers/pwm/pwm-omap-dmtimer.c +20 -7
@@ -31,6 +31,7 @@#include <linux/time.h> #define DM_TIMER_LOAD_MIN 0xfffffffe +#define DM_TIMER_MAX 0xffffffffstruct pwm_omap_dmtimer_chip {struct pwm_chip chip;
@@ -46,13 +47,13 @@ to_pwm_omap_dmtimer_chip(struct pwm_chip return container_of(chip, struct pwm_omap_dmtimer_chip, chip); } -static int pwm_omap_dmtimer_calc_value (unsigned long clk_rate,int ns) +static u32 pwm_omap_dmtimer_get_clock_cycles (unsigned long clk_rate,int ns) {u64 c = (u64 )clk_rate * ns;do_div (c,NSEC_PER_SEC ); -return DM_TIMER_LOAD_MIN - c; +return c; }static void pwm_omap_dmtimer_start (struct pwm_omap_dmtimer_chip *omap)
@@ -99,7 +100,8 @@ static int pwm_omap_dmtimer_config(struc int duty_ns, int period_ns) {struct pwm_omap_dmtimer_chip *omap =to_pwm_omap_dmtimer_chip (chip); -int load_value, match_value; +u32 period_cycles, duty_cycles; +u32 load_value, match_value;struct clk *fclk;unsigned long clk_rate;bool timer_active;
@@ -133,11 +135,22 @@ static int pwm_omap_dmtimer_config(struc/* * Calculate the appropriate load and match values based on the * specified period and duty cycle. The load value determines the -* cycle time and the match value determines the duty cycle. +* period time and the match value determines the duty time. +* +* The period lasts for (DM_TIMER_MAX-load_value+1) clock cycles. +* Similarly, the active time lasts (match_value-load_value+1) cycles. +* The non-active time is the remainder: (DM_TIMER_MAX-match_value) +* clock cycles. +* +* References: +* OMAP4430/60/70 TRM sections 22.2.4.10 and 22.2.4.11 +* AM335x Sitara TRM sections 20.1.3.5 and 20.1.3.6 */ - load_value =pwm_omap_dmtimer_calc_value (clk_rate, period_ns); - match_value =pwm_omap_dmtimer_calc_value (clk_rate, - period_ns - duty_ns); + period_cycles =pwm_omap_dmtimer_get_clock_cycles (clk_rate, period_ns); + duty_cycles =pwm_omap_dmtimer_get_clock_cycles (clk_rate, duty_ns); + + load_value = (DM_TIMER_MAX - period_cycles) +1 ; + match_value = load_value + duty_cycles -1 ;/* * We MUST stop the associated dual-mode timer before attempting to
Patches currently in stable-queue which might be from [email protected] are
queue-4.5/pwm-omap-dmtimer-fix-inaccurate-period-and-duty-cycle-calculations.patch queue-4.5/pwm-omap-dmtimer-add-sanity-checking-for-load-and-match-values.patch queue-4.5/pwm-omap-dmtimer-round-load-and-match-values-rather-than-truncate.patch