All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guru Das Srinagesh <gurus@codeaurora.org>
To: linux-pwm@vger.kernel.org,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: Subbaraman Narayanamurthy <subbaram@codeaurora.org>,
	David Collins <collinsd@codeaurora.org>,
	linux-kernel@vger.kernel.org, Joe Perches <joe@perches.com>,
	Arnd Bergmann <arnd@arndb.de>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	Guenter Roeck <linux@roeck-us.net>,
	Daniel Thompson <daniel.thompson@linaro.org>,
	Dan Carpenter <dan.carpenter@oracle.com>,
	Guru Das Srinagesh <gurus@codeaurora.org>
Subject: [RESEND PATCH v14 06/11] pwm: imx27: Use 64-bit division macro and function
Date: Mon,  4 May 2020 11:50:12 -0700	[thread overview]
Message-ID: <72e4dcdde37461ed7f9490a4742b65204787e687.1588616856.git.gurus@codeaurora.org> (raw)
In-Reply-To: <cover.1588616856.git.gurus@codeaurora.org>
In-Reply-To: <cover.1588616856.git.gurus@codeaurora.org>

Since the PWM framework is switching struct pwm_state.period's
datatype to u64, prepare for this transition by using
DIV_ROUND_UP_ULL to handle a 64-bit dividend, and div64_u64 to handle a
64-bit divisor.

Also handle a possible overflow in the calculation of period_cycles when
both clk_rate and period are large numbers. This logic was unit-tested
out by calculating period_cycles using both the existing logic and the
proposed one, and the results are as below.

----------------------------------------------------------------------------
 clk_rate            period           existing            proposed
----------------------------------------------------------------------------
1000000000   18446744073709551615    18446744072    18446744073000000000
                   (U64_MAX)
----------------------------------------------------------------------------
1000000000        4294967291         4294967291         4294967291
----------------------------------------------------------------------------

Overflow occurs in the first case with the existing logic, whereas the
proposed logic handles it better, sacrificing some precision in a best-effort
attempt to handle overflow. As for the second case where there are
more typical values of period, the proposed logic handles that correctly
too.

Signed-off-by: Guru Das Srinagesh <gurus@codeaurora.org>
---
 drivers/pwm/pwm-imx27.c | 53 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 45 insertions(+), 8 deletions(-)

diff --git a/drivers/pwm/pwm-imx27.c b/drivers/pwm/pwm-imx27.c
index a6e40d4..164cb65 100644
--- a/drivers/pwm/pwm-imx27.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -203,7 +203,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
 	sr = readl(imx->mmio_base + MX3_PWMSR);
 	fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr);
 	if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
-		period_ms = DIV_ROUND_UP(pwm_get_period(pwm),
+		period_ms = DIV_ROUND_UP_ULL(pwm_get_period(pwm),
 					 NSEC_PER_MSEC);
 		msleep(period_ms);
 
@@ -213,6 +213,45 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
 	}
 }
 
