From patchwork Sat Jan 30 04:26:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "David Rivshin (Allworx)" X-Patchwork-Id: 8169541 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C702A9F818 for ; Sat, 30 Jan 2016 04:32:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E1D1A20396 for ; Sat, 30 Jan 2016 04:32:55 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id F149720142 for ; Sat, 30 Jan 2016 04:32:54 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aPNBn-0007tu-W0; Sat, 30 Jan 2016 04:31:12 +0000 Received: from mail-qk0-x244.google.com ([2607:f8b0:400d:c09::244]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aPNBW-0007k7-QA for linux-arm-kernel@lists.infradead.org; Sat, 30 Jan 2016 04:30:55 +0000 Received: by mail-qk0-x244.google.com with SMTP id u128so2652239qkh.1 for ; Fri, 29 Jan 2016 20:30:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5pFa6dqew6cGuQNTo/VK0SoZ/RtIkD7frAHwtaMVYlQ=; b=0FSz2hdc3vb301H5gViA7wpNXbznQHb0qWsmuBMoxsowKToL6fEukUymse6hidpi93 xsIFyrJYuS+mfbzVfja0Uvvq3Vi9ghJdJuH8m+DpuODW6RVEk74ZRLLrbqEFUkhRNqIs WULXfFixHksc0zCnE76mipB6aT9WLJk50WPO/1/qbHzpDwkXE2sIptGX/QBOXGJlV/7B 4tF+CXMKe9ybGzD34B3/ZlYtC906tG6h2Hb/D7bpCbwR7yCMknBHSQGG+feMuJDHGCHX ZJux0OX8LCYuyUkCdcJ9dgdJPadF4UJwbjeAr1h+4Rf/UhFxIYvrNBc+CTKhCXUw2qSW LDPA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5pFa6dqew6cGuQNTo/VK0SoZ/RtIkD7frAHwtaMVYlQ=; b=EOYQk2msXCzQpqlns9Ys5TyfySaQTGhyvb8B0w6GfCVzfX/KcXHcVzPl4t3UiI2M8Q YnGwpjk7D7TANJYQvdGEqRYFZpAeu1ir9GiZa5pZhwjq58pDbiDfNmID1AsaTTB5yWui swC+EZwK9slPVFRYEGjKYnnhQids4lf4Q6TcjsSakOJF7Ghs+YMbYQmALvLrFFJcXXKw +wnrL9+QGb4yssuftXlwO7GxX1LF015lN9RE1sOvVrxQFAkiijc4Mv6OTf3+1ig/YEau XZX7f2q8hNdqz4xcr0LQuG4ZgNsI6ZgaunCrU2VcBFYkS3n0M5mtFty8+BJgLTLeEyC2 g47g== X-Gm-Message-State: AG10YOTLh28xLLPJPkdrtVzoPDUUqhrDvovmRIwtGrmj+HeZYr8GMhqHMX3acrWBLnCHhA== X-Received: by 10.55.77.206 with SMTP id a197mr14983120qkb.43.1454128233514; Fri, 29 Jan 2016 20:30:33 -0800 (PST) Received: from drivshin-linux.crosskeys.inscitek.com ([24.213.148.66]) by smtp.gmail.com with ESMTPSA id y104sm8404563qgd.33.2016.01.29.20.30.32 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Jan 2016 20:30:33 -0800 (PST) From: "David Rivshin (Allworx)" To: linux-pwm@vger.kernel.org, Thierry Reding , Neil Armstrong Subject: [PATCH 1/4] pwm: omap-dmtimer: fix inaccurate period/duty_cycle calculation Date: Fri, 29 Jan 2016 23:26:51 -0500 Message-Id: <1454128014-22866-2-git-send-email-drivshin.allworx@gmail.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1454128014-22866-1-git-send-email-drivshin.allworx@gmail.com> References: <1454128014-22866-1-git-send-email-drivshin.allworx@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160129_203055_014154_B207CF68 X-CRM114-Status: GOOD ( 12.52 ) X-Spam-Score: -2.7 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Tony Lindgren , Joachim Eastwood , NeilBrown , Grant Erickson , linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.1 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: David Rivshin 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) Fixes: 6604c6556db9 ("pwm: Add PWM driver for OMAP using dual-mode timers") Signed-off-by: David Rivshin Acked-by: Neil Armstrong Tested-by: Adam Ford --- drivers/pwm/pwm-omap-dmtimer.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c index 826634e..0083e75 100644 --- a/drivers/pwm/pwm-omap-dmtimer.c +++ b/drivers/pwm/pwm-omap-dmtimer.c @@ -31,6 +31,7 @@ #include #define DM_TIMER_LOAD_MIN 0xfffffffe +#define DM_TIMER_MAX 0xffffffff struct pwm_omap_dmtimer_chip { struct pwm_chip chip; @@ -46,13 +47,13 @@ to_pwm_omap_dmtimer_chip(struct pwm_chip *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(struct pwm_chip *chip, 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(struct pwm_chip *chip, /* * 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