From patchwork Wed Apr 13 08:50:45 2022 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: 12811748 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D3F5C433F5 for ; Wed, 13 Apr 2022 08:51:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234112AbiDMIxu (ORCPT ); Wed, 13 Apr 2022 04:53:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35030 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234367AbiDMIxb (ORCPT ); Wed, 13 Apr 2022 04:53:31 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F24645780 for ; Wed, 13 Apr 2022 01:51:10 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1neYiO-0006X8-8U; Wed, 13 Apr 2022 10:51:04 +0200 Received: from [2a0a:edc0:0:900:1d::77] (helo=ptz.office.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1neYiL-002kH6-UN; Wed, 13 Apr 2022 10:51:00 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1neYiJ-002yxD-Mw; Wed, 13 Apr 2022 10:50:59 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Laurent Pinchart , Simon Horman , Geert Uytterhoeven , Magnus Damm , Thierry Reding , Lee Jones Cc: linux-pwm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH 1/6] pwm: renesas-tpu: Make use of dev_err_probe() Date: Wed, 13 Apr 2022 10:50:45 +0200 Message-Id: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1510; h=from:subject; bh=CA6sUWp+2onbHGId++hzJboYLYFVTVZJJ6p4WBfgdhs=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiVo7SRyDyCSYIZpHCg2Hs/jQR5SNNsNjqCDyUhZ+E 2l9PJmiJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYlaO0gAKCRDB/BR4rcrsCQXJB/ 9llofpQXnzXsy5ATK2QRKX8A7uldnxk63qKAofO1uts+ynmgIq03kS2RRYLvbUK2Yp/y7nFTzoOy/i drW6RiGAYZ9mznZFNs7dmS0B+5cN4oqQ2rx6uFQhCaqYff56Z5ifOs89Blf6wIb/3pD2rU0MDe/AEB FfaMRBqSFLmDuqnQVzkQWRnLhHh2NyP/PVsDbsX3ua0eaHagNncOWFvzQJUnjZJXWW3M2+WvfQChri VJIoQCwmyVca1m4kZBk274oAFn9YpsD803vGeUZzdLY2lGdxfdGsgyenr2XYj5BzOcHA8k46Ikkx8w 4ubZCzgMAwbeAMuR+ZUU+m+0+jy4Ur X-Developer-Key: i=u.kleine-koenig@pengutronix.de; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 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-renesas-soc@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org The added benefit is that the error code is mentioned in the error message and its usage is a bit more compact than open coding it. This also improves behaviour in case devm_clk_get() returns -EPROBE_DEFER. While touching this code, consistenly start error messages with upper case. Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven --- drivers/pwm/pwm-renesas-tpu.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) base-commit: 3123109284176b1532874591f7c81f3837bbdc17 diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 4381df90a527..c3ae78e37789 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -398,10 +398,8 @@ static int tpu_probe(struct platform_device *pdev) return PTR_ERR(tpu->base); tpu->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(tpu->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - return PTR_ERR(tpu->clk); - } + if (IS_ERR(tpu->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(tpu->clk), "Failed to get clock\n"); /* Initialize and register the device. */ platform_set_drvdata(pdev, tpu); @@ -414,9 +412,8 @@ static int tpu_probe(struct platform_device *pdev) ret = pwmchip_add(&tpu->chip); if (ret < 0) { - dev_err(&pdev->dev, "failed to register PWM chip\n"); pm_runtime_disable(&pdev->dev); - return ret; + return dev_err_probe(&pdev->dev, ret, "Failed to register PWM chip\n"); } return 0; From patchwork Wed Apr 13 08:50:46 2022 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: 12811744 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE242C433EF for ; Wed, 13 Apr 2022 08:51:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234049AbiDMIxp (ORCPT ); Wed, 13 Apr 2022 04:53:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35006 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234363AbiDMIxb (ORCPT ); Wed, 13 Apr 2022 04:53:31 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E41245067 for ; Wed, 13 Apr 2022 01:51:10 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1neYiO-0006X7-8U; Wed, 13 Apr 2022 10:51:04 +0200 Received: from [2a0a:edc0:0:900:1d::77] (helo=ptz.office.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1neYiL-002kH4-TR; Wed, 13 Apr 2022 10:51:00 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1neYiJ-002yxG-RQ; Wed, 13 Apr 2022 10:50:59 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Laurent Pinchart , Simon Horman , Geert Uytterhoeven , Magnus Damm , Thierry Reding , Lee Jones Cc: linux-pwm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH 2/6] pwm: renesas-tpu: Make use of devm functions Date: Wed, 13 Apr 2022 10:50:46 +0200 Message-Id: <20220413085050.61144-2-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> References: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1521; h=from:subject; bh=GQIjFTHH+m4bqfUU/FS0euTwoRnVbN4aUwj1unBWxXw=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiVo7W+Quq8tjxbG0UpwFLaVAwzZpUHVZ62ZegI3JI 0RZuPwKJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYlaO1gAKCRDB/BR4rcrsCRuzCA CcjM3aqNyYCf/u5dVbeJvgP+TM/8MpXWGOfUIU1vzgpLrPtqX4a7PIA8EVVLuWnE/kh7SE6t2/ZGsM QZq/g8p1lNKU43R5PyfHa1w4RgwCLNCE6qigL3I3w+gYYft1yN6IZCBed9yWYuBxXtHDKk/NCwQjo1 cIny9UmbaRSz4e/d5ax9HO+/llYe3JGR9J/FzCKw0QFf7Suo0oVdYrbLjD202y5g3zRmxyrL5x/Doo IK4pYxyZuRz65Y/V+q4i0mavXT7JPVOy2wB76epKL+t5/bC6OmC72+ep7KTY57gHsIqe+cnSenxSbW YwnNDBBzqADN+XKuPbfsLYhUjPCLvL X-Developer-Key: i=u.kleine-koenig@pengutronix.de; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 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-renesas-soc@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org This simplifies an error path in .probe() and allows to drop the .remove() function. Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven --- drivers/pwm/pwm-renesas-tpu.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index c3ae78e37789..12376988c70e 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -408,24 +408,13 @@ static int tpu_probe(struct platform_device *pdev) tpu->chip.ops = &tpu_pwm_ops; tpu->chip.npwm = TPU_CHANNEL_MAX; - pm_runtime_enable(&pdev->dev); + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Failed to enable runtime PM\n"); - ret = pwmchip_add(&tpu->chip); - if (ret < 0) { - pm_runtime_disable(&pdev->dev); + ret = devm_pwmchip_add(&pdev->dev, &tpu->chip); + if (ret < 0) return dev_err_probe(&pdev->dev, ret, "Failed to register PWM chip\n"); - } - - return 0; -} - -static int tpu_remove(struct platform_device *pdev) -{ - struct tpu_device *tpu = platform_get_drvdata(pdev); - - pwmchip_remove(&tpu->chip); - - pm_runtime_disable(&pdev->dev); return 0; } @@ -444,7 +433,6 @@ MODULE_DEVICE_TABLE(of, tpu_of_table); static struct platform_driver tpu_driver = { .probe = tpu_probe, - .remove = tpu_remove, .driver = { .name = "renesas-tpu-pwm", .of_match_table = of_match_ptr(tpu_of_table), From patchwork Wed Apr 13 08:50:47 2022 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: 12811743 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 67969C433F5 for ; Wed, 13 Apr 2022 08:51:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229626AbiDMIxo (ORCPT ); Wed, 13 Apr 2022 04:53:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35026 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234366AbiDMIxb (ORCPT ); Wed, 13 Apr 2022 04:53:31 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E3023FDB2 for ; Wed, 13 Apr 2022 01:51:10 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1neYiO-0006XD-8U; Wed, 13 Apr 2022 10:51:04 +0200 Received: from [2a0a:edc0:0:900:1d::77] (helo=ptz.office.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1neYiM-002kHE-B9; Wed, 13 Apr 2022 10:51:00 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1neYiJ-002yxJ-Vl; Wed, 13 Apr 2022 10:50:59 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Laurent Pinchart , Simon Horman , Geert Uytterhoeven , Magnus Damm , Thierry Reding , Lee Jones Cc: linux-pwm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH 3/6] pwm: renesas-tpu: Implement .apply() callback Date: Wed, 13 Apr 2022 10:50:47 +0200 Message-Id: <20220413085050.61144-3-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> References: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2481; h=from:subject; bh=hU990ahcpNkN/uIHQtEs2r+/NQQA4gbu9dhJ31FKAyU=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiVo7bRZYv+BiPRoAv2aj5OK1GAernahdYjdRFrXpU qZ1mOySJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYlaO2wAKCRDB/BR4rcrsCSiUCA CLPr2/qWEr0UJZLJT9YsrOrToVKkAMZrl9QlET8TGYhjS0+dzNSs4s6CFqDP98gQLBH8Dnc3d5M/m+ Wxl9bctAFAbcMA9grJwP670oU0cLGSXckRCJDQh/FN9Tm2bBkv0aVmoJ27MggrtOEZKzHMgvgnygY8 RygsApHQZb6x03WLvLMNuHy6bvx8jeUvsElXOsgVG6g+Shp1EnQCs3SuK8X7oC0vHv6hMLB/Eyz/R9 Rr7450fv5N2xnzKy2dANNc4nTGNc2pqly51OqC0THaQK63KjwUoxhky0ee90LPd8Y/as2H9fSMjvg4 wEZeoSFvRgYPoptDghnY7dTpqzduH6 X-Developer-Key: i=u.kleine-koenig@pengutronix.de; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 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-renesas-soc@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org To eventually get rid of all legacy drivers convert this driver to the modern world implementing .apply(). As pwm->state might not be updated in tpu_pwm_apply() before calling tpu_pwm_config(), an additional parameter is needed for tpu_pwm_config() to not change the implemented logic. Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven --- drivers/pwm/pwm-renesas-tpu.c | 44 ++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 12376988c70e..100c21e27648 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -242,7 +242,7 @@ static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *_pwm) } static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, - int duty_ns, int period_ns) + int duty_ns, int period_ns, bool enabled) { static const unsigned int prescalers[] = { 1, 4, 16, 64 }; struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); @@ -293,7 +293,7 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, pwm->duty = duty; /* If the channel is disabled we're done. */ - if (!pwm_is_enabled(_pwm)) + if (!enabled) return 0; if (duty_only && pwm->timer_on) { @@ -366,13 +366,45 @@ static void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *_pwm) tpu_pwm_timer_stop(pwm); } +static int tpu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + int err; + bool enabled = pwm->state.enabled; + + if (state->polarity != pwm->state.polarity) { + if (enabled) { + tpu_pwm_disable(chip, pwm); + enabled = false; + } + + err = tpu_pwm_set_polarity(chip, pwm, state->polarity); + if (err) + return err; + } + + if (!state->enabled) { + if (enabled) + chip->ops->disable(chip, pwm); + + return 0; + } + + err = tpu_pwm_config(pwm->chip, pwm, + state->duty_cycle, state->period, enabled); + if (err) + return err; + + if (!enabled) + err = tpu_pwm_enable(chip, pwm); + + return err; +} + static const struct pwm_ops tpu_pwm_ops = { .request = tpu_pwm_request, .free = tpu_pwm_free, - .config = tpu_pwm_config, - .set_polarity = tpu_pwm_set_polarity, - .enable = tpu_pwm_enable, - .disable = tpu_pwm_disable, + .apply = tpu_pwm_apply, .owner = THIS_MODULE, }; From patchwork Wed Apr 13 08:50:48 2022 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: 12811746 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 48651C4167B for ; Wed, 13 Apr 2022 08:51:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234085AbiDMIxq (ORCPT ); Wed, 13 Apr 2022 04:53:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234368AbiDMIxb (ORCPT ); Wed, 13 Apr 2022 04:53:31 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E3B444753 for ; Wed, 13 Apr 2022 01:51:10 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1neYiO-0006XC-8U; Wed, 13 Apr 2022 10:51:04 +0200 Received: from [2a0a:edc0:0:900:1d::77] (helo=ptz.office.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1neYiM-002kHC-AH; Wed, 13 Apr 2022 10:51:00 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1neYiK-002yxM-4Y; Wed, 13 Apr 2022 10:51:00 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Laurent Pinchart , Simon Horman , Geert Uytterhoeven , Magnus Damm , Thierry Reding , Lee Jones Cc: linux-pwm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH 4/6] pwm: renesas-tpu: Rename variables to match the usual naming Date: Wed, 13 Apr 2022 10:50:48 +0200 Message-Id: <20220413085050.61144-4-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> References: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11426; h=from:subject; bh=RAN+Sgmd0OlLs64H2z+B6ZCNu3MmR6N1zXMaR2oWcW8=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiVo7fcuPXFIO472fD1KEeWIlaW3S7/eMgdnXQEllU os2SIDCJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYlaO3wAKCRDB/BR4rcrsCXzwB/ wMuS1Uf5XBebMV8f0oSvknTSSFhBNxw/DnoKK7HkOFFRVMHh8c6jsp5+xk9DCSxO/HMeEHDhUfKLhl H5i4aDKTZqMYBe59/uueIfkcOo88PqMkrDBExutcJU9GO/3PJsJpB0dRiDJckovMizl8037ALVoPMK F3+85f8hcJtxL2VXi5N1LUdqUN7qMU6wFkiNGU7RXAV24zMBStRBwI4XvKvCAXFAGDHqql5yzclEGC GVaCF/rK/Uy8rIb4EfXxSNUZ/UlkgqVYQQe9tfiqaIg7Lex6hWbopRh/5/Pkh45QpZpsaVi16B5IfA sGithOdCh300615XtqcNlZWRVmZda/ X-Developer-Key: i=u.kleine-koenig@pengutronix.de; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 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-renesas-soc@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org The driver used "pwm" for struct tpu_pwm_device pointers. This name is usually only used for struct pwm_device pointers which this driver calls "_pwm". So rename to the driver data pointers to "tpd" which then allows to drop the underscore from "_pwm". Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven --- drivers/pwm/pwm-renesas-tpu.c | 172 +++++++++++++++++----------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 100c21e27648..671f1f824da8 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -89,71 +89,71 @@ struct tpu_device { #define to_tpu_device(c) container_of(c, struct tpu_device, chip) -static void tpu_pwm_write(struct tpu_pwm_device *pwm, int reg_nr, u16 value) +static void tpu_pwm_write(struct tpu_pwm_device *tpd, int reg_nr, u16 value) { - void __iomem *base = pwm->tpu->base + TPU_CHANNEL_OFFSET - + pwm->channel * TPU_CHANNEL_SIZE; + void __iomem *base = tpd->tpu->base + TPU_CHANNEL_OFFSET + + tpd->channel * TPU_CHANNEL_SIZE; iowrite16(value, base + reg_nr); } -static void tpu_pwm_set_pin(struct tpu_pwm_device *pwm, +static void tpu_pwm_set_pin(struct tpu_pwm_device *tpd, enum tpu_pin_state state) { static const char * const states[] = { "inactive", "PWM", "active" }; - dev_dbg(&pwm->tpu->pdev->dev, "%u: configuring pin as %s\n", - pwm->channel, states[state]); + dev_dbg(&tpd->tpu->pdev->dev, "%u: configuring pin as %s\n", + tpd->channel, states[state]); switch (state) { case TPU_PIN_INACTIVE: - tpu_pwm_write(pwm, TPU_TIORn, - pwm->polarity == PWM_POLARITY_INVERSED ? + tpu_pwm_write(tpd, TPU_TIORn, + tpd->polarity == PWM_POLARITY_INVERSED ? TPU_TIOR_IOA_1 : TPU_TIOR_IOA_0); break; case TPU_PIN_PWM: - tpu_pwm_write(pwm, TPU_TIORn, - pwm->polarity == PWM_POLARITY_INVERSED ? + tpu_pwm_write(tpd, TPU_TIORn, + tpd->polarity == PWM_POLARITY_INVERSED ? TPU_TIOR_IOA_0_SET : TPU_TIOR_IOA_1_CLR); break; case TPU_PIN_ACTIVE: - tpu_pwm_write(pwm, TPU_TIORn, - pwm->polarity == PWM_POLARITY_INVERSED ? + tpu_pwm_write(tpd, TPU_TIORn, + tpd->polarity == PWM_POLARITY_INVERSED ? TPU_TIOR_IOA_0 : TPU_TIOR_IOA_1); break; } } -static void tpu_pwm_start_stop(struct tpu_pwm_device *pwm, int start) +static void tpu_pwm_start_stop(struct tpu_pwm_device *tpd, int start) { unsigned long flags; u16 value; - spin_lock_irqsave(&pwm->tpu->lock, flags); - value = ioread16(pwm->tpu->base + TPU_TSTR); + spin_lock_irqsave(&tpd->tpu->lock, flags); + value = ioread16(tpd->tpu->base + TPU_TSTR); if (start) - value |= 1 << pwm->channel; + value |= 1 << tpd->channel; else - value &= ~(1 << pwm->channel); + value &= ~(1 << tpd->channel); - iowrite16(value, pwm->tpu->base + TPU_TSTR); - spin_unlock_irqrestore(&pwm->tpu->lock, flags); + iowrite16(value, tpd->tpu->base + TPU_TSTR); + spin_unlock_irqrestore(&tpd->tpu->lock, flags); } -static int tpu_pwm_timer_start(struct tpu_pwm_device *pwm) +static int tpu_pwm_timer_start(struct tpu_pwm_device *tpd) { int ret; - if (!pwm->timer_on) { + if (!tpd->timer_on) { /* Wake up device and enable clock. */ - pm_runtime_get_sync(&pwm->tpu->pdev->dev); - ret = clk_prepare_enable(pwm->tpu->clk); + pm_runtime_get_sync(&tpd->tpu->pdev->dev); + ret = clk_prepare_enable(tpd->tpu->clk); if (ret) { - dev_err(&pwm->tpu->pdev->dev, "cannot enable clock\n"); + dev_err(&tpd->tpu->pdev->dev, "cannot enable clock\n"); return ret; } - pwm->timer_on = true; + tpd->timer_on = true; } /* @@ -161,8 +161,8 @@ static int tpu_pwm_timer_start(struct tpu_pwm_device *pwm) * completely. First drive the pin to the inactive state to avoid * glitches. */ - tpu_pwm_set_pin(pwm, TPU_PIN_INACTIVE); - tpu_pwm_start_stop(pwm, false); + tpu_pwm_set_pin(tpd, TPU_PIN_INACTIVE); + tpu_pwm_start_stop(tpd, false); /* * - Clear TCNT on TGRB match @@ -172,80 +172,80 @@ static int tpu_pwm_timer_start(struct tpu_pwm_device *pwm) * - Output 1 until TGRA, output 0 until TGRB (active high polarity * - PWM mode */ - tpu_pwm_write(pwm, TPU_TCRn, TPU_TCR_CCLR_TGRB | TPU_TCR_CKEG_RISING | - pwm->prescaler); - tpu_pwm_write(pwm, TPU_TMDRn, TPU_TMDR_MD_PWM); - tpu_pwm_set_pin(pwm, TPU_PIN_PWM); - tpu_pwm_write(pwm, TPU_TGRAn, pwm->duty); - tpu_pwm_write(pwm, TPU_TGRBn, pwm->period); + tpu_pwm_write(tpd, TPU_TCRn, TPU_TCR_CCLR_TGRB | TPU_TCR_CKEG_RISING | + tpd->prescaler); + tpu_pwm_write(tpd, TPU_TMDRn, TPU_TMDR_MD_PWM); + tpu_pwm_set_pin(tpd, TPU_PIN_PWM); + tpu_pwm_write(tpd, TPU_TGRAn, tpd->duty); + tpu_pwm_write(tpd, TPU_TGRBn, tpd->period); - dev_dbg(&pwm->tpu->pdev->dev, "%u: TGRA 0x%04x TGRB 0x%04x\n", - pwm->channel, pwm->duty, pwm->period); + dev_dbg(&tpd->tpu->pdev->dev, "%u: TGRA 0x%04x TGRB 0x%04x\n", + tpd->channel, tpd->duty, tpd->period); /* Start the channel. */ - tpu_pwm_start_stop(pwm, true); + tpu_pwm_start_stop(tpd, true); return 0; } -static void tpu_pwm_timer_stop(struct tpu_pwm_device *pwm) +static void tpu_pwm_timer_stop(struct tpu_pwm_device *tpd) { - if (!pwm->timer_on) + if (!tpd->timer_on) return; /* Disable channel. */ - tpu_pwm_start_stop(pwm, false); + tpu_pwm_start_stop(tpd, false); /* Stop clock and mark device as idle. */ - clk_disable_unprepare(pwm->tpu->clk); - pm_runtime_put(&pwm->tpu->pdev->dev); + clk_disable_unprepare(tpd->tpu->clk); + pm_runtime_put(&tpd->tpu->pdev->dev); - pwm->timer_on = false; + tpd->timer_on = false; } /* ----------------------------------------------------------------------------- * PWM API */ -static int tpu_pwm_request(struct pwm_chip *chip, struct pwm_device *_pwm) +static int tpu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) { struct tpu_device *tpu = to_tpu_device(chip); - struct tpu_pwm_device *pwm; + struct tpu_pwm_device *tpd; - if (_pwm->hwpwm >= TPU_CHANNEL_MAX) + if (pwm->hwpwm >= TPU_CHANNEL_MAX) return -EINVAL; - pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); - if (pwm == NULL) + tpd = kzalloc(sizeof(*tpd), GFP_KERNEL); + if (tpd == NULL) return -ENOMEM; - pwm->tpu = tpu; - pwm->channel = _pwm->hwpwm; - pwm->polarity = PWM_POLARITY_NORMAL; - pwm->prescaler = 0; - pwm->period = 0; - pwm->duty = 0; + tpd->tpu = tpu; + tpd->channel = pwm->hwpwm; + tpd->polarity = PWM_POLARITY_NORMAL; + tpd->prescaler = 0; + tpd->period = 0; + tpd->duty = 0; - pwm->timer_on = false; + tpd->timer_on = false; - pwm_set_chip_data(_pwm, pwm); + pwm_set_chip_data(pwm, tpd); return 0; } -static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *_pwm) +static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) { - struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); - tpu_pwm_timer_stop(pwm); - kfree(pwm); + tpu_pwm_timer_stop(tpd); + kfree(tpd); } -static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, +static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns, bool enabled) { static const unsigned int prescalers[] = { 1, 4, 16, 64 }; - struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); struct tpu_device *tpu = to_tpu_device(chip); unsigned int prescaler; bool duty_only = false; @@ -285,29 +285,29 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, "rate %u, prescaler %u, period %u, duty %u\n", clk_rate, prescalers[prescaler], period, duty); - if (pwm->prescaler == prescaler && pwm->period == period) + if (tpd->prescaler == prescaler && tpd->period == period) duty_only = true; - pwm->prescaler = prescaler; - pwm->period = period; - pwm->duty = duty; + tpd->prescaler = prescaler; + tpd->period = period; + tpd->duty = duty; /* If the channel is disabled we're done. */ if (!enabled) return 0; - if (duty_only && pwm->timer_on) { + if (duty_only && tpd->timer_on) { /* * If only the duty cycle changed and the timer is already * running, there's no need to reconfigure it completely, Just * modify the duty cycle. */ - tpu_pwm_write(pwm, TPU_TGRAn, pwm->duty); - dev_dbg(&tpu->pdev->dev, "%u: TGRA 0x%04x\n", pwm->channel, - pwm->duty); + tpu_pwm_write(tpd, TPU_TGRAn, tpd->duty); + dev_dbg(&tpu->pdev->dev, "%u: TGRA 0x%04x\n", tpd->channel, + tpd->duty); } else { /* Otherwise perform a full reconfiguration. */ - ret = tpu_pwm_timer_start(pwm); + ret = tpu_pwm_timer_start(tpd); if (ret < 0) return ret; } @@ -317,29 +317,29 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, * To avoid running the timer when not strictly required, handle * 0% and 100% duty cycles as fixed levels and stop the timer. */ - tpu_pwm_set_pin(pwm, duty ? TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); - tpu_pwm_timer_stop(pwm); + tpu_pwm_set_pin(tpd, duty ? TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); + tpu_pwm_timer_stop(tpd); } return 0; } -static int tpu_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *_pwm, +static int tpu_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, enum pwm_polarity polarity) { - struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); - pwm->polarity = polarity; + tpd->polarity = polarity; return 0; } -static int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *_pwm) +static int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { - struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); int ret; - ret = tpu_pwm_timer_start(pwm); + ret = tpu_pwm_timer_start(tpd); if (ret < 0) return ret; @@ -347,23 +347,23 @@ static int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *_pwm) * To avoid running the timer when not strictly required, handle 0% and * 100% duty cycles as fixed levels and stop the timer. */ - if (pwm->duty == 0 || pwm->duty == pwm->period) { - tpu_pwm_set_pin(pwm, pwm->duty ? + if (tpd->duty == 0 || tpd->duty == tpd->period) { + tpu_pwm_set_pin(tpd, tpd->duty ? TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); - tpu_pwm_timer_stop(pwm); + tpu_pwm_timer_stop(tpd); } return 0; } -static void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *_pwm) +static void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { - struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); + struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); /* The timer must be running to modify the pin output configuration. */ - tpu_pwm_timer_start(pwm); - tpu_pwm_set_pin(pwm, TPU_PIN_INACTIVE); - tpu_pwm_timer_stop(pwm); + tpu_pwm_timer_start(tpd); + tpu_pwm_set_pin(tpd, TPU_PIN_INACTIVE); + tpu_pwm_timer_stop(tpd); } static int tpu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, From patchwork Wed Apr 13 08:50:49 2022 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: 12811745 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E11F3C43219 for ; Wed, 13 Apr 2022 08:51:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234080AbiDMIxq (ORCPT ); Wed, 13 Apr 2022 04:53:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234365AbiDMIxb (ORCPT ); Wed, 13 Apr 2022 04:53:31 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D4C73EA86 for ; Wed, 13 Apr 2022 01:51:10 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1neYiO-0006XH-8U; Wed, 13 Apr 2022 10:51:04 +0200 Received: from [2a0a:edc0:0:900:1d::77] (helo=ptz.office.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1neYiM-002kHL-JB; Wed, 13 Apr 2022 10:51:01 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1neYiK-002yxP-9N; Wed, 13 Apr 2022 10:51:00 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Laurent Pinchart , Simon Horman , Geert Uytterhoeven , Magnus Damm , Thierry Reding , Lee Jones Cc: linux-pwm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH 5/6] pwm: renesas-tpu: Improve maths to compute register settings Date: Wed, 13 Apr 2022 10:50:49 +0200 Message-Id: <20220413085050.61144-5-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> References: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2642; h=from:subject; bh=rYHIrAA48GsGOD8/J/9zAejAgt04LHzoAn8QOvls2gg=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiVo7jXFFbQ+1aXVOiQZTPKlTBShl3fynGmhvwshUg nxYU4AiJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYlaO4wAKCRDB/BR4rcrsCf22B/ 4u2hBVNzCo91PC8eHJOy4/nie79XOqsuDO/3OrLXaQu1/fXeaxXJKHQQUQpMxtHwdpZwJtVOSMmkzK xOIbLZ2QrKzY8xxCutD0xcd2NaSl2Ui4EU4zikOlcrDW9ZE0WF+VPj+T7M/enWjSmA6yES/H+zRBKS fKgOmwdOOJnrEe0N8wm8NlL7kX+QM45clpY89mHhw5/YrHTT0jOp8K6w7sSvqS7EZWZmUNTzgTzl/P uE33JFSTJtJGZYPI8MUPm9UV9WrPmRU328DAbNWropQIg+y9ZI3Fa13JzB736jxhdTj8AITEYyirBh V58POE5YwLSqu4cco+D/fD5qeLdWSx X-Developer-Key: i=u.kleine-koenig@pengutronix.de; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 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-renesas-soc@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org The newly computed register values are intended to exactly match the previously computed values. The main improvement is that the prescaler is computed directly instead of with a loop. This uses the fact, that prescalers[i] = 1 << (2 * i). Assuming a moderately smart compiler, the needed number of divisions for the case where the requested period is too big, is reduced from 5 to 2. Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven --- drivers/pwm/pwm-renesas-tpu.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 671f1f824da8..fce7df418d62 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -244,7 +244,6 @@ static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, int duty_ns, int period_ns, bool enabled) { - static const unsigned int prescalers[] = { 1, 4, 16, 64 }; struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); struct tpu_device *tpu = to_tpu_device(chip); unsigned int prescaler; @@ -254,26 +253,21 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u32 duty; int ret; - /* - * Pick a prescaler to avoid overflowing the counter. - * TODO: Pick the highest acceptable prescaler. - */ clk_rate = clk_get_rate(tpu->clk); - for (prescaler = 0; prescaler < ARRAY_SIZE(prescalers); ++prescaler) { - period = clk_rate / prescalers[prescaler] - / (NSEC_PER_SEC / period_ns); - if (period <= 0xffff) - break; - } + period = clk_rate / (NSEC_PER_SEC / period_ns); + if (period >= 64 * 0x10000 || period == 0) + return -EINVAL; - if (prescaler == ARRAY_SIZE(prescalers) || period == 0) { - dev_err(&tpu->pdev->dev, "clock rate mismatch\n"); - return -ENOTSUPP; - } + if (period < 0x10000) + prescaler = 0; + else + prescaler = ilog2(period / 0x10000) / 2 + 1; + + period >>= 2 * prescaler; if (duty_ns) { - duty = clk_rate / prescalers[prescaler] + duty = (clk_rate >> 2 * prescaler) / (NSEC_PER_SEC / duty_ns); if (duty > period) return -EINVAL; @@ -283,7 +277,7 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, dev_dbg(&tpu->pdev->dev, "rate %u, prescaler %u, period %u, duty %u\n", - clk_rate, prescalers[prescaler], period, duty); + clk_rate, 1 << (2 * prescaler), period, duty); if (tpd->prescaler == prescaler && tpd->period == period) duty_only = true; From patchwork Wed Apr 13 08:50:50 2022 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: 12811747 X-Patchwork-Delegate: geert@linux-m68k.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3F074C433EF for ; Wed, 13 Apr 2022 08:51:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234109AbiDMIxr (ORCPT ); Wed, 13 Apr 2022 04:53:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34984 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234362AbiDMIxa (ORCPT ); Wed, 13 Apr 2022 04:53:30 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6D5C73FBE6 for ; Wed, 13 Apr 2022 01:51:10 -0700 (PDT) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1neYiO-0006XF-8U; Wed, 13 Apr 2022 10:51:04 +0200 Received: from [2a0a:edc0:0:900:1d::77] (helo=ptz.office.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.94.2) (envelope-from ) id 1neYiM-002kHI-Ec; Wed, 13 Apr 2022 10:51:01 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1neYiK-002yxS-Dd; Wed, 13 Apr 2022 10:51:00 +0200 From: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= To: Laurent Pinchart , Simon Horman , Geert Uytterhoeven , Magnus Damm , Thierry Reding , Lee Jones Cc: linux-pwm@vger.kernel.org, linux-renesas-soc@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH 6/6] pwm: renesas-tpu: Improve precision of period and duty_cycle calculation Date: Wed, 13 Apr 2022 10:50:50 +0200 Message-Id: <20220413085050.61144-6-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> References: <20220413085050.61144-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3173; h=from:subject; bh=To3Or6W+jc16XwScrmzN0w37nRFhAJ8ifH/qhlKS3/0=; b=owEBbAGT/pANAwAKAcH8FHityuwJAcsmYgBiVo7mBSJF2KbShxT9qqTI64K+NJjqTXe9nRPXylKi 1l7ujOSJATIEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYlaO5gAKCRDB/BR4rcrsCdIoB/ j33Mhrq2HiFzH3VwKNbf6FTbf34SXIzTEmRVKuUVMk3AkWO4aNRJhdBMe0TDxut9QlxXrsHux1mhr3 ntZHKfSrN8ru2+WvhLb5St+AaMF846DvGMZALktUhE8vatNJOHXh9p71zFSU5i94KXtoZ9tAVANs9d ftYiuRWRraEF+aV4HdRGwEuvtR9nGpJb6p3x5AXxyHtOJ47yji5IcEmt0BbF0OHmmCFPvGtbncdRER kR8MTI/A9vcmAyXNB+aK/mehbw+KLF+wb/HtQoOL4HZcxuc4pY23+xd/+U4SZt6FMA6I2dETcDxMwV IKHs/M8jRoSVnp9J6hUHHvbQKSTgQ= X-Developer-Key: i=u.kleine-koenig@pengutronix.de; a=openpgp; fpr=0D2511F322BFAB1C1580266BE2DCDD9132669BD6 X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 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-renesas-soc@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-renesas-soc@vger.kernel.org Dividing by the result of a division looses precision. Consider for example clk_rate = 33000000 and period_ns = 500001. Then clk_rate / (NSEC_PER_SEC / period_ns) has the exact value 16500.033, but in C this evaluates to 16508. It gets worse for even bigger values of period_ns, so with period_ns = 500000001, the exact result is 16500000.033 while in C we get 33000000. For that reason use clk_rate * period_ns / NSEC_PER_SEC instead which doesn't suffer from this problem. To ensure this doesn't overflow add a safeguard check for clk_rate. Incidentally this fixes a division by zero if period_ns > NSEC_PER_SEC. Another side effect is that values bigger than INT_MAX for period and duty_cyle are not wrongly discarded any more. Fixes: 99b82abb0a35 ("pwm: Add Renesas TPU PWM driver") Signed-off-by: Uwe Kleine-König Reviewed-by: Geert Uytterhoeven Tested-by: Geert Uytterhoeven --- drivers/pwm/pwm-renesas-tpu.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index fce7df418d62..c8c7a896fc55 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -242,42 +242,52 @@ static void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) } static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, - int duty_ns, int period_ns, bool enabled) + u64 duty_ns, u64 period_ns, bool enabled) { struct tpu_pwm_device *tpd = pwm_get_chip_data(pwm); struct tpu_device *tpu = to_tpu_device(chip); unsigned int prescaler; bool duty_only = false; u32 clk_rate; - u32 period; + u64 period; u32 duty; int ret; clk_rate = clk_get_rate(tpu->clk); + if (unlikely(clk_rate > 1000000000UL)) { + /* + * This won't happen in the nearer future, so this is only a + * safeguard to prevent the following calculation from + * overflowing. With this clk_rate * period_ns / NSEC_PER_SEC is + * not greater than period_ns and so fits into an u64. + */ + return -EINVAL; + } - period = clk_rate / (NSEC_PER_SEC / period_ns); + period = mul_u64_u64_div_u64(clk_rate, period_ns, NSEC_PER_SEC); if (period >= 64 * 0x10000 || period == 0) return -EINVAL; if (period < 0x10000) prescaler = 0; else - prescaler = ilog2(period / 0x10000) / 2 + 1; + /* + * We know period to fit into an u32, so cast accordingly to + * make the division a bit cheaper + */ + prescaler = ilog2((u32)period / 0x10000) / 2 + 1; period >>= 2 * prescaler; - if (duty_ns) { - duty = (clk_rate >> 2 * prescaler) - / (NSEC_PER_SEC / duty_ns); - if (duty > period) - return -EINVAL; - } else { + if (duty_ns) + duty = mul_u64_u64_div_u64(clk_rate, duty_ns, + (u64)NSEC_PER_SEC << (2 * prescaler)); + else duty = 0; - } dev_dbg(&tpu->pdev->dev, "rate %u, prescaler %u, period %u, duty %u\n", - clk_rate, 1 << (2 * prescaler), period, duty); + clk_rate, 1 << (2 * prescaler), (u32)period, duty); if (tpd->prescaler == prescaler && tpd->period == period) duty_only = true;