aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-stm32.c
diff options
context:
space:
mode:
authorFabrice Gasnier <fabrice.gasnier@st.com>2018-02-14 05:04:33 -0500
committerThierry Reding <thierry.reding@gmail.com>2018-03-27 18:37:37 -0400
commit4eb67a209645a87b8aca070aa9735eed90177829 (patch)
tree4ad3d7082201ff0399725c80c99304f9620289d6 /drivers/pwm/pwm-stm32.c
parent3af0bdd1d027292d40c7f1d13420bc298b3e1660 (diff)
pwm: stm32: Protect common prescaler for all channels
There may be a race, when configuring two PWM channels, with different prescaler values, when there's no active channel yet. Add mutex lock to avoid concurrent access on PWM apply state. This is also precursor patch for PWM capture support. Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com> Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-stm32.c')
-rw-r--r--drivers/pwm/pwm-stm32.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 014e2a759fa6..2708212933f7 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -20,6 +20,7 @@
20 20
21struct stm32_pwm { 21struct stm32_pwm {
22 struct pwm_chip chip; 22 struct pwm_chip chip;
23 struct mutex lock; /* protect pwm config/enable */
23 struct clk *clk; 24 struct clk *clk;
24 struct regmap *regmap; 25 struct regmap *regmap;
25 u32 max_arr; 26 u32 max_arr;
@@ -212,9 +213,23 @@ static int stm32_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
212 return ret; 213 return ret;
213} 214}
214 215
216static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
217 struct pwm_state *state)
218{
219 struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
220 int ret;
221
222 /* protect common prescaler for all active channels */
223 mutex_lock(&priv->lock);
224 ret = stm32_pwm_apply(chip, pwm, state);
225 mutex_unlock(&priv->lock);
226
227 return ret;
228}
229
215static const struct pwm_ops stm32pwm_ops = { 230static const struct pwm_ops stm32pwm_ops = {
216 .owner = THIS_MODULE, 231 .owner = THIS_MODULE,
217 .apply = stm32_pwm_apply, 232 .apply = stm32_pwm_apply_locked,
218}; 233};
219 234
220static int stm32_pwm_set_breakinput(struct stm32_pwm *priv, 235static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
@@ -334,6 +349,7 @@ static int stm32_pwm_probe(struct platform_device *pdev)
334 if (!priv) 349 if (!priv)
335 return -ENOMEM; 350 return -ENOMEM;
336 351
352 mutex_init(&priv->lock);
337 priv->regmap = ddata->regmap; 353 priv->regmap = ddata->regmap;
338 priv->clk = ddata->clk; 354 priv->clk = ddata->clk;
339 priv->max_arr = ddata->max_arr; 355 priv->max_arr = ddata->max_arr;