public inbox for linux-amlogic@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH 0/3] clk: amlogic: optimize the PLL driver
@ 2025-10-22  6:58 Chuan Liu via B4 Relay
  2025-10-22  6:58 ` [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting Chuan Liu via B4 Relay
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Chuan Liu via B4 Relay @ 2025-10-22  6:58 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Michael Turquette, Stephen Boyd,
	Kevin Hilman, Martin Blumenstingl
  Cc: linux-amlogic, linux-clk, linux-arm-kernel, linux-kernel,
	Chuan Liu

This patch series consists of three topics involving the amlogic PLL
driver:
- Fix out-of-range PLL frequency setting
- Optimize PLL enable timing
- Correct l_detect bit control

For easier review and management, these are submitted as a single
patch series.

Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
---
Chuan Liu (3):
      clk: amlogic: Fix out-of-range PLL frequency setting
      clk: amlogic: Optimize PLL enable timing
      clk: amlogic: Correct l_detect bit control

 drivers/clk/meson/a1-pll.c  |  1 +
 drivers/clk/meson/clk-pll.c | 76 ++++++++++++++++++++++++++++-----------------
 drivers/clk/meson/clk-pll.h |  2 ++
 3 files changed, 51 insertions(+), 28 deletions(-)
---
base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
change-id: 20251020-optimize_pll_driver-7bef91876c41

Best regards,
-- 
Chuan Liu <chuan.liu@amlogic.com>



_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting
  2025-10-22  6:58 [PATCH 0/3] clk: amlogic: optimize the PLL driver Chuan Liu via B4 Relay
@ 2025-10-22  6:58 ` Chuan Liu via B4 Relay
  2025-10-22 11:57   ` Jerome Brunet
  2025-10-22  6:58 ` [PATCH 2/3] clk: amlogic: Optimize PLL enable timing Chuan Liu via B4 Relay
  2025-10-22  6:58 ` [PATCH 3/3] clk: amlogic: Correct l_detect bit control Chuan Liu via B4 Relay
  2 siblings, 1 reply; 9+ messages in thread
From: Chuan Liu via B4 Relay @ 2025-10-22  6:58 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Michael Turquette, Stephen Boyd,
	Kevin Hilman, Martin Blumenstingl
  Cc: linux-amlogic, linux-clk, linux-arm-kernel, linux-kernel,
	Chuan Liu

From: Chuan Liu <chuan.liu@amlogic.com>

meson_clk_get_pll_range_index incorrectly determines the maximum value
of 'm'.

Fixes: 8eed1db1adec6 ("clk: meson: pll: update driver for the g12a")
Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
---
 drivers/clk/meson/clk-pll.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 1ea6579a760f..b07e1eb19d12 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -191,7 +191,7 @@ static int meson_clk_get_pll_range_index(unsigned long rate,
 	*m = meson_clk_get_pll_range_m(rate, parent_rate, *n, pll);
 
 	/* the pre-divider gives a multiplier too big - stop */
-	if (*m >= (1 << pll->m.width))
+	if (*m > pll->range->max)
 		return -EINVAL;
 
 	return 0;

-- 
2.42.0



_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
  2025-10-22  6:58 [PATCH 0/3] clk: amlogic: optimize the PLL driver Chuan Liu via B4 Relay
  2025-10-22  6:58 ` [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting Chuan Liu via B4 Relay
@ 2025-10-22  6:58 ` Chuan Liu via B4 Relay
  2025-10-22 12:01   ` Jerome Brunet
  2025-10-22  6:58 ` [PATCH 3/3] clk: amlogic: Correct l_detect bit control Chuan Liu via B4 Relay
  2 siblings, 1 reply; 9+ messages in thread
From: Chuan Liu via B4 Relay @ 2025-10-22  6:58 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Michael Turquette, Stephen Boyd,
	Kevin Hilman, Martin Blumenstingl
  Cc: linux-amlogic, linux-clk, linux-arm-kernel, linux-kernel,
	Chuan Liu

From: Chuan Liu <chuan.liu@amlogic.com>

Amlogic PLL locking procedure shall follow this timing sequence:
1 Assert reset signal: Ensures PLL circuits enter known initial state.
2 Deassert lock-detect signal: Avoid lock signal false triggering.
3 Assert enable signal: Powers up PLL supply.
4 udelay(20): Wait for Bandgap and LDO to power up and stabilize.
5 Enable self-adaptation current module (Optional).
6 Deassert reset signal: Releases PLL to begin normal operation.
7 udelay(20): Wait for PLL loop stabilization.
8 Assert lock-detect signal: lock detection circuit starts to work.
9 Monitor lock status signal: Wait for PLL lock completion.
10 If the PLL fails to lock, it should be disabled, This makes the
logic more complete, and also helps save unnecessary power consumption
when the PLL is malfunctioning.

Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
---
 drivers/clk/meson/clk-pll.c | 68 ++++++++++++++++++++++++++-------------------
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index b07e1eb19d12..26c83db487e8 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -353,6 +353,23 @@ static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
 	return -EIO;
 }
 
+static void meson_clk_pll_disable(struct clk_hw *hw)
+{
+	struct clk_regmap *clk = to_clk_regmap(hw);
+	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+	/* Put the pll is in reset */
+	if (MESON_PARM_APPLICABLE(&pll->rst))
+		meson_parm_write(clk->map, &pll->rst, 1);
+
+	/* Disable the pll */
+	meson_parm_write(clk->map, &pll->en, 0);
+
+	/* Disable PLL internal self-adaption current module */
+	if (MESON_PARM_APPLICABLE(&pll->current_en))
+		meson_parm_write(clk->map, &pll->current_en, 0);
+}
+
 static int meson_clk_pll_enable(struct clk_hw *hw)
 {
 	struct clk_regmap *clk = to_clk_regmap(hw);
@@ -366,53 +383,48 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 	if (MESON_PARM_APPLICABLE(&pll->rst))
 		meson_parm_write(clk->map, &pll->rst, 1);
 
+	/* Disable the PLL lock-detect module */
+	if (MESON_PARM_APPLICABLE(&pll->l_detect))
+		meson_parm_write(clk->map, &pll->l_detect, 1);
+
 	/* Enable the pll */
 	meson_parm_write(clk->map, &pll->en, 1);
-
-	/* Take the pll out reset */
-	if (MESON_PARM_APPLICABLE(&pll->rst))
-		meson_parm_write(clk->map, &pll->rst, 0);
+	/* Wait for Bandgap and LDO to power up and stabilize */
+	udelay(20);
 
 	/*
 	 * Compared with the previous SoCs, self-adaption current module
 	 * is newly added for A1, keep the new power-on sequence to enable the
 	 * PLL. The sequence is:
-	 * 1. enable the pll, delay for 10us
+	 * 1. enable the pll, ensure a minimum delay of 10μs
 	 * 2. enable the pll self-adaption current module, delay for 40us
 	 * 3. enable the lock detect module
 	 */
 	if (MESON_PARM_APPLICABLE(&pll->current_en)) {
-		udelay(10);
 		meson_parm_write(clk->map, &pll->current_en, 1);
-		udelay(40);
-	}
-
-	if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
-		meson_parm_write(clk->map, &pll->l_detect, 1);
-		meson_parm_write(clk->map, &pll->l_detect, 0);
+		udelay(20);
 	}
 
-	if (meson_clk_pll_wait_lock(hw))
-		return -EIO;
+	/* Take the pll out reset */
+	if (MESON_PARM_APPLICABLE(&pll->rst))
+		meson_parm_write(clk->map, &pll->rst, 0);
 
-	return 0;
-}
+	/* Wait for PLL loop stabilization */
+	udelay(20);
 
-static void meson_clk_pll_disable(struct clk_hw *hw)
-{
-	struct clk_regmap *clk = to_clk_regmap(hw);
-	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+	/* Enable the lock-detect module */
+	if (MESON_PARM_APPLICABLE(&pll->l_detect))
+		meson_parm_write(clk->map, &pll->l_detect, 0);
 
-	/* Put the pll is in reset */
-	if (MESON_PARM_APPLICABLE(&pll->rst))
-		meson_parm_write(clk->map, &pll->rst, 1);
+	if (meson_clk_pll_wait_lock(hw)) {
+		/* disable PLL when PLL lock failed. */
+		meson_clk_pll_disable(hw);
+		pr_warn("%s: PLL lock failed!!!\n", clk_hw_get_name(hw));
 
-	/* Disable the pll */
-	meson_parm_write(clk->map, &pll->en, 0);
+		return -EIO;
+	}
 
-	/* Disable PLL internal self-adaption current module */
-	if (MESON_PARM_APPLICABLE(&pll->current_en))
-		meson_parm_write(clk->map, &pll->current_en, 0);
+	return 0;
 }
 
 static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,

-- 
2.42.0



_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/3] clk: amlogic: Correct l_detect bit control
  2025-10-22  6:58 [PATCH 0/3] clk: amlogic: optimize the PLL driver Chuan Liu via B4 Relay
  2025-10-22  6:58 ` [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting Chuan Liu via B4 Relay
  2025-10-22  6:58 ` [PATCH 2/3] clk: amlogic: Optimize PLL enable timing Chuan Liu via B4 Relay
@ 2025-10-22  6:58 ` Chuan Liu via B4 Relay
  2 siblings, 0 replies; 9+ messages in thread
From: Chuan Liu via B4 Relay @ 2025-10-22  6:58 UTC (permalink / raw)
  To: Neil Armstrong, Jerome Brunet, Michael Turquette, Stephen Boyd,
	Kevin Hilman, Martin Blumenstingl
  Cc: linux-amlogic, linux-clk, linux-arm-kernel, linux-kernel,
	Chuan Liu

From: Chuan Liu <chuan.liu@amlogic.com>

l_detect controls the enable/disable of the PLL lock-detect module.

For A1, the l_detect signal is active-low:
0 -> Enable lock-detect module;
1 -> Disable lock-detect module.

Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
---
 drivers/clk/meson/a1-pll.c  |  1 +
 drivers/clk/meson/clk-pll.c | 16 ++++++++++++----
 drivers/clk/meson/clk-pll.h |  2 ++
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c
index 1f82e9c7c14e..bfe559c71402 100644
--- a/drivers/clk/meson/a1-pll.c
+++ b/drivers/clk/meson/a1-pll.c
@@ -137,6 +137,7 @@ static struct clk_regmap a1_hifi_pll = {
 		.range = &a1_hifi_pll_range,
 		.init_regs = a1_hifi_pll_init_regs,
 		.init_count = ARRAY_SIZE(a1_hifi_pll_init_regs),
+		.flags = CLK_MESON_PLL_L_DETECT_N
 	},
 	.hw.init = &(struct clk_init_data){
 		.name = "hifi_pll",
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 26c83db487e8..602c93aba3cc 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -384,8 +384,12 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 		meson_parm_write(clk->map, &pll->rst, 1);
 
 	/* Disable the PLL lock-detect module */
-	if (MESON_PARM_APPLICABLE(&pll->l_detect))
-		meson_parm_write(clk->map, &pll->l_detect, 1);
+	if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
+		if (pll->flags & CLK_MESON_PLL_L_DETECT_N)
+			meson_parm_write(clk->map, &pll->l_detect, 1);
+		else
+			meson_parm_write(clk->map, &pll->l_detect, 0);
+	}
 
 	/* Enable the pll */
 	meson_parm_write(clk->map, &pll->en, 1);
@@ -413,8 +417,12 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 	udelay(20);
 
 	/* Enable the lock-detect module */
-	if (MESON_PARM_APPLICABLE(&pll->l_detect))
-		meson_parm_write(clk->map, &pll->l_detect, 0);
+	if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
+		if (pll->flags & CLK_MESON_PLL_L_DETECT_N)
+			meson_parm_write(clk->map, &pll->l_detect, 0);
+		else
+			meson_parm_write(clk->map, &pll->l_detect, 1);
+	}
 
 	if (meson_clk_pll_wait_lock(hw)) {
 		/* disable PLL when PLL lock failed. */
diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h
index 949157fb7bf5..83295a24721f 100644
--- a/drivers/clk/meson/clk-pll.h
+++ b/drivers/clk/meson/clk-pll.h
@@ -29,6 +29,8 @@ struct pll_mult_range {
 
 #define CLK_MESON_PLL_ROUND_CLOSEST	BIT(0)
 #define CLK_MESON_PLL_NOINIT_ENABLED	BIT(1)
+/* l_detect signal is active-low */
+#define CLK_MESON_PLL_L_DETECT_N	BIT(2)
 
 struct meson_clk_pll_data {
 	struct parm en;

-- 
2.42.0



_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting
  2025-10-22  6:58 ` [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting Chuan Liu via B4 Relay
@ 2025-10-22 11:57   ` Jerome Brunet
  2025-10-22 13:50     ` Chuan Liu
  0 siblings, 1 reply; 9+ messages in thread
From: Jerome Brunet @ 2025-10-22 11:57 UTC (permalink / raw)
  To: Chuan Liu via B4 Relay
  Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Kevin Hilman,
	Martin Blumenstingl, chuan.liu, linux-amlogic, linux-clk,
	linux-arm-kernel, linux-kernel

On Wed 22 Oct 2025 at 14:58, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com@kernel.org> wrote:

> From: Chuan Liu <chuan.liu@amlogic.com>
>
> meson_clk_get_pll_range_index incorrectly determines the maximum value
> of 'm'.

This explanation is little light !

How did the problem show up ? Under which condition ? How did you come
this conclusion ?

Other people having problems might benefit from the explanation 

>
> Fixes: 8eed1db1adec6 ("clk: meson: pll: update driver for the g12a")
> Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
> ---
>  drivers/clk/meson/clk-pll.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 1ea6579a760f..b07e1eb19d12 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -191,7 +191,7 @@ static int meson_clk_get_pll_range_index(unsigned long rate,
>  	*m = meson_clk_get_pll_range_m(rate, parent_rate, *n, pll);
>  
>  	/* the pre-divider gives a multiplier too big - stop */
> -	if (*m >= (1 << pll->m.width))
> +	if (*m > pll->range->max)

Making sure m does not exceed the maximum value is valid too.
You should check both conditions then

>  		return -EINVAL;
>  
>  	return 0;

-- 
Jerome

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
  2025-10-22  6:58 ` [PATCH 2/3] clk: amlogic: Optimize PLL enable timing Chuan Liu via B4 Relay
@ 2025-10-22 12:01   ` Jerome Brunet
  2025-10-22 14:07     ` Chuan Liu
  0 siblings, 1 reply; 9+ messages in thread
From: Jerome Brunet @ 2025-10-22 12:01 UTC (permalink / raw)
  To: Chuan Liu via B4 Relay
  Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Kevin Hilman,
	Martin Blumenstingl, chuan.liu, linux-amlogic, linux-clk,
	linux-arm-kernel, linux-kernel

On Wed 22 Oct 2025 at 14:58, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com@kernel.org> wrote:

> From: Chuan Liu <chuan.liu@amlogic.com>
>
> Amlogic PLL locking procedure shall follow this timing sequence:
> 1 Assert reset signal: Ensures PLL circuits enter known initial state.
> 2 Deassert lock-detect signal: Avoid lock signal false triggering.
> 3 Assert enable signal: Powers up PLL supply.
> 4 udelay(20): Wait for Bandgap and LDO to power up and stabilize.
> 5 Enable self-adaptation current module (Optional).
> 6 Deassert reset signal: Releases PLL to begin normal operation.
> 7 udelay(20): Wait for PLL loop stabilization.
> 8 Assert lock-detect signal: lock detection circuit starts to work.
> 9 Monitor lock status signal: Wait for PLL lock completion.
> 10 If the PLL fails to lock, it should be disabled, This makes the
> logic more complete, and also helps save unnecessary power consumption
> when the PLL is malfunctioning.

Is this applicable to all supported SoC ? from meson8 to s4 ?

What did you test ?


>
> Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
> ---
>  drivers/clk/meson/clk-pll.c | 68 ++++++++++++++++++++++++++-------------------
>  1 file changed, 40 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index b07e1eb19d12..26c83db487e8 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -353,6 +353,23 @@ static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
>  	return -EIO;
>  }
>  
> +static void meson_clk_pll_disable(struct clk_hw *hw)
> +{
> +	struct clk_regmap *clk = to_clk_regmap(hw);
> +	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> +
> +	/* Put the pll is in reset */
> +	if (MESON_PARM_APPLICABLE(&pll->rst))
> +		meson_parm_write(clk->map, &pll->rst, 1);
> +
> +	/* Disable the pll */
> +	meson_parm_write(clk->map, &pll->en, 0);
> +
> +	/* Disable PLL internal self-adaption current module */
> +	if (MESON_PARM_APPLICABLE(&pll->current_en))
> +		meson_parm_write(clk->map, &pll->current_en, 0);
> +}

I don't get why you moved that code around and make the diff even harder
to read

> +
>  static int meson_clk_pll_enable(struct clk_hw *hw)
>  {
>  	struct clk_regmap *clk = to_clk_regmap(hw);
> @@ -366,53 +383,48 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>  	if (MESON_PARM_APPLICABLE(&pll->rst))
>  		meson_parm_write(clk->map, &pll->rst, 1);
>  
> +	/* Disable the PLL lock-detect module */
> +	if (MESON_PARM_APPLICABLE(&pll->l_detect))
> +		meson_parm_write(clk->map, &pll->l_detect, 1);
> +
>  	/* Enable the pll */
>  	meson_parm_write(clk->map, &pll->en, 1);
> -
> -	/* Take the pll out reset */
> -	if (MESON_PARM_APPLICABLE(&pll->rst))
> -		meson_parm_write(clk->map, &pll->rst, 0);
> +	/* Wait for Bandgap and LDO to power up and stabilize */
> +	udelay(20);
>  
>  	/*
>  	 * Compared with the previous SoCs, self-adaption current module
>  	 * is newly added for A1, keep the new power-on sequence to enable the
>  	 * PLL. The sequence is:
> -	 * 1. enable the pll, delay for 10us
> +	 * 1. enable the pll, ensure a minimum delay of 10μs
>  	 * 2. enable the pll self-adaption current module, delay for 40us
>  	 * 3. enable the lock detect module
>  	 */
>  	if (MESON_PARM_APPLICABLE(&pll->current_en)) {
> -		udelay(10);
>  		meson_parm_write(clk->map, &pll->current_en, 1);
> -		udelay(40);
> -	}
> -
> -	if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
> -		meson_parm_write(clk->map, &pll->l_detect, 1);
> -		meson_parm_write(clk->map, &pll->l_detect, 0);
> +		udelay(20);
>  	}
>  
> -	if (meson_clk_pll_wait_lock(hw))
> -		return -EIO;
> +	/* Take the pll out reset */
> +	if (MESON_PARM_APPLICABLE(&pll->rst))
> +		meson_parm_write(clk->map, &pll->rst, 0);
>  
> -	return 0;
> -}
> +	/* Wait for PLL loop stabilization */
> +	udelay(20);
>  
> -static void meson_clk_pll_disable(struct clk_hw *hw)
> -{
> -	struct clk_regmap *clk = to_clk_regmap(hw);
> -	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> +	/* Enable the lock-detect module */
> +	if (MESON_PARM_APPLICABLE(&pll->l_detect))
> +		meson_parm_write(clk->map, &pll->l_detect, 0);
>  
> -	/* Put the pll is in reset */
> -	if (MESON_PARM_APPLICABLE(&pll->rst))
> -		meson_parm_write(clk->map, &pll->rst, 1);
> +	if (meson_clk_pll_wait_lock(hw)) {
> +		/* disable PLL when PLL lock failed. */
> +		meson_clk_pll_disable(hw);
> +		pr_warn("%s: PLL lock failed!!!\n", clk_hw_get_name(hw));
>  
> -	/* Disable the pll */
> -	meson_parm_write(clk->map, &pll->en, 0);
> +		return -EIO;
> +	}
>  
> -	/* Disable PLL internal self-adaption current module */
> -	if (MESON_PARM_APPLICABLE(&pll->current_en))
> -		meson_parm_write(clk->map, &pll->current_en, 0);
> +	return 0;
>  }
>  
>  static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,

-- 
Jerome

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting
  2025-10-22 11:57   ` Jerome Brunet
@ 2025-10-22 13:50     ` Chuan Liu
  0 siblings, 0 replies; 9+ messages in thread
From: Chuan Liu @ 2025-10-22 13:50 UTC (permalink / raw)
  To: Jerome Brunet, Chuan Liu via B4 Relay
  Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Kevin Hilman,
	Martin Blumenstingl, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-kernel

Hi Jerome,
Thanks for your review.


On 10/22/2025 7:57 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Wed 22 Oct 2025 at 14:58, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com@kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu@amlogic.com>
>>
>> meson_clk_get_pll_range_index incorrectly determines the maximum value
>> of 'm'.
> 
> This explanation is little light !
> 
> How did the problem show up ? Under which condition ? How did you come
> this conclusion ?

In actual use cases, we haven't encountered any issues caused by this,
because we ensure that range->max <= (1 << pll->m.width) when
configuring the range.

If the calculated 'm' falls into the range:
- range->max < m < (1 << pll->m.width)
An incorrect 'm' value may be selected here. Therefore, comparing
against range->max is more appropriate in this case.

> 
> Other people having problems might benefit from the explanation
> 
>>
>> Fixes: 8eed1db1adec6 ("clk: meson: pll: update driver for the g12a")
>> Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
>> ---
>>   drivers/clk/meson/clk-pll.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>> index 1ea6579a760f..b07e1eb19d12 100644
>> --- a/drivers/clk/meson/clk-pll.c
>> +++ b/drivers/clk/meson/clk-pll.c
>> @@ -191,7 +191,7 @@ static int meson_clk_get_pll_range_index(unsigned long rate,
>>        *m = meson_clk_get_pll_range_m(rate, parent_rate, *n, pll);
>>
>>        /* the pre-divider gives a multiplier too big - stop */
>> -     if (*m >= (1 << pll->m.width))
>> +     if (*m > pll->range->max)
> 
> Making sure m does not exceed the maximum value is valid too.
> You should check both conditions then

Ok, fix it in the next version.

> 
>>                return -EINVAL;
>>
>>        return 0;
> 
> --
> Jerome


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
  2025-10-22 12:01   ` Jerome Brunet
@ 2025-10-22 14:07     ` Chuan Liu
  2025-10-30  8:45       ` Jerome Brunet
  0 siblings, 1 reply; 9+ messages in thread
From: Chuan Liu @ 2025-10-22 14:07 UTC (permalink / raw)
  To: Jerome Brunet, Chuan Liu via B4 Relay
  Cc: Neil Armstrong, Michael Turquette, Stephen Boyd, Kevin Hilman,
	Martin Blumenstingl, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-kernel

Hi Jerome,


On 10/22/2025 8:01 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Wed 22 Oct 2025 at 14:58, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com@kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu@amlogic.com>
>>
>> Amlogic PLL locking procedure shall follow this timing sequence:
>> 1 Assert reset signal: Ensures PLL circuits enter known initial state.
>> 2 Deassert lock-detect signal: Avoid lock signal false triggering.
>> 3 Assert enable signal: Powers up PLL supply.
>> 4 udelay(20): Wait for Bandgap and LDO to power up and stabilize.
>> 5 Enable self-adaptation current module (Optional).
>> 6 Deassert reset signal: Releases PLL to begin normal operation.
>> 7 udelay(20): Wait for PLL loop stabilization.
>> 8 Assert lock-detect signal: lock detection circuit starts to work.
>> 9 Monitor lock status signal: Wait for PLL lock completion.
>> 10 If the PLL fails to lock, it should be disabled, This makes the
>> logic more complete, and also helps save unnecessary power consumption
>> when the PLL is malfunctioning.
> 
> Is this applicable to all supported SoC ? from meson8 to s4 ?

Yes.

> 
> What did you test ?

We have tested this on the G12A and later SoCs without any issues.
Internally, we have adopted this configuration sequence in our branch
and verified it on a large number of SoCs.

We haven't maintained the meson series for a while, so it hasn't been
included in our recent validation. I also don't have any meson boards
on hand. If you have one available, it would be appreciated if you
could help verify this, Thanks.

This PLL sequence adjustment for meson SoCs adds a 20us delay after
enabling the PLL and after releasing its reset. The delay addresses
rare PLL lock failures observed under low temperatures. As a result,
it slightly increases enable time but improves stability.

> 
> 
>>
>> Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
>> ---
>>   drivers/clk/meson/clk-pll.c | 68 ++++++++++++++++++++++++++-------------------
>>   1 file changed, 40 insertions(+), 28 deletions(-)
>>
>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>> index b07e1eb19d12..26c83db487e8 100644
>> --- a/drivers/clk/meson/clk-pll.c
>> +++ b/drivers/clk/meson/clk-pll.c
>> @@ -353,6 +353,23 @@ static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
>>        return -EIO;
>>   }
>>
>> +static void meson_clk_pll_disable(struct clk_hw *hw)
>> +{
>> +     struct clk_regmap *clk = to_clk_regmap(hw);
>> +     struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
>> +
>> +     /* Put the pll is in reset */
>> +     if (MESON_PARM_APPLICABLE(&pll->rst))
>> +             meson_parm_write(clk->map, &pll->rst, 1);
>> +
>> +     /* Disable the pll */
>> +     meson_parm_write(clk->map, &pll->en, 0);
>> +
>> +     /* Disable PLL internal self-adaption current module */
>> +     if (MESON_PARM_APPLICABLE(&pll->current_en))
>> +             meson_parm_write(clk->map, &pll->current_en, 0);
>> +}
> 
> I don't get why you moved that code around and make the diff even harder
> to read

Sorry about the misaligned formatting. I moved meson_clk_pll_disable()
earlier in the code because I added handling for PLL lock failures,
which unintentionally broke the alignment.

I'll split the PLL lock failure handling into a separate patch in the
next version to make review easier.

> 
>> +
>>   static int meson_clk_pll_enable(struct clk_hw *hw)
>>   {
>>        struct clk_regmap *clk = to_clk_regmap(hw);
>> @@ -366,53 +383,48 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>>        if (MESON_PARM_APPLICABLE(&pll->rst))
>>                meson_parm_write(clk->map, &pll->rst, 1);
>>
>> +     /* Disable the PLL lock-detect module */
>> +     if (MESON_PARM_APPLICABLE(&pll->l_detect))
>> +             meson_parm_write(clk->map, &pll->l_detect, 1);
>> +
>>        /* Enable the pll */
>>        meson_parm_write(clk->map, &pll->en, 1);
>> -
>> -     /* Take the pll out reset */
>> -     if (MESON_PARM_APPLICABLE(&pll->rst))
>> -             meson_parm_write(clk->map, &pll->rst, 0);
>> +     /* Wait for Bandgap and LDO to power up and stabilize */
>> +     udelay(20);
>>
>>        /*
>>         * Compared with the previous SoCs, self-adaption current module
>>         * is newly added for A1, keep the new power-on sequence to enable the
>>         * PLL. The sequence is:
>> -      * 1. enable the pll, delay for 10us
>> +      * 1. enable the pll, ensure a minimum delay of 10μs
>>         * 2. enable the pll self-adaption current module, delay for 40us
>>         * 3. enable the lock detect module
>>         */
>>        if (MESON_PARM_APPLICABLE(&pll->current_en)) {
>> -             udelay(10);
>>                meson_parm_write(clk->map, &pll->current_en, 1);
>> -             udelay(40);
>> -     }
>> -
>> -     if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
>> -             meson_parm_write(clk->map, &pll->l_detect, 1);
>> -             meson_parm_write(clk->map, &pll->l_detect, 0);
>> +             udelay(20);
>>        }
>>
>> -     if (meson_clk_pll_wait_lock(hw))
>> -             return -EIO;
>> +     /* Take the pll out reset */
>> +     if (MESON_PARM_APPLICABLE(&pll->rst))
>> +             meson_parm_write(clk->map, &pll->rst, 0);
>>
>> -     return 0;
>> -}
>> +     /* Wait for PLL loop stabilization */
>> +     udelay(20);
>>
>> -static void meson_clk_pll_disable(struct clk_hw *hw)
>> -{
>> -     struct clk_regmap *clk = to_clk_regmap(hw);
>> -     struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
>> +     /* Enable the lock-detect module */
>> +     if (MESON_PARM_APPLICABLE(&pll->l_detect))
>> +             meson_parm_write(clk->map, &pll->l_detect, 0);
>>
>> -     /* Put the pll is in reset */
>> -     if (MESON_PARM_APPLICABLE(&pll->rst))
>> -             meson_parm_write(clk->map, &pll->rst, 1);
>> +     if (meson_clk_pll_wait_lock(hw)) {
>> +             /* disable PLL when PLL lock failed. */
>> +             meson_clk_pll_disable(hw);
>> +             pr_warn("%s: PLL lock failed!!!\n", clk_hw_get_name(hw));
>>
>> -     /* Disable the pll */
>> -     meson_parm_write(clk->map, &pll->en, 0);
>> +             return -EIO;
>> +     }
>>
>> -     /* Disable PLL internal self-adaption current module */
>> -     if (MESON_PARM_APPLICABLE(&pll->current_en))
>> -             meson_parm_write(clk->map, &pll->current_en, 0);
>> +     return 0;
>>   }
>>
>>   static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> 
> --
> Jerome


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
  2025-10-22 14:07     ` Chuan Liu
@ 2025-10-30  8:45       ` Jerome Brunet
  0 siblings, 0 replies; 9+ messages in thread
From: Jerome Brunet @ 2025-10-30  8:45 UTC (permalink / raw)
  To: Chuan Liu
  Cc: Chuan Liu via B4 Relay, Neil Armstrong, Michael Turquette,
	Stephen Boyd, Kevin Hilman, Martin Blumenstingl, linux-amlogic,
	linux-clk, linux-arm-kernel, linux-kernel

On Wed 22 Oct 2025 at 22:07, Chuan Liu <chuan.liu@amlogic.com> wrote:

> Hi Jerome,
>
>
> On 10/22/2025 8:01 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>> On Wed 22 Oct 2025 at 14:58, Chuan Liu via B4 Relay
>> <devnull+chuan.liu.amlogic.com@kernel.org> wrote:
>> 
>>> From: Chuan Liu <chuan.liu@amlogic.com>
>>>
>>> Amlogic PLL locking procedure shall follow this timing sequence:
>>> 1 Assert reset signal: Ensures PLL circuits enter known initial state.
>>> 2 Deassert lock-detect signal: Avoid lock signal false triggering.
>>> 3 Assert enable signal: Powers up PLL supply.
>>> 4 udelay(20): Wait for Bandgap and LDO to power up and stabilize.
>>> 5 Enable self-adaptation current module (Optional).
>>> 6 Deassert reset signal: Releases PLL to begin normal operation.
>>> 7 udelay(20): Wait for PLL loop stabilization.
>>> 8 Assert lock-detect signal: lock detection circuit starts to work.
>>> 9 Monitor lock status signal: Wait for PLL lock completion.
>>> 10 If the PLL fails to lock, it should be disabled, This makes the
>>> logic more complete, and also helps save unnecessary power consumption
>>> when the PLL is malfunctioning.
>> Is this applicable to all supported SoC ? from meson8 to s4 ?
>
> Yes.
>
>> What did you test ?
>
> We have tested this on the G12A and later SoCs without any issues.
> Internally, we have adopted this configuration sequence in our branch
> and verified it on a large number of SoCs.
>
> We haven't maintained the meson series for a while, so it hasn't been
> included in our recent validation. I also don't have any meson boards
> on hand. If you have one available, it would be appreciated if you
> could help verify this, Thanks.

It's very interresting that you ask the community to test and validate
chips sold by your compagny, chip that are still sold *today* and readility
available on most market places.

I'd be happy to forward you a few links if that helps.

>
> This PLL sequence adjustment for meson SoCs adds a 20us delay after
> enabling the PLL and after releasing its reset. The delay addresses
> rare PLL lock failures observed under low temperatures. As a result,
> it slightly increases enable time but improves stability.
>
>> 
>>>
>>> Signed-off-by: Chuan Liu <chuan.liu@amlogic.com>
>>> ---
>>>   drivers/clk/meson/clk-pll.c | 68 ++++++++++++++++++++++++++-------------------
>>>   1 file changed, 40 insertions(+), 28 deletions(-)
>>>
>>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>>> index b07e1eb19d12..26c83db487e8 100644
>>> --- a/drivers/clk/meson/clk-pll.c
>>> +++ b/drivers/clk/meson/clk-pll.c
>>> @@ -353,6 +353,23 @@ static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
>>>        return -EIO;
>>>   }
>>>
>>> +static void meson_clk_pll_disable(struct clk_hw *hw)
>>> +{
>>> +     struct clk_regmap *clk = to_clk_regmap(hw);
>>> +     struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
>>> +
>>> +     /* Put the pll is in reset */
>>> +     if (MESON_PARM_APPLICABLE(&pll->rst))
>>> +             meson_parm_write(clk->map, &pll->rst, 1);
>>> +
>>> +     /* Disable the pll */
>>> +     meson_parm_write(clk->map, &pll->en, 0);
>>> +
>>> +     /* Disable PLL internal self-adaption current module */
>>> +     if (MESON_PARM_APPLICABLE(&pll->current_en))
>>> +             meson_parm_write(clk->map, &pll->current_en, 0);
>>> +}
>> I don't get why you moved that code around and make the diff even harder
>> to read
>
> Sorry about the misaligned formatting. I moved meson_clk_pll_disable()
> earlier in the code because I added handling for PLL lock failures,
> which unintentionally broke the alignment.
>
> I'll split the PLL lock failure handling into a separate patch in the
> next version to make review easier.
>
>> 
>>> +
>>>   static int meson_clk_pll_enable(struct clk_hw *hw)
>>>   {
>>>        struct clk_regmap *clk = to_clk_regmap(hw);
>>> @@ -366,53 +383,48 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>>>        if (MESON_PARM_APPLICABLE(&pll->rst))
>>>                meson_parm_write(clk->map, &pll->rst, 1);
>>>
>>> +     /* Disable the PLL lock-detect module */
>>> +     if (MESON_PARM_APPLICABLE(&pll->l_detect))
>>> +             meson_parm_write(clk->map, &pll->l_detect, 1);
>>> +
>>>        /* Enable the pll */
>>>        meson_parm_write(clk->map, &pll->en, 1);
>>> -
>>> -     /* Take the pll out reset */
>>> -     if (MESON_PARM_APPLICABLE(&pll->rst))
>>> -             meson_parm_write(clk->map, &pll->rst, 0);
>>> +     /* Wait for Bandgap and LDO to power up and stabilize */
>>> +     udelay(20);
>>>
>>>        /*
>>>         * Compared with the previous SoCs, self-adaption current module
>>>         * is newly added for A1, keep the new power-on sequence to enable the
>>>         * PLL. The sequence is:
>>> -      * 1. enable the pll, delay for 10us
>>> +      * 1. enable the pll, ensure a minimum delay of 10μs
>>>         * 2. enable the pll self-adaption current module, delay for 40us
>>>         * 3. enable the lock detect module
>>>         */
>>>        if (MESON_PARM_APPLICABLE(&pll->current_en)) {
>>> -             udelay(10);
>>>                meson_parm_write(clk->map, &pll->current_en, 1);
>>> -             udelay(40);
>>> -     }
>>> -
>>> -     if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
>>> -             meson_parm_write(clk->map, &pll->l_detect, 1);
>>> -             meson_parm_write(clk->map, &pll->l_detect, 0);
>>> +             udelay(20);
>>>        }
>>>
>>> -     if (meson_clk_pll_wait_lock(hw))
>>> -             return -EIO;
>>> +     /* Take the pll out reset */
>>> +     if (MESON_PARM_APPLICABLE(&pll->rst))
>>> +             meson_parm_write(clk->map, &pll->rst, 0);
>>>
>>> -     return 0;
>>> -}
>>> +     /* Wait for PLL loop stabilization */
>>> +     udelay(20);
>>>
>>> -static void meson_clk_pll_disable(struct clk_hw *hw)
>>> -{
>>> -     struct clk_regmap *clk = to_clk_regmap(hw);
>>> -     struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
>>> +     /* Enable the lock-detect module */
>>> +     if (MESON_PARM_APPLICABLE(&pll->l_detect))
>>> +             meson_parm_write(clk->map, &pll->l_detect, 0);
>>>
>>> -     /* Put the pll is in reset */
>>> -     if (MESON_PARM_APPLICABLE(&pll->rst))
>>> -             meson_parm_write(clk->map, &pll->rst, 1);
>>> +     if (meson_clk_pll_wait_lock(hw)) {
>>> +             /* disable PLL when PLL lock failed. */
>>> +             meson_clk_pll_disable(hw);
>>> +             pr_warn("%s: PLL lock failed!!!\n", clk_hw_get_name(hw));
>>>
>>> -     /* Disable the pll */
>>> -     meson_parm_write(clk->map, &pll->en, 0);
>>> +             return -EIO;
>>> +     }
>>>
>>> -     /* Disable PLL internal self-adaption current module */
>>> -     if (MESON_PARM_APPLICABLE(&pll->current_en))
>>> -             meson_parm_write(clk->map, &pll->current_en, 0);
>>> +     return 0;
>>>   }
>>>
>>>   static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>> --
>> Jerome

-- 
Jerome

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-10-30  8:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-22  6:58 [PATCH 0/3] clk: amlogic: optimize the PLL driver Chuan Liu via B4 Relay
2025-10-22  6:58 ` [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting Chuan Liu via B4 Relay
2025-10-22 11:57   ` Jerome Brunet
2025-10-22 13:50     ` Chuan Liu
2025-10-22  6:58 ` [PATCH 2/3] clk: amlogic: Optimize PLL enable timing Chuan Liu via B4 Relay
2025-10-22 12:01   ` Jerome Brunet
2025-10-22 14:07     ` Chuan Liu
2025-10-30  8:45       ` Jerome Brunet
2025-10-22  6:58 ` [PATCH 3/3] clk: amlogic: Correct l_detect bit control Chuan Liu via B4 Relay

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox