All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/6] pwm: tegra: several improvements
@ 2021-06-17  9:51 Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 1/6] pwm: tegra: Drop an if block with an always false condition Uwe Kleine-König
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

This series improves the tegra-pwm driver. There are a few problems left though:

 - if the PWM is configured to a 100% duty cycle it writes bit 24 which is
   either bogus or needs a comment.

 - clock handling is broken: If pwm_disable() is called without calling
   pwm_enable() before, this triggers a warning in clk_disable(). This also 
   might trigger a HW fault as the register is accessed without enabling the
   clock first.

 - The calculation of period and duty_cycle is imprecise as it divides by the
   result of a division and it discards relevant bits from pc->clk_rate without
   rounding. (I bet there are more problems, I only checked quickly
   trying to implement .get_state(), but I gave up.)

I didn't address these because I have neither any hardware to test nor
documentation. So this series is only compile tested.

Best regards
Uwe

Uwe Kleine-König (6):
  pwm: tegra: Drop an if block with an always false condition
  pwm: tegra: Don't modify HW state in .remove callback
  pwm: tegra: Don't needlessly enable and disable the clock in .remove()
  pwm: tegra: Assert reset only after the PWM was unregistered
  pwm: tegra: Implement .apply callback
  pwm: tegra: unfold legacy callbacks into tegra_pwm_apply()

 drivers/pwm/pwm-tegra.c | 246 ++++++++++++++++++----------------------
 1 file changed, 112 insertions(+), 134 deletions(-)

-- 
2.30.2


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

* [PATCH v1 1/6] pwm: tegra: Drop an if block with an always false condition
  2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
@ 2021-06-17  9:51 ` Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 2/6] pwm: tegra: Don't modify HW state in .remove callback Uwe Kleine-König
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

tegra_pwm_remove() is only called after tegra_pwm_probe() successfully
completed. In this case platform_set_drvdata() was called with a
non-NULL value and so platform_get_drvdata(pdev) cannot return NULL.

Returning an error code from a platform_driver's remove function is
ignored anyway, so it's a good thing this exit path is gone.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-tegra.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index c529a170bcdd..fa025795198b 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -303,9 +303,6 @@ static int tegra_pwm_remove(struct platform_device *pdev)
 	unsigned int i;
 	int err;
 
-	if (WARN_ON(!pc))
-		return -ENODEV;
-
 	err = clk_prepare_enable(pc->clk);
 	if (err < 0)
 		return err;
-- 
2.30.2


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

* [PATCH v1 2/6] pwm: tegra: Don't modify HW state in .remove callback
  2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 1/6] pwm: tegra: Drop an if block with an always false condition Uwe Kleine-König
@ 2021-06-17  9:51 ` Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 3/6] pwm: tegra: Don't needlessly enable and disable the clock in .remove() Uwe Kleine-König
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

A consumer is expected to disable a PWM before calling pwm_put(). And if
they didn't there is hopefully a good reason (or the consumer needs
fixing). Also if disabling an enabled PWM was the right thing to do,
this should better be done in the framework instead of in each low level
driver.

So drop the hardware modification from the .remove() callback.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-tegra.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index fa025795198b..a051cf43e7d7 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -300,25 +300,12 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 static int tegra_pwm_remove(struct platform_device *pdev)
 {
 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
-	unsigned int i;
 	int err;
 
 	err = clk_prepare_enable(pc->clk);
 	if (err < 0)
 		return err;
 
-	for (i = 0; i < pc->chip.npwm; i++) {
-		struct pwm_device *pwm = &pc->chip.pwms[i];
-
-		if (!pwm_is_enabled(pwm))
-			if (clk_prepare_enable(pc->clk) < 0)
-				continue;
-
-		pwm_writel(pc, i, 0);
-
-		clk_disable_unprepare(pc->clk);
-	}
-
 	reset_control_assert(pc->rst);
 	clk_disable_unprepare(pc->clk);
 
-- 
2.30.2


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

* [PATCH v1 3/6] pwm: tegra: Don't needlessly enable and disable the clock in .remove()
  2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 1/6] pwm: tegra: Drop an if block with an always false condition Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 2/6] pwm: tegra: Don't modify HW state in .remove callback Uwe Kleine-König
