diff options
author | Philipp Zabel <p.zabel@pengutronix.de> | 2023-10-19 22:07:04 +0200 |
---|---|---|
committer | Thierry Reding <thierry.reding@gmail.com> | 2023-12-20 16:04:14 +0100 |
commit | 19f1016ea9600ed89bc24247c36ff5934ad94fbb (patch) | |
tree | 303b570495600e7811eb9266ea2c638cd1e5d423 | |
parent | e56ec7b7527c2be54a0c15064c71838fd5c49d4b (diff) | |
download | lwn-19f1016ea9600ed89bc24247c36ff5934ad94fbb.tar.gz lwn-19f1016ea9600ed89bc24247c36ff5934ad94fbb.zip |
pwm: stm32: Fix enable count for clk in .probe()
Make the driver take over hardware state without disabling in .probe()
and enable the clock for each enabled channel.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
[ukleinek: split off from a patch that also implemented .get_state()]
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Fixes: 7edf7369205b ("pwm: Add driver for STM32 plaftorm")
Reviewed-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
-rw-r--r-- | drivers/pwm/pwm-stm32.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c index 9a7d7891edde..5f10cba492ec 100644 --- a/drivers/pwm/pwm-stm32.c +++ b/drivers/pwm/pwm-stm32.c @@ -605,17 +605,21 @@ static void stm32_pwm_detect_complementary(struct stm32_pwm *priv) priv->have_complementary_output = (ccer != 0); } -static unsigned int stm32_pwm_detect_channels(struct stm32_pwm *priv) +static unsigned int stm32_pwm_detect_channels(struct stm32_pwm *priv, + unsigned int *num_enabled) { - u32 ccer; + u32 ccer, ccer_backup; /* * If channels enable bits don't exist writing 1 will have no * effect so we can detect and count them. */ + regmap_read(priv->regmap, TIM_CCER, &ccer_backup); regmap_set_bits(priv->regmap, TIM_CCER, TIM_CCER_CCXE); regmap_read(priv->regmap, TIM_CCER, &ccer); - regmap_clear_bits(priv->regmap, TIM_CCER, TIM_CCER_CCXE); + regmap_write(priv->regmap, TIM_CCER, ccer_backup); + + *num_enabled = hweight32(ccer_backup & TIM_CCER_CCXE); return hweight32(ccer & TIM_CCER_CCXE); } @@ -626,6 +630,8 @@ static int stm32_pwm_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct stm32_timers *ddata = dev_get_drvdata(pdev->dev.parent); struct stm32_pwm *priv; + unsigned int num_enabled; + unsigned int i; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); @@ -648,7 +654,11 @@ static int stm32_pwm_probe(struct platform_device *pdev) priv->chip.dev = dev; priv->chip.ops = &stm32pwm_ops; - priv->chip.npwm = stm32_pwm_detect_channels(priv); + priv->chip.npwm = stm32_pwm_detect_channels(priv, &num_enabled); + + /* Initialize clock refcount to number of enabled PWM channels. */ + for (i = 0; i < num_enabled; i++) + clk_enable(priv->clk); ret = devm_pwmchip_add(dev, &priv->chip); if (ret < 0) |