diff mbox series

[V2,2/2] pwm: tegra: Ensure the clock rate is not less than needed

Message ID 20221028123356.133796-2-jonathanh@nvidia.com
State Accepted
Headers show
Series [V2,1/2] pwm: tegra: Improve required rate calculation | expand

Commit Message

Jon Hunter Oct. 28, 2022, 12:33 p.m. UTC
When dynamically scaling the PWM clock, the function
dev_pm_opp_set_rate() may set the PWM clock to a rate that is lower than
what is required. The clock rate requested when calling
dev_pm_opp_set_rate() is the minimum clock rate that is needed to drive
the PWM to achieve the required period. Hence, if the actual clock
rate is less than the requested clock rate, then the required period
cannot be achieved and configuring the PWM fails. Fix this by
calling clk_round_rate() to check if the clock rate that will be provided
is sufficient and if not, double the required clock rate to ensure the
required period can be attained.

Fixes: 8c193f4714df ("pwm: tegra: Optimize period calculation")
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
Changes since V1:
- Multiplied the required_clk_rate by 2 instead of adding 1 to the
  PWM_DUTY_WIDTH and recalculating the rate. Overall rate should be
  similar.
- Updated comment based upon Uwe's feedback.

 drivers/pwm/pwm-tegra.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

Comments

Thierry Reding Nov. 3, 2022, 3:17 p.m. UTC | #1
On Fri, Oct 28, 2022 at 01:33:56PM +0100, Jon Hunter wrote:
> When dynamically scaling the PWM clock, the function
> dev_pm_opp_set_rate() may set the PWM clock to a rate that is lower than
> what is required. The clock rate requested when calling
> dev_pm_opp_set_rate() is the minimum clock rate that is needed to drive
> the PWM to achieve the required period. Hence, if the actual clock
> rate is less than the requested clock rate, then the required period
> cannot be achieved and configuring the PWM fails. Fix this by
> calling clk_round_rate() to check if the clock rate that will be provided
> is sufficient and if not, double the required clock rate to ensure the
> required period can be attained.
> 
> Fixes: 8c193f4714df ("pwm: tegra: Optimize period calculation")
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
> Changes since V1:
> - Multiplied the required_clk_rate by 2 instead of adding 1 to the
>   PWM_DUTY_WIDTH and recalculating the rate. Overall rate should be
>   similar.
> - Updated comment based upon Uwe's feedback.
> 
>  drivers/pwm/pwm-tegra.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)

Uwe, any objections to this? I'm assuming not, since you proposed this
variant yourself, but would be good to get your Acked-by nevertheless.

Thanks,
Thierry
Uwe Kleine-König Nov. 3, 2022, 9:35 p.m. UTC | #2
On Fri, Oct 28, 2022 at 01:33:56PM +0100, Jon Hunter wrote:
> When dynamically scaling the PWM clock, the function
> dev_pm_opp_set_rate() may set the PWM clock to a rate that is lower than
> what is required. The clock rate requested when calling
> dev_pm_opp_set_rate() is the minimum clock rate that is needed to drive
> the PWM to achieve the required period. Hence, if the actual clock
> rate is less than the requested clock rate, then the required period
> cannot be achieved and configuring the PWM fails. Fix this by
> calling clk_round_rate() to check if the clock rate that will be provided
> is sufficient and if not, double the required clock rate to ensure the
> required period can be attained.
> 
> Fixes: 8c193f4714df ("pwm: tegra: Optimize period calculation")
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
> Changes since V1:
> - Multiplied the required_clk_rate by 2 instead of adding 1 to the
>   PWM_DUTY_WIDTH and recalculating the rate. Overall rate should be
>   similar.
> - Updated comment based upon Uwe's feedback.
> 
>  drivers/pwm/pwm-tegra.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
> index b05ea2e8accc..6fc4b69a3ba7 100644
> --- a/drivers/pwm/pwm-tegra.c
> +++ b/drivers/pwm/pwm-tegra.c
> @@ -148,6 +148,17 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
>  		required_clk_rate = DIV_ROUND_UP_ULL(NSEC_PER_SEC << PWM_DUTY_WIDTH,
>  						     period_ns);
>  
> +		if (required_clk_rate > clk_round_rate(pc->clk, required_clk_rate))
> +			/*
> +			 * required_clk_rate is a lower bound for the input
> +			 * rate; for lower rates there is no value for PWM_SCALE
> +			 * that yields a period less than or equal to the
> +			 * requested period. Hence, for lower rates, double the
> +			 * required_clk_rate to get a clock rate that can meet
> +			 * the requested period.
> +			 */
> +			required_clk_rate *= 2;

Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

Thanks
Uwe

> +
>  		err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
>  		if (err < 0)
>  			return -EINVAL;
> -- 
> 2.25.1
> 
>
Thierry Reding Nov. 8, 2022, 1:49 p.m. UTC | #3
On Fri, Oct 28, 2022 at 01:33:56PM +0100, Jon Hunter wrote:
> When dynamically scaling the PWM clock, the function
> dev_pm_opp_set_rate() may set the PWM clock to a rate that is lower than
> what is required. The clock rate requested when calling
> dev_pm_opp_set_rate() is the minimum clock rate that is needed to drive
> the PWM to achieve the required period. Hence, if the actual clock
> rate is less than the requested clock rate, then the required period
> cannot be achieved and configuring the PWM fails. Fix this by
> calling clk_round_rate() to check if the clock rate that will be provided
> is sufficient and if not, double the required clock rate to ensure the
> required period can be attained.
> 
> Fixes: 8c193f4714df ("pwm: tegra: Optimize period calculation")
> Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
> ---
> Changes since V1:
> - Multiplied the required_clk_rate by 2 instead of adding 1 to the
>   PWM_DUTY_WIDTH and recalculating the rate. Overall rate should be
>   similar.
> - Updated comment based upon Uwe's feedback.
> 
>  drivers/pwm/pwm-tegra.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)

Applied, thanks.

Thierry
diff mbox series

Patch

diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
index b05ea2e8accc..6fc4b69a3ba7 100644
--- a/drivers/pwm/pwm-tegra.c
+++ b/drivers/pwm/pwm-tegra.c
@@ -148,6 +148,17 @@  static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 		required_clk_rate = DIV_ROUND_UP_ULL(NSEC_PER_SEC << PWM_DUTY_WIDTH,
 						     period_ns);
 
+		if (required_clk_rate > clk_round_rate(pc->clk, required_clk_rate))
+			/*
+			 * required_clk_rate is a lower bound for the input
+			 * rate; for lower rates there is no value for PWM_SCALE
+			 * that yields a period less than or equal to the
+			 * requested period. Hence, for lower rates, double the
+			 * required_clk_rate to get a clock rate that can meet
+			 * the requested period.
+			 */
+			required_clk_rate *= 2;
+
 		err = dev_pm_opp_set_rate(pc->dev, required_clk_rate);
 		if (err < 0)
 			return -EINVAL;