All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
@ 2026-07-22  0:56 Enzo Adriano
  2026-07-22  1:09 ` sashiko-bot
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Enzo Adriano @ 2026-07-22  0:56 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd
  Cc: Brian Masney, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Andre Przywara, Junhui Liu, linux-clk, linux-arm-kernel,
	linux-sunxi, linux-kernel

Some sunxi-ng MP clocks have an M divider but no P divider. The A523
MBUS, IOMMU and DRAM clocks use this layout and also require the update
bit when changing their rate.

ccu_mp_set_rate() unconditionally builds and applies a mask for the P
field. With a zero-width P field this produces an invalid GENMASK()
range and can clear bits outside a P divider, including the clock gate.

The callback also ignores CCU_FEATURE_UPDATE_BIT, so hardware that
requires the update bit may not latch the new divider value.

Only update the P field when it exists, and set CCU_SUNXI_UPDATE_BIT for
MP clocks carrying the feature. This matches the existing sunxi-ng div,
mux and gate helper behavior.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/r/20260712081341.9D1431F00A3D@smtp.kernel.org
Fixes: 6702d17f54a8 ("clk: sunxi-ng: a523: add video mod clocks")
Assisted-by: Codex:gpt-5
Signed-off-by: Enzo Adriano <enzo.adriano.code@gmail.com>
---
Based on clk-next 8cdeaa50eae8 (Linux 7.2-rc2).
Tested with strict checkpatch and an arm64 W=1 build of ccu_mp.o.
No hardware runtime claim is made.

 drivers/clk/sunxi-ng/ccu_mp.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index 7cdb0eedc69b..aa6cb20447f1 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -237,12 +237,17 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	reg = readl(cmp->common.base + cmp->common.reg);
 	reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
-	reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
+	if (cmp->p.width)
+		reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
+	if (cmp->common.features & CCU_FEATURE_UPDATE_BIT)
+		reg |= CCU_SUNXI_UPDATE_BIT;
 	reg |= (m - cmp->m.offset) << cmp->m.shift;
-	if (shift)
-		reg |= ilog2(p) << cmp->p.shift;
-	else
-		reg |= (p - cmp->p.offset) << cmp->p.shift;
+	if (cmp->p.width) {
+		if (shift)
+			reg |= ilog2(p) << cmp->p.shift;
+		else
+			reg |= (p - cmp->p.offset) << cmp->p.shift;
+	}
 
 	writel(reg, cmp->common.base + cmp->common.reg);
 
-- 
2.53.0

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

* Re: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
  2026-07-22  0:56 [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers Enzo Adriano
@ 2026-07-22  1:09 ` sashiko-bot
  2026-07-22  9:24 ` Andre Przywara
  2026-07-22 13:27 ` Chen-Yu Tsai
  2 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-07-22  1:09 UTC (permalink / raw)
  To: Enzo Adriano; +Cc: linux-sunxi

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [High] The patch resolves an invalid GENMASK evaluation for 0-width P dividers but fails to apply the same check for 0-width M dividers, leaving a register corruption bug intact.
- [High] When an unreachable low clock rate is requested, `ccu_mp_find_best` fails to find a suitable divider and returns `m = 0` and `p = 0`, leading to integer underflows that severely corrupt the CCU hardware register.
--

--- Patch [1]: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers ---
commit e8027d463bc82dfb3ec7ba4b45f1688fa59d1694
Author: Enzo Adriano <enzo.adriano.code@gmail.com>

clk: sunxi-ng: ccu_mp: fix clocks without P dividers

This commit modifies the sunxi-ng MP clock driver to conditionally apply the
P divider mask only when the P field is present. It also ensures the update
bit is set if required by the hardware. This prevents invalid GENMASK
evaluations and missing hardware updates.

Closes: https://lore.kernel.org/r/20260712081341.9D1431F00A3D@smtp.kernel.org

> diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> index 7cdb0eedc69b5..aa6cb20447f19 100644
> --- a/drivers/clk/sunxi-ng/ccu_mp.c
> +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> @@ -237,12 +237,17 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
>  
>  	reg = readl(cmp->common.base + cmp->common.reg);
>  	reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);