@ 2021-06-17  9:51 ` Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 4/6] pwm: tegra: Assert reset only after the PWM was unregistered Uwe Kleine-König
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

There is no reason to enable the PWM clock just to assert the reset
control. (If the reset control depends on the clock this is a bug and
probably it doesn't because in .probe() the reset is deasserted without
the clock being enabled.)

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-tegra.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index a051cf43e7d7..e865743e5989 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -300,14 +300,8 @@ static int tegra_pwm_probe(struct platform_device *pdev)
 static int tegra_pwm_remove(struct platform_device *pdev)
 {
 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
-	int err;
-
-	err = clk_prepare_enable(pc->clk);
-	if (err < 0)
-		return err;
 
 	reset_control_assert(pc->rst);
-	clk_disable_unprepare(pc->clk);
 
 	return pwmchip_remove(&pc->chip);
 }
-- 
2.30.2


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

* [PATCH v1 4/6] pwm: tegra: Assert reset only after the PWM was unregistered
  2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
                   ` (2 preceding siblings ...)
  2021-06-17  9:51 ` [PATCH v1 3/6] pwm: tegra: Don't needlessly enable and disable the clock in .remove() Uwe Kleine-König
@ 2021-06-17  9:51 ` Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 5/6] pwm: tegra: Implement .apply callback Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 6/6] pwm: tegra: unfold legacy callbacks into tegra_pwm_apply() Uwe Kleine-König
  5 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

The driver is supposed to stay functional until pwmchip_remove()
returns. So the reset must be asserted only after that.

pwmchip_remove() always returns 0, so the return code can be ignored
which keeps the tegra_pwm_remove() a bit simpler.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-tegra.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index e865743e5989..11a10b575ace 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -301,9 +301,11 @@ static int tegra_pwm_remove(struct platform_device *pdev)
 {
 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
 
+	pwmchip_remove(&pc->chip);
+
 	reset_control_assert(pc->rst);
 
-	return pwmchip_remove(&pc->chip);
+	return 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
-- 
2.30.2


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

* [PATCH v1 5/6] pwm: tegra: Implement .apply callback
  2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
                   ` (3 preceding siblings ...)
  2021-06-17  9:51 ` [PATCH v1 4/6] pwm: tegra: Assert reset only after the PWM was unregistered Uwe Kleine-König
@ 2021-06-17  9:51 ` Uwe Kleine-König
  2021-06-28 12:29   ` Thierry Reding
  2021-07-16  7:30   ` Uwe Kleine-König
  2021-06-17  9:51 ` [PATCH v1 6/6] pwm: tegra: unfold legacy callbacks into tegra_pwm_apply() Uwe Kleine-König
  5 siblings, 2 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

To ease review this reuses the formerly implemented callbacks.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-tegra.c | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 11a10b575ace..1161c6323e60 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -227,10 +227,36 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 	clk_disable_unprepare(pc->clk);
 }
 
+static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			   const struct pwm_state *state)
+{
+	int err;
+
+	if (state->polarity != PWM_POLARITY_INVERSED)
+		return -EINVAL;
+
+	if (!state->enabled) {
+		if (pwm->state.enabled)
+			tegra_pwm_disable(chip, pwm);
+		return 0;
+	}
+
+	if (state->period != pwm->state.period ||
+	    state->duty_cycle != pwm->state.duty_cycle) {
+		err = tegra_pwm_config(pwm->chip, pwm, (int)state->duty_cycle,
+				       (int)state->period);
+		if (err)
+			return err;
+	}
+
+	if (!pwm->state.enabled)
+		return tegra_pwm_enable(chip, pwm);
+
+	return 0;
+}
+
 static const struct pwm_ops tegra_pwm_ops = {
-	.config = tegra_pwm_config,
-	.enable = tegra_pwm_enable,
-	.disable = tegra_pwm_disable,
+	.apply = tegra_pwm_apply,
 	.owner = THIS_MODULE,
 };
 
-- 
2.30.2


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

