* [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
* 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 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
* [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
* 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 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
* [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
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