From patchwork Wed Apr 20 12:12:35 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: 12820153 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 0673DC4332F for ; Wed, 20 Apr 2022 12:13:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243765AbiDTMPp (ORCPT ); Wed, 20 Apr 2022 08:15:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55558 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352208AbiDTMPl (ORCPT ); Wed, 20 Apr 2022 08:15:41 -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 00F2B3FD9F for ; Wed, 20 Apr 2022 05:12:54 -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 1nh9CT-00022G-QD; Wed, 20 Apr 2022 14:12:50 +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 1nh9CT-0049d9-IV; Wed, 20 Apr 2022 14:12:48 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1nh9CR-004TjP-Bh; Wed, 20 Apr 2022 14:12:47 +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-renesas-soc@vger.kernel.org, linux-pwm@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH v2 1/6] pwm: renesas-tpu: Make use of dev_err_probe() Date: Wed, 20 Apr 2022 14:12:35 +0200 Message-Id: <20220420121240.67781-2-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> References: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1513; h=from:subject; bh=JivNFMG/z4JeGqeX79lb9aRv8j7uIu1q/mvnNaxM3To=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiX/ijrJRk1V/r/AZjlh9RbAxavLxrSjeh6hNH4jER ZdJXenWJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYl/4owAKCRDB/BR4rcrsCWVXB/ 90gac5gMe2eBImJ4fxE2FIFg1mOO4vpXSkG4scShZh8oSDGz+mHT/Sdrii5d20J+PLbiZZAUH8noNg Pz0rZDmV4Py+f9NdksaIDP7sTUoR0xY/A87oxVR88kzFjwFC4Yl+7CK/knApLVIwqW4vuawSaIn0/v MOuElSLas7yP8fOc6PNXN/WNbv7W/oUwUlxf87oWheu0Nf4IYz+58KleWUOyebOc7ZDF2MCf3iBNRo qzHpuNdrRTmpaBZ8cnixVwdzLhxG7mW3LRjfJEeH/VSo+5cGAz/NubVGB7BtrI/SXhjPMrmutDgdbm 47gv3dSXGw/d3LoT2ruETg8UpTFaNi 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, consistently start error messages with upper case. Reviewed-by: Geert Uytterhoeven Signed-off-by: Uwe Kleine-König --- drivers/pwm/pwm-renesas-tpu.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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 20 12:12:36 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: 12820151 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 90443C433F5 for ; Wed, 20 Apr 2022 12:13:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352844AbiDTMPl (ORCPT ); Wed, 20 Apr 2022 08:15:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55552 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245115AbiDTMPl (ORCPT ); Wed, 20 Apr 2022 08:15:41 -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 030363FDA3 for ; Wed, 20 Apr 2022 05:12:55 -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 1nh9CT-00022H-QD; Wed, 20 Apr 2022 14:12:49 +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 1nh9CT-0049dD-NZ; Wed, 20 Apr 2022 14:12:48 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1nh9CR-004TjS-HB; Wed, 20 Apr 2022 14:12:47 +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-renesas-soc@vger.kernel.org, linux-pwm@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH v2 2/6] pwm: renesas-tpu: Make use of devm functions Date: Wed, 20 Apr 2022 14:12:36 +0200 Message-Id: <20220420121240.67781-3-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> References: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1580; h=from:subject; bh=RizOx7NVXQuWK1Haoa7Gvw6F5E+q4jAUSM2k+H7UdsA=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiX/imRIR1HDv8SwoJh5CjqhfSU/DW5wYAShAy+b2U r/FqClCJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYl/4pgAKCRDB/BR4rcrsCSfLB/ 9LhtqGRm2esY8qqYYMUcfk/Ba7rct5DwuI/InJTwldfw0JYLT0MM0lE+NdBlsGcQlAckUA2gEgYhSV OlNgOhl2/KHRnwmj0mtVpj0gRp8AJ5aEA4cPFhXde1UohEuQ+2SRPdR7xwmkCwEOoRlrnsDek+dZfp R1RgrEov6pEQal39rscgkvwZxgf7FaI0zdrxDHOKeDSzaEZNuXL3aYzduCu1D056zTIyH4o/DdeVpu 6dxp7HNJx5PgwON2ccpIwwJqyTQFST/9ZrUYYfZb0UXmcVuVz3q7ctvtqJWTkVapcRTBnyWBTURnQf MYIPa3fCeMJ/JgWpw1OCjkPNt5DU/h 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. Reviewed-by: Geert Uytterhoeven Signed-off-by: Uwe Kleine-König --- 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 20 12:12:37 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: 12820152 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 C6648C433FE for ; Wed, 20 Apr 2022 12:13:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245115AbiDTMPn (ORCPT ); Wed, 20 Apr 2022 08:15:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55554 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243765AbiDTMPl (ORCPT ); Wed, 20 Apr 2022 08:15:41 -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 1DC733FDBC for ; Wed, 20 Apr 2022 05:12:55 -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 1nh9CT-00022J-QD; Wed, 20 Apr 2022 14:12:49 +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 1nh9CU-0049dM-BT; Wed, 20 Apr 2022 14:12:48 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1nh9CR-004TjV-MG; Wed, 20 Apr 2022 14:12:47 +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-renesas-soc@vger.kernel.org, linux-pwm@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH v2 3/6] pwm: renesas-tpu: Implement .apply() callback Date: Wed, 20 Apr 2022 14:12:37 +0200 Message-Id: <20220420121240.67781-4-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> References: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2478; h=from:subject; bh=i/DbamAN54FzxHHPR0pW4sRTy4Kf59NwNWV7VxjTUzk=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiX/iqqLgSOGS/1b8wnJDCtNb5K7kfk2RHZAKdetgm jZL6NGqJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYl/4qgAKCRDB/BR4rcrsCSt8CA CBKJNZsRWNBb50Hf8q2v34VKVP2PoD7toTYIPEZtjwvX7gKOiWjEMu2P7DzzY2Ja2hbq2xXnpvMzuQ xDpA0idlGWoOFch31tOGL3mYAgt7ci807ObP2zfYwlQC5hYQlJLeB7EQaMFJ5ukJw0a2ES6Rh7LSFB NzP33wf/NuhqU00c3gBLgMESKbPVRMA7DqSemR4L9JFqNiWyjtnFN0odxDlQ6UEc3D8Hbb4OTQ6/jm zR1l0Mjwj4fP3qKfIwmL65lGRfZcmTP9rOuzzYyEtRewOVQVUiPF7QCyvPvqET0VRJ3/pt4diEsxen HtkCHXftJCVMFUjTu9orTigxKCQuwv 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 --- 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..bebae65a6ed7 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) + tpu_pwm_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 20 12:12:38 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: 12820157 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 D3D1BC4167E for ; Wed, 20 Apr 2022 12:13:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352807AbiDTMPs (ORCPT ); Wed, 20 Apr 2022 08:15:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55566 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352850AbiDTMPm (ORCPT ); Wed, 20 Apr 2022 08:15:42 -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 D360740931 for ; Wed, 20 Apr 2022 05:12:55 -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 1nh9CT-00022I-QD; Wed, 20 Apr 2022 14:12:49 +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 1nh9CU-0049dI-2K; Wed, 20 Apr 2022 14:12:48 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1nh9CR-004TjY-V0; Wed, 20 Apr 2022 14:12:47 +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-renesas-soc@vger.kernel.org, linux-pwm@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH v2 4/6] pwm: renesas-tpu: Rename variables to match the usual naming Date: Wed, 20 Apr 2022 14:12:38 +0200 Message-Id: <20220420121240.67781-5-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> References: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=11426; h=from:subject; bh=vV57d6AreuVFiBrIu5rjQqcCl2bAMR8gpBs3bRF3tvA=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiX/itCffj6vn3ekULQbjGueD00eYgVkhLDFmNSLQr K6WgsdmJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYl/4rQAKCRDB/BR4rcrsCTWFCA CVcjW1+OXhBXHvUlD15w/O6TVrvCouFx9VPSTr+XDkFMTHXP8+fJy5ogTtb9NcE2rshbEEQ8O/ZbsC M4tPe3fDcwryaNn/qFOm4m0hvOkh0n8AEb59kLkt2Fg4Oyb7zyUDxr1K6h5c3ozIQLLFFWdsgFBpXs ljzMfgMe2zTU0IKBzm7JITPBY04TrvKrYyg+b02Ea9G9UaCyKjye+BduB/xikS5+uPj/gAV7mD6yX3 4BH3RdG3K5Bu1TDQS2clkGmz8tElWLlqa3Vnl6LLZgCuSMCTki3r1NIzfvH5eW6D3KnFfmold1rYLS EeTcdaEotzGHooUD9USIHnnX6o67B1 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 bebae65a6ed7..5bced2050ece 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 20 12:12:39 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: 12820154 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 59841C43217 for ; Wed, 20 Apr 2022 12:13:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353006AbiDTMPr (ORCPT ); Wed, 20 Apr 2022 08:15:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55568 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352770AbiDTMPl (ORCPT ); Wed, 20 Apr 2022 08:15:41 -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 8BF43403E5 for ; Wed, 20 Apr 2022 05:12:55 -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 1nh9CT-00022K-QD; Wed, 20 Apr 2022 14:12:49 +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 1nh9CU-0049dL-BA; Wed, 20 Apr 2022 14:12:48 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1nh9CS-004Tjc-4s; Wed, 20 Apr 2022 14:12:48 +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-renesas-soc@vger.kernel.org, linux-pwm@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH v2 5/6] pwm: renesas-tpu: Improve maths to compute register settings Date: Wed, 20 Apr 2022 14:12:39 +0200 Message-Id: <20220420121240.67781-6-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> References: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3209; h=from:subject; bh=pPojDEu8z/W+/Kd6UveQxXHJ9q84tC1SOQi5YlALafE=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiX/ixNXAhCHjiYXdiwdodnuRuPu1zzi1W00JTOrPc xKC5xc+JATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYl/4sQAKCRDB/BR4rcrsCdazB/ 92Ln8NX2iZKelpuVLDEwcyRb/vtTlv1TYQOA5ASb06DyqSrTZumcFXkSAfsdpkTBIaYlEdKrPeOkX8 DDWKPozqKUICiKJZLWHovoCE2a/NiNxR1PvOCvCJt7nRABieJjMcbWLa2+2/6DGIx9IXn5mvqImMMh QIKQ5a/T6959hSbkDihOktwxvPftXNpermnN8MblfodJQZZx4G+AJfoIxnM2nU23LBWlnAF0PEfSli QQt/FbOcZQs3q55X+kGY+7V8xUjp1gGzxOkhgNp5v/OSqGWI+Zb/9OsFEy/lVCUPMSuQBKdGKzRaag 4W+bMq3S+M2egiigtU1jHcV/fgjjTQ 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 without a loop that involves two divisions in each step. 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 --- drivers/pwm/pwm-renesas-tpu.c | 50 ++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 5bced2050ece..60ba7cf275c7 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,47 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, u32 duty; int ret; + clk_rate = clk_get_rate(tpu->clk); + + period = clk_rate / (NSEC_PER_SEC / period_ns); + /* - * Pick a prescaler to avoid overflowing the counter. - * TODO: Pick the highest acceptable prescaler. + * Find the minimal prescaler in [0..3] such that + * + * period >> (2 * prescaler) < 0x10000 + * + * This could be calculated using something like: + * + * prescaler = max(ilog2(period) / 2, 7) - 7; + * + * but given there are only four allowed results and that ilog2 isn't + * cheap on all platforms using a switch statement is more effective. */ - clk_rate = clk_get_rate(tpu->clk); + switch (period) { + case 1 ... 0xffff: + prescaler = 0; + break; - for (prescaler = 0; prescaler < ARRAY_SIZE(prescalers); ++prescaler) { - period = clk_rate / prescalers[prescaler] - / (NSEC_PER_SEC / period_ns); - if (period <= 0xffff) - break; - } + case 0x10000 ... 0x3ffff: + prescaler = 1; + break; - if (prescaler == ARRAY_SIZE(prescalers) || period == 0) { - dev_err(&tpu->pdev->dev, "clock rate mismatch\n"); - return -ENOTSUPP; + case 0x40000 ... 0xfffff: + prescaler = 2; + break; + + case 0x100000 ... 0x3fffff: + prescaler = 3; + break; + + default: + return -EINVAL; } + 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 +303,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 20 12:12:40 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: 12820156 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 5B808C4321E for ; Wed, 20 Apr 2022 12:13:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352746AbiDTMPs (ORCPT ); Wed, 20 Apr 2022 08:15:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55572 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352807AbiDTMPl (ORCPT ); Wed, 20 Apr 2022 08:15:41 -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 F1F7D393EE for ; Wed, 20 Apr 2022 05:12:54 -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 1nh9CU-00022V-CW; Wed, 20 Apr 2022 14:12:50 +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 1nh9CV-0049dR-2D; Wed, 20 Apr 2022 14:12:49 +0200 Received: from ukl by ptz.office.stw.pengutronix.de with local (Exim 4.94.2) (envelope-from ) id 1nh9CS-004Tjg-Ap; Wed, 20 Apr 2022 14:12:48 +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-renesas-soc@vger.kernel.org, linux-pwm@vger.kernel.org, kernel@pengutronix.de Subject: [PATCH v2 6/6] pwm: renesas-tpu: Improve precision of period and duty_cycle calculation Date: Wed, 20 Apr 2022 14:12:40 +0200 Message-Id: <20220420121240.67781-7-u.kleine-koenig@pengutronix.de> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> References: <20220420121240.67781-1-u.kleine-koenig@pengutronix.de> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=3068; h=from:subject; bh=qhmj+/kClimdnaMQquEEOOHX5xZ+ZRCX9FU00iWnViM=; b=owEBbQGS/pANAwAKAcH8FHityuwJAcsmYgBiX/i09g8CTVqTyKus3foEapayKgO+ir799otZKwof S7D4f3qJATMEAAEKAB0WIQR+cioWkBis/z50pAvB/BR4rcrsCQUCYl/4tAAKCRDB/BR4rcrsCb1fCA CSWg4qs1CDKt47OWQYbajjaAIkiiTZiL6UiB7gD8Rk9sq+I4g3X3dyD+5LAtCYwVHm+p1lgQa1a0PS fAqLWMPfKBYRwPrsekaR4qa2FfQ42NOq3sN7JA2Vkj8wb7/kECp9j2n3dI1M0pGJrZAurXDDnUt/sn AK3lN79Q3Or/NRbsULoEAIj3HyvhyfoBarxzGg/o4gj/JbpKzzkq0+AWMBOKT66EtLIIKaeA4w76pr sifzthRq27fo+KsTH0w9qPrwrUekqHj/0xn3jvWVTvsKh4UBkF65jHOIzWIiThmXMGN9QGbi2wvSlM b5nuyxPpah01sQ+Zsw3bIkNB0C1XeH 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. Note that duty > period can never happen, so the respective check can be dropped. 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 --- drivers/pwm/pwm-renesas-tpu.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 60ba7cf275c7..9e6978c39788 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c @@ -242,20 +242,29 @@ 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 > NSEC_PER_SEC)) { + /* + * 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); /* * Find the minimal prescaler in [0..3] such that @@ -292,18 +301,15 @@ static int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 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;