All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paul Cercueil <paul@crapouillou.net>
To: Rob Herring <robh+dt@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Thierry Reding <thierry.reding@gmail.com>,
	Daniel Lezcano <daniel.lezcano@linaro.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Wim Van Sebroeck <wim@linux-watchdog.org>,
	Ralf Baechle <ralf@linux-mips.org>,
	Paul Burton <paul.burton@mips.com>,
	James Hogan <jhogan@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	Michael Turquette <mturquette@baylibre.com>,
	Stephen Boyd <sboyd@kernel.org>
Cc: Mathieu Malaterre <malat@debian.org>,
	od@zcrc.me, linux-pwm@vger.kernel.org,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-watchdog@vger.kernel.org, linux-mips@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-clk@vger.kernel.org,
	Paul Cercueil <paul@crapouillou.net>
Subject: [PATCH v11 14/27] pwm: jz4740: Improve algorithm of clock calculation
Date: Thu, 28 Mar 2019 00:16:18 +0100	[thread overview]
Message-ID: <20190327231631.15708-15-paul@crapouillou.net> (raw)
In-Reply-To: <20190327231631.15708-1-paul@crapouillou.net>

The previous algorithm hardcoded details about how the TCU clocks work.

The new algorithm will compute the maximum frequency at which the clock
can run for the given period/duty parameters, and use clk_set_max_rate()
to ensure that we will always compute period/duty values that fit in our
16-bit register fields.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
Tested-by: Mathieu Malaterre <malat@debian.org>
Tested-by: Artur Rojek <contact@artur-rojek.eu>
---
 drivers/pwm/pwm-jz4740.c | 51 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 35 insertions(+), 16 deletions(-)

diff --git a/drivers/pwm/pwm-jz4740.c b/drivers/pwm/pwm-jz4740.c
index 1a0eab0abafe..b55ee879e23d 100644
--- a/drivers/pwm/pwm-jz4740.c
+++ b/drivers/pwm/pwm-jz4740.c
@@ -108,24 +108,47 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
 	struct clk *clk = pwm_get_chip_data(pwm),
 		   *parent_clk = clk_get_parent(clk);
-	unsigned long rate, period, duty;
+	unsigned long rate, parent_rate, period, duty;
 	unsigned long long tmp;
-	unsigned int prescaler = 0;
+	int ret;
 
-	rate = clk_get_rate(parent_clk);
-	tmp = (unsigned long long)rate * state->period;
-	do_div(tmp, 1000000000);
-	period = tmp;
+	parent_rate = clk_get_rate(parent_clk);
+
+	jz4740_pwm_disable(chip, pwm);
+
+	/* Reset the clock to the maximum rate, and we'll reduce it if needed */
+	ret = clk_set_rate(clk, parent_rate);
+	if (ret)
+		return ret;
 
-	while (period > 0xffff && prescaler < 6) {
-		period >>= 2;
-		rate >>= 2;
-		++prescaler;
+	/*
+	 * Limit the clock to a maximum rate that still gives us a period value
+	 * which fits in 16 bits.
+	 */
+	tmp = 0xffffull * NSEC_PER_SEC;
+	do_div(tmp, state->period);
+
+	ret = clk_set_max_rate(clk, tmp);
+	if (ret) {
+		dev_err(chip->dev, "Unable to set max rate: %i\n", ret);
+		return ret;
 	}
 
-	if (prescaler == 6)
-		return -EINVAL;
+	/*
+	 * Read back the clock rate, as it may have been modified by
+	 * clk_set_max_rate()
+	 */
+	rate = clk_get_rate(clk);
+
+	if (rate != parent_rate)
+		dev_dbg(chip->dev, "PWM clock updated to %lu Hz\n", rate);
 
+	/* Calculate period value */
+	tmp = (unsigned long long)rate * state->period;
+	do_div(tmp, NSEC_PER_SEC);
+	period = (unsigned long)tmp;
+
+	/* Calculate duty value */
 	tmp = (unsigned long long)period * state->duty_cycle;
 	do_div(tmp, state->period);
 	duty = period - tmp;
@@ -133,8 +156,6 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	if (duty >= period)
 		duty = period - 1;
 
-	jz4740_pwm_disable(chip, pwm);
-
 	/*
 	 * Set abrupt shutdown.
 	 *
@@ -144,8 +165,6 @@ static int jz4740_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	regmap_update_bits(jz4740->map, TCU_REG_TCSRc(pwm->hwpwm),
 			   TCU_TCSR_PWM_SD, TCU_TCSR_PWM_SD);
 
-	clk_set_rate(clk, rate);
-
 	/* Reset counter to 0 */
 	regmap_write(jz4740->map, TCU_REG_TCNTc(pwm->hwpwm), 0);
 
-- 
2.11.0


  parent reply	other threads:[~2019-03-27 23:17 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-27 23:16 [PATCH v11 00/27] Ingenic JZ47xx TCU pachset v11 Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 01/27] dt-bindings: ingenic: Add DT bindings for TCU clocks Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 02/27] doc: Add doc for the Ingenic TCU hardware Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 03/27] dt-bindings: Add doc for the Ingenic TCU drivers Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 04/27] clocksource: Add a new timer-ingenic driver Paul Cercueil
