diff options
Diffstat (limited to 'drivers/pwm/pwm-stm32.c')
-rw-r--r-- | drivers/pwm/pwm-stm32.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index ed3961b7b938..9a50acde1e61 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c | |||
@@ -168,7 +168,7 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, | |||
168 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); | 168 | struct stm32_pwm *priv = to_stm32_pwm_dev(chip); |
169 | unsigned long long prd, div, dty; | 169 | unsigned long long prd, div, dty; |
170 | unsigned long rate; | 170 | unsigned long rate; |
171 | unsigned int psc = 0; | 171 | unsigned int psc = 0, scale; |
172 | u32 raw_prd, raw_dty; | 172 | u32 raw_prd, raw_dty; |
173 | int ret = 0; | 173 | int ret = 0; |
174 | 174 | ||
@@ -219,6 +219,28 @@ static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm, | |||
219 | if (ret) | 219 | if (ret) |
220 | goto stop; | 220 | goto stop; |
221 | 221 | ||
222 | /* | ||
223 | * Got a capture. Try to improve accuracy at high rates: | ||
224 | * - decrease counter clock prescaler, scale up to max rate. | ||
225 | */ | ||
226 | if (raw_prd) { | ||
227 | u32 max_arr = priv->max_arr - 0x1000; /* arbitrary margin */ | ||
228 | |||
229 | scale = max_arr / min(max_arr, raw_prd); | ||
230 | } else { | ||
231 | scale = priv->max_arr; /* bellow resolution, use max scale */ | ||
232 | } | ||
233 | |||
234 | if (psc && scale > 1) { | ||
235 | /* 2nd measure with new scale */ | ||
236 | psc /= scale; | ||
237 | regmap_write(priv->regmap, TIM_PSC, psc); | ||
238 | ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, | ||
239 | &raw_dty); | ||
240 | if (ret) | ||
241 | goto stop; | ||
242 | } | ||
243 | |||
222 | prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC; | 244 | prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC; |
223 | result->period = DIV_ROUND_UP_ULL(prd, rate); | 245 | result->period = DIV_ROUND_UP_ULL(prd, rate); |
224 | dty = (unsigned long long)raw_dty * (psc + 1) * NSEC_PER_SEC; | 246 | dty = (unsigned long long)raw_dty * (psc + 1) * NSEC_PER_SEC; |