From patchwork Wed Nov 29 03:03:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yixun Lan X-Patchwork-Id: 842422 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-pwm-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ymljB1r9lz9s7f for ; Wed, 29 Nov 2017 14:03:26 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751368AbdK2DDZ (ORCPT ); Tue, 28 Nov 2017 22:03:25 -0500 Received: from mail-sh2.amlogic.com ([58.32.228.45]:46616 "EHLO mail-sh2.amlogic.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751254AbdK2DDZ (ORCPT ); Tue, 28 Nov 2017 22:03:25 -0500 Received: from localhost.localdomain (10.18.20.164) by mail-sh2.amlogic.com (10.18.11.6) with Microsoft SMTP Server id 15.0.1320.4; Wed, 29 Nov 2017 11:02:43 +0800 From: Yixun Lan To: Thierry Reding , , CC: Neil Armstrong , Jerome Brunet , Carlo Caione , Kevin Hilman , Yixun Lan , , , Jian Hu Subject: [PATCH] pwm: meson: fix harware duty calculation Date: Wed, 29 Nov 2017 11:03:08 +0800 Message-ID: <20171129030308.22036-1-yixun.lan@amlogic.com> X-Mailer: git-send-email 2.15.0 MIME-Version: 1.0 X-Originating-IP: [10.18.20.164] Sender: linux-pwm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pwm@vger.kernel.org From: Jian Hu The actual HIGH/LOW signal output from the PWM is equal to the value programed to HW register plus one, this is designed by HW. This fix should apply to all Meson SoC(include GX/GXL/GXBB, Meson6,8) Fixes: 211ed630753d ("pwm: Add support for Meson PWM Controller") Signed-off-by: Jian Hu Signed-off-by: Yixun Lan --- drivers/pwm/pwm-meson.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index d589331d1884..78d9b8c1a4bc 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -193,6 +193,11 @@ static int meson_pwm_calc(struct meson_pwm *meson, break; } + if (cnt < 2) { + dev_err(meson->chip.dev, "invalid period\n"); + return -EINVAL; + } + if (pre_div == MISC_CLK_DIV_MASK) { dev_err(meson->chip.dev, "unable to get period pre_div\n"); return -EINVAL; @@ -201,19 +206,23 @@ static int meson_pwm_calc(struct meson_pwm *meson, dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period, pre_div, cnt); + /* + * Due to the design of hardware, values of 'hi', 'lo' are 1 based + * which mean the actual output from hardware is 'hi' + 1, 'lo' + 1 + */ if (duty == period) { channel->pre_div = pre_div; - channel->hi = cnt; + channel->hi = cnt - 1; channel->lo = 0; } else if (duty == 0) { channel->pre_div = pre_div; channel->hi = 0; - channel->lo = cnt; + channel->lo = cnt - 1; } else { /* Then check is we can have the duty with the same pre_div */ duty_cnt = DIV_ROUND_CLOSEST_ULL((u64)duty * 1000, fin_ps * (pre_div + 1)); - if (duty_cnt > 0xffff) { + if (duty_cnt > 0xffff || !duty_cnt) { dev_err(meson->chip.dev, "unable to get duty cycle\n"); return -EINVAL; } @@ -222,8 +231,8 @@ static int meson_pwm_calc(struct meson_pwm *meson, duty, pre_div, duty_cnt); channel->pre_div = pre_div; - channel->hi = duty_cnt; - channel->lo = cnt - duty_cnt; + channel->hi = duty_cnt - 1; + channel->lo = cnt - duty_cnt - 1; } return 0;