aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-stm32.c
diff options
context:
space:
mode:
authorFabrice Gasnier <fabrice.gasnier@st.com>2018-05-16 03:35:59 -0400
committerLee Jones <lee.jones@linaro.org>2018-05-16 04:11:13 -0400
commitd66ffb91c374fc500fe666645184e278774bad38 (patch)
tree999aae9d7ca17a10e2614f0cd4b1a518be514bb8 /drivers/pwm/pwm-stm32.c
parent53e38fe73f941291fd20794c15c3bb7b104a4a17 (diff)
pwm: stm32: Improve capture by tuning counter prescaler
Currently, capture is based on timeout window to configure prescaler. PWM capture framework provides 1s window at the time of writing. There's place for improvement, after input signal has been captured once: - Finer tune counter clock prescaler, by using 1st capture result (with arbitrary margin). - Do a 2nd capture, with scaled capture window. This increases accuracy, especially at high rates. Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Acked-by: Thierry Reding <thierry.reding@gmail.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/pwm/pwm-stm32.c')
-rw-r--r--drivers/pwm/pwm-stm32.c24
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;