aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-rcar.c
diff options
context:
space:
mode:
authorYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>2019-01-09 03:19:08 -0500
committerThierry Reding <thierry.reding@gmail.com>2019-03-04 06:14:21 -0500
commitb4f9a7268dbe9d55a6bc8c3123cb518657743b76 (patch)
tree57314d875a9aff683bac92357e6b6dfe4dbd121c /drivers/pwm/pwm-rcar.c
parent8cc2b970397c59b25ffb22e0e4a86753fa162619 (diff)
pwm: rcar: Improve calculation of divider
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> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-rcar.c')
-rw-r--r--drivers/pwm/pwm-rcar.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 1e13fbb41fd1..cfe7dd1b448e 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -8,6 +8,8 @@
8#include <linux/clk.h> 8#include <linux/clk.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <linux/io.h> 10#include <linux/io.h>
11#include <linux/log2.h>
12#include <linux/math64.h>
11#include <linux/module.h> 13#include <linux/module.h>
12#include <linux/of.h> 14#include <linux/of.h>
13#include <linux/platform_device.h> 15#include <linux/platform_device.h>
@@ -68,19 +70,15 @@ static void rcar_pwm_update(struct rcar_pwm_chip *rp, u32 mask, u32 data,
68static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns) 70static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns)
69{ 71{
70 unsigned long clk_rate = clk_get_rate(rp->clk); 72 unsigned long clk_rate = clk_get_rate(rp->clk);
71 unsigned long long max; /* max cycle / nanoseconds */ 73 u64 div, tmp;
72 unsigned int div;
73 74
74 if (clk_rate == 0) 75 if (clk_rate == 0)
75 return -EINVAL; 76 return -EINVAL;
76 77
77 for (div = 0; div <= RCAR_PWM_MAX_DIVISION; div++) { 78 div = (u64)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE;
78 max = (unsigned long long)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE * 79 tmp = (u64)period_ns * clk_rate + div - 1;
79 (1 << div); 80 tmp = div64_u64(tmp, div);
80 do_div(max, clk_rate); 81 div = ilog2(tmp - 1) + 1;
81 if (period_ns <= max)
82 break;
83 }
84 82
85 return (div <= RCAR_PWM_MAX_DIVISION) ? div : -ERANGE; 83 return (div <= RCAR_PWM_MAX_DIVISION) ? div : -ERANGE;
86} 84}