[Severity: High]
This isn't a bug introduced by this patch, but since we are fixing the
invalid GENMASK for 0-width P dividers, should we apply the same check for
M dividers?

If an MP clock has no M divider (m.width == 0), the GENMASK will underflow
and produce an all-ones mask. The ~GENMASK operation then zeroes out the
entire hardware register, clearing critical fields like the clock gate.

> -	reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> +	if (cmp->p.width)
> +		reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> +	if (cmp->common.features & CCU_FEATURE_UPDATE_BIT)
> +		reg |= CCU_SUNXI_UPDATE_BIT;
>  	reg |= (m - cmp->m.offset) << cmp->m.shift;

[Severity: High]
This is a pre-existing issue, but can this operation corrupt the hardware
register if an extremely low rate is requested?

If a driver or user requests a rate lower than the minimum achievable rate,
ccu_mp_find_best() will skip all rates:

drivers/clk/sunxi-ng/ccu_mp.c:ccu_mp_find_best() {
    ...
	if (tmp_rate > rate)
		continue;
    ...
}

This causes it to return the initial values for m and p as 0. Back in
ccu_mp_set_rate(), an m of 0 will cause m - cmp->m.offset to underflow
(for example, 0 - 1 = 0xFFFFFFFF). This value is then left-shifted and
OR'd into the register, overwriting adjacent hardware fields with 1s.

> -	if (shift)
> -		reg |= ilog2(p) << cmp->p.shift;
> -	else
> -		reg |= (p - cmp->p.offset) << cmp->p.shift;
> +	if (cmp->p.width) {
> +		if (shift)
> +			reg |= ilog2(p) << cmp->p.shift;
> +		else
> +			reg |= (p - cmp->p.offset) << cmp->p.shift;
> +	}
>  
>  	writel(reg, cmp->common.base + cmp->common.reg);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260722005643.1208942-1-enzo.adriano.code@gmail.com?part=1

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

* Re: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
  2026-07-22  0:56 [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers Enzo Adriano
  2026-07-22  1:09 ` sashiko-bot
@ 2026-07-22  9:24 ` Andre Przywara
  2026-07-22 13:27 ` Chen-Yu Tsai
  2 siblings, 0 replies; 10+ messages in thread
From: Andre Przywara @ 2026-07-22  9:24 UTC (permalink / raw)
  To: Enzo Adriano, Michael Turquette, Stephen Boyd
  Cc: Brian Masney, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Junhui Liu, linux-clk, linux-arm-kernel, linux-sunxi,
	linux-kernel

Hi,

On 7/22/26 02:56, Enzo Adriano wrote:
> Some sunxi-ng MP clocks have an M divider but no P divider. The A523
> MBUS, IOMMU and DRAM clocks use this layout and also require the update
> bit when changing their rate.
> 
> ccu_mp_set_rate() unconditionally builds and applies a mask for the P
> field. With a zero-width P field this produces an invalid GENMASK()
> range and can clear bits outside a P divider, including the clock gate.
> 
> The callback also ignores CCU_FEATURE_UPDATE_BIT, so hardware that
> requires the update bit may not latch the new divider value.
> 
> Only update the P field when it exists, and set CCU_SUNXI_UPDATE_BIT for
> MP clocks carrying the feature. This matches the existing sunxi-ng div,
> mux and gate helper behavior.
> 
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/r/20260712081341.9D1431F00A3D@smtp.kernel.org
> Fixes: 6702d17f54a8 ("clk: sunxi-ng: a523: add video mod clocks")
> Assisted-by: Codex:gpt-5
> Signed-off-by: Enzo Adriano <enzo.adriano.code@gmail.com>
> ---
> Based on clk-next 8cdeaa50eae8 (Linux 7.2-rc2).
> Tested with strict checkpatch and an arm64 W=1 build of ccu_mp.o.
> No hardware runtime claim is made.

Does that mean it's not tested on hardware?

> 
>   drivers/clk/sunxi-ng/ccu_mp.c | 15 ++++++++++-----
>   1 file changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> index 7cdb0eedc69b..aa6cb20447f1 100644
> --- a/drivers/clk/sunxi-ng/ccu_mp.c
> +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> @@ -237,12 +237,17 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
>   
>   	reg = readl(cmp->common.base + cmp->common.reg);
>   	reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
> -	reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> +	if (cmp->p.width)
> +		reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> +	if (cmp->common.features & CCU_FEATURE_UPDATE_BIT)
> +		reg |= CCU_SUNXI_UPDATE_BIT;
>   	reg |= (m - cmp->m.offset) << cmp->m.shift;
> -	if (shift)
> -		reg |= ilog2(p) << cmp->p.shift;
> -	else
> -		reg |= (p - cmp->p.offset) << cmp->p.shift;
> +	if (cmp->p.width) {

Can you merge that into the upper conditional branch? So that it's just 
one if statement?
And then apply the same treatment to the M divider, which is set to 0 by 
some A523 clocks (hstimer and r-timer).

Cheers,
Andre

> +		if (shift)
> +			reg |= ilog2(p) << cmp->p.shift;
> +		else
> +			reg |= (p - cmp->p.offset) << cmp->p.shift;
> +	}
>   
>   	writel(reg, cmp->common.base + cmp->common.reg);
>   


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

* Re: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
  2026-07-22  0:56 [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers Enzo Adriano
  2026-07-22  1:09 ` sashiko-bot
  2026-07-22  9:24 ` Andre Przywara
@ 2026-07-22 13:27 ` Chen-Yu Tsai
  2026-07-22 17:37   ` Enzo Adriano
  2 siblings, 1 reply; 10+ messages in thread
From: Chen-Yu Tsai @ 2026-07-22 13:27 UTC (permalink / raw)
  To: Enzo Adriano, Andre Przywara
  Cc: Michael Turquette, Stephen Boyd, Brian Masney, Jernej Skrabec,
	Samuel Holland, Junhui Liu, linux-clk, linux-arm-kernel,
	linux-sunxi, linux-kernel

On Wed, Jul 22, 2026 at 8:56 AM Enzo Adriano
<enzo.adriano.code@gmail.com> wrote:
>
> Some sunxi-ng MP clocks have an M divider but no P divider. The A523
> MBUS, IOMMU and DRAM clocks use this layout and also require the update
> bit when changing their rate.
>
> ccu_mp_set_rate() unconditionally builds and applies a mask for the P
> field. With a zero-width P field this produces an invalid GENMASK()
> range and can clear bits outside a P divider, including the clock gate.
>
> The callback also ignores CCU_FEATURE_UPDATE_BIT, so hardware that
> requires the update bit may not latch the new divider value.
>
> Only update the P field when it exists, and set CCU_SUNXI_UPDATE_BIT for
> MP clocks carrying the feature. This matches the existing sunxi-ng div,
> mux and gate helper behavior.

No. If the clock only has one divider, then it should use the single divider
clk class. That one also supports CCU_FEATURE_UPDATE_BIT.

ChenYu

> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/r/20260712081341.9D1431F00A3D@smtp.kernel.org
> Fixes: 6702d17f54a8 ("clk: sunxi-ng: a523: add video mod clocks")
> Assisted-by: Codex:gpt-5
> Signed-off-by: Enzo Adriano <enzo.adriano.code@gmail.com>
> ---
> Based on clk-next 8cdeaa50eae8 (Linux 7.2-rc2).
> Tested with strict checkpatch and an arm64 W=1 build of ccu_mp.o.
> No hardware runtime claim is made.
>
>  drivers/clk/sunxi-ng/ccu_mp.c | 15 ++++++++++-----
>  1 file changed, 10 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
> index 7cdb0eedc69b..aa6cb20447f1 100644
> --- a/drivers/clk/sunxi-ng/ccu_mp.c
> +++ b/drivers/clk/sunxi-ng/ccu_mp.c
> @@ -237,12 +237,17 @@ static int ccu_mp_set_rate(struct clk_hw *hw, unsigned long rate,
>
>         reg = readl(cmp->common.base + cmp->common.reg);
>         reg &= ~GENMASK(cmp->m.width + cmp->m.shift - 1, cmp->m.shift);
> -       reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> +       if (cmp->p.width)
> +               reg &= ~GENMASK(cmp->p.width + cmp->p.shift - 1, cmp->p.shift);
> +       if (cmp->common.features & CCU_FEATURE_UPDATE_BIT)
> +               reg |= CCU_SUNXI_UPDATE_BIT;
>         reg |= (m - cmp->m.offset) << cmp->m.shift;
> -       if (shift)
> -               reg |= ilog2(p) << cmp->p.shift;
> -       else
> -               reg |= (p - cmp->p.offset) << cmp->p.shift;
> +       if (cmp->p.width) {
> +               if (shift)
> +                       reg |= ilog2(p) << cmp->p.shift;
> +               else
> +                       reg |= (p - cmp->p.offset) << cmp->p.shift;
> +       }
>
>         writel(reg, cmp->common.base + cmp->common.reg);
>
> --
> 2.53.0

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

* Re: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
  2026-07-22 13:27 ` Chen-Yu Tsai
@ 2026-07-22 17:37   ` Enzo Adriano
  2026-07-22 17:43     ` Chen-Yu Tsai
  2026-07-22 22:48     ` Andre Przywara
  0 siblings, 2 replies; 10+ messages in thread
From: Enzo Adriano @ 2026-07-22 17:37 UTC (permalink / raw)
  To: Chen-Yu Tsai, Andre Przywara
  Cc: Michael Turquette, Stephen Boyd, Brian Masney, Jernej Skrabec,
	Samuel Holland, Junhui Liu, linux-clk, linux-arm-kernel,
	linux-sunxi, linux-kernel

Hi Andre, Chen-Yu,

Correct, this was not tested on hardware; it was build-tested only.

Thanks for the review. Chen-Yu's point is right: these one-divider clocks
should use the single-divider clock class, which already supports
CCU_FEATURE_UPDATE_BIT. I'll drop this generic ccu_mp patch; there will be
no v2.

This analysis was done with AI assistance and each finding was checked
against the cited sources.

Regards,
Enzo

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

* Re: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
  2026-07-22 17:37   ` Enzo Adriano
@ 2026-07-22 17:43     ` Chen-Yu Tsai
  2026-07-22 22:48     ` Andre Przywara
  1 sibling, 0 replies; 10+ messages in thread
From: Chen-Yu Tsai @ 2026-07-22 17:43 UTC (permalink / raw)
  To: Enzo Adriano
  Cc: Andre Przywara, Michael Turquette, Stephen Boyd, Brian Masney,
	Jernej Skrabec, Samuel Holland, Junhui Liu, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel

On Thu, Jul 23, 2026 at 1:37 AM Enzo Adriano
<enzo.adriano.code@gmail.com> wrote:
>
> Hi Andre, Chen-Yu,
>
> Correct, this was not tested on hardware; it was build-tested only.

For future patches, if you only build-tested it (which is a hard requirement),
please mark the patches with "RFT" (so the subject prefix is "[PATCH RFT]")
and note in the footer that it needs to be tested on actual hardware.


ChenYu

> Thanks for the review. Chen-Yu's point is right: these one-divider clocks
> should use the single-divider clock class, which already supports
> CCU_FEATURE_UPDATE_BIT. I'll drop this generic ccu_mp patch; there will be
> no v2.
>
> This analysis was done with AI assistance and each finding was checked
> against the cited sources.
>
> Regards,
> Enzo

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

* Re: [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers
  2026-07-22 17:37   ` Enzo Adriano
  2026-07-22 17:43     ` Chen-Yu Tsai
@ 2026-07-22 22:48     ` Andre Przywara
  2026-08-12 20:15       ` [PATCH RFT 0/2] clk: sunxi-ng: fix A523/T527 single-divider clocks Enzo Adriano
  1 sibling, 1 reply; 10+ messages in thread
From: Andre Przywara @ 2026-07-22 22:48 UTC (permalink / raw)
  To: Enzo Adriano
  Cc: Chen-Yu Tsai, Michael Turquette, Stephen Boyd, Brian Masney,
	Jernej Skrabec, Samuel Holland, Junhui Liu, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel

On Wed, 22 Jul 2026 13:37:14 -0400
Enzo Adriano <enzo.adriano.code@gmail.com> wrote:

> Hi Andre, Chen-Yu,
> 
> Correct, this was not tested on hardware; it was build-tested only.
> 
> Thanks for the review. Chen-Yu's point is right: these one-divider clocks
> should use the single-divider clock class, which already supports
> CCU_FEATURE_UPDATE_BIT. I'll drop this generic ccu_mp patch; there will be
> no v2.

But there clocks that use a _MP_ initialiser with width = 0, both for M
and P. Which leads to GENMASK(-1, 0), as you mentioned. So we need
patches to fix: to convert the HSTIMER clocks to use
SUNXI_CCU_P_DATA_WITH_MUX_GATE, which is a pure div clock that doesn't
have that problem. Same with the r-timer clocks in ccu-sun55i-a523-r.c.
And there is mbus, iommu and dram that have no P.

Are you going to make and post patches for these?

Cheers,
Andre

> 
> This analysis was done with AI assistance and each finding was checked
> against the cited sources.
> 
> Regards,
> Enzo
> 



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

* [PATCH RFT 0/2] clk: sunxi-ng: fix A523/T527 single-divider clocks
  2026-07-22 22:48     ` Andre Przywara
@ 2026-08-12 20:15       ` Enzo Adriano
  2026-08-12 20:15         ` [PATCH RFT 1/2] clk: sunxi-ng: add feature-aware M divider helper Enzo Adriano
  2026-08-12 20:15         ` [PATCH RFT 2/2] clk: sunxi-ng: a523: use single-divider clock helpers Enzo Adriano
  0 siblings, 2 replies; 10+ messages in thread
From: Enzo Adriano @ 2026-08-12 20:15 UTC (permalink / raw)
  To: Andre Przywara, Michael Turquette, Stephen Boyd, Chen-Yu Tsai
  Cc: Brian Masney, Jernej Skrabec, Samuel Holland, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel, Enzo Adriano

Andre asked whether we would post the A523/T527 conversions for the clocks
whose ccu_mp descriptors declare one divider field with width zero. This
series implements those conversions.

Patch 1 adds a feature-aware M-divider helper so M-only clocks can retain
the CCU update-bit handling. Patch 2 converts MBUS, IOMMU, and DRAM to that
M-only class and converts HSTIMER0-5 and R-TIMER0-2 to the existing P-only
class.

I do not have matching A523/T527 hardware, so this is deliberately an RFT
series and carries no Tested-by claim. The series has passed semantic and
register-bit preservation models, KUnit tests, strict checkpatch, sparse,
GCC and Clang builds, full arm64 Image/modules/DTB builds, reproducibility
checks, and hostile review. It also applies and builds cleanly together
with the current A523/T527 GPU clock-model v2 series.

not tested on A523/T527 hardware; testing on actual hardware is needed.

In particular, testing of clock rate changes and affected users of MBUS,
IOMMU, DRAM, HSTIMER0-5, and R-TIMER0-2 would be appreciated.

---

Enzo Adriano (2):
  clk: sunxi-ng: add feature-aware M divider helper
  clk: sunxi-ng: a523: use single-divider clock helpers

 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c |  37 +++---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c   | 136 +++++++++++------------
 drivers/clk/sunxi-ng/ccu_div.h           |  18 ++-
 3 files changed, 96 insertions(+), 95 deletions(-)


base-commit: 8cdeaa50eae8dad34885515f62559ee83e7e8dda
-- 
2.53.0

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

* [PATCH RFT 1/2] clk: sunxi-ng: add feature-aware M divider helper
  2026-08-12 20:15       ` [PATCH RFT 0/2] clk: sunxi-ng: fix A523/T527 single-divider clocks Enzo Adriano
@ 2026-08-12 20:15         ` Enzo Adriano
  2026-08-12 20:15         ` [PATCH RFT 2/2] clk: sunxi-ng: a523: use single-divider clock helpers Enzo Adriano
  1 sibling, 0 replies; 10+ messages in thread
From: Enzo Adriano @ 2026-08-12 20:15 UTC (permalink / raw)
  To: Andre Przywara, Michael Turquette, Stephen Boyd, Chen-Yu Tsai
  Cc: Brian Masney, Jernej Skrabec, Samuel Holland, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel, Enzo Adriano

Allow single M-divider clocks to retain common CCU features such as the
hardware update bit without using the two-divider MP class.

Assisted-by: Codex:gpt-5
Signed-off-by: Enzo Adriano <enzo.adriano.code@gmail.com>
---
not tested on A523/T527 hardware; testing on actual hardware is needed.

 drivers/clk/sunxi-ng/ccu_div.h | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index be00b3277e976f..fd222ef0b8af90 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -212,10 +212,10 @@ struct ccu_div {
 	SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg,		\
 			      _mshift, _mwidth, 0, _flags)
 
-#define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
-				       _mshift, _mwidth,		\
-				       _muxshift, _muxwidth,		\
-				       _gate, _flags)			\
+#define SUNXI_CCU_M_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents, _reg, \
+					    _mshift, _mwidth,		\
+					    _muxshift, _muxwidth,	\
+					    _gate, _flags, _features)	\
 	struct ccu_div _struct = {					\
 		.enable	= _gate,					\
 		.div	= _SUNXI_CCU_DIV(_mshift, _mwidth),		\
@@ -226,9 +226,19 @@ struct ccu_div {
 								   _parents, \
 								   &ccu_div_ops, \
 								   _flags), \
+			.features	= _features,			\
 		},							\
 	}
 
+#define SUNXI_CCU_M_DATA_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
+				       _mshift, _mwidth,		\
+				       _muxshift, _muxwidth,		\
+				       _gate, _flags)			\
+	SUNXI_CCU_M_DATA_WITH_MUX_GATE_FEAT(_struct, _name, _parents,	\
+					    _reg, _mshift, _mwidth,	\
+					    _muxshift, _muxwidth,	\
+					    _gate, _flags, 0)
+
 #define SUNXI_CCU_M_DATA_WITH_MUX(_struct, _name, _parents, _reg,	\
 				  _mshift, _mwidth,			\
 				  _muxshift, _muxwidth,			\
-- 
2.53.0

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

* [PATCH RFT 2/2] clk: sunxi-ng: a523: use single-divider clock helpers
  2026-08-12 20:15       ` [PATCH RFT 0/2] clk: sunxi-ng: fix A523/T527 single-divider clocks Enzo Adriano
  2026-08-12 20:15         ` [PATCH RFT 1/2] clk: sunxi-ng: add feature-aware M divider helper Enzo Adriano
@ 2026-08-12 20:15         ` Enzo Adriano
  1 sibling, 0 replies; 10+ messages in thread
From: Enzo Adriano @ 2026-08-12 20:15 UTC (permalink / raw)
  To: Andre Przywara, Michael Turquette, Stephen Boyd, Chen-Yu Tsai
  Cc: Brian Masney, Jernej Skrabec, Samuel Holland, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel, Enzo Adriano,
	Sashiko

The A523 MBUS, IOMMU, and DRAM clocks have an M divider but no P
divider, while HSTIMER0-5 and R-TIMER0-2 have a P divider but no M
divider. They currently use the two-divider ccu_mp class by declaring
the missing field with width zero.

ccu_mp_set_rate() unconditionally masks both divider fields, so a zero
width forms an invalid GENMASK() range and can clear unrelated register
bits. The M-only clocks also require the hardware update bit, which
ccu_mp operations do not handle.

Use the single-divider M helper for MBUS, IOMMU, and DRAM, and the
power-of-two P helper for the timer clocks. Preserve the parents,
registers, real divider fields, muxes, gates, clock flags, and
update-bit features.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/r/20260722010926.0A8B01F000E9@smtp.kernel.org
Link: https://lore.kernel.org/r/20260712081341.9D1431F00A3D@smtp.kernel.org
Suggested-by: Chen-Yu Tsai <wens@kernel.org>
Fixes: 6702d17f54a8 ("clk: sunxi-ng: a523: add video mod clocks")
Fixes: 74b0443a0d0a ("clk: sunxi-ng: a523: add system mod clocks")
Fixes: 8cea339cfb81 ("clk: sunxi-ng: add support for the A523/T527 PRCM CCU")
Link: https://lore.kernel.org/r/CAGb2v67GDBTq8vdxNxBfNVSe=oStcgaJzm0ig2WAEXNQSkVa1g@mail.gmail.com
Link: https://lore.kernel.org/r/20260723004856.55158e84@ryzen.lan
Assisted-by: Codex:gpt-5
Signed-off-by: Enzo Adriano <enzo.adriano.code@gmail.com>
---
not tested on A523/T527 hardware; testing on actual hardware is needed.

 drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c |  37 +++---
 drivers/clk/sunxi-ng/ccu-sun55i-a523.c   | 136 +++++++++++------------
 2 files changed, 82 insertions(+), 91 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
index db0e36d8838e74..349230e28c1c3a 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523-r.c
@@ -43,27 +43,24 @@ static SUNXI_CCU_M_DATA_WITH_MUX(r_apb1_clk, "r-apb1",
 				 24, 3,	/* mux */
 				 0);
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
-				       r_ahb_apb_parents, 0x100,
-				       0, 0,	/* no M */
-				       1, 3,	/* P */
-				       4, 3,	/* mux */
-				       BIT(0),
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer0, "r-timer0",
+				      r_ahb_apb_parents, 0x100,
+				      1, 3,	/* P */
+				      4, 3,	/* mux */
+				      BIT(0),
+				      0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
+				      r_ahb_apb_parents, 0x104,
+				      1, 3,	/* P */
+				      4, 3,	/* mux */
+				      BIT(0),
+				      0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
+				      r_ahb_apb_parents, 0x108,
+				      1, 3,	/* P */
+				      4, 3,	/* mux */
+				      BIT(0),
 				      0);
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer1, "r-timer1",
-				       r_ahb_apb_parents, 0x104,
-				       0, 0,	/* no M */
-				       1, 3,	/* P */
-				       4, 3,	/* mux */
-				       BIT(0),
-				       0);
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(r_cpu_timer2, "r-timer2",
-				       r_ahb_apb_parents, 0x108,
-				       0, 0,	/* no M */
-				       1, 3,	/* P */
-				       4, 3,	/* mux */
-				       BIT(0),
-				       0);
 
 static SUNXI_CCU_GATE_HW(bus_r_timer_clk, "bus-r-timer", &r_ahb_clk.common.hw,
 			 0x11c, BIT(0), 0);