* [PATCH v1 6/6] pwm: tegra: unfold legacy callbacks into tegra_pwm_apply()
  2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
                   ` (4 preceding siblings ...)
  2021-06-17  9:51 ` [PATCH v1 5/6] pwm: tegra: Implement .apply callback Uwe Kleine-König
@ 2021-06-17  9:51 ` Uwe Kleine-König
  5 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-17  9:51 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: Jonathan Hunter, Philipp Zabel, linux-pwm, linux-tegra, kernel

This just puts the implementation of tegra_pwm_disable(),
tegra_pwm_enable() and tegra_pwm_config() into their only caller.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-tegra.c | 244 ++++++++++++++++++----------------------
 1 file changed, 108 insertions(+), 136 deletions(-)

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index 1161c6323e60..e57a43f1b1b2 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -92,166 +92,138 @@ static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num,
 	writel(val, chip->regs + (num << 4));
 }
 
-static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-			    int duty_ns, int period_ns)
+static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			   const struct pwm_state *state)
 {
 	struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
-	unsigned long long c = duty_ns, hz;
-	unsigned long rate, required_clk_rate;
-	u32 val = 0;
 	int err;
+	u32 val;
 
-	/*
-	 * Convert from duty_ns / period_ns to a fixed number of duty ticks
-	 * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the
-	 * nearest integer during division.
-	 */
-	c *= (1 << PWM_DUTY_WIDTH);
-	c = DIV_ROUND_CLOSEST_ULL(c, period_ns);
+	if (state->polarity != PWM_POLARITY_INVERSED)
+		return -EINVAL;
 
-	val = (u32)c << PWM_DUTY_SHIFT;
+	if (!state->enabled) {
+		if (pwm->state.enabled) {
+			val = pwm_readl(pc, pwm->hwpwm);
+			val &= ~PWM_ENABLE;
+			pwm_writel(pc, pwm->hwpwm, val);
+			clk_disable_unprepare(pc->clk);
+		}
+		return 0;
+	}
 
-	/*
-	 *  min period = max clock limit >> PWM_DUTY_WIDTH
-	 */
-	if (period_ns < pc->min_period_ns)
-		return -EINVAL;
+	if (state->period != pwm->state.period ||
+	    state->duty_cycle != pwm->state.duty_cycle) {
+		int period_ns = state->period;
+		int duty_ns = state->duty_cycle;
+		unsigned long long c = duty_ns, hz;
+		unsigned long rate, required_clk_rate;
 
-	/*
-	 * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
-	 * cycles at the PWM clock rate will take period_ns nanoseconds.
-	 *
-	 * num_channels: If single instance of PWM controller has multiple
-	 * channels (e.g. Tegra210 or older) then it is not possible to
-	 * configure separate clock rates to each of the channels, in such
-	 * case the value stored during probe will be referred.
-	 *
-	 * If every PWM controller instance has one channel respectively, i.e.
-	 * nums_channels == 1 then only the clock rate can be modified
-	 * dynamically (e.g. Tegra186 or Tegra194).
-	 */
-	if (pc->soc->num_channels == 1) {
 		/*
-		 * Rate is multiplied with 2^PWM_DUTY_WIDTH so that it matches
-		 * with the maximum possible rate that the controller can
-		 * provide. Any further lower value can be derived by setting
-		 * PFM bits[0:12].
-		 *
-		 * required_clk_rate is a reference rate for source clock and
-		 * it is derived based on user requested period. By setting the
-		 * source clock rate as required_clk_rate, PWM controller will
-		 * be able to configure the requested period.
+		 * Convert from duty_ns / period_ns to a fixed number of duty ticks
+		 * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the
+		 * nearest integer during division.
 		 */
-		required_clk_rate =
-			(NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH;
+		c *= (1 << PWM_DUTY_WIDTH);
+		c = DIV_ROUND_CLOSEST_ULL(c, period_ns);
 
-		err = clk_set_rate(pc->clk, required_clk_rate);
-		if (err < 0)
+		val = (u32)c << PWM_DUTY_SHIFT;
+
+		/*
+		 *  min period = max clock limit >> PWM_DUTY_WIDTH
+		 */
+		if (period_ns < pc->min_period_ns)
 			return -EINVAL;
 
-		/* Store the new rate for further references */
-		pc->clk_rate = clk_get_rate(pc->clk);
-	}
+		/*
+		 * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
+		 * cycles at the PWM clock rate will take period_ns nanoseconds.
+		 *
+		 * num_channels: If single instance of PWM controller has multiple
+		 * channels (e.g. Tegra210 or older) then it is not possible to
+		 * configure separate clock rates to each of the channels, in such
+		 * case the value stored during probe will be referred.
+		 *
+		 * If every PWM controller instance has one channel respectively, i.e.
+		 * nums_channels == 1 then only the clock rate can be modified
+		 * dynamically (e.g. Tegra186 or Tegra194).
+		 */
+		if (pc->soc->num_channels == 1) {
+			/*
+			 * Rate is multiplied with 2^PWM_DUTY_WIDTH so that it matches
+			 * with the maximum possible rate that the controller can
+			 * provide. Any further lower value can be derived by setting
+			 * PFM bits[0:12].
+			 *
+			 * required_clk_rate is a reference rate for source clock and
+			 * it is derived based on user requested period. By setting the
+			 * source clock rate as required_clk_rate, PWM controller will
+			 * be able to configure the requested period.
+			 */
+			required_clk_rate =
+				(NSEC_PER_SEC / period_ns) << PWM_DUTY_WIDTH;
+
+			err = clk_set_rate(pc->clk, required_clk_rate);
+			if (err < 0)
+				return -EINVAL;
+
+			/* Store the new rate for further references */
+			pc->clk_rate = clk_get_rate(pc->clk);
+		}
+
+		rate = pc->clk_rate >> PWM_DUTY_WIDTH;
+
+		/* Consider precision in PWM_SCALE_WIDTH rate calculation */
+		hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns);
+		rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz);
 
-	rate = pc->clk_rate >> PWM_DUTY_WIDTH;
+		/*
+		 * Since the actual PWM divider is the register's frequency divider
+		 * field plus 1, we need to decrement to get the correct value to
+		 * write to the register.
+		 */
+		if (rate > 0)
+			rate--;
 
-	/* Consider precision in PWM_SCALE_WIDTH rate calculation */
-	hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns);
-	rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz);
+		/*
+		 * Make sure that the rate will fit in the register's frequency
+		 * divider field.
+		 */
+		if (rate >> PWM_SCALE_WIDTH)
+			return -EINVAL;
 
-	/*
-	 * Since the actual PWM divider is the register's frequency divider
-	 * field plus 1, we need to decrement to get the correct value to
-	 * write to the register.
-	 */
-	if (rate > 0)
-		rate--;
+		val |= rate << PWM_SCALE_SHIFT;
 
-	/*
-	 * Make sure that the rate will fit in the register's frequency
-	 * divider field.
-	 */
-	if (rate >> PWM_SCALE_WIDTH)
-		return -EINVAL;
+		/*
+		 * If the PWM channel is disabled, make sure to turn on the clock
+		 * before writing the register. Otherwise, keep it enabled.
+		 */
+		if (!pwm_is_enabled(pwm)) {
+			err = clk_prepare_enable(pc->clk);
+			if (err < 0)
+				return err;
+		} else
+			val |= PWM_ENABLE;
 
-	val |= rate << PWM_SCALE_SHIFT;
+		pwm_writel(pc, pwm->hwpwm, val);
 
-	/*
-	 * If the PWM channel is disabled, make sure to turn on the clock
-	 * before writing the register. Otherwise, keep it enabled.
-	 */
-	if (!pwm_is_enabled(pwm)) {
+		/*
+		 * If the PWM is not enabled, turn the clock off again to save power.
+		 */
+		if (!pwm_is_enabled(pwm))
+			clk_disable_unprepare(pc->clk);
+	}
+
+	if (!pwm->state.enabled) {
 		err = clk_prepare_enable(pc->clk);
 		if (err < 0)
 			return err;
-	} else
-		val |= PWM_ENABLE;
-
-	pwm_writel(pc, pwm->hwpwm, val);
-
-	/*
-	 * If the PWM is not enabled, turn the clock off again to save power.
-	 */
-	if (!pwm_is_enabled(pwm))
-		clk_disable_unprepare(pc->clk);
-
-	return 0;
-}
-
-static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
-	int rc = 0;
-	u32 val;
 
-	rc = clk_prepare_enable(pc->clk);
-	if (rc < 0)
-		return rc;
-
-	val = pwm_readl(pc, pwm->hwpwm);
-	val |= PWM_ENABLE;
-	pwm_writel(pc, pwm->hwpwm, val);
-
-	return 0;
-}
-
-static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
-	u32 val;
-
-	val = pwm_readl(pc, pwm->hwpwm);
-	val &= ~PWM_ENABLE;
-	pwm_writel(pc, pwm->hwpwm, val);
-
-	clk_disable_unprepare(pc->clk);
-}
-
-static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
-			   const struct pwm_state *state)
-{
-	int err;
-
-	if (state->polarity != PWM_POLARITY_INVERSED)
-		return -EINVAL;
-
-	if (!state->enabled) {
-		if (pwm->state.enabled)
-			tegra_pwm_disable(chip, pwm);
-		return 0;
-	}
-
-	if (state->period != pwm->state.period ||
-	    state->duty_cycle != pwm->state.duty_cycle) {
-		err = tegra_pwm_config(pwm->chip, pwm, (int)state->duty_cycle,
-				       (int)state->period);
-		if (err)
-			return err;
+		val = pwm_readl(pc, pwm->hwpwm);
+		val |= PWM_ENABLE;
+		pwm_writel(pc, pwm->hwpwm, val);
 	}
 
-	if (!pwm->state.enabled)
-		return tegra_pwm_enable(chip, pwm);
-
 	return 0;
 }
 
-- 
2.30.2


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

* Re: [PATCH v1 5/6] pwm: tegra: Implement .apply callback
  2021-06-17  9:51 ` [PATCH v1 5/6] pwm: tegra: Implement .apply callback Uwe Kleine-König