2019-04-05 20:44   ` Thomas Gleixner
2019-03-27 23:16 ` [PATCH v11 05/27] clocksource: Add driver for the Ingenic JZ47xx OST Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 06/27] MAINTAINERS: Add myself as maintainer for Ingenic TCU drivers Paul Cercueil
2019-03-28  1:29   ` Joe Perches
2019-03-27 23:16 ` [PATCH v11 07/27] watchdog: jz4740: Use WDT clock provided by TCU driver Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 08/27] watchdog: jz4740: Use regmap " Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 09/27] watchdog: jz4740: Avoid starting watchdog in set_timeout Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 10/27] watchdog: jz4740: Drop dependency on MACH_JZ47xx, use COMPILE_TEST Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 11/27] pwm: jz4740: Apply configuration atomically Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 12/27] pwm: jz4740: Use regmap from TCU driver Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 13/27] pwm: jz4740: Use clocks " Paul Cercueil
2019-03-27 23:16 ` Paul Cercueil [this message]
2019-03-27 23:16 ` [PATCH v11 15/27] pwm: jz4740: Allow selection of PWM channels 0 and 1 Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 16/27] pwm: jz4740: Drop dependency on MACH_INGENIC, use COMPILE_TEST Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 17/27] pwm: jz4740: Remove unused devicetree compatible strings Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 18/27] clk: jz4740: Add TCU clock Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 19/27] MIPS: Kconfig: Select TCU timer driver when MACH_INGENIC is set Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 20/27] MIPS: jz4740: Add DTS nodes for the TCU drivers Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 21/27] MIPS: qi_lb60: Move PWM devices to devicetree Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 22/27] MIPS: qi_lb60: Reduce system timer and clocksource to 750 kHz Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 23/27] MIPS: CI20: Reduce system timer and clocksource to 3 MHz Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 24/27] MIPS: CI20: defconfig: enable OST driver Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 25/27] MIPS: GCW0: Reduce system timer and clocksource to 750 kHz Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 26/27] MIPS: GCW0: defconfig: Enable OST, watchdog, PWM drivers Paul Cercueil
2019-03-27 23:16 ` [PATCH v11 27/27] MIPS: jz4740: Drop obsolete code Paul Cercueil

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=20190327231631.15708-15-paul@crapouillou.net \
    --to=paul@crapouillou.net \
    --cc=corbet@lwn.net \
    --cc=daniel.lezcano@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=jhogan@kernel.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=linux-pwm@vger.kernel.org \
    --cc=linux-watchdog@vger.kernel.org \
    --cc=malat@debian.org \
    --cc=mark.rutland@arm.com \
    --cc=mturquette@baylibre.com \
    --cc=od@zcrc.me \
    --cc=paul.burton@mips.com \
    --cc=ralf@linux-mips.org \
    --cc=robh+dt@kernel.org \
    --cc=sboyd@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=thierry.reding@gmail.com \
    --cc=wim@linux-watchdog.org \
    /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.