diff mbox series

[v1,6/6] pwm: tegra: unfold legacy callbacks into tegra_pwm_apply()

Message ID 20210617095145.163694-7-u.kleine-koenig@pengutronix.de
State Not Applicable
Headers show
Series pwm: tegra: several improvements | expand

Commit Message

Uwe Kleine-König June 17, 2021, 9:51 a.m. UTC
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 mbox series

Patch

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;
 }