@ 2021-06-28 12:29   ` Thierry Reding
  2021-06-28 16:46     ` Uwe Kleine-König
  2021-07-16  7:30   ` Uwe Kleine-König
  1 sibling, 1 reply; 10+ messages in thread
From: Thierry Reding @ 2021-06-28 12:29 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Lee Jones, Jonathan Hunter, Philipp Zabel, linux-pwm,
	linux-tegra, kernel

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

On Thu, Jun 17, 2021 at 11:51:44AM +0200, Uwe Kleine-König wrote:
> To ease review this reuses the formerly implemented callbacks.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/pwm/pwm-tegra.c | 32 +++++++++++++++++++++++++++++---
>  1 file changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
> index 11a10b575ace..1161c6323e60 100644
> --- a/drivers/pwm/pwm-tegra.c
> +++ b/drivers/pwm/pwm-tegra.c
> @@ -227,10 +227,36 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
>  	clk_disable_unprepare(pc->clk);
>  }
>  
> +static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> +			   const struct pwm_state *state)
> +{
> +	int err;
> +
> +	if (state->polarity != PWM_POLARITY_INVERSED)
> +		return -EINVAL;

Where does this come from? I can't see this condition anywhere in the
existing driver.

Thierry

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

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

* Re: [PATCH v1 5/6] pwm: tegra: Implement .apply callback
  2021-06-28 12:29   ` Thierry Reding
