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>
This commit is contained in:
parent
5165166e8a
commit
6ad6b838e1
1 changed files with 30 additions and 14 deletions
|
@ -59,6 +59,8 @@ struct sti_pwm_chip {
|
||||||
unsigned long *pwm_periods;
|
unsigned long *pwm_periods;
|
||||||
struct pwm_chip chip;
|
struct pwm_chip chip;
|
||||||
struct pwm_device *cur;
|
struct pwm_device *cur;
|
||||||
|
unsigned int en_count;
|
||||||
|
struct mutex sti_pwm_lock; /* To sync between enable/disable calls */
|
||||||
void __iomem *mmio;
|
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 sti_pwm_chip *pc = to_sti_pwmchip(chip);
|
||||||
struct device *dev = pc->dev;
|
struct device *dev = pc->dev;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
ret = clk_enable(pc->clk);
|
/*
|
||||||
if (ret)
|
* Since we have a common enable for all PWM channels,
|
||||||
return ret;
|
* do not enable if already enabled.
|
||||||
|
*/
|
||||||
ret = regmap_field_write(pc->pwm_en, 1);
|
mutex_lock(&pc->sti_pwm_lock);
|
||||||
if (ret)
|
if (!pc->en_count) {
|
||||||
dev_err(dev, "%s,pwm_en write failed\n", __func__);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
|
||||||
{
|
{
|
||||||
struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
|
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_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);
|
clk_disable(pc->clk);
|
||||||
|
mutex_unlock(&pc->sti_pwm_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pwm_ops sti_pwm_ops = {
|
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->cdata = cdata;
|
||||||
pc->dev = dev;
|
pc->dev = dev;
|
||||||
|
pc->en_count = 0;
|
||||||
|
mutex_init(&pc->sti_pwm_lock);
|
||||||
|
|
||||||
ret = sti_pwm_probe_dt(pc);
|
ret = sti_pwm_probe_dt(pc);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
Loading…
Add table
Reference in a new issue