diff options
Diffstat (limited to 'drivers/pwm')
-rw-r--r-- | drivers/pwm/pwm-sti.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c index 2d3260571b5a..f98afe4906fb 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c | |||
@@ -59,6 +59,8 @@ struct sti_pwm_chip { | |||
59 | unsigned long *pwm_periods; | 59 | unsigned long *pwm_periods; |
60 | struct pwm_chip chip; | 60 | struct pwm_chip chip; |
61 | struct pwm_device *cur; | 61 | struct pwm_device *cur; |
62 | unsigned int en_count; | ||
63 | struct mutex sti_pwm_lock; /* To sync between enable/disable calls */ | ||
62 | void __iomem *mmio; | 64 | void __iomem *mmio; |
63 | }; | 65 | }; |
64 | 66 | ||
@@ -236,32 +238,44 @@ static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | |||
236 | { | 238 | { |
237 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); | 239 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); |
238 | struct device *dev = pc->dev; | 240 | struct device *dev = pc->dev; |
239 | int ret; | 241 | int ret = 0; |
240 | |||
241 | ret = clk_enable(pc->clk); | ||
242 | if (ret) | ||
243 | return ret; | ||
244 | 242 | ||
245 | ret = regmap_field_write(pc->pwm_en, 1); | 243 | /* |
246 | if (ret) | 244 | * Since we have a common enable for all PWM channels, |
247 | dev_err(dev, "%s,pwm_en write failed\n", __func__); | 245 | * do not enable if already enabled. |
246 | */ | ||
247 | mutex_lock(&pc->sti_pwm_lock); | ||
248 | if (!pc->en_count) { | ||
249 | ret = clk_enable(pc->clk); | ||
250 | if (ret) | ||
251 | goto out; | ||
248 | 252 | ||
253 | ret = regmap_field_write(pc->pwm_en, 1); | ||
254 | if (ret) { | ||
255 | dev_err(dev, "failed to enable PWM device:%d\n", | ||
256 | pwm->hwpwm); | ||
257 | goto out; | ||
258 | } | ||
259 | } | ||
260 | pc->en_count++; | ||
261 | out: | ||
262 | mutex_unlock(&pc->sti_pwm_lock); | ||
249 | return ret; | 263 | return ret; |
250 | } | 264 | } |
251 | 265 | ||
252 | static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | 266 | static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
253 | { | 267 | { |
254 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); | 268 | struct sti_pwm_chip *pc = to_sti_pwmchip(chip); |
255 | struct device *dev = pc->dev; | ||
256 | unsigned int val; | ||
257 | 269 | ||
270 | mutex_lock(&pc->sti_pwm_lock); | ||
271 | if (--pc->en_count) { | ||
272 | mutex_unlock(&pc->sti_pwm_lock); | ||
273 | return; | ||
274 | } | ||
258 | regmap_field_write(pc->pwm_en, 0); | 275 | regmap_field_write(pc->pwm_en, 0); |
259 | 276 | ||
260 | regmap_read(pc->regmap, STI_CNT, &val); | ||
261 | |||
262 | dev_dbg(dev, "pwm counter :%u\n", val); | ||
263 | |||
264 | clk_disable(pc->clk); | 277 | clk_disable(pc->clk); |
278 | mutex_unlock(&pc->sti_pwm_lock); | ||
265 | } | 279 | } |
266 | 280 | ||
267 | static const struct pwm_ops sti_pwm_ops = { | 281 | static const struct pwm_ops sti_pwm_ops = { |
@@ -352,6 +366,8 @@ static int sti_pwm_probe(struct platform_device *pdev) | |||
352 | 366 | ||
353 | pc->cdata = cdata; | 367 | pc->cdata = cdata; |
354 | pc->dev = dev; | 368 | pc->dev = dev; |
369 | pc->en_count = 0; | ||
370 | mutex_init(&pc->sti_pwm_lock); | ||
355 | 371 | ||
356 | ret = sti_pwm_probe_dt(pc); | 372 | ret = sti_pwm_probe_dt(pc); |
357 | if (ret) | 373 | if (ret) |