diff --git a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
index 20dad06b37ca31..5c632e475aaa04 100644
--- a/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
+++ b/drivers/clk/sunxi-ng/ccu-sun55i-a523.c
@@ -380,14 +380,14 @@ static const struct clk_parent_data mbus_parents[] = {
 	{ .hw = &pll_periph1_150M_clk.hw },
 	{ .fw_name = "hosc" },
 };
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
-					    0x540,
-					    0, 5,		/* M */
-					    0, 0,		/* no P */
-					    24, 3,	/* mux */
-					    BIT(31),	/* gate */
-					    CLK_IS_CRITICAL,
-					    CCU_FEATURE_UPDATE_BIT);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE_FEAT(mbus_clk, "mbus", mbus_parents,
+					   0x540,
+					   0, 5,	/* M */
+					   24, 3,	/* mux */
+					   BIT(31),	/* gate */
+					   CLK_IS_CRITICAL,
+					   CCU_FEATURE_UPDATE_BIT);
 
 static const struct clk_hw *mbus_hws[] = { &mbus_clk.common.hw };
 
@@ -513,58 +513,53 @@ static const struct clk_parent_data hstimer_parents[] = {
 	{ .fw_name = "losc" },
 	{ .hw = &pll_periph0_200M_clk.hw },
 };
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
-				       hstimer_parents, 0x730,
-				       0, 0,	/* M */
-				       0, 3,	/* P */
-				       24, 3,	/* mux */
-				       BIT(31),	/* gate */
-				       0);
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
-				       hstimer_parents,
-				       0x734,
-				       0, 0,	/* M */
-				       0, 3,	/* P */
-				       24, 3,	/* mux */
-				       BIT(31),	/* gate */
-				       0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(hstimer0_clk, "hstimer0",
+				      hstimer_parents, 0x730,
+				      0, 3,	/* P */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
-				       hstimer_parents,
-				       0x738,
-				       0, 0,	/* M */
-				       0, 3,	/* P */
-				       24, 3,	/* mux */
-				       BIT(31),	/* gate */
-				       0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(hstimer1_clk, "hstimer1",
+				      hstimer_parents,
+				      0x734,
+				      0, 3,	/* P */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
-				       hstimer_parents,
-				       0x73c,
-				       0, 0,	/* M */
-				       0, 3,	/* P */
-				       24, 3,	/* mux */
-				       BIT(31),	/* gate */
-				       0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(hstimer2_clk, "hstimer2",
+				      hstimer_parents,
+				      0x738,
+				      0, 3,	/* P */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
-				       hstimer_parents,
-				       0x740,
-				       0, 0,	/* M */
-				       0, 3,	/* P */
-				       24, 3,	/* mux */
-				       BIT(31),	/* gate */
-				       0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(hstimer3_clk, "hstimer3",
+				      hstimer_parents,
+				      0x73c,
+				      0, 3,	/* P */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
-				       hstimer_parents,
-				       0x744,
-				       0, 0,	/* M */
-				       0, 3,	/* P */
-				       24, 3,	/* mux */
-				       BIT(31),	/* gate */
-				       0);
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(hstimer4_clk, "hstimer4",
+				      hstimer_parents,
+				      0x740,
+				      0, 3,	/* P */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
+
+static SUNXI_CCU_P_DATA_WITH_MUX_GATE(hstimer5_clk, "hstimer5",
+				      hstimer_parents,
+				      0x744,
+				      0, 3,	/* P */
+				      24, 3,	/* mux */
+				      BIT(31),	/* gate */
+				      0);
 
 static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", ahb_hws, 0x74c,
 			  BIT(0), 0);
@@ -584,14 +579,13 @@ static const struct clk_parent_data iommu_parents[] = {
 	{ .fw_name = "hosc" },
 };
 
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
-					    0x7b0,
-					    0, 5,	/* M */
-					    0, 0,	/* no P */
-					    24, 3,	/* mux */
-					    BIT(31),	/* gate */
-					    CLK_SET_RATE_PARENT,
-					    CCU_FEATURE_UPDATE_BIT);
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE_FEAT(iommu_clk, "iommu", iommu_parents,
+					   0x7b0,
+					   0, 5,	/* M */
+					   24, 3,	/* mux */
+					   BIT(31),	/* gate */
+					   CLK_SET_RATE_PARENT,
+					   CCU_FEATURE_UPDATE_BIT);
 
 static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, 0x7bc,
 			  BIT(0), 0);
@@ -603,14 +597,14 @@ static const struct clk_parent_data dram_parents[] = {
 	{ .hw = &pll_periph0_400M_clk.hw },
 	{ .hw = &pll_periph0_150M_clk.hw },
 };
-static SUNXI_CCU_MP_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
-					    0x800,
-					    0, 5,	/* M */
-					    0, 0,	/* no P */
-					    24, 3,	/* mux */
-					    BIT(31),	/* gate */
-					    CLK_IS_CRITICAL,
-					    CCU_FEATURE_UPDATE_BIT);
+
+static SUNXI_CCU_M_DATA_WITH_MUX_GATE_FEAT(dram_clk, "dram", dram_parents,
+					   0x800,
+					   0, 5,	/* M */
+					   24, 3,	/* mux */
+					   BIT(31),	/* gate */
+					   CLK_IS_CRITICAL,
+					   CCU_FEATURE_UPDATE_BIT);
 
 static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws,
 			  0x804, BIT(0), 0);
-- 
2.53.0


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

end of thread, other threads:[~2026-08-12 20:15 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-22  0:56 [PATCH] clk: sunxi-ng: ccu_mp: fix clocks without P dividers Enzo Adriano
2026-07-22  1:09 ` sashiko-bot
2026-07-22  9:24 ` Andre Przywara
2026-07-22 13:27 ` Chen-Yu Tsai
2026-07-22 17:37   ` Enzo Adriano
2026-07-22 17:43     ` Chen-Yu Tsai
2026-07-22 22:48     ` Andre Przywara
2026-08-12 20:15       ` [PATCH RFT 0/2] clk: sunxi-ng: fix A523/T527 single-divider clocks Enzo Adriano
2026-08-12 20:15         ` [PATCH RFT 1/2] clk: sunxi-ng: add feature-aware M divider helper Enzo Adriano
2026-08-12 20:15         ` [PATCH RFT 2/2] clk: sunxi-ng: a523: use single-divider clock helpers Enzo Adriano

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.