@ 2021-06-28 16:46     ` Uwe Kleine-König
  0 siblings, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-06-28 16:46 UTC (permalink / raw)
  To: Thierry Reding
  Cc: linux-pwm, Philipp Zabel, Jonathan Hunter, kernel, linux-tegra,
	Lee Jones

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

On Mon, Jun 28, 2021 at 02:29:35PM +0200, Thierry Reding wrote:
> On Thu, Jun 17, 2021 at 11:51:44AM +0200, Uwe Kleine-König wrote:
> > To ease review this reuses the formerly implemented callbacks.
> > 
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> > ---
> >  drivers/pwm/pwm-tegra.c | 32 +++++++++++++++++++++++++++++---
> >  1 file changed, 29 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
> > index 11a10b575ace..1161c6323e60 100644
> > --- a/drivers/pwm/pwm-tegra.c
> > +++ b/drivers/pwm/pwm-tegra.c
> > @@ -227,10 +227,36 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
> >  	clk_disable_unprepare(pc->clk);
> >  }
> >  
> > +static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> > +			   const struct pwm_state *state)
> > +{
> > +	int err;
> > +
> > +	if (state->polarity != PWM_POLARITY_INVERSED)
> > +		return -EINVAL;
> 
> Where does this come from? I can't see this condition anywhere in the
> existing driver.

The old driver doesn't implement .set_polarity, so this condition
originates from

        if (state->polarity != pwm->state.polarity) {
                if (!chip->ops->set_polarity) {
                        err = -EINVAL;
                        goto out_err;
                }
		...

in the legacy code path in the core.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

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

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

* Re: [PATCH v1 5/6] pwm: tegra: Implement .apply callback
  2021-06-17  9:51 ` [PATCH v1 5/6] pwm: tegra: Implement .apply callback Uwe Kleine-König
  2021-06-28 12:29   ` Thierry Reding
@ 2021-07-16  7:30   ` Uwe Kleine-König
  1 sibling, 0 replies; 10+ messages in thread
