diff options
author | Ajit Pal Singh <ajitpal.singh@st.com> | 2014-07-14 14:33:31 (GMT) |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2014-08-08 11:12:45 (GMT) |
commit | 6ad6b838e11d8d67950716e0715b1d71bdd0769e (patch) | |
tree | 3510898dbd6dc9c4ebbb4a50a4adbe05dca6670a /drivers/pwm/pwm-sti.c | |
parent | 5165166e8a1551fb80afa5fdaad6f2ea34d92285 (diff) | |
download | linux-6ad6b838e11d8d67950716e0715b1d71bdd0769e.tar.xz |
pwm: sti: Sync between enable/disable calls
ST PWM IP has a common enable/disable control for all the PWM
channels on a PWM cell. Disables PWM output on the PWM HW only
when disable is called for the last channel.
Signed-off-by: Ajit Pal Singh <ajitpal.singh@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm/pwm-sti.c')
-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 2d32605..f98afe4 100644 --- a/drivers/pwm/pwm-sti.c +++ b/drivers/pwm/pwm-sti.c @@ -59,6 +59,8 @@ struct sti_pwm_chip { unsigned long *pwm_periods; struct pwm_chip chip; struct pwm_device *cur; + unsigned int en_count; + struct mutex sti_pwm_lock; /* To sync between enable/disable calls */ void __iomem *mmio; }; @@ -236,32 +238,44 @@ static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { struct sti_pwm_chip *pc = to_sti_pwmchip(chip); struct device *dev = pc->dev; - int ret; - - ret = clk_enable(pc->clk); - if (ret) - return ret; + int ret = 0; - ret = regmap_field_write(pc->pwm_en, 1); - if (ret) - dev_err(dev, "%s,pwm_en write failed\n", __func__); + /* + * Since we have a common enable for all PWM channels, + * do not enable if already enabled. + */ + mutex_lock(&pc->sti_pwm_lock); + if (!pc->en_count) { + ret = clk_enable(pc->clk); + if (ret) + goto out; + ret = regmap_field_write(pc->pwm_en, 1); + if (ret) { + dev_err(dev, "failed to enable PWM device:%d\n", + pwm->hwpwm); + goto out; + } + } + pc->en_count++; +out: + mutex_unlock(&pc->sti_pwm_lock); return ret; } static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { struct sti_pwm_chip *pc = to_sti_pwmchip(chip); - struct device *dev = pc->dev; - unsigned int val; + mutex_lock(&pc->sti_pwm_lock); + if (--pc->en_count) { + mutex_unlock(&pc->sti_pwm_lock); + return; + } regmap_field_write(pc->pwm_en, 0); - regmap_read(pc->regmap, STI_CNT, &val); - - dev_dbg(dev, "pwm counter :%u\n", val); - clk_disable(pc->clk); + mutex_unlock(&pc->sti_pwm_lock); } static const struct pwm_ops sti_pwm_ops = { @@ -352,6 +366,8 @@ static int sti_pwm_probe(struct platform_device *pdev) pc->cdata = cdata; pc->dev = dev; + pc->en_count = 0; + mutex_init(&pc->sti_pwm_lock); ret = sti_pwm_probe_dt(pc); if (ret) |