diff options
Diffstat (limited to 'drivers/pwm/pwm-atmel-tcb.c')
-rw-r--r-- | drivers/pwm/pwm-atmel-tcb.c | 113 |
1 files changed, 53 insertions, 60 deletions
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c index 528e54c5999d..f9a9c12cbcdd 100644 --- a/drivers/pwm/pwm-atmel-tcb.c +++ b/drivers/pwm/pwm-atmel-tcb.c @@ -81,7 +81,8 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip, tcbpwm->period = 0; tcbpwm->div = 0; - spin_lock(&tcbpwmc->lock); + guard(spinlock)(&tcbpwmc->lock); + regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); /* * Get init config from Timer Counter registers if @@ -107,7 +108,6 @@ static int atmel_tcb_pwm_request(struct pwm_chip *chip, cmr |= ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO | ATMEL_TC_EEVT_XC0; regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), cmr); - spin_unlock(&tcbpwmc->lock); return 0; } @@ -137,7 +137,6 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, if (tcbpwm->duty == 0) polarity = !polarity; - spin_lock(&tcbpwmc->lock); regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); /* flush old setting and set the new one */ @@ -172,8 +171,6 @@ static void atmel_tcb_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm, ATMEL_TC_SWTRG); tcbpwmc->bkup.enabled = 0; } - - spin_unlock(&tcbpwmc->lock); } static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, @@ -194,7 +191,6 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, if (tcbpwm->duty == 0) polarity = !polarity; - spin_lock(&tcbpwmc->lock); regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CMR), &cmr); /* flush old setting and set the new one */ @@ -256,7 +252,6 @@ static int atmel_tcb_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(tcbpwmc->channel, CCR), ATMEL_TC_SWTRG | ATMEL_TC_CLKEN); tcbpwmc->bkup.enabled = 1; - spin_unlock(&tcbpwmc->lock); return 0; } @@ -265,7 +260,8 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, { struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); struct atmel_tcb_pwm_device *tcbpwm = &tcbpwmc->pwms[pwm->hwpwm]; - struct atmel_tcb_pwm_device *atcbpwm = NULL; + /* companion PWM sharing register values period and div */ + struct atmel_tcb_pwm_device *atcbpwm = &tcbpwmc->pwms[pwm->hwpwm ^ 1]; int i = 0; int slowclk = 0; unsigned period; @@ -310,11 +306,6 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, duty = div_u64(duty_ns, min); period = div_u64(period_ns, min); - if (pwm->hwpwm == 0) - atcbpwm = &tcbpwmc->pwms[1]; - else - atcbpwm = &tcbpwmc->pwms[0]; - /* * PWM devices provided by the TCB driver are grouped by 2. * PWM devices in a given group must be configured with the @@ -323,8 +314,7 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, * We're checking the period value of the second PWM device * in this group before applying the new config. */ - if ((atcbpwm && atcbpwm->duty > 0 && - atcbpwm->duty != atcbpwm->period) && + if ((atcbpwm->duty > 0 && atcbpwm->duty != atcbpwm->period) && (atcbpwm->div != i || atcbpwm->period != period)) { dev_err(pwmchip_parent(chip), "failed to configure period_ns: PWM group already configured with a different value\n"); @@ -341,9 +331,12 @@ static int atmel_tcb_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, static int atmel_tcb_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) { + struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); int duty_cycle, period; int ret; + guard(spinlock)(&tcbpwmc->lock); + if (!state->enabled) { atmel_tcb_pwm_disable(chip, pwm, state->polarity); return 0; @@ -389,17 +382,17 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) { struct pwm_chip *chip; const struct of_device_id *match; - struct atmel_tcb_pwm_chip *tcbpwm; + struct atmel_tcb_pwm_chip *tcbpwmc; const struct atmel_tcb_config *config; struct device_node *np = pdev->dev.of_node; char clk_name[] = "t0_clk"; int err; int channel; - chip = devm_pwmchip_alloc(&pdev->dev, NPWM, sizeof(*tcbpwm)); + chip = devm_pwmchip_alloc(&pdev->dev, NPWM, sizeof(*tcbpwmc)); if (IS_ERR(chip)) return PTR_ERR(chip); - tcbpwm = to_tcb_chip(chip); + tcbpwmc = to_tcb_chip(chip); err = of_property_read_u32(np, "reg", &channel); if (err < 0) { @@ -409,20 +402,20 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) return err; } - tcbpwm->regmap = syscon_node_to_regmap(np->parent); - if (IS_ERR(tcbpwm->regmap)) - return PTR_ERR(tcbpwm->regmap); + tcbpwmc->regmap = syscon_node_to_regmap(np->parent); + if (IS_ERR(tcbpwmc->regmap)) + return PTR_ERR(tcbpwmc->regmap); - tcbpwm->slow_clk = of_clk_get_by_name(np->parent, "slow_clk"); - if (IS_ERR(tcbpwm->slow_clk)) - return PTR_ERR(tcbpwm->slow_clk); + tcbpwmc->slow_clk = of_clk_get_by_name(np->parent, "slow_clk"); + if (IS_ERR(tcbpwmc->slow_clk)) + return PTR_ERR(tcbpwmc->slow_clk); clk_name[1] += channel; - tcbpwm->clk = of_clk_get_by_name(np->parent, clk_name); - if (IS_ERR(tcbpwm->clk)) - tcbpwm->clk = of_clk_get_by_name(np->parent, "t0_clk"); - if (IS_ERR(tcbpwm->clk)) { - err = PTR_ERR(tcbpwm->clk); + tcbpwmc->clk = of_clk_get_by_name(np->parent, clk_name); + if (IS_ERR(tcbpwmc->clk)) + tcbpwmc->clk = of_clk_get_by_name(np->parent, "t0_clk"); + if (IS_ERR(tcbpwmc->clk)) { + err = PTR_ERR(tcbpwmc->clk); goto err_slow_clk; } @@ -430,22 +423,22 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) config = match->data; if (config->has_gclk) { - tcbpwm->gclk = of_clk_get_by_name(np->parent, "gclk"); - if (IS_ERR(tcbpwm->gclk)) { - err = PTR_ERR(tcbpwm->gclk); + tcbpwmc->gclk = of_clk_get_by_name(np->parent, "gclk"); + if (IS_ERR(tcbpwmc->gclk)) { + err = PTR_ERR(tcbpwmc->gclk); goto err_clk; } } chip->ops = &atmel_tcb_pwm_ops; - tcbpwm->channel = channel; - tcbpwm->width = config->counter_width; + tcbpwmc->channel = channel; + tcbpwmc->width = config->counter_width; - err = clk_prepare_enable(tcbpwm->slow_clk); + err = clk_prepare_enable(tcbpwmc->slow_clk); if (err) goto err_gclk; - spin_lock_init(&tcbpwm->lock); + spin_lock_init(&tcbpwmc->lock); err = pwmchip_add(chip); if (err < 0) @@ -456,16 +449,16 @@ static int atmel_tcb_pwm_probe(struct platform_device *pdev) return 0; err_disable_clk: - clk_disable_unprepare(tcbpwm->slow_clk); + clk_disable_unprepare(tcbpwmc->slow_clk); err_gclk: - clk_put(tcbpwm->gclk); + clk_put(tcbpwmc->gclk); err_clk: - clk_put(tcbpwm->clk); + clk_put(tcbpwmc->clk); err_slow_clk: - clk_put(tcbpwm->slow_clk); + clk_put(tcbpwmc->slow_clk); return err; } @@ -473,14 +466,14 @@ err_slow_clk: static void atmel_tcb_pwm_remove(struct platform_device *pdev) { struct pwm_chip *chip = platform_get_drvdata(pdev); - struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip); + struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); pwmchip_remove(chip); - clk_disable_unprepare(tcbpwm->slow_clk); - clk_put(tcbpwm->gclk); - clk_put(tcbpwm->clk); - clk_put(tcbpwm->slow_clk); + clk_disable_unprepare(tcbpwmc->slow_clk); + clk_put(tcbpwmc->gclk); + clk_put(tcbpwmc->clk); + clk_put(tcbpwmc->slow_clk); } static const struct of_device_id atmel_tcb_pwm_dt_ids[] = { @@ -492,14 +485,14 @@ MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids); static int atmel_tcb_pwm_suspend(struct device *dev) { struct pwm_chip *chip = dev_get_drvdata(dev); - struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip); - struct atmel_tcb_channel *chan = &tcbpwm->bkup; - unsigned int channel = tcbpwm->channel; + struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); + struct atmel_tcb_channel *chan = &tcbpwmc->bkup; + unsigned int channel = tcbpwmc->channel; - regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, CMR), &chan->cmr); - regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RA), &chan->ra); - regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RB), &chan->rb); - regmap_read(tcbpwm->regmap, ATMEL_TC_REG(channel, RC), &chan->rc); + regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, CMR), &chan->cmr); + regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, RA), &chan->ra); + regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, RB), &chan->rb); + regmap_read(tcbpwmc->regmap, ATMEL_TC_REG(channel, RC), &chan->rc); return 0; } @@ -507,17 +500,17 @@ static int atmel_tcb_pwm_suspend(struct device *dev) static int atmel_tcb_pwm_resume(struct device *dev) { struct pwm_chip *chip = dev_get_drvdata(dev); - struct atmel_tcb_pwm_chip *tcbpwm = to_tcb_chip(chip); - struct atmel_tcb_channel *chan = &tcbpwm->bkup; - unsigned int channel = tcbpwm->channel; + struct atmel_tcb_pwm_chip *tcbpwmc = to_tcb_chip(chip); + struct atmel_tcb_channel *chan = &tcbpwmc->bkup; + unsigned int channel = tcbpwmc->channel; - regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, CMR), chan->cmr); - regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RA), chan->ra); - regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RB), chan->rb); - regmap_write(tcbpwm->regmap, ATMEL_TC_REG(channel, RC), chan->rc); + regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, CMR), chan->cmr); + regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, RA), chan->ra); + regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, RB), chan->rb); + regmap_write(tcbpwmc->regmap, ATMEL_TC_REG(channel, RC), chan->rc); if (chan->enabled) - regmap_write(tcbpwm->regmap, + regmap_write(tcbpwmc->regmap, ATMEL_TC_CLKEN | ATMEL_TC_SWTRG, ATMEL_TC_REG(channel, CCR)); |