]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
pwm: mediatek: Initialize clks when the hardware is enabled at probe time
authorUwe Kleine-König <u.kleine-koenig@baylibre.com>
Fri, 25 Jul 2025 15:45:08 +0000 (17:45 +0200)
committerUwe Kleine-König <ukleinek@kernel.org>
Mon, 15 Sep 2025 09:39:45 +0000 (11:39 +0200)
When a PWM is already configured by the bootloader (e.g. to power a
backlight), the clk enable count must be increased to keep clock usage
balanced. So check which PWMs are enabled during probe and enable the
respective clocks.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20250725154506.2610172-14-u.kleine-koenig@baylibre.com
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
drivers/pwm/pwm-mediatek.c

index 7fe003bcc74d7bf1fe7ce38b1b65b9e35ad4f702..faa0205d4a0dc5f710bcd632b997d4845762f2dd 100644 (file)
@@ -232,6 +232,49 @@ static const struct pwm_ops pwm_mediatek_ops = {
        .apply = pwm_mediatek_apply,
 };
 
+static int pwm_mediatek_init_used_clks(struct pwm_mediatek_chip *pc)
+{
+       const struct pwm_mediatek_of_data *soc = pc->soc;
+       unsigned int hwpwm;
+       u32 enabled, handled = 0;
+       int ret;
+
+       ret = clk_prepare_enable(pc->clk_top);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(pc->clk_main);
+       if (ret)
+               goto err_enable_main;
+
+       enabled = readl(pc->regs) & GENMASK(soc->num_pwms - 1, 0);
+
+       while (enabled & ~handled) {
+               hwpwm = ilog2(enabled & ~handled);
+
+               ret = pwm_mediatek_clk_enable(pc, hwpwm);
+               if (ret) {
+                       while (handled) {
+                               hwpwm = ilog2(handled);
+
+                               pwm_mediatek_clk_disable(pc, hwpwm);
+                               handled &= ~BIT(hwpwm);
+                       }
+
+                       break;
+               }
+
+               handled |= BIT(hwpwm);
+       }
+
+       clk_disable_unprepare(pc->clk_main);
+err_enable_main:
+
+       clk_disable_unprepare(pc->clk_top);
+
+       return ret;
+}
+
 static int pwm_mediatek_probe(struct platform_device *pdev)
 {
        struct pwm_chip *chip;
@@ -279,6 +322,10 @@ static int pwm_mediatek_probe(struct platform_device *pdev)
                                             "Failed to get %s clock\n", name);
        }
 
+       ret = pwm_mediatek_init_used_clks(pc);
+       if (ret)
+               return dev_err_probe(&pdev->dev, ret, "Failed to initialize used clocks\n");
+
        chip->ops = &pwm_mediatek_ops;
 
        ret = devm_pwmchip_add(&pdev->dev, chip);