]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
clk: meson: add 'NOINIT_ENABLED' flag to eliminate init for enabled PLL
authorDmitry Rokosov <ddrokosov@salutedevices.com>
Wed, 15 May 2024 18:47:24 +0000 (21:47 +0300)
committerJerome Brunet <jbrunet@baylibre.com>
Mon, 10 Jun 2024 10:16:01 +0000 (12:16 +0200)
When dealing with certain PLLs, it is necessary to avoid modifying them
if they have already been initialized by lower levels. For instance, in
the A1 SoC Family, the sys_pll is enabled as the parent for the cpuclk,
and it cannot be disabled during the initialization sequence. Therefore,
initialization phase must be skipped.

Signed-off-by: Dmitry Rokosov <ddrokosov@salutedevices.com>
Link: https://lore.kernel.org/r/20240515185103.20256-2-ddrokosov@salutedevices.com
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clk-pll.h

index 07db8b5c30001d9fa709882c55a9050ebdd09dd3..467dc8b61a370b2e14df110575e5e6e7231c3697 100644 (file)
@@ -289,11 +289,35 @@ static int meson_clk_pll_wait_lock(struct clk_hw *hw)
        return -ETIMEDOUT;
 }
 
+static int meson_clk_pll_is_enabled(struct clk_hw *hw)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+       if (MESON_PARM_APPLICABLE(&pll->rst) &&
+           meson_parm_read(clk->map, &pll->rst))
+               return 0;
+
+       if (!meson_parm_read(clk->map, &pll->en) ||
+           !meson_parm_read(clk->map, &pll->l))
+               return 0;
+
+       return 1;
+}
+
 static int meson_clk_pll_init(struct clk_hw *hw)
 {
        struct clk_regmap *clk = to_clk_regmap(hw);
        struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
 
+       /*
+        * Keep the clock running, which was already initialized and enabled
+        * from the bootloader stage, to avoid any glitches.
+        */
+       if ((pll->flags & CLK_MESON_PLL_NOINIT_ENABLED) &&
+           meson_clk_pll_is_enabled(hw))
+               return 0;
+
        if (pll->init_count) {
                if (MESON_PARM_APPLICABLE(&pll->rst))
                        meson_parm_write(clk->map, &pll->rst, 1);
@@ -308,22 +332,6 @@ static int meson_clk_pll_init(struct clk_hw *hw)
        return 0;
 }
 
-static int meson_clk_pll_is_enabled(struct clk_hw *hw)
-{
-       struct clk_regmap *clk = to_clk_regmap(hw);
-       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-
-       if (MESON_PARM_APPLICABLE(&pll->rst) &&
-           meson_parm_read(clk->map, &pll->rst))
-               return 0;
-
-       if (!meson_parm_read(clk->map, &pll->en) ||
-           !meson_parm_read(clk->map, &pll->l))
-               return 0;
-
-       return 1;
-}
-
 static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
 {
        int retries = 10;
index a2228c0fdce5bd6b4b5a168177fdb2af070a4d0a..7b6b87274073d03d11256f96cc191f071279e0ab 100644 (file)
@@ -28,6 +28,7 @@ struct pll_mult_range {
        }
 
 #define CLK_MESON_PLL_ROUND_CLOSEST    BIT(0)
+#define CLK_MESON_PLL_NOINIT_ENABLED   BIT(1)
 
 struct meson_clk_pll_data {
        struct parm en;