summaryrefslogtreecommitdiffstats
path: root/drivers/pwm/pwm-sti.c
diff options
context:
space:
mode:
authorAjit Pal Singh <ajitpal.singh@st.com>2014-07-14 15:33:31 +0100
committerThierry Reding <thierry.reding@gmail.com>2014-08-08 13:12:45 +0200
commit6ad6b838e11d8d67950716e0715b1d71bdd0769e (patch)
tree3510898dbd6dc9c4ebbb4a50a4adbe05dca6670a /drivers/pwm/pwm-sti.c
parent5165166e8a1551fb80afa5fdaad6f2ea34d92285 (diff)
downloadlinux-6ad6b838e11d8d67950716e0715b1d71bdd0769e.tar.bz2
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.c44
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 {
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)