[PATCH 2/3] clk: stm32mp1: don't disable a PLL while its P/Q/R outputs are enabled

Gabriel Fernandez gabriel.fernandez at foss.st.com
Tue Oct 20 02:48:54 PDT 2026


The clock framework only accounts for the users that enabled a PLL
output through it. An output that is already enabled in hardware, for
instance by an earlier boot stage, and not (yet) claimed by its consumer
is unknown to the framework. If another output of the same PLL is then
enabled and disabled by Linux, the PLL enable count drops to zero and
pll_disable() unconditionally clears PLLON, which silently cuts the
clock of the output that is still running.

Don't clear PLLON while at least one of the DIVPEN, DIVQEN or DIVREN
bits is set. The PLL is then switched off by a later disable, once all
its outputs are off.

Signed-off-by: Gabriel Fernandez <gabriel.fernandez at foss.st.com>
---
 drivers/clk/stm32/clk-stm32mp1.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/stm32/clk-stm32mp1.c b/drivers/clk/stm32/clk-stm32mp1.c
index 8f7bb2c31809..077dd3342911 100644
--- a/drivers/clk/stm32/clk-stm32mp1.c
+++ b/drivers/clk/stm32/clk-stm32mp1.c
@@ -755,6 +755,7 @@ struct stm32_pll_obj {
 
 #define PLL_ON		BIT(0)
 #define PLL_RDY		BIT(1)
+#define PLL_DIV_PQR_EN	GENMASK(6, 4)
 #define DIVN_MASK	0x1FF
 #define DIVM_MASK	0x3F
 #define DIVM_SHIFT	16
@@ -820,8 +821,12 @@ static void pll_disable(struct clk_hw *hw)
 	spin_lock_irqsave(clk_elem->lock, flags);
 
 	reg = readl_relaxed(clk_elem->reg);
-	reg &= ~PLL_ON;
-	writel_relaxed(reg, clk_elem->reg);
+
+	/* Keep the PLL on as long as one of its P/Q/R outputs is enabled */
+	if (!(reg & PLL_DIV_PQR_EN)) {
+		reg &= ~PLL_ON;
+		writel_relaxed(reg, clk_elem->reg);
+	}
 
 	spin_unlock_irqrestore(clk_elem->lock, flags);
 }

-- 
2.43.0




More information about the linux-arm-kernel mailing list