From: Uwe Kleine-König @ 2021-07-16  7:30 UTC (permalink / raw)
  To: Thierry Reding, Lee Jones
  Cc: linux-tegra, linux-pwm, kernel, Philipp Zabel, Jonathan Hunter

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

Hello,

On Thu, Jun 17, 2021 at 11:51:44AM +0200, Uwe Kleine-König wrote:
> To ease review this reuses the formerly implemented callbacks.
> 
> Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
> ---
>  drivers/pwm/pwm-tegra.c | 32 +++++++++++++++++++++++++++++---
>  1 file changed, 29 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
> index 11a10b575ace..1161c6323e60 100644
> --- a/drivers/pwm/pwm-tegra.c
> +++ b/drivers/pwm/pwm-tegra.c
> @@ -227,10 +227,36 @@ static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
>  	clk_disable_unprepare(pc->clk);
>  }
>  
> +static int tegra_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> +			   const struct pwm_state *state)
> +{
> +	int err;
> +
> +	if (state->polarity != PWM_POLARITY_INVERSED)
> +		return -EINVAL;
> +
> +	if (!state->enabled) {
> +		if (pwm->state.enabled)
> +			tegra_pwm_disable(chip, pwm);
> +		return 0;
> +	}
> +
> +	if (state->period != pwm->state.period ||
> +	    state->duty_cycle != pwm->state.duty_cycle) {
> +		err = tegra_pwm_config(pwm->chip, pwm, (int)state->duty_cycle,
> +				       (int)state->period);

This patch has the same problem as my other apply conversions. I'll have
to rework that before it is safe to take this.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |

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

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

end of thread, other threads:[~2021-07-16  7:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-17  9:51 [PATCH v1 0/6] pwm: tegra: several improvements Uwe Kleine-König
2021-06-17  9:51 ` [PATCH v1 1/6] pwm: tegra: Drop an if block with an always false condition Uwe Kleine-König
2021-06-17  9:51 ` [PATCH v1 2/6] pwm: tegra: Don't modify HW state in .remove callback Uwe Kleine-König
2021-06-17  9:51 ` [PATCH v1 3/6] pwm: tegra: Don't needlessly enable and disable the clock in .remove() Uwe Kleine-König
2021-06-17  9:51 ` [PATCH v1 4/6] pwm: tegra: Assert reset only after the PWM was unregistered Uwe Kleine-König
2021-06-17  9:51 ` [PATCH v1 5/6] pwm: tegra: Implement .apply callback Uwe Kleine-König
2021-06-28 12:29   ` Thierry Reding
2021-06-28 16:46     ` Uwe Kleine-König
2021-07-16  7:30   ` Uwe Kleine-König
2021-06-17  9:51 ` [PATCH v1 6/6] pwm: tegra: unfold legacy callbacks into tegra_pwm_apply() Uwe Kleine-König

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.