From patchwork Tue Apr 20 09:51:18 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= X-Patchwork-Id: 12213665 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 456BCC433ED for ; Tue, 20 Apr 2021 09:53:57 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8205261077 for ; Tue, 20 Apr 2021 09:53:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8205261077 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=3jyboHYyC7g41glhtOupY881hDPixEMSEzRsUEmJHRU=; b=oUbL8YBAxDlO5xzKkHYoVKFkq UHP7dJKAUN8DI3KvVjKcK4PW1sXiaRh12+wsFH4GpWTcvUlaghqJTPBdy6bkRYT8A1LnepnS5mikS /LB5djwmkwkpwl81zl8qgMDjIUJ7pTW4N4dl8KE7OomnYNQwaYmc5y3EFnfxNzHBLrxOXa3shIVrZ 1Ewdw25uFwfxY+5e8xJPG7xGkTpps4QRyOM7vXGntkfGSxhl9MPJTfjdEKGMiI1/NjpAXxdHpxLlp zrfncfziTYUQckg36LOsvLAbYyM1hDnjvKuysfOqYh6MtvkgPd70MVH2TKKw7O+HtInqgt2i8fzv0 yUO9I++Lw==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lYn2h-00Bog3-7X; Tue, 20 Apr 2021 09:51:39 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lYn2e-00Bofe-N5 for linux-arm-kernel@desiato.infradead.org; Tue, 20 Apr 2021 09:51:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:Content-ID:Content-Description; bh=cLNxXGxl+c5mt7ecOOVn1MVrMrJOTD4C3ftcEnc0d6w=; b=KNRNfRcp6OY55Xvk8e1aWBsFG2 MNhIpZzWFrJlKxWxjqw9DPaY639a5JfjVip7oRCEc+W4suBEkzhZYO0QS/UrkRsPWJ+mb34npDcKb lqzfo/uAC2BpFmiqWkTBJ6dntjN20rEscykveH8dOChtw8FcROoCGcmZr4PXrYLoPww2aP1ymkzby ztaHDWn+hMHg3A2wVvmyistiTdJKS/J9YsTVrLoIxL0LKYcw3fwAlVjkaQLCiwC6ck5XAA0HgRb8w Z0NepOcJLUjVtc3/ZjVBqWKMp+m4JSjdctU1FYRAlI6FjCcDj48Iyjw61pgNgxZyO9k4xGKXTMprW iVWq6oQA==; Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lYn2c-00C086-2r for linux-arm-kernel@lists.infradead.org; Tue, 20 Apr 2021 09:51:35 +0000 Received: from ptx.hi.pengutronix.de ([2001:67c:670:100:1d::c0]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lYn2T-0001iF-SN; Tue, 20 Apr 2021 11:51:25 +0200 Received: from ukl by ptx.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1lYn2R-0000PK-Pq; Tue, 20 Apr 2021 11:51:23 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Claudiu Beznea , Thierry Reding , Lee Jones Subject: [PATCH 2/2] pwm: atmel: Improve duty cycle calculation in .apply() Date: Tue, 20 Apr 2021 11:51:18 +0200 Message-Id: <20210420095118.1571344-2-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210420095118.1571344-1-u.kleine-koenig@pengutronix.de> References: <20210420095118.1571344-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::c0 X-SA-Exim-Mail-From: ukl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210420_025134_151566_EC01FA93 X-CRM114-Status: GOOD ( 17.16 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-pwm@vger.kernel.org, Alexandre Belloni , Ludovic Desroches , kernel@pengutronix.de, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org In the calculation of the register value determining the duty cycle the requested period is used instead of the actually implemented period which results in suboptimal settings. The following example assumes an input clock of 133333333 Hz on one of the SoCs with 16 bit period. When the following state is to be applied: .period = 414727681 .duty_cycle = 652806 the following register values used to be calculated: PRES = 10 CPRD = 54000 CDTY = 53916 which yields an actual duty cycle of a bit more than 645120 ns. The setting PRES = 10 CPRD = 54000 CDTY = 53915 however yields a duty of 652800 ns which is between the current result and the requested value and so is a better approximation. The reason for this error is that for the calculation of CDTY the requested period was used instead of the actually implemented one. Signed-off-by: Uwe Kleine-König --- drivers/pwm/pwm-atmel.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c index ebaeb50dcfde..29b5ad03f715 100644 --- a/drivers/pwm/pwm-atmel.c +++ b/drivers/pwm/pwm-atmel.c @@ -124,6 +124,7 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip, } static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, + unsigned long clkrate, const struct pwm_state *state, unsigned long *cprd, u32 *pres) { @@ -132,7 +133,7 @@ static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, int shift; /* Calculate the period cycles and prescale value */ - cycles *= clk_get_rate(atmel_pwm->clk); + cycles *= clkrate; do_div(cycles, NSEC_PER_SEC); /* @@ -158,12 +159,14 @@ static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip, } static void atmel_pwm_calculate_cdty(const struct pwm_state *state, - unsigned long cprd, unsigned long *cdty) + unsigned long clkrate, unsigned long cprd, + u32 pres, unsigned long *cdty) { unsigned long long cycles = state->duty_cycle; - cycles *= cprd; - do_div(cycles, state->period); + cycles *= clkrate; + do_div(cycles, NSEC_PER_SEC); + cycles >>= pres; *cdty = cprd - cycles; } @@ -244,17 +247,23 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, pwm_get_state(pwm, &cstate); if (state->enabled) { + unsigned long clkrate = clk_get_rate(atmel_pwm->clk); + if (cstate.enabled && cstate.polarity == state->polarity && cstate.period == state->period) { + u32 cmr = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR); + cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, atmel_pwm->data->regs.period); - atmel_pwm_calculate_cdty(state, cprd, &cdty); + pres = cmr & PWM_CMR_CPRE_MSK; + + atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty); atmel_pwm_update_cdty(chip, pwm, cdty); return 0; } - ret = atmel_pwm_calculate_cprd_and_pres(chip, state, &cprd, + ret = atmel_pwm_calculate_cprd_and_pres(chip, clkrate, state, &cprd, &pres); if (ret) { dev_err(chip->dev, @@ -262,7 +271,7 @@ static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, return ret; } - atmel_pwm_calculate_cdty(state, cprd, &cdty); + atmel_pwm_calculate_cdty(state, clkrate, cprd, pres, &cdty); if (cstate.enabled) { atmel_pwm_disable(chip, pwm, false);