+static int pwm_imx27_calc_period_cycles(const struct pwm_state *state,
+					unsigned long clk_rate,
+					unsigned long *period_cycles)
+{
+	u64 c = 0, c1, c2;
+
+	c1 = clk_rate;
+	c2 = state->period;
+	if (c2 > c1) {
+		c2 = c1;
+		c1 = state->period;
+	}
+
+	if (!c1 || !c2) {
+		pr_err("clk rate and period should be nonzero\n");
+		return -EINVAL;
+	}
+
+	if (c2 <= div64_u64(U64_MAX, c1)) {
+		c = c1 * c2;
+		do_div(c, 1000000000);
+	} else if (c2 <= div64_u64(U64_MAX, div64_u64(c1, 1000))) {
+		do_div(c1, 1000);
+		c = c1 * c2;
+		do_div(c, 1000000);
+	} else if (c2 <= div64_u64(U64_MAX, div64_u64(c1, 1000000))) {
+		do_div(c1, 1000000);
+		c = c1 * c2;
+		do_div(c, 1000);
+	} else if (c2 <= div64_u64(U64_MAX, div64_u64(c1, 1000000000))) {
+		do_div(c1, 1000000000);
+		c = c1 * c2;
+	}
+
+	*period_cycles = c;
+
+	return 0;
+}
+
 static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			   const struct pwm_state *state)
 {
@@ -225,18 +264,16 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 
 	pwm_get_state(pwm, &cstate);
 
-	c = clk_get_rate(imx->clk_per);
-	c *= state->period;
-
-	do_div(c, 1000000000);
-	period_cycles = c;
+	ret = pwm_imx27_calc_period_cycles(state, clk_get_rate(imx->clk_per),
+					   &period_cycles);
+	if (ret)
+		return ret;
 
 	prescale = period_cycles / 0x10000 + 1;
 
 	period_cycles /= prescale;
 	c = (unsigned long long)period_cycles * state->duty_cycle;
-	do_div(c, state->period);
-	duty_cycles = c;
+	duty_cycles = div64_u64(c, state->period);
 
 	/*
 	 * according to imx pwm RM, the real period value should be PERIOD
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


  parent reply	other threads:[~2020-05-04 18:50 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-04 18:50 [RESEND PATCH v14 00/11] Convert PWM period and duty cycle to u64 Guru Das Srinagesh
2020-05-13  0:39 ` Guru Das Srinagesh
2020-05-13  0:39 ` Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 01/11] drm/i915: Use 64-bit division macro Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 02/11] hwmon: pwm-fan: " Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 03/11] ir-rx51: " Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 04/11] pwm: clps711x: Cast period to u32 before use as divisor Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 05/11] pwm: pwm-imx-tpm: Use 64-bit division macro Guru Das Srinagesh
2020-05-04 18:50 ` Guru Das Srinagesh [this message]
2020-05-04 18:50 ` [RESEND PATCH v14 07/11] pwm: sifive: " Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 08/11] pwm: sun4i: Use nsecs_to_jiffies to avoid a division Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 09/11] backlight: pwm_bl: Use 64-bit division function Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 10/11] clk: pwm: " Guru Das Srinagesh
2020-05-04 18:50 ` [RESEND PATCH v14 11/11] pwm: core: Convert period and duty cycle to u64 Guru Das Srinagesh
2020-05-13  0:39 [RESEND PATCH v14 00/11] Convert PWM " Guru Das Srinagesh
2020-05-20 22:55 ` Guru Das Srinagesh
2020-05-20 22:55 ` Guru Das Srinagesh
2020-05-13  0:39 ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 01/11] drm/i915: Use 64-bit division macro Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 02/11] hwmon: pwm-fan: " Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 03/11] ir-rx51: " Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 04/11] pwm: clps711x: Cast period to u32 before use as divisor Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-21 10:19   ` Daniel Thompson
2020-05-21 10:19     ` Daniel Thompson
2020-05-21 20:25     ` Guru Das Srinagesh
2020-05-21 20:25       ` Guru Das Srinagesh
2020-05-22  9:37       ` Daniel Thompson
2020-05-22  9:37         ` Daniel Thompson
2020-05-22 23:19         ` Guru Das Srinagesh
2020-05-22 23:19           ` Guru Das Srinagesh
2020-05-23 17:08           ` Daniel Thompson
2020-05-23 17:08             ` Daniel Thompson
2020-05-13  0:39 ` [RESEND PATCH v14 05/11] pwm: pwm-imx-tpm: Use 64-bit division macro Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 06/11] pwm: imx27: Use 64-bit division macro and function Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-20 22:55   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 07/11] pwm: sifive: Use 64-bit division macro Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 08/11] pwm: sun4i: Use nsecs_to_jiffies to avoid a division Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 09/11] backlight: pwm_bl: Use 64-bit division function Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 10/11] clk: pwm: " Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh
2020-05-13  0:39 ` [RESEND PATCH v14 11/11] pwm: core: Convert period and duty cycle to u64 Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-20 22:56   ` Guru Das Srinagesh
2020-05-13  0:39   ` Guru Das Srinagesh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=72e4dcdde37461ed7f9490a4742b65204787e687.1588616856.git.gurus@codeaurora.org \
    --to=gurus@codeaurora.org \
    --cc=arnd@arndb.de \
    --cc=collinsd@codeaurora.org \
    --cc=dan.carpenter@oracle.com \
    --cc=daniel.thompson@linaro.org \
    --cc=geert@linux-m68k.org \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=subbaram@codeaurora.org \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.