|
8 | 8 | * - The hardware cannot generate a 0% duty cycle.
|
9 | 9 | */
|
10 | 10 |
|
| 11 | +#include <linux/bitfield.h> |
11 | 12 | #include <linux/clk.h>
|
12 | 13 | #include <linux/err.h>
|
13 | 14 | #include <linux/io.h>
|
@@ -102,23 +103,24 @@ static void rcar_pwm_set_clock_control(struct rcar_pwm_chip *rp,
|
102 | 103 | rcar_pwm_write(rp, value, RCAR_PWMCR);
|
103 | 104 | }
|
104 | 105 |
|
105 |
| -static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, int duty_ns, |
106 |
| - int period_ns) |
| 106 | +static int rcar_pwm_set_counter(struct rcar_pwm_chip *rp, int div, u64 duty_ns, |
| 107 | + u64 period_ns) |
107 | 108 | {
|
108 |
| - unsigned long long one_cycle, tmp; /* 0.01 nanoseconds */ |
| 109 | + unsigned long long tmp; |
109 | 110 | unsigned long clk_rate = clk_get_rate(rp->clk);
|
110 | 111 | u32 cyc, ph;
|
111 | 112 |
|
112 |
| - one_cycle = NSEC_PER_SEC * 100ULL << div; |
113 |
| - do_div(one_cycle, clk_rate); |
| 113 | + /* div <= 24 == RCAR_PWM_MAX_DIVISION, so the shift doesn't overflow. */ |
| 114 | + tmp = mul_u64_u64_div_u64(period_ns, clk_rate, (u64)NSEC_PER_SEC << div); |
| 115 | + if (tmp > FIELD_MAX(RCAR_PWMCNT_CYC0_MASK)) |
| 116 | + tmp = FIELD_MAX(RCAR_PWMCNT_CYC0_MASK); |
114 | 117 |
|
115 |
| - tmp = period_ns * 100ULL; |
116 |
| - do_div(tmp, one_cycle); |
117 |
| - cyc = (tmp << RCAR_PWMCNT_CYC0_SHIFT) & RCAR_PWMCNT_CYC0_MASK; |
| 118 | + cyc = FIELD_PREP(RCAR_PWMCNT_CYC0_MASK, tmp); |
118 | 119 |
|
119 |
| - tmp = duty_ns * 100ULL; |
120 |
| - do_div(tmp, one_cycle); |
121 |
| - ph = tmp & RCAR_PWMCNT_PH0_MASK; |
| 120 | + tmp = mul_u64_u64_div_u64(duty_ns, clk_rate, (u64)NSEC_PER_SEC << div); |
| 121 | + if (tmp > FIELD_MAX(RCAR_PWMCNT_PH0_MASK)) |
| 122 | + tmp = FIELD_MAX(RCAR_PWMCNT_PH0_MASK); |
| 123 | + ph = FIELD_PREP(RCAR_PWMCNT_PH0_MASK, tmp); |
122 | 124 |
|
123 | 125 | /* Avoid prohibited setting */
|
124 | 126 | if (cyc == 0 || ph == 0)
|
|
0 commit comments