linux-renesas-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation
@ 2019-01-09  8:19 Yoshihiro Shimoda
  2019-01-09  8:19 ` [PATCH v3 1/4] pwm: rcar: Add support "atomic" API Yoshihiro Shimoda
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Yoshihiro Shimoda @ 2019-01-09  8:19 UTC (permalink / raw)
  To: thierry.reding; +Cc: linux-pwm, linux-renesas-soc, Yoshihiro Shimoda

This patch series adds support for PWM "atomic" API and improve
the clock calculation.

Changes from v2 [1]:
 - Add Acked-by of Uwe in patch [234]/4.
 - Modify a condition to support normal polarity only.
 - Fix possible to output wrong a duty cycle when disabling in patch 1/4.
 - Fix overflow value on 32-bit arch in patch 4/4.

Changes from v1 [2]:
 - Remove workaround code of output pseudo low level for now because it is
   rejected on the ML.
 - Add a condition for polarity because the HW doesn't support polarity change
   in patch 1/4.
 - Improve the clock calculation in patch 4/4.

[1]
https://patchwork.kernel.org/project/linux-renesas-soc/list/?series=63219

Remarks:
On the email thread of patch 2/4, we discuss about suspend/resume
handling and I suposed to improve it. However, I need more time
how to improve it. So, for now, I don't improve it on this patch series.

[2]
https://patchwork.kernel.org/project/linux-renesas-soc/list/?series=53193


Yoshihiro Shimoda (4):
  pwm: rcar: Add support "atomic" API
  pwm: rcar: Use "atomic" API on rcar_pwm_resume()
  pwm: rcar: remove legacy APIs
  pwm: rcar: improve calculation of divider

 drivers/pwm/pwm-rcar.c | 99 ++++++++++++++++++++++++--------------------------
 1 file changed, 48 insertions(+), 51 deletions(-)

-- 
1.9.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v3 1/4] pwm: rcar: Add support "atomic" API
  2019-01-09  8:19 [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Yoshihiro Shimoda
@ 2019-01-09  8:19 ` Yoshihiro Shimoda
  2019-01-09  8:19 ` [PATCH v3 2/4] pwm: rcar: Use "atomic" API on rcar_pwm_resume() Yoshihiro Shimoda
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Yoshihiro Shimoda @ 2019-01-09  8:19 UTC (permalink / raw)
  To: thierry.reding; +Cc: linux-pwm, linux-renesas-soc, Yoshihiro Shimoda

This patch adds support for "atomic" API. This behavior differs with
legacy APIs a little.

 Legacy APIs:
  The PWMCNT register will be updated in rcar_pwm_config() even if
  the PWM state is disabled.

 Atomic API:
  The PWMCNT register will be updated in rcar_pwm_apply() only if
  the PWM state is enabled. Otherwize, if a PWM runs with 30% duty
  cycles and the pwm_apply_state() is called with state->enabled = 0,
  ->duty_cycle = 60 and ->period = 100, this is possible to output
  a 60% duty cycle.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
 drivers/pwm/pwm-rcar.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index a41812f..e3ab663 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -192,12 +192,49 @@ static void rcar_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 	rcar_pwm_update(rp, RCAR_PWMCR_EN0, 0, RCAR_PWMCR);
 }
 
+static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			  struct pwm_state *state)
+{
+	struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
+	struct pwm_state cur_state;
+	int div, ret;
+
+	/* This HW/driver only supports normal polarity */
+	pwm_get_state(pwm, &cur_state);
+	if (state->polarity != PWM_POLARITY_NORMAL)
+		return -ENOTSUPP;
+
+	if (!state->enabled) {
+		rcar_pwm_disable(chip, pwm);
+		return 0;
+	}
+
+	div = rcar_pwm_get_clock_division(rp, state->period);
+	if (div < 0)
+		return div;
+
+	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR);
+
+	ret = rcar_pwm_set_counter(rp, div, state->duty_cycle, state->period);
+	if (!ret)
+		rcar_pwm_set_clock_control(rp, div);
+
+	/* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */
+	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR);
+
+	if (!ret && state->enabled)
+		ret = rcar_pwm_enable(chip, pwm);
+
+	return ret;
+}
+
 static const struct pwm_ops rcar_pwm_ops = {
 	.request = rcar_pwm_request,
 	.free = rcar_pwm_free,
 	.config = rcar_pwm_config,
 	.enable = rcar_pwm_enable,
 	.disable = rcar_pwm_disable,
+	.apply = rcar_pwm_apply,
 	.owner = THIS_MODULE,
 };
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 2/4] pwm: rcar: Use "atomic" API on rcar_pwm_resume()
  2019-01-09  8:19 [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Yoshihiro Shimoda
  2019-01-09  8:19 ` [PATCH v3 1/4] pwm: rcar: Add support "atomic" API Yoshihiro Shimoda
@ 2019-01-09  8:19 ` Yoshihiro Shimoda
  2019-03-04 11:18   ` Thierry Reding
  2019-01-09  8:19 ` [PATCH v3 3/4] pwm: rcar: remove legacy APIs Yoshihiro Shimoda
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Yoshihiro Shimoda @ 2019-01-09  8:19 UTC (permalink / raw)
  To: thierry.reding; +Cc: linux-pwm, linux-renesas-soc, Yoshihiro Shimoda

To remove legacy API related functions in the future, this patch
uses "atomic" related function instead. No change in behavior.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-rcar.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index e3ab663..652a937 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -316,18 +316,16 @@ static int rcar_pwm_suspend(struct device *dev)
 static int rcar_pwm_resume(struct device *dev)
 {
 	struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev);
+	struct pwm_state state;
 
 	if (!test_bit(PWMF_REQUESTED, &pwm->flags))
 		return 0;
 
 	pm_runtime_get_sync(dev);
 
-	rcar_pwm_config(pwm->chip, pwm, pwm->state.duty_cycle,
-			pwm->state.period);
-	if (pwm_is_enabled(pwm))
-		rcar_pwm_enable(pwm->chip, pwm);
+	pwm_get_state(pwm, &state);
 
-	return 0;
+	return rcar_pwm_apply(pwm->chip, pwm, &state);
 }
 #endif /* CONFIG_PM_SLEEP */
 static SIMPLE_DEV_PM_OPS(rcar_pwm_pm_ops, rcar_pwm_suspend, rcar_pwm_resume);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 3/4] pwm: rcar: remove legacy APIs
  2019-01-09  8:19 [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Yoshihiro Shimoda
  2019-01-09  8:19 ` [PATCH v3 1/4] pwm: rcar: Add support "atomic" API Yoshihiro Shimoda
  2019-01-09  8:19 ` [PATCH v3 2/4] pwm: rcar: Use "atomic" API on rcar_pwm_resume() Yoshihiro Shimoda
@ 2019-01-09  8:19 ` Yoshihiro Shimoda
  2019-01-09  8:19 ` [PATCH v3 4/4] pwm: rcar: improve calculation of divider Yoshihiro Shimoda
  2019-03-04 11:14 ` [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Thierry Reding
  4 siblings, 0 replies; 7+ messages in thread
From: Yoshihiro Shimoda @ 2019-01-09  8:19 UTC (permalink / raw)
  To: thierry.reding; +Cc: linux-pwm, linux-renesas-soc, Yoshihiro Shimoda

This patch removes legacy APIs. Since rcar_pwm_{en,dis}able()
functions are reused on "atomic" API, this patch changes
the arguments of these functions. No change in behavior.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-rcar.c | 44 ++++----------------------------------------
 1 file changed, 4 insertions(+), 40 deletions(-)

diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 652a937..1e13fbb 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -139,39 +139,8 @@ static void rcar_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 	pm_runtime_put(chip->dev);
 }
 
-static int rcar_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-			   int duty_ns, int period_ns)
+static int rcar_pwm_enable(struct rcar_pwm_chip *rp)
 {
-	struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
-	int div, ret;
-
-	div = rcar_pwm_get_clock_division(rp, period_ns);
-	if (div < 0)
-		return div;
-
-	/*
-	 * Let the core driver set pwm->period if disabled and duty_ns == 0.
-	 * But, this driver should prevent to set the new duty_ns if current
-	 * duty_cycle is not set
-	 */
-	if (!pwm_is_enabled(pwm) && !duty_ns && !pwm->state.duty_cycle)
-		return 0;
-
-	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, RCAR_PWMCR_SYNC, RCAR_PWMCR);
-
-	ret = rcar_pwm_set_counter(rp, div, duty_ns, period_ns);
-	if (!ret)
-		rcar_pwm_set_clock_control(rp, div);
-
-	/* The SYNC should be set to 0 even if rcar_pwm_set_counter failed */
-	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR);
-
-	return ret;
-}
-
-static int rcar_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
 	u32 value;
 
 	/* Don't enable the PWM device if CYC0 or PH0 is 0 */
@@ -185,10 +154,8 @@ static int rcar_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
 	return 0;
 }
 
-static void rcar_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+static void rcar_pwm_disable(struct rcar_pwm_chip *rp)
 {
-	struct rcar_pwm_chip *rp = to_rcar_pwm_chip(chip);
-
 	rcar_pwm_update(rp, RCAR_PWMCR_EN0, 0, RCAR_PWMCR);
 }
 
@@ -205,7 +172,7 @@ static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 		return -ENOTSUPP;
 
 	if (!state->enabled) {
-		rcar_pwm_disable(chip, pwm);
+		rcar_pwm_disable(rp);
 		return 0;
 	}
 
@@ -223,7 +190,7 @@ static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 	rcar_pwm_update(rp, RCAR_PWMCR_SYNC, 0, RCAR_PWMCR);
 
 	if (!ret && state->enabled)
-		ret = rcar_pwm_enable(chip, pwm);
+		ret = rcar_pwm_enable(rp);
 
 	return ret;
 }
@@ -231,9 +198,6 @@ static int rcar_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 static const struct pwm_ops rcar_pwm_ops = {
 	.request = rcar_pwm_request,
 	.free = rcar_pwm_free,
-	.config = rcar_pwm_config,
-	.enable = rcar_pwm_enable,
-	.disable = rcar_pwm_disable,
 	.apply = rcar_pwm_apply,
 	.owner = THIS_MODULE,
 };
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v3 4/4] pwm: rcar: improve calculation of divider
  2019-01-09  8:19 [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Yoshihiro Shimoda
                   ` (2 preceding siblings ...)
  2019-01-09  8:19 ` [PATCH v3 3/4] pwm: rcar: remove legacy APIs Yoshihiro Shimoda
@ 2019-01-09  8:19 ` Yoshihiro Shimoda
  2019-03-04 11:14 ` [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Thierry Reding
  4 siblings, 0 replies; 7+ messages in thread
From: Yoshihiro Shimoda @ 2019-01-09  8:19 UTC (permalink / raw)
  To: thierry.reding; +Cc: linux-pwm, linux-renesas-soc, Yoshihiro Shimoda

The rcar_pwm_get_clock_division() has a loop to calculate the divider,
but the value of div should be calculatable without a loop. So,
this patch improves it.

This algorithm is suggested by Uwe Kleine-König and Laurent Pinchart.

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-rcar.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 1e13fbb..cfe7dd1 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -8,6 +8,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/log2.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -68,19 +70,15 @@ static void rcar_pwm_update(struct rcar_pwm_chip *rp, u32 mask, u32 data,
 static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns)
 {
 	unsigned long clk_rate = clk_get_rate(rp->clk);
-	unsigned long long max; /* max cycle / nanoseconds */
-	unsigned int div;
+	u64 div, tmp;
 
 	if (clk_rate == 0)
 		return -EINVAL;
 
-	for (div = 0; div <= RCAR_PWM_MAX_DIVISION; div++) {
-		max = (unsigned long long)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE *
-			(1 << div);
-		do_div(max, clk_rate);
-		if (period_ns <= max)
-			break;
-	}
+	div = (u64)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE;
+	tmp = (u64)period_ns * clk_rate + div - 1;
+	tmp = div64_u64(tmp, div);
+	div = ilog2(tmp - 1) + 1;
 
 	return (div <= RCAR_PWM_MAX_DIVISION) ? div : -ERANGE;
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation
  2019-01-09  8:19 [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Yoshihiro Shimoda
                   ` (3 preceding siblings ...)
  2019-01-09  8:19 ` [PATCH v3 4/4] pwm: rcar: improve calculation of divider Yoshihiro Shimoda
@ 2019-03-04 11:14 ` Thierry Reding
  4 siblings, 0 replies; 7+ messages in thread
From: Thierry Reding @ 2019-03-04 11:14 UTC (permalink / raw)
  To: Yoshihiro Shimoda; +Cc: linux-pwm, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 1493 bytes --]

On Wed, Jan 09, 2019 at 05:19:04PM +0900, Yoshihiro Shimoda wrote:
> This patch series adds support for PWM "atomic" API and improve
> the clock calculation.
> 
> Changes from v2 [1]:
>  - Add Acked-by of Uwe in patch [234]/4.
>  - Modify a condition to support normal polarity only.
>  - Fix possible to output wrong a duty cycle when disabling in patch 1/4.
>  - Fix overflow value on 32-bit arch in patch 4/4.
> 
> Changes from v1 [2]:
>  - Remove workaround code of output pseudo low level for now because it is
>    rejected on the ML.
>  - Add a condition for polarity because the HW doesn't support polarity change
>    in patch 1/4.
>  - Improve the clock calculation in patch 4/4.
> 
> [1]
> https://patchwork.kernel.org/project/linux-renesas-soc/list/?series=63219
> 
> Remarks:
> On the email thread of patch 2/4, we discuss about suspend/resume
> handling and I suposed to improve it. However, I need more time
> how to improve it. So, for now, I don't improve it on this patch series.
> 
> [2]
> https://patchwork.kernel.org/project/linux-renesas-soc/list/?series=53193
> 
> 
> Yoshihiro Shimoda (4):
>   pwm: rcar: Add support "atomic" API
>   pwm: rcar: Use "atomic" API on rcar_pwm_resume()
>   pwm: rcar: remove legacy APIs
>   pwm: rcar: improve calculation of divider
> 
>  drivers/pwm/pwm-rcar.c | 99 ++++++++++++++++++++++++--------------------------
>  1 file changed, 48 insertions(+), 51 deletions(-)

Applied, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v3 2/4] pwm: rcar: Use "atomic" API on rcar_pwm_resume()
  2019-01-09  8:19 ` [PATCH v3 2/4] pwm: rcar: Use "atomic" API on rcar_pwm_resume() Yoshihiro Shimoda
@ 2019-03-04 11:18   ` Thierry Reding
  0 siblings, 0 replies; 7+ messages in thread
From: Thierry Reding @ 2019-03-04 11:18 UTC (permalink / raw)
  To: Yoshihiro Shimoda; +Cc: linux-pwm, linux-renesas-soc

[-- Attachment #1: Type: text/plain, Size: 2236 bytes --]

On Wed, Jan 09, 2019 at 05:19:06PM +0900, Yoshihiro Shimoda wrote:
> To remove legacy API related functions in the future, this patch
> uses "atomic" related function instead. No change in behavior.
> 
> Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/pwm/pwm-rcar.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
> index e3ab663..652a937 100644
> --- a/drivers/pwm/pwm-rcar.c
> +++ b/drivers/pwm/pwm-rcar.c
> @@ -316,18 +316,16 @@ static int rcar_pwm_suspend(struct device *dev)
>  static int rcar_pwm_resume(struct device *dev)
>  {
>  	struct pwm_device *pwm = rcar_pwm_dev_to_pwm_dev(dev);
> +	struct pwm_state state;
>  
>  	if (!test_bit(PWMF_REQUESTED, &pwm->flags))
>  		return 0;
>  
>  	pm_runtime_get_sync(dev);
>  
> -	rcar_pwm_config(pwm->chip, pwm, pwm->state.duty_cycle,
> -			pwm->state.period);
> -	if (pwm_is_enabled(pwm))
> -		rcar_pwm_enable(pwm->chip, pwm);
> +	pwm_get_state(pwm, &state);
>  
> -	return 0;
> +	return rcar_pwm_apply(pwm->chip, pwm, &state);
>  }
>  #endif /* CONFIG_PM_SLEEP */
>  static SIMPLE_DEV_PM_OPS(rcar_pwm_pm_ops, rcar_pwm_suspend, rcar_pwm_resume);

As was recently discussed elsewhere, it should really be up to the
consumer of PWMs to reinitialize the PWM on resume. However, this is a
preexisting condition, so let's do it in a follow-up.

Do you have any cases where you really rely on this? Resume ordering
does not guarantee that the PWM and consumer will be resumed in the
right order, so you may be enabling the PWM too soon, or too late, by
doing this in the PWM driver.

There are patches in the works to help with this using device links, but
I think even with those there will be cases where the consumer will want
to directly control when the PWM is restored, so you should consider
moving the driver away from implementing suspend/resume itself.

It'd be interesting to hear if there any cases where things break if you
simply remove these PM callbacks. If so we should investigate and fix
them so that these can be removed.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-03-04 11:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-09  8:19 [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Yoshihiro Shimoda
2019-01-09  8:19 ` [PATCH v3 1/4] pwm: rcar: Add support "atomic" API Yoshihiro Shimoda
2019-01-09  8:19 ` [PATCH v3 2/4] pwm: rcar: Use "atomic" API on rcar_pwm_resume() Yoshihiro Shimoda
2019-03-04 11:18   ` Thierry Reding
2019-01-09  8:19 ` [PATCH v3 3/4] pwm: rcar: remove legacy APIs Yoshihiro Shimoda
2019-01-09  8:19 ` [PATCH v3 4/4] pwm: rcar: improve calculation of divider Yoshihiro Shimoda
2019-03-04 11:14 ` [PATCH v3 0/4] pwm: rcar: Add support "atomic" API and improve calculation Thierry Reding

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).