From jbrunet at baylibre.com  Wed Oct  1 00:45:06 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Wed, 01 Oct 2025 09:45:06 +0200
Subject: [PATCH 00/19] clk: amlogic: Add PLLs and peripheral clocks for
 A4 and A5 SoCs
In-Reply-To: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
	(Chuan Liu via's message of "Tue, 30 Sep 2025 17:37:13 +0800")
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
Message-ID: <1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>

On Tue 30 Sep 2025 at 17:37, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:

> This patch series includes changes related to the PLL and peripheral
> clocks for both the A4 and A5 SoCs.
>
> The patches for A5 were previously submitted up to V3 by Xianwei.
> https://lore.kernel.org/all/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com/
> After friendly coordination, I?ve taken over and continued the
> submission as part of this series. The dt-bindings patch retains Rob's
> original "Reviewed-by" tag, and I hope this hasn?t caused any
> additional confusion.

... and yet you restart the versioning of the series making it harder
for people to follow that

>
> Both A4 and A5 belong to the Audio series. Judging by their names, one
> might assume that A5 is an upgrade to A4, but in fact, A5 was released
> a year earlier than A4.
>
> Since there are differences in the PLLs and peripheral clocks between
> the A4 and A5 SoCs (especially the PLL), and taking into account factors
> such as memory footprint and maintainability, this series does not
> attempt to merge the two into a shared driver as was done for
> G12A/G12B/SM1.

... and we end up with 19 patches series while it could be splitted into
manageable series, for each controller of each SoC

>
> This patch series includes all related dt-bindings, driver, and dts
> changes for the PLLs and peripheral clocks. Following our past convention
> for clock-related submissions, the dts changes are placed at the end
> and submitted separately. If this ordering makes it harder for
> maintainers to review or pick patches, please feel free to point it out.
>
> Co-developed-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
> Chuan Liu (19):
>       dt-bindings: clock: Add Amlogic A4 SCMI clock controller
>       dt-bindings: clock: Add Amlogic A4 PLL clock controller
>       dt-bindings: clock: Add Amlogic A4 peripherals clock controller
>       clk: amlogic: Optimize PLL enable timing
>       clk: amlogic: Correct l_detect bit control
>       clk: amlogic: Fix out-of-range PLL frequency setting
>       clk: amlogic: Add A4 PLL clock controller driver
>       clk: amlogic: Add A4 clock peripherals controller driver
>       arm64: dts: amlogic: A4: Add scmi-clk node
>       arm64: dts: amlogic: A4: Add PLL controller node
>       arm64: dts: amlogic: A4: Add peripherals clock controller node
>       dt-bindings: clock: Add Amlogic A5 SCMI clock controller support
>       dt-bindings: clock: Add Amlogic A5 PLL clock controller
>       dt-bindings: clock: Add Amlogic A5 peripherals clock controller
>       clk: amlogic: Add A5 PLL clock controller driver
>       clk: amlogic: Add A5 clock peripherals controller driver
>       arm64: dts: amlogic: A5: Add scmi-clk node
>       arm64: dts: amlogic: A5: Add PLL controller node
>       arm64: dts: amlogic: A5: Add peripheral clock controller node
>
>  .../clock/amlogic,a4-peripherals-clkc.yaml         | 122 +++
>  .../bindings/clock/amlogic,a4-pll-clkc.yaml        |  61 ++
>  .../clock/amlogic,a5-peripherals-clkc.yaml         | 134 ++++
>  .../bindings/clock/amlogic,a5-pll-clkc.yaml        |  63 ++
>  arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  80 ++
>  arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |  87 ++
>  drivers/clk/meson/Kconfig                          |  53 ++
>  drivers/clk/meson/Makefile                         |   4 +
>  drivers/clk/meson/a1-pll.c                         |   1 +
>  drivers/clk/meson/a4-peripherals.c                 | 764 ++++++++++++++++++
>  drivers/clk/meson/a4-pll.c                         | 242 ++++++
>  drivers/clk/meson/a5-peripherals.c                 | 883 +++++++++++++++++++++
>  drivers/clk/meson/a5-pll.c                         | 476 +++++++++++
>  drivers/clk/meson/clk-pll.c                        |  76 +-
>  drivers/clk/meson/clk-pll.h                        |   2 +
>  .../clock/amlogic,a4-peripherals-clkc.h            | 129 +++
>  include/dt-bindings/clock/amlogic,a4-pll-clkc.h    |  15 +
>  include/dt-bindings/clock/amlogic,a4-scmi-clkc.h   |  42 +
>  .../clock/amlogic,a5-peripherals-clkc.h            | 132 +++
>  include/dt-bindings/clock/amlogic,a5-pll-clkc.h    |  24 +
>  include/dt-bindings/clock/amlogic,a5-scmi-clkc.h   |  44 +
>  21 files changed, 3406 insertions(+), 28 deletions(-)
> ---
> base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
> change-id: 20250928-a4_a5_add_clock_driver-2b7c9d695633
>
> Best regards,

-- 
Jerome


From martin.blumenstingl at googlemail.com  Sat Oct  4 12:52:34 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 4 Oct 2025 21:52:34 +0200
Subject: [PATCH 1/2] soc: amlogic: canvas: fix device leak on lookup
In-Reply-To: <20250926142454.5929-2-johan@kernel.org>
References: <20250926142454.5929-1-johan@kernel.org> <20250926142454.5929-2-johan@kernel.org>
Message-ID: <CAFBinCBT+8aFH68gKja7PS6BtPUBcEfW4KRv8GFyADiK_QB7dw@mail.gmail.com>

On Fri, Sep 26, 2025 at 4:25?PM Johan Hovold <johan at kernel.org> wrote:
>
> Make sure to drop the reference taken to the canvas platform device when
> looking up its driver data.
>
> Note that holding a reference to a device does not prevent its driver
> data from going away so there is no point in keeping the reference.
>
> Also note that commit 28f851e6afa8 ("soc: amlogic: canvas: add missing
> put_device() call in meson_canvas_get()") fixed the leak in a lookup
> error path, but the reference is still leaking on success.
>
> Fixes: d4983983d987 ("soc: amlogic: add meson-canvas driver")
> Cc: stable at vger.kernel.org      # 4.20: 28f851e6afa8
> Cc: Yu Kuai <yukuai3 at huawei.com>
> Signed-off-by: Johan Hovold <johan at kernel.org>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

I haven't used the scope-based resource management myself as pointed
out by Markus.
That said, as far as I understand it's a feature in newer kernels and
this patch may be backported until 5.4 (oldest -stable kernel still
supported).
So let's go with this simple approach from Johan - we can still
improve this (without having to worry about backports).


Best regards,
Martin


From martin.blumenstingl at googlemail.com  Sat Oct  4 12:53:12 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 4 Oct 2025 21:53:12 +0200
Subject: [PATCH 2/2] soc: amlogic: canvas: simplify lookup error handling
In-Reply-To: <20250926142454.5929-3-johan@kernel.org>
References: <20250926142454.5929-1-johan@kernel.org> <20250926142454.5929-3-johan@kernel.org>
Message-ID: <CAFBinCAbHR3g5QGdjDjJisdC0y4gPJJA2it9-qt016T4BigGzQ@mail.gmail.com>

On Fri, Sep 26, 2025 at 4:25?PM Johan Hovold <johan at kernel.org> wrote:
>
> Simplify the canvas lookup error handling by dropping the OF node
> reference sooner.
>
> Signed-off-by: Johan Hovold <johan at kernel.org>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>


From martin.blumenstingl at googlemail.com  Sat Oct  4 12:58:32 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 4 Oct 2025 21:58:32 +0200
Subject: [PATCH 2/2] arm64: dts: meson: add initial device-tree for Tanix
 TX9 Pro
In-Reply-To: <6B97C24A-A1C0-46F9-BC74-3E7D2119B6D6@gmail.com>
References: <20250927125006.824293-1-christianshewitt@gmail.com>
 <20250927125006.824293-2-christianshewitt@gmail.com> <CAFBinCDQc=2xrKbGunSKJjLhGd0bCGN+3oYd_bg0ySs+WHxZjA@mail.gmail.com>
 <6B97C24A-A1C0-46F9-BC74-3E7D2119B6D6@gmail.com>
Message-ID: <CAFBinCBrG0xZ6sWwZYtB2k_giZoOKjB_AmtbidVtyhib=UzDfg@mail.gmail.com>

On Mon, Sep 29, 2025 at 1:43?AM Christian Hewitt
<christianshewitt at gmail.com> wrote:
>
> > On 29 Sep 2025, at 1:12?am, Martin Blumenstingl <martin.blumenstingl at googlemail.com> wrote:
> >
> > Hi Christian,
> >
> > thank you for the patch!
> >
> > On Sat, Sep 27, 2025 at 2:50?PM Christian Hewitt
> > <christianshewitt at gmail.com> wrote:
> > [...]
> >> +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-tx9-pro.dts
> >> @@ -0,0 +1,90 @@
> >> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> >> +/*
> >> + * Copyright (c) 2016 Endless Computers, Inc.
> >> + * Author: Carlo Caione <carlo at endlessm.com>
> > Is Carlo really the author?
>
> He?s the author of the original device tree that 95%
> of the content for this one is taken from; as is the
> case for most older Amlogic hardware. The decision
> on which bits to copy and paste was all mine, but I?m
> not  sure that skill deserves too much credit :)
I just wasn't sure whether it was a left-over or on purpose.

> I can resend with my own name (or mine appended) if
> that would be preferred?
I'll ultimately leave it up to Neil. Maybe if he wants your name in
too, he can just append it when applying?


From martin.blumenstingl at googlemail.com  Sat Oct  4 13:00:02 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 4 Oct 2025 22:00:02 +0200
Subject: [PATCH 2/2] arm64: dts: meson: add initial device-tree for Tanix
 TX9 Pro
In-Reply-To: <20250927125006.824293-2-christianshewitt@gmail.com>
References: <20250927125006.824293-1-christianshewitt@gmail.com> <20250927125006.824293-2-christianshewitt@gmail.com>
Message-ID: <CAFBinCBeN-wjn-LBpgX9N_evzF1gL0nU8DPk5GSC28_s+tX+AA@mail.gmail.com>

On Sat, Sep 27, 2025 at 2:50?PM Christian Hewitt
<christianshewitt at gmail.com> wrote:
>
> Oranth Tanix TX9 Pro is based on the Amlogic Q200 reference design with
> an S912 chip and the following specs:
>
> - 3GB DDR3 RAM
> - 32GB eMMC
> - 10/100/1000 Base-T Ethernet
> - AP6356 Wireless (802.11 b/g/n/ac, BT 5.0)
> - HDMI 2.0a video
> - VFD for clock/status
> - 2x USB 2.0 ports
> - IR receiver
> - 1x Power LED (white)
> - 1x Update/Reset button (underside)
> - 1x micro SD card slot
>
> Signed-off-by: Christian Hewitt <christianshewitt at gmail.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>

> ---
> Checkpatch generates the 'phy-mode "rgmii" without comment'
> warning but this dts is using the same rgmii format as all
> other Amlogic boards, so I have omitted a comment.
So far we've been mimicking the vendor kernel (which sets up the MAC
to generate the delays and disables them on PHY level).
If we change it we should do so for all devices.


Best regards,
Martin


From martin.blumenstingl at googlemail.com  Sat Oct  4 13:00:11 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 4 Oct 2025 22:00:11 +0200
Subject: [PATCH 1/2] dt-bindings: arm: amlogic: add support for Tanix TX9 Pro
In-Reply-To: <20250927125006.824293-1-christianshewitt@gmail.com>
References: <20250927125006.824293-1-christianshewitt@gmail.com>
Message-ID: <CAFBinCD9qq0_ppwt9gbyKW3kcSr8PTX+rnVPbrM33YOABxSoGA@mail.gmail.com>

On Sat, Sep 27, 2025 at 2:50?PM Christian Hewitt
<christianshewitt at gmail.com> wrote:
>
> The Oranth Tanix TX9 Pro is an Android STB using the Amlogic S912 chip
>
> Signed-off-by: Christian Hewitt <christianshewitt at gmail.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl at googlemail.com>


From martin.blumenstingl at googlemail.com  Sat Oct  4 13:22:38 2025
From: martin.blumenstingl at googlemail.com (Martin Blumenstingl)
Date: Sat, 4 Oct 2025 22:22:38 +0200
Subject: [PATCH] drm/meson: add support for 2560x1440 resolution output
In-Reply-To: <C8A273D4-5F5F-4BD8-911A-67EC9C3FF1F4@gmail.com>
References: <20250927130239.825060-1-christianshewitt@gmail.com>
 <CAFBinCCsTqsn06A5oVXGTW6PgmSQH0bHE+8PSftyWNRAbYUTcA@mail.gmail.com> <C8A273D4-5F5F-4BD8-911A-67EC9C3FF1F4@gmail.com>
Message-ID: <CAFBinCB9hxgJt_rqdy_1bM0FjnnCt1K=Au77yxeuWox1wSvdDw@mail.gmail.com>

Hi Christian,

On Mon, Sep 29, 2025 at 1:58?AM Christian Hewitt
<christianshewitt at gmail.com> wrote:
>
> > On 29 Sep 2025, at 1:24?am, Martin Blumenstingl <martin.blumenstingl at googlemail.com> wrote:
> >
> > Hi Christian,
> >
> > On Sat, Sep 27, 2025 at 3:02?PM Christian Hewitt
> > <christianshewitt at gmail.com> wrote:
> > [...]
> >> @@ -894,6 +908,10 @@ static void meson_vclk_set(struct meson_drm *priv,
> >>                        m = 0xf7;
> >>                        frac = vic_alternate_clock ? 0x8148 : 0x10000;
> >>                        break;
> >> +               case 4830000:
> >> +                       m = 0xc9;
> >> +                       frac = 0xd560;
> >> +                       break;
> > Initially I thought this was wrong because it's only added for the
> > G12A (which is also used on G12B and SM1) code-path, leaving out the
> > GX SoCs.
> >
> > Was the 2560x1440 mode tested on a computer monitor or a TV?
> > I suspect it's the former, so I think it expected the code to take the
> > MESON_VCLK_TARGET_DMT path, which automatically calculates m and frac.
> >
> > I'll give it a try on Friday as I do have a computer monitor with that
> > resolution - so any hints for testing are welcome!
>
> The original patch is from Hardkernel sources - I?ve picked it several
> years ago and then updated values semi-recently after 1000ULL changes.
> The user who originally requested that I cherry-pick it (and tested it)
> was using an Odroid N2+ board (G12B) with a Dell monitor IIRC. It?s not
> tested by myself as I only have TV?s not monitors, so it will be good
> to have your confirmation (either way). If it?s wrong I?ll be happy to
> drop it - I?m just trying to upstream and offload some longer-running
> and allegedly good patches in the LibreELEC kernel patchset.
So I've tried it on a Le Potato (S905X SoC) board. This patch doesn't
do anything here (as expected, since it only targets the G12A and
later code-path).

Doing some more analysis, it seems that
meson_venc_hdmi_supported_mode() simply prevents using any mode with
more than 1920 pixels.
I attached a simple patch to overcome this (discarding any
meson_vclk.c changes):
$ cat /sys/class/drm/card1-HDMI-A-1/modes
2560x1440
2048x1152
1920x1200
1920x1080
...

My monitor's OSD tells me that I'm running at 2560x1440 at 60Hz.

@Neil, should we bump the limits in meson_venc.c to "4Kx2K at 60" (that's
a quote from both, S905/GXBB and S905D3/SM1 datasheets), most likely
meaning: 4096x2160?


Best regards,
Martin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: meson_venc-hdmi-support-1440p-screen.diff
Type: text/x-patch
Size: 661 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20251004/f551a94a/attachment.bin>

From christianshewitt at gmail.com  Sun Oct  5 05:36:15 2025
From: christianshewitt at gmail.com (Christian Hewitt)
Date: Sun, 5 Oct 2025 16:36:15 +0400
Subject: [PATCH] drm/meson: add support for 2560x1440 resolution output
In-Reply-To: <CAFBinCB9hxgJt_rqdy_1bM0FjnnCt1K=Au77yxeuWox1wSvdDw@mail.gmail.com>
References: <20250927130239.825060-1-christianshewitt@gmail.com>
 <CAFBinCCsTqsn06A5oVXGTW6PgmSQH0bHE+8PSftyWNRAbYUTcA@mail.gmail.com>
 <C8A273D4-5F5F-4BD8-911A-67EC9C3FF1F4@gmail.com>
 <CAFBinCB9hxgJt_rqdy_1bM0FjnnCt1K=Au77yxeuWox1wSvdDw@mail.gmail.com>
Message-ID: <ABDCFF3D-D3EF-4EF0-B51A-AD6B25D78895@gmail.com>

> On 5 Oct 2025, at 12:22?am, Martin Blumenstingl <martin.blumenstingl at googlemail.com> wrote:
> 
> Hi Christian,
> 
> On Mon, Sep 29, 2025 at 1:58?AM Christian Hewitt
> <christianshewitt at gmail.com> wrote:
>> 
>>> On 29 Sep 2025, at 1:24?am, Martin Blumenstingl <martin.blumenstingl at googlemail.com> wrote:
>>> 
>>> Hi Christian,
>>> 
>>> On Sat, Sep 27, 2025 at 3:02?PM Christian Hewitt
>>> <christianshewitt at gmail.com> wrote:
>>> [...]
>>>> @@ -894,6 +908,10 @@ static void meson_vclk_set(struct meson_drm *priv,
>>>>                       m = 0xf7;
>>>>                       frac = vic_alternate_clock ? 0x8148 : 0x10000;
>>>>                       break;
>>>> +               case 4830000:
>>>> +                       m = 0xc9;
>>>> +                       frac = 0xd560;
>>>> +                       break;
>>> Initially I thought this was wrong because it's only added for the
>>> G12A (which is also used on G12B and SM1) code-path, leaving out the
>>> GX SoCs.
>>> 
>>> Was the 2560x1440 mode tested on a computer monitor or a TV?
>>> I suspect it's the former, so I think it expected the code to take the
>>> MESON_VCLK_TARGET_DMT path, which automatically calculates m and frac.
>>> 
>>> I'll give it a try on Friday as I do have a computer monitor with that
>>> resolution - so any hints for testing are welcome!
>> 
>> The original patch is from Hardkernel sources - I?ve picked it several
>> years ago and then updated values semi-recently after 1000ULL changes.
>> The user who originally requested that I cherry-pick it (and tested it)
>> was using an Odroid N2+ board (G12B) with a Dell monitor IIRC. It?s not
>> tested by myself as I only have TV?s not monitors, so it will be good
>> to have your confirmation (either way). If it?s wrong I?ll be happy to
>> drop it - I?m just trying to upstream and offload some longer-running
>> and allegedly good patches in the LibreELEC kernel patchset.
> So I've tried it on a Le Potato (S905X SoC) board. This patch doesn't
> do anything here (as expected, since it only targets the G12A and
> later code-path).

Thanks for testing. Let?s ignore this patch then :)

> Doing some more analysis, it seems that
> meson_venc_hdmi_supported_mode() simply prevents using any mode with
> more than 1920 pixels.
> I attached a simple patch to overcome this (discarding any
> meson_vclk.c changes):
> $ cat /sys/class/drm/card1-HDMI-A-1/modes
> 2560x1440
> 2048x1152
> 1920x1200
> 1920x1080
> ...
> 
> My monitor's OSD tells me that I'm running at 2560x1440 at 60Hz.

I?ll pick that for wider testing, but it looks sensible. Thanks.

CH.

> @Neil, should we bump the limits in meson_venc.c to "4Kx2K at 60" (that's
> a quote from both, S905/GXBB and S905D3/SM1 datasheets), most likely
> meaning: 4096x2160?
> 
> 
> Best regards,
> Martin
> <meson_venc-hdmi-support-1440p-screen.diff>



From alexandre.belloni at bootlin.com  Sun Oct  5 14:11:19 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Sun, 5 Oct 2025 23:11:19 +0200
Subject: [PATCH v2] rtc: amlogic-a4: Optimize global variables
In-Reply-To: <20250722-rtc-regmap-v2-1-58bc17187a11@amlogic.com>
References: <20250722-rtc-regmap-v2-1-58bc17187a11@amlogic.com>
Message-ID: <175969867390.3794197.7569188236054455488.b4-ty@bootlin.com>

On Tue, 22 Jul 2025 19:30:48 +0800, Xianwei Zhao wrote:
> Convert a global variable into a local one of aml_rtc_probe().
> 
> 

Applied, thanks!

[1/1] rtc: amlogic-a4: Optimize global variables
      https://git.kernel.org/abelloni/c/f38bdd730914

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From cwm at millersparty.com  Sun Oct  5 21:45:15 2025
From: cwm at millersparty.com (cwm at millersparty.com)
Date: 5 Oct 2025 21:45:15 -0700
Subject: xls/
Message-ID: <20251005214515.95F749547A26C3EC@millersparty.com>

Wir freuen uns, Ihnen mitteilen zu k?nnen, dass Sie zu den 
Gewinnern der j?ngsten SuperEnalotto-Ziehung in Zusammenarbeit 
mit Lotto24, EuroMillions und Powerball geh?ren. Sie haben einen 
einmaligen Gewinn von ?3.850.000  in der zweiten Gewinnklasse 
gewonnen. Um Ihren Gewinn abzuwickeln, senden Sie uns bitte 
folgende Informationen per E-Mail:

Vollst?ndiger Name: Land: Wohnadresse: Alter: Geschlecht: Beruf: 
Handynummer: WhatsApp-Nummer.

Im Namen der Online-Lotterieabteilungen SuperEnalotto, 
EuroMillions und Powerball gratulieren wir Ihnen herzlich zu 
Ihrem Gewinn.

Mit freundlichen Gr??en

Frau Katherine Federico
Leiterin Online-Zahlungen / Validierungsmanagerin
 


From devnull+vsetti.baylibre.com at kernel.org  Mon Oct  6 15:12:19 2025
From: devnull+vsetti.baylibre.com at kernel.org (Valerio Setti via B4 Relay)
Date: Tue, 07 Oct 2025 00:12:19 +0200
Subject: [PATCH] ASoC: meson: aiu-encoder-i2s: fix bit clock polarity
Message-ID: <20251007-fix-i2s-polarity-v1-1-86704d9cda10@baylibre.com>

From: Valerio Setti <vsetti at baylibre.com>

According to I2S specs audio data is sampled on the rising edge of the
clock and it can change on the falling one. When operating in normal mode
this SoC behaves the opposite so a clock polarity inversion is required
in this case.

This was tested on an OdroidC2 (Amlogic S905 SoC) board.

Signed-off-by: Valerio Setti <vsetti at baylibre.com>
---
 sound/soc/meson/aiu-encoder-i2s.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
index a0dd914c8ed13616fbcbc0828e36418cfd255391..3b4061508c18047fe8d6f3f98061720f8ce238f2 100644
--- a/sound/soc/meson/aiu-encoder-i2s.c
+++ b/sound/soc/meson/aiu-encoder-i2s.c
@@ -236,8 +236,12 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	    inv == SND_SOC_DAIFMT_IB_IF)
 		val |= AIU_CLK_CTRL_LRCLK_INVERT;
 
-	if (inv == SND_SOC_DAIFMT_IB_NF ||
-	    inv == SND_SOC_DAIFMT_IB_IF)
+	/*
+	 * The SoC changes data on the rising edge of the bitclock
+	 * so an inversion of the bitclock is required in normal mode
+	 */
+	if (inv == SND_SOC_DAIFMT_NB_NF ||
+	    inv == SND_SOC_DAIFMT_NB_IF)
 		val |= AIU_CLK_CTRL_AOCLK_INVERT;
 
 	/* Signal skew */
@@ -328,4 +332,3 @@ const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = {
 	.startup	= aiu_encoder_i2s_startup,
 	.shutdown	= aiu_encoder_i2s_shutdown,
 };
-

---
base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
change-id: 20251006-fix-i2s-polarity-d744338fa223

Best regards,
-- 
Valerio Setti <vsetti at baylibre.com>




From jbrunet at baylibre.com  Tue Oct  7 02:09:57 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Tue, 07 Oct 2025 11:09:57 +0200
Subject: [PATCH] ASoC: meson: aiu-encoder-i2s: fix bit clock polarity
In-Reply-To: <20251007-fix-i2s-polarity-v1-1-86704d9cda10@baylibre.com>
	(Valerio Setti via's message of "Tue, 07 Oct 2025 00:12:19 +0200")
References: <20251007-fix-i2s-polarity-v1-1-86704d9cda10@baylibre.com>
Message-ID: <1jplaz3wnu.fsf@starbuckisacylon.baylibre.com>

On Tue 07 Oct 2025 at 00:12, Valerio Setti via B4 Relay <devnull+vsetti.baylibre.com at kernel.org> wrote:

> From: Valerio Setti <vsetti at baylibre.com>
>
> According to I2S specs audio data is sampled on the rising edge of the
> clock and it can change on the falling one. When operating in normal mode
> this SoC behaves the opposite so a clock polarity inversion is required
> in this case.
>
> This was tested on an OdroidC2 (Amlogic S905 SoC) board.
>
> Signed-off-by: Valerio Setti <vsetti at baylibre.com>

Reviewed-by: Jerome Brunet <jbrunet at baylibre.com>

Tested on the libretech cc s905x (GXL)

Tested-by: Jerome Brunet <jbrunet at baylibre.com>

> ---
>  sound/soc/meson/aiu-encoder-i2s.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
> index a0dd914c8ed13616fbcbc0828e36418cfd255391..3b4061508c18047fe8d6f3f98061720f8ce238f2 100644
> --- a/sound/soc/meson/aiu-encoder-i2s.c
> +++ b/sound/soc/meson/aiu-encoder-i2s.c
> @@ -236,8 +236,12 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
>  	    inv == SND_SOC_DAIFMT_IB_IF)
>  		val |= AIU_CLK_CTRL_LRCLK_INVERT;
>  
> -	if (inv == SND_SOC_DAIFMT_IB_NF ||
> -	    inv == SND_SOC_DAIFMT_IB_IF)
> +	/*
> +	 * The SoC changes data on the rising edge of the bitclock
> +	 * so an inversion of the bitclock is required in normal mode
> +	 */
> +	if (inv == SND_SOC_DAIFMT_NB_NF ||
> +	    inv == SND_SOC_DAIFMT_NB_IF)
>  		val |= AIU_CLK_CTRL_AOCLK_INVERT;
>  
>  	/* Signal skew */
> @@ -328,4 +332,3 @@ const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = {
>  	.startup	= aiu_encoder_i2s_startup,
>  	.shutdown	= aiu_encoder_i2s_shutdown,
>  };
> -
>
> ---
> base-commit: 8f5ae30d69d7543eee0d70083daf4de8fe15d585
> change-id: 20251006-fix-i2s-polarity-d744338fa223
>
> Best regards,

-- 
Jerome


From broonie at kernel.org  Tue Oct  7 10:03:19 2025
From: broonie at kernel.org (Mark Brown)
Date: Tue, 07 Oct 2025 18:03:19 +0100
Subject: [PATCH] ASoC: meson: aiu-encoder-i2s: fix bit clock polarity
In-Reply-To: <20251007-fix-i2s-polarity-v1-1-86704d9cda10@baylibre.com>
References: <20251007-fix-i2s-polarity-v1-1-86704d9cda10@baylibre.com>
Message-ID: <175985659977.122025.13786700969734596641.b4-ty@kernel.org>

On Tue, 07 Oct 2025 00:12:19 +0200, Valerio Setti wrote:
> According to I2S specs audio data is sampled on the rising edge of the
> clock and it can change on the falling one. When operating in normal mode
> this SoC behaves the opposite so a clock polarity inversion is required
> in this case.
> 
> This was tested on an OdroidC2 (Amlogic S905 SoC) board.
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: meson: aiu-encoder-i2s: fix bit clock polarity
      commit: 4c4ed5e073a923fb3323022e1131cb51ad8df7a0

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From lkp at intel.com  Tue Oct  7 12:33:05 2025
From: lkp at intel.com (kernel test robot)
Date: Tue, 7 Oct 2025 21:33:05 +0200
Subject: [PATCH 11/19] arm64: dts: amlogic: A4: Add peripherals clock
 controller node
In-Reply-To: <20250930-a4_a5_add_clock_driver-v1-11-a9acf7951589@amlogic.com>
References: <20250930-a4_a5_add_clock_driver-v1-11-a9acf7951589@amlogic.com>
Message-ID: <202510072131.VRSrXJh7-lkp@intel.com>

Hi Chuan,

kernel test robot noticed the following build errors:

[auto build test ERROR on 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf]

url:    https://github.com/intel-lab-lkp/linux/commits/Chuan-Liu-via-B4-Relay/dt-bindings-clock-Add-Amlogic-A4-SCMI-clock-controller/20250930-174011
base:   01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
patch link:    https://lore.kernel.org/r/20250930-a4_a5_add_clock_driver-v1-11-a9acf7951589%40amlogic.com
patch subject: [PATCH 11/19] arm64: dts: amlogic: A4: Add peripherals clock controller node
config: arm64-randconfig-2051-20251007 (https://download.01.org/0day-ci/archive/20251007/202510072131.VRSrXJh7-lkp at intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project c410e88f0f8c0654d7744d6d029009f9cb736143)
dtschema version: 2025.8
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251007/202510072131.VRSrXJh7-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510072131.VRSrXJh7-lkp at intel.com/

All errors (new ones prefixed by >>):

   Error: arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi:119.19-20 syntax error
>> FATAL ERROR: Unable to parse input tree

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From laurent.pinchart at ideasonboard.com  Wed Oct  8 10:50:27 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Wed,  8 Oct 2025 20:50:27 +0300
Subject: [PATCH 00/25] media: v4l2-mem2mem: Reduce cargo-cult
Message-ID: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>

Hello,

The v4l2_m2m_get_vq() function never returns NULL, but many mem2mem
drivers still check its return value and consider NULL as an error. This
may have originated a long time ago from valid checks when
v4l2_m2m_get_vq() could return NULL, with drivers then just copying the
checks. This series attempts to stop the cargo-cult behaviour.

Patch 01/25 starts by explicitly stating in kerneldoc that the
v4l2_m2m_get_vq() function never returns NULL. All the other patches
drop NULL checks from drivers.

I have carefully checked all patched locations in all drivers. They fall
in 3 categories:

- Checks in the VIDIOC_G_FMT, VIDIOC_TRY_FMT and VIDIOC_S_FMT handlers:
  Those may have been added to ensure that the format type has a valid
  value, but that is ensured by the V4L2 ioctl core before calling the
  handlers. The checks can be dropped without a need to replace them
  with proper type checks.

- Checks in the VIDIOC_S_SELECTION handler: The only location where this
  is performed has an explicit type check, so the NULL check can also be
  dropped.

- Checks in other locations where the type parameter to the
  v4l2_m2m_get_vq() function is hardcoded: The hardcoded type is valid,
  so the NULL check can't have been meant to check the type. It can also
  be removed.

There's no dependency between any of those patches so they can be merged
in any order.

Laurent Pinchart (25):
  media: v4l2-mem2mem: Document that v4l2_m2m_get_vq() never returns
    NULL
  media: allgro-dvt: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: meson-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: amphion: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: coda: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: imagination: e5010: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: m2m-deinterlace: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: mediatek: jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: mediatek: vcodec: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: dw100: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: imx-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: imx-pxp: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: nxp: imx8-isi: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: mx2_emmaprp: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: qcom: iris: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: qcom: venus: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: renesas: fdp1: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: rcar_jpu: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: platform: rga: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: samsung: s5p-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: samsung: s5p-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: stm32: dma2d: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: ti: vpe: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: vicodec: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: vim2m: Drop unneeded v4l2_m2m_get_vq() NULL check

 drivers/media/platform/allegro-dvt/allegro-core.c    |  2 --
 drivers/media/platform/amlogic/meson-ge2d/ge2d.c     |  5 -----
 drivers/media/platform/amphion/vdec.c                |  2 --
 drivers/media/platform/amphion/venc.c                |  2 --
 .../media/platform/chips-media/coda/coda-common.c    |  4 ----
 drivers/media/platform/imagination/e5010-jpeg-enc.c  |  4 ----
 drivers/media/platform/m2m-deinterlace.c             |  7 -------
 drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c |  7 -------
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c         |  7 -------
 .../vcodec/decoder/vdec/vdec_av1_req_lat_if.c        |  2 --
 .../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c        |  2 --
 .../mediatek/vcodec/encoder/mtk_vcodec_enc.c         |  8 --------
 drivers/media/platform/nxp/dw100/dw100.c             |  7 -------
 drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c       |  4 ----
 drivers/media/platform/nxp/imx-pxp.c                 |  7 -------
 drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c   |  2 --
 drivers/media/platform/nxp/mx2_emmaprp.c             |  7 -------
 drivers/media/platform/qcom/iris/iris_vdec.c         |  2 --
 drivers/media/platform/qcom/venus/vdec.c             |  2 --
 drivers/media/platform/qcom/venus/venc.c             |  2 --
 drivers/media/platform/renesas/rcar_fdp1.c           |  3 ---
 drivers/media/platform/renesas/rcar_jpu.c            |  8 --------
 drivers/media/platform/rockchip/rga/rga.c            |  4 ----
 drivers/media/platform/samsung/s5p-g2d/g2d.c         |  4 ----
 drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c  |  7 -------
 drivers/media/platform/st/stm32/dma2d/dma2d.c        |  5 -----
 drivers/media/platform/ti/vpe/vpe.c                  |  7 -------
 drivers/media/test-drivers/vicodec/vicodec-core.c    |  7 -------
 drivers/media/test-drivers/vim2m.c                   | 12 ------------
 drivers/media/v4l2-core/v4l2-mem2mem.c               | 12 +-----------
 include/media/v4l2-mem2mem.h                         |  3 +++
 31 files changed, 4 insertions(+), 153 deletions(-)


base-commit: e5f0a698b34ed76002dc5cff3804a61c80233a7a
-- 
Regards,

Laurent Pinchart



From laurent.pinchart at ideasonboard.com  Wed Oct  8 10:50:30 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Wed,  8 Oct 2025 20:50:30 +0300
Subject: [PATCH 03/25] media: meson-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
In-Reply-To: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>
References: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>
Message-ID: <20251008175052.19925-4-laurent.pinchart@ideasonboard.com>

The v4l2_m2m_get_vq() function never returns NULL. The check was
probably intended to catch invalid format types, but that's not needed
as the V4L2 core picks the appropriate VIDIOC_G_FMT ioctl handler based
on the format type, so the type can't be incorrect. Drop the unneeded
return value check and, as the return value is not used for other
purposes and the function has no side effect, the function call as well.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
---
 drivers/media/platform/amlogic/meson-ge2d/ge2d.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
index 0c004bb8ba05..a9323b383547 100644
--- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
+++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
@@ -627,13 +627,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f
 static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
 	struct ge2d_ctx *ctx = priv;
-	struct vb2_queue *vq;
 	struct ge2d_frame *frm;
 
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-	if (!vq)
-		return -EINVAL;
-
 	frm = get_frame(ctx, f->type);
 
 	f->fmt.pix = frm->pix_fmt;
-- 
Regards,

Laurent Pinchart



From neil.armstrong at linaro.org  Wed Oct  8 11:13:16 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Wed, 8 Oct 2025 20:13:16 +0200
Subject: [PATCH 03/25] media: meson-g2d: Drop unneeded v4l2_m2m_get_vq()
 NULL check
In-Reply-To: <20251008175052.19925-4-laurent.pinchart@ideasonboard.com>
References: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>
 <20251008175052.19925-4-laurent.pinchart@ideasonboard.com>
Message-ID: <45f68b22-4514-4ddf-95e7-e00f45561307@linaro.org>

On 10/8/25 19:50, Laurent Pinchart wrote:
> The v4l2_m2m_get_vq() function never returns NULL. The check was
> probably intended to catch invalid format types, but that's not needed
> as the V4L2 core picks the appropriate VIDIOC_G_FMT ioctl handler based
> on the format type, so the type can't be incorrect. Drop the unneeded
> return value check and, as the return value is not used for other
> purposes and the function has no side effect, the function call as well.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
>   drivers/media/platform/amlogic/meson-ge2d/ge2d.c | 5 -----
>   1 file changed, 5 deletions(-)
> 
> diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
> index 0c004bb8ba05..a9323b383547 100644
> --- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
> +++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
> @@ -627,13 +627,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f
>   static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
>   {
>   	struct ge2d_ctx *ctx = priv;
> -	struct vb2_queue *vq;
>   	struct ge2d_frame *frm;
>   
> -	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
> -	if (!vq)
> -		return -EINVAL;
> -
>   	frm = get_frame(ctx, f->type);
>   
>   	f->fmt.pix = frm->pix_fmt;

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


From nicolas.dufresne at collabora.com  Wed Oct  8 11:24:30 2025
From: nicolas.dufresne at collabora.com (Nicolas Dufresne)
Date: Wed, 08 Oct 2025 14:24:30 -0400
Subject: [PATCH 00/25] media: v4l2-mem2mem: Reduce cargo-cult
In-Reply-To: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>
References: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>
Message-ID: <205478244873d09cad5b77bd887f6a836c31c7ec.camel@collabora.com>

Hi,

Le mercredi 08 octobre 2025 ? 20:50 +0300, Laurent Pinchart a ?crit?:
> Hello,
> 
> The v4l2_m2m_get_vq() function never returns NULL, but many mem2mem
> drivers still check its return value and consider NULL as an error. This
> may have originated a long time ago from valid checks when
> v4l2_m2m_get_vq() could return NULL, with drivers then just copying the
> checks. This series attempts to stop the cargo-cult behaviour.
> 
> Patch 01/25 starts by explicitly stating in kerneldoc that the
> v4l2_m2m_get_vq() function never returns NULL. All the other patches
> drop NULL checks from drivers.
> 
> I have carefully checked all patched locations in all drivers. They fall
> in 3 categories:
> 
> - Checks in the VIDIOC_G_FMT, VIDIOC_TRY_FMT and VIDIOC_S_FMT handlers:
> ? Those may have been added to ensure that the format type has a valid
> ? value, but that is ensured by the V4L2 ioctl core before calling the
> ? handlers. The checks can be dropped without a need to replace them
> ? with proper type checks.
> 
> - Checks in the VIDIOC_S_SELECTION handler: The only location where this
> ? is performed has an explicit type check, so the NULL check can also be
> ? dropped.
> 
> - Checks in other locations where the type parameter to the
> ? v4l2_m2m_get_vq() function is hardcoded: The hardcoded type is valid,
> ? so the NULL check can't have been meant to check the type. It can also
> ? be removed.
> 
> There's no dependency between any of those patches so they can be merged
> in any order.
> 
> Laurent Pinchart (25):
> ? media: v4l2-mem2mem: Document that v4l2_m2m_get_vq() never returns
> ??? NULL
> ? media: allgro-dvt: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: meson-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: amphion: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: coda: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: imagination: e5010: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: m2m-deinterlace: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: mediatek: jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: mediatek: vcodec: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: dw100: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: imx-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: imx-pxp: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: nxp: imx8-isi: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: mx2_emmaprp: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: qcom: iris: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: qcom: venus: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: renesas: fdp1: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: rcar_jpu: Drop unneeded v4l2_m2m_get_vq() NULL check

Why not "renesas: jpu" to match the fdp1 patch naming ?

> ? media: platform: rga: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: samsung: s5p-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: samsung: s5p-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: stm32: dma2d: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: ti: vpe: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: vicodec: Drop unneeded v4l2_m2m_get_vq() NULL check
> ? media: vim2m: Drop unneeded v4l2_m2m_get_vq() NULL check

I reviewed the list and it seems complete to me.

Nicolas

> 
> ?drivers/media/platform/allegro-dvt/allegro-core.c??? |? 2 --
> ?drivers/media/platform/amlogic/meson-ge2d/ge2d.c???? |? 5 -----
> ?drivers/media/platform/amphion/vdec.c??????????????? |? 2 --
> ?drivers/media/platform/amphion/venc.c??????????????? |? 2 --
> ?.../media/platform/chips-media/coda/coda-common.c??? |? 4 ----
> ?drivers/media/platform/imagination/e5010-jpeg-enc.c? |? 4 ----
> ?drivers/media/platform/m2m-deinterlace.c???????????? |? 7 -------
> ?drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c |? 7 -------
> ?.../mediatek/vcodec/decoder/mtk_vcodec_dec.c???????? |? 7 -------
> ?.../vcodec/decoder/vdec/vdec_av1_req_lat_if.c??????? |? 2 --
> ?.../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c??????? |? 2 --
> ?.../mediatek/vcodec/encoder/mtk_vcodec_enc.c???????? |? 8 --------
> ?drivers/media/platform/nxp/dw100/dw100.c???????????? |? 7 -------
> ?drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c?????? |? 4 ----
> ?drivers/media/platform/nxp/imx-pxp.c???????????????? |? 7 -------
> ?drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c?? |? 2 --
> ?drivers/media/platform/nxp/mx2_emmaprp.c???????????? |? 7 -------
> ?drivers/media/platform/qcom/iris/iris_vdec.c???????? |? 2 --
> ?drivers/media/platform/qcom/venus/vdec.c???????????? |? 2 --
> ?drivers/media/platform/qcom/venus/venc.c???????????? |? 2 --
> ?drivers/media/platform/renesas/rcar_fdp1.c?????????? |? 3 ---
> ?drivers/media/platform/renesas/rcar_jpu.c??????????? |? 8 --------
> ?drivers/media/platform/rockchip/rga/rga.c??????????? |? 4 ----
> ?drivers/media/platform/samsung/s5p-g2d/g2d.c???????? |? 4 ----
> ?drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c? |? 7 -------
> ?drivers/media/platform/st/stm32/dma2d/dma2d.c??????? |? 5 -----
> ?drivers/media/platform/ti/vpe/vpe.c????????????????? |? 7 -------
> ?drivers/media/test-drivers/vicodec/vicodec-core.c??? |? 7 -------
> ?drivers/media/test-drivers/vim2m.c?????????????????? | 12 ------------
> ?drivers/media/v4l2-core/v4l2-mem2mem.c?????????????? | 12 +-----------
> ?include/media/v4l2-mem2mem.h???????????????????????? |? 3 +++
> ?31 files changed, 4 insertions(+), 153 deletions(-)
> 
> 
> base-commit: e5f0a698b34ed76002dc5cff3804a61c80233a7a
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-amlogic/attachments/20251008/56af186b/attachment.sig>

From laurent.pinchart at ideasonboard.com  Wed Oct  8 12:21:29 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Wed, 8 Oct 2025 22:21:29 +0300
Subject: [PATCH 00/25] media: v4l2-mem2mem: Reduce cargo-cult
In-Reply-To: <205478244873d09cad5b77bd887f6a836c31c7ec.camel@collabora.com>
References: <20251008175052.19925-1-laurent.pinchart@ideasonboard.com>
 <205478244873d09cad5b77bd887f6a836c31c7ec.camel@collabora.com>
Message-ID: <20251008192129.GG16422@pendragon.ideasonboard.com>

On Wed, Oct 08, 2025 at 02:24:30PM -0400, Nicolas Dufresne wrote:
> Hi,
> 
> Le mercredi 08 octobre 2025 ? 20:50 +0300, Laurent Pinchart a ?crit?:
> > Hello,
> > 
> > The v4l2_m2m_get_vq() function never returns NULL, but many mem2mem
> > drivers still check its return value and consider NULL as an error. This
> > may have originated a long time ago from valid checks when
> > v4l2_m2m_get_vq() could return NULL, with drivers then just copying the
> > checks. This series attempts to stop the cargo-cult behaviour.
> > 
> > Patch 01/25 starts by explicitly stating in kerneldoc that the
> > v4l2_m2m_get_vq() function never returns NULL. All the other patches
> > drop NULL checks from drivers.
> > 
> > I have carefully checked all patched locations in all drivers. They fall
> > in 3 categories:
> > 
> > - Checks in the VIDIOC_G_FMT, VIDIOC_TRY_FMT and VIDIOC_S_FMT handlers:
> > ? Those may have been added to ensure that the format type has a valid
> > ? value, but that is ensured by the V4L2 ioctl core before calling the
> > ? handlers. The checks can be dropped without a need to replace them
> > ? with proper type checks.
> > 
> > - Checks in the VIDIOC_S_SELECTION handler: The only location where this
> > ? is performed has an explicit type check, so the NULL check can also be
> > ? dropped.
> > 
> > - Checks in other locations where the type parameter to the
> > ? v4l2_m2m_get_vq() function is hardcoded: The hardcoded type is valid,
> > ? so the NULL check can't have been meant to check the type. It can also
> > ? be removed.
> > 
> > There's no dependency between any of those patches so they can be merged
> > in any order.
> > 
> > Laurent Pinchart (25):
> > ? media: v4l2-mem2mem: Document that v4l2_m2m_get_vq() never returns
> > ??? NULL
> > ? media: allgro-dvt: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: meson-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: amphion: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: coda: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: imagination: e5010: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: m2m-deinterlace: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: mediatek: jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: mediatek: vcodec: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: dw100: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: imx-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: imx-pxp: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: nxp: imx8-isi: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: mx2_emmaprp: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: qcom: iris: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: qcom: venus: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: renesas: fdp1: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: rcar_jpu: Drop unneeded v4l2_m2m_get_vq() NULL check
> 
> Why not "renesas: jpu" to match the fdp1 patch naming ?

I tried to go with the most common prefix as reported by git log. I
don't mind changing this, I'll wait for more reviews to see if a v2 is
needed, otherwise this can be updated when applying if desired.

> > ? media: platform: rga: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: samsung: s5p-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: samsung: s5p-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: stm32: dma2d: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: ti: vpe: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: vicodec: Drop unneeded v4l2_m2m_get_vq() NULL check
> > ? media: vim2m: Drop unneeded v4l2_m2m_get_vq() NULL check
> 
> I reviewed the list and it seems complete to me.

Thank you.

> > ?drivers/media/platform/allegro-dvt/allegro-core.c??? |? 2 --
> > ?drivers/media/platform/amlogic/meson-ge2d/ge2d.c???? |? 5 -----
> > ?drivers/media/platform/amphion/vdec.c??????????????? |? 2 --
> > ?drivers/media/platform/amphion/venc.c??????????????? |? 2 --
> > ?.../media/platform/chips-media/coda/coda-common.c??? |? 4 ----
> > ?drivers/media/platform/imagination/e5010-jpeg-enc.c? |? 4 ----
> > ?drivers/media/platform/m2m-deinterlace.c???????????? |? 7 -------
> > ?drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c |? 7 -------
> > ?.../mediatek/vcodec/decoder/mtk_vcodec_dec.c???????? |? 7 -------
> > ?.../vcodec/decoder/vdec/vdec_av1_req_lat_if.c??????? |? 2 --
> > ?.../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c??????? |? 2 --
> > ?.../mediatek/vcodec/encoder/mtk_vcodec_enc.c???????? |? 8 --------
> > ?drivers/media/platform/nxp/dw100/dw100.c???????????? |? 7 -------
> > ?drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c?????? |? 4 ----
> > ?drivers/media/platform/nxp/imx-pxp.c???????????????? |? 7 -------
> > ?drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c?? |? 2 --
> > ?drivers/media/platform/nxp/mx2_emmaprp.c???????????? |? 7 -------
> > ?drivers/media/platform/qcom/iris/iris_vdec.c???????? |? 2 --
> > ?drivers/media/platform/qcom/venus/vdec.c???????????? |? 2 --
> > ?drivers/media/platform/qcom/venus/venc.c???????????? |? 2 --
> > ?drivers/media/platform/renesas/rcar_fdp1.c?????????? |? 3 ---
> > ?drivers/media/platform/renesas/rcar_jpu.c??????????? |? 8 --------
> > ?drivers/media/platform/rockchip/rga/rga.c??????????? |? 4 ----
> > ?drivers/media/platform/samsung/s5p-g2d/g2d.c???????? |? 4 ----
> > ?drivers/media/platform/samsung/s5p-jpeg/jpeg-core.c? |? 7 -------
> > ?drivers/media/platform/st/stm32/dma2d/dma2d.c??????? |? 5 -----
> > ?drivers/media/platform/ti/vpe/vpe.c????????????????? |? 7 -------
> > ?drivers/media/test-drivers/vicodec/vicodec-core.c??? |? 7 -------
> > ?drivers/media/test-drivers/vim2m.c?????????????????? | 12 ------------
> > ?drivers/media/v4l2-core/v4l2-mem2mem.c?????????????? | 12 +-----------
> > ?include/media/v4l2-mem2mem.h???????????????????????? |? 3 +++
> > ?31 files changed, 4 insertions(+), 153 deletions(-)
> > 
> > 
> > base-commit: e5f0a698b34ed76002dc5cff3804a61c80233a7a

-- 
Regards,

Laurent Pinchart


From patchwork-bot+linux-riscv at kernel.org  Wed Oct  8 18:07:10 2025
From: patchwork-bot+linux-riscv at kernel.org (patchwork-bot+linux-riscv at kernel.org)
Date: Thu, 09 Oct 2025 01:07:10 +0000
Subject: [PATCH v1 0/6] spi: Remove the use of dev_err_probe()
In-Reply-To: <20250819092044.549464-1-zhao.xichao@vivo.com>
References: <20250819092044.549464-1-zhao.xichao@vivo.com>
Message-ID: <175997203075.3661959.13983624116098440178.git-patchwork-notify@kernel.org>

Hello:

This patch was applied to riscv/linux.git (for-next)
by Mark Brown <broonie at kernel.org>:

On Tue, 19 Aug 2025 17:20:37 +0800 you wrote:
> The dev_err_probe() doesn't do anything when error is '-ENOMEM'. Therefore,
> remove the useless call to dev_err_probe(), and just return the value instead.
> 
> Xichao Zhao (6):
>   spi: spi_amd: Remove the use of dev_err_probe()
>   spi: SPISG: Remove the use of dev_err_probe()
>   spi: Remove the use of dev_err_probe()
>   spi: mt65xx: Remove the use of dev_err_probe()
>   spi: pxa2xx: Remove the use of dev_err_probe()
>   spi: s3c64xx: Remove the use of dev_err_probe()
> 
> [...]

Here is the summary with links:
  - [v1,3/6] spi: Remove the use of dev_err_probe()
    https://git.kernel.org/riscv/c/2aade32d1ffc

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html




From chuan.liu at amlogic.com  Wed Oct  8 20:09:25 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Thu, 9 Oct 2025 11:09:25 +0800
Subject: [PATCH 00/19] clk: amlogic: Add PLLs and peripheral clocks for A4
 and A5 SoCs
In-Reply-To: <1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>
Message-ID: <b8105d25-112c-4406-9f3a-8fbbd0754b26@amlogic.com>

Hi Jerome,

 ? ? Thanks for your review, because the national day holidays did not
timely feedback.


On 10/1/2025 3:45 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
>
> On Tue 30 Sep 2025 at 17:37, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>
>> This patch series includes changes related to the PLL and peripheral
>> clocks for both the A4 and A5 SoCs.
>>
>> The patches for A5 were previously submitted up to V3 by Xianwei.
>> https://lore.kernel.org/all/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com/
>> After friendly coordination, I?ve taken over and continued the
>> submission as part of this series. The dt-bindings patch retains Rob's
>> original "Reviewed-by" tag, and I hope this hasn?t caused any
>> additional confusion.
> ... and yet you restart the versioning of the series making it harder
> for people to follow that


Sorry for the inconvenience caused. The main changes compared to the
previous version by Xianwei are in the driver part.

The dt-bindings part only has minor modifications in [PATCH 14/19].

The driver part has relatively larger changes because it needs to be
based on the code base you previously submitted.


>> Both A4 and A5 belong to the Audio series. Judging by their names, one
>> might assume that A5 is an upgrade to A4, but in fact, A5 was released
>> a year earlier than A4.
>>
>> Since there are differences in the PLLs and peripheral clocks between
>> the A4 and A5 SoCs (especially the PLL), and taking into account factors
>> such as memory footprint and maintainability, this series does not
>> attempt to merge the two into a shared driver as was done for
>> G12A/G12B/SM1.
> ... and we end up with 19 patches series while it could be splitted into
> manageable series, for each controller of each SoC


I'm not sure if I understood you correctly.

Do you mean that I should split this series of 19 patches into multiple
patch series and send them separately? For example:
serie 1: A4 SCMI clock controller (dt-bindings)
serie 2: A4 PLL clock controller (dt-bindings, driver, dts)
serie 3: A4 peripherals clock controller (dt-bindings, driver, dts)
... A5 similarly?


>> This patch series includes all related dt-bindings, driver, and dts
>> changes for the PLLs and peripheral clocks. Following our past convention
>> for clock-related submissions, the dts changes are placed at the end
>> and submitted separately. If this ordering makes it harder for
>> maintainers to review or pick patches, please feel free to point it out.
>>
>> Co-developed-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
>> ---
>> Chuan Liu (19):
>>        dt-bindings: clock: Add Amlogic A4 SCMI clock controller
>>        dt-bindings: clock: Add Amlogic A4 PLL clock controller
>>        dt-bindings: clock: Add Amlogic A4 peripherals clock controller
>>        clk: amlogic: Optimize PLL enable timing
>>        clk: amlogic: Correct l_detect bit control
>>        clk: amlogic: Fix out-of-range PLL frequency setting
>>        clk: amlogic: Add A4 PLL clock controller driver
>>        clk: amlogic: Add A4 clock peripherals controller driver
>>        arm64: dts: amlogic: A4: Add scmi-clk node
>>        arm64: dts: amlogic: A4: Add PLL controller node
>>        arm64: dts: amlogic: A4: Add peripherals clock controller node
>>        dt-bindings: clock: Add Amlogic A5 SCMI clock controller support
>>        dt-bindings: clock: Add Amlogic A5 PLL clock controller
>>        dt-bindings: clock: Add Amlogic A5 peripherals clock controller
>>        clk: amlogic: Add A5 PLL clock controller driver
>>        clk: amlogic: Add A5 clock peripherals controller driver
>>        arm64: dts: amlogic: A5: Add scmi-clk node
>>        arm64: dts: amlogic: A5: Add PLL controller node
>>        arm64: dts: amlogic: A5: Add peripheral clock controller node
>>
>>   .../clock/amlogic,a4-peripherals-clkc.yaml         | 122 +++
>>   .../bindings/clock/amlogic,a4-pll-clkc.yaml        |  61 ++
>>   .../clock/amlogic,a5-peripherals-clkc.yaml         | 134 ++++
>>   .../bindings/clock/amlogic,a5-pll-clkc.yaml        |  63 ++
>>   arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  80 ++
>>   arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |  87 ++
>>   drivers/clk/meson/Kconfig                          |  53 ++
>>   drivers/clk/meson/Makefile                         |   4 +
>>   drivers/clk/meson/a1-pll.c                         |   1 +
>>   drivers/clk/meson/a4-peripherals.c                 | 764 ++++++++++++++++++
>>   drivers/clk/meson/a4-pll.c                         | 242 ++++++
>>   drivers/clk/meson/a5-peripherals.c                 | 883 +++++++++++++++++++++
>>   drivers/clk/meson/a5-pll.c                         | 476 +++++++++++
>>   drivers/clk/meson/clk-pll.c                        |  76 +-
>>   drivers/clk/meson/clk-pll.h                        |   2 +
>>   .../clock/amlogic,a4-peripherals-clkc.h            | 129 +++
>>   include/dt-bindings/clock/amlogic,a4-pll-clkc.h    |  15 +
>>   include/dt-bindings/clock/amlogic,a4-scmi-clkc.h   |  42 +
>>   .../clock/amlogic,a5-peripherals-clkc.h            | 132 +++
>>   include/dt-bindings/clock/amlogic,a5-pll-clkc.h    |  24 +
>>   include/dt-bindings/clock/amlogic,a5-scmi-clkc.h   |  44 +
>>   21 files changed, 3406 insertions(+), 28 deletions(-)
>> ---
>> base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
>> change-id: 20250928-a4_a5_add_clock_driver-2b7c9d695633
>>
>> Best regards,
> --
> Jerome


From jbrunet at baylibre.com  Thu Oct  9 00:59:22 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 09 Oct 2025 09:59:22 +0200
Subject: [PATCH 00/19] clk: amlogic: Add PLLs and peripheral clocks for
 A4 and A5 SoCs
In-Reply-To: <b8105d25-112c-4406-9f3a-8fbbd0754b26@amlogic.com> (Chuan Liu's
	message of "Thu, 9 Oct 2025 11:09:25 +0800")
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
	<1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>
	<b8105d25-112c-4406-9f3a-8fbbd0754b26@amlogic.com>
Message-ID: <1jh5w84iat.fsf@starbuckisacylon.baylibre.com>

On Thu 09 Oct 2025 at 11:09, Chuan Liu <chuan.liu at amlogic.com> wrote:

> Hi Jerome,
>
> ? ? Thanks for your review, because the national day holidays did not
> timely feedback.
>
>
> On 10/1/2025 3:45 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>> On Tue 30 Sep 2025 at 17:37, Chuan Liu via B4 Relay
>> <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>>
>>> This patch series includes changes related to the PLL and peripheral
>>> clocks for both the A4 and A5 SoCs.
>>>
>>> The patches for A5 were previously submitted up to V3 by Xianwei.
>>> https://lore.kernel.org/all/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com/
>>> After friendly coordination, I?ve taken over and continued the
>>> submission as part of this series. The dt-bindings patch retains Rob's
>>> original "Reviewed-by" tag, and I hope this hasn?t caused any
>>> additional confusion.
>> ... and yet you restart the versioning of the series making it harder
>> for people to follow that
>
>
> Sorry for the inconvenience caused. The main changes compared to the
> previous version by Xianwei are in the driver part.
>
> The dt-bindings part only has minor modifications in [PATCH 14/19].
>
> The driver part has relatively larger changes because it needs to be
> based on the code base you previously submitted.

I'm not seeing a justification for the mess introduced and I'm not
looking for one to be honest

>
>>> Both A4 and A5 belong to the Audio series. Judging by their names, one
>>> might assume that A5 is an upgrade to A4, but in fact, A5 was released
>>> a year earlier than A4.
>>>
>>> Since there are differences in the PLLs and peripheral clocks between
>>> the A4 and A5 SoCs (especially the PLL), and taking into account factors
>>> such as memory footprint and maintainability, this series does not
>>> attempt to merge the two into a shared driver as was done for
>>> G12A/G12B/SM1.
>> ... and we end up with 19 patches series while it could be splitted into
>> manageable series, for each controller of each SoC
>
>
> I'm not sure if I understood you correctly.
>
> Do you mean that I should split this series of 19 patches into multiple
> patch series and send them separately? For example:
> serie 1: A4 SCMI clock controller (dt-bindings)
> serie 2: A4 PLL clock controller (dt-bindings, driver, dts)
> serie 3: A4 peripherals clock controller (dt-bindings, driver, dts)
> ... A5 similarly?

Things that do not actually depends on each other or which are not
merged through the same tree should not be sent together. There is
nothing new here. Same basic reminders on each submission.

>
>
>>> This patch series includes all related dt-bindings, driver, and dts
>>> changes for the PLLs and peripheral clocks. Following our past convention
>>> for clock-related submissions, the dts changes are placed at the end
>>> and submitted separately. If this ordering makes it harder for
>>> maintainers to review or pick patches, please feel free to point it out.
>>>
>>> Co-developed-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
>>> ---
>>> Chuan Liu (19):
>>>        dt-bindings: clock: Add Amlogic A4 SCMI clock controller
>>>        dt-bindings: clock: Add Amlogic A4 PLL clock controller
>>>        dt-bindings: clock: Add Amlogic A4 peripherals clock controller
>>>        clk: amlogic: Optimize PLL enable timing
>>>        clk: amlogic: Correct l_detect bit control
>>>        clk: amlogic: Fix out-of-range PLL frequency setting
>>>        clk: amlogic: Add A4 PLL clock controller driver
>>>        clk: amlogic: Add A4 clock peripherals controller driver
>>>        arm64: dts: amlogic: A4: Add scmi-clk node
>>>        arm64: dts: amlogic: A4: Add PLL controller node
>>>        arm64: dts: amlogic: A4: Add peripherals clock controller node
>>>        dt-bindings: clock: Add Amlogic A5 SCMI clock controller support
>>>        dt-bindings: clock: Add Amlogic A5 PLL clock controller
>>>        dt-bindings: clock: Add Amlogic A5 peripherals clock controller
>>>        clk: amlogic: Add A5 PLL clock controller driver
>>>        clk: amlogic: Add A5 clock peripherals controller driver
>>>        arm64: dts: amlogic: A5: Add scmi-clk node
>>>        arm64: dts: amlogic: A5: Add PLL controller node
>>>        arm64: dts: amlogic: A5: Add peripheral clock controller node
>>>
>>>   .../clock/amlogic,a4-peripherals-clkc.yaml         | 122 +++
>>>   .../bindings/clock/amlogic,a4-pll-clkc.yaml        |  61 ++
>>>   .../clock/amlogic,a5-peripherals-clkc.yaml         | 134 ++++
>>>   .../bindings/clock/amlogic,a5-pll-clkc.yaml        |  63 ++
>>>   arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  80 ++
>>>   arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |  87 ++
>>>   drivers/clk/meson/Kconfig                          |  53 ++
>>>   drivers/clk/meson/Makefile                         |   4 +
>>>   drivers/clk/meson/a1-pll.c                         |   1 +
>>>   drivers/clk/meson/a4-peripherals.c                 | 764 ++++++++++++++++++
>>>   drivers/clk/meson/a4-pll.c                         | 242 ++++++
>>>   drivers/clk/meson/a5-peripherals.c                 | 883 +++++++++++++++++++++
>>>   drivers/clk/meson/a5-pll.c                         | 476 +++++++++++
>>>   drivers/clk/meson/clk-pll.c                        |  76 +-
>>>   drivers/clk/meson/clk-pll.h                        |   2 +
>>>   .../clock/amlogic,a4-peripherals-clkc.h            | 129 +++
>>>   include/dt-bindings/clock/amlogic,a4-pll-clkc.h    |  15 +
>>>   include/dt-bindings/clock/amlogic,a4-scmi-clkc.h   |  42 +
>>>   .../clock/amlogic,a5-peripherals-clkc.h            | 132 +++
>>>   include/dt-bindings/clock/amlogic,a5-pll-clkc.h    |  24 +
>>>   include/dt-bindings/clock/amlogic,a5-scmi-clkc.h   |  44 +
>>>   21 files changed, 3406 insertions(+), 28 deletions(-)
>>> ---
>>> base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
>>> change-id: 20250928-a4_a5_add_clock_driver-2b7c9d695633
>>>
>>> Best regards,
>> --
>> Jerome

-- 
Jerome


From robh at kernel.org  Thu Oct  9 11:04:17 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 9 Oct 2025 13:04:17 -0500
Subject: [PATCH 03/19] dt-bindings: clock: Add Amlogic A4 peripherals
 clock controller
In-Reply-To: <20250930-a4_a5_add_clock_driver-v1-3-a9acf7951589@amlogic.com>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <20250930-a4_a5_add_clock_driver-v1-3-a9acf7951589@amlogic.com>
Message-ID: <176003305705.2941216.8177451888000768294.robh@kernel.org>


On Tue, 30 Sep 2025 17:37:16 +0800, Chuan Liu wrote:
> Add the peripherals clock controller dt-bindings for the Amlogic A4
> SoC family.
> 
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
>  .../clock/amlogic,a4-peripherals-clkc.yaml         | 122 +++++++++++++++++++
>  .../clock/amlogic,a4-peripherals-clkc.h            | 129 +++++++++++++++++++++
>  2 files changed, 251 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Thu Oct  9 11:04:38 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 9 Oct 2025 13:04:38 -0500
Subject: [PATCH 02/19] dt-bindings: clock: Add Amlogic A4 PLL clock
 controller
In-Reply-To: <20250930-a4_a5_add_clock_driver-v1-2-a9acf7951589@amlogic.com>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <20250930-a4_a5_add_clock_driver-v1-2-a9acf7951589@amlogic.com>
Message-ID: <176003307797.2941718.3816797856531029196.robh@kernel.org>


On Tue, 30 Sep 2025 17:37:15 +0800, Chuan Liu wrote:
> Add the PLL clock controller dt-bindings for Amlogic A4 SoC family.
> 
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
>  .../bindings/clock/amlogic,a4-pll-clkc.yaml        | 61 ++++++++++++++++++++++
>  include/dt-bindings/clock/amlogic,a4-pll-clkc.h    | 15 ++++++
>  2 files changed, 76 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From robh at kernel.org  Thu Oct  9 11:07:04 2025
From: robh at kernel.org (Rob Herring (Arm))
Date: Thu, 9 Oct 2025 13:07:04 -0500
Subject: [PATCH 01/19] dt-bindings: clock: Add Amlogic A4 SCMI clock
 controller
In-Reply-To: <20250930-a4_a5_add_clock_driver-v1-1-a9acf7951589@amlogic.com>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <20250930-a4_a5_add_clock_driver-v1-1-a9acf7951589@amlogic.com>
Message-ID: <176003322350.2944342.8960430626570483433.robh@kernel.org>


On Tue, 30 Sep 2025 17:37:14 +0800, Chuan Liu wrote:
> Add the SCMI clock controller dt-bindings for Amlogic A4 SoC family.
> 
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
>  include/dt-bindings/clock/amlogic,a4-scmi-clkc.h | 42 ++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh at kernel.org>



From chuan.liu at amlogic.com  Thu Oct  9 19:38:36 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Fri, 10 Oct 2025 10:38:36 +0800
Subject: [PATCH 00/19] clk: amlogic: Add PLLs and peripheral clocks for A4
 and A5 SoCs
In-Reply-To: <1jh5w84iat.fsf@starbuckisacylon.baylibre.com>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>
 <b8105d25-112c-4406-9f3a-8fbbd0754b26@amlogic.com>
 <1jh5w84iat.fsf@starbuckisacylon.baylibre.com>
Message-ID: <7a5d3f57-4c0e-483c-9d6f-9556583180a7@amlogic.com>

Hi Jerome,


On 10/9/2025 3:59 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
>
> On Thu 09 Oct 2025 at 11:09, Chuan Liu <chuan.liu at amlogic.com> wrote:
>
>> Hi Jerome,
>>
>>      Thanks for your review, because the national day holidays did not
>> timely feedback.
>>
>>
>> On 10/1/2025 3:45 PM, Jerome Brunet wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>> On Tue 30 Sep 2025 at 17:37, Chuan Liu via B4 Relay
>>> <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>>>
>>>> This patch series includes changes related to the PLL and peripheral
>>>> clocks for both the A4 and A5 SoCs.
>>>>
>>>> The patches for A5 were previously submitted up to V3 by Xianwei.
>>>> https://lore.kernel.org/all/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com/
>>>> After friendly coordination, I?ve taken over and continued the
>>>> submission as part of this series. The dt-bindings patch retains Rob's
>>>> original "Reviewed-by" tag, and I hope this hasn?t caused any
>>>> additional confusion.
>>> ... and yet you restart the versioning of the series making it harder
>>> for people to follow that
>>
>> Sorry for the inconvenience caused. The main changes compared to the
>> previous version by Xianwei are in the driver part.
>>
>> The dt-bindings part only has minor modifications in [PATCH 14/19].
>>
>> The driver part has relatively larger changes because it needs to be
>> based on the code base you previously submitted.
> I'm not seeing a justification for the mess introduced and I'm not
> looking for one to be honest


Previously, I provided a basic version of the A5 clock driver to
Xianwei, and he helped improve it before submitting it.

Xianwei has been responsible for upstreaming many of our modules.
Since clock drivers require significant effort, I?m sharing the
workload by submitting some of the clock-related patches.

The three versions previously submitted by Xianwei mainly focused on
improving the dt-bindings based on Rob?s feedback. The driver part
remained unchanged.

The driver part in my current patch series has undergone relatively
large modifications to adapt to the latest code base, so comparing it
to the previous versions may not be very meaningful.

If it's more appropriate for the A5 clock-related patches to continue
evolving based on Xianwei's earlier v3 series, please feel free to
point it out. I will continue to assist Xianwei in completing the
submission of the remaining A5 clock patches.


>>>> Both A4 and A5 belong to the Audio series. Judging by their names, one
>>>> might assume that A5 is an upgrade to A4, but in fact, A5 was released
>>>> a year earlier than A4.
>>>>
>>>> Since there are differences in the PLLs and peripheral clocks between
>>>> the A4 and A5 SoCs (especially the PLL), and taking into account factors
>>>> such as memory footprint and maintainability, this series does not
>>>> attempt to merge the two into a shared driver as was done for
>>>> G12A/G12B/SM1.
>>> ... and we end up with 19 patches series while it could be splitted into
>>> manageable series, for each controller of each SoC
>>
>> I'm not sure if I understood you correctly.
>>
>> Do you mean that I should split this series of 19 patches into multiple
>> patch series and send them separately? For example:
>> serie 1: A4 SCMI clock controller (dt-bindings)
>> serie 2: A4 PLL clock controller (dt-bindings, driver, dts)
>> serie 3: A4 peripherals clock controller (dt-bindings, driver, dts)
>> ... A5 similarly?
> Things that do not actually depends on each other or which are not
> merged through the same tree should not be sent together. There is
> nothing new here. Same basic reminders on each submission.


Sorry, but I'm still not quite sure if I understood you correctly.

This series of 19 patches mainly falls into three major categories:
* Optimize PLL driver
* PLLs and peripherals for A4
* PLLs and peripherals for A5

Are you suggesting that the PLL driver part should be sent as a
separate patch series, while the A4 and A5 parts should still follow
the previous A5/C3-style submission?


>>
>>>> This patch series includes all related dt-bindings, driver, and dts
>>>> changes for the PLLs and peripheral clocks. Following our past convention
>>>> for clock-related submissions, the dts changes are placed at the end
>>>> and submitted separately. If this ordering makes it harder for
>>>> maintainers to review or pick patches, please feel free to point it out.
>>>>
>>>> Co-developed-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>>> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
>>>> ---
>>>> Chuan Liu (19):
>>>>         dt-bindings: clock: Add Amlogic A4 SCMI clock controller
>>>>         dt-bindings: clock: Add Amlogic A4 PLL clock controller
>>>>         dt-bindings: clock: Add Amlogic A4 peripherals clock controller
>>>>         clk: amlogic: Optimize PLL enable timing
>>>>         clk: amlogic: Correct l_detect bit control
>>>>         clk: amlogic: Fix out-of-range PLL frequency setting
>>>>         clk: amlogic: Add A4 PLL clock controller driver
>>>>         clk: amlogic: Add A4 clock peripherals controller driver
>>>>         arm64: dts: amlogic: A4: Add scmi-clk node
>>>>         arm64: dts: amlogic: A4: Add PLL controller node
>>>>         arm64: dts: amlogic: A4: Add peripherals clock controller node
>>>>         dt-bindings: clock: Add Amlogic A5 SCMI clock controller support
>>>>         dt-bindings: clock: Add Amlogic A5 PLL clock controller
>>>>         dt-bindings: clock: Add Amlogic A5 peripherals clock controller
>>>>         clk: amlogic: Add A5 PLL clock controller driver
>>>>         clk: amlogic: Add A5 clock peripherals controller driver
>>>>         arm64: dts: amlogic: A5: Add scmi-clk node
>>>>         arm64: dts: amlogic: A5: Add PLL controller node
>>>>         arm64: dts: amlogic: A5: Add peripheral clock controller node
>>>>
>>>>    .../clock/amlogic,a4-peripherals-clkc.yaml         | 122 +++
>>>>    .../bindings/clock/amlogic,a4-pll-clkc.yaml        |  61 ++
>>>>    .../clock/amlogic,a5-peripherals-clkc.yaml         | 134 ++++
>>>>    .../bindings/clock/amlogic,a5-pll-clkc.yaml        |  63 ++
>>>>    arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi        |  80 ++
>>>>    arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |  87 ++
>>>>    drivers/clk/meson/Kconfig                          |  53 ++
>>>>    drivers/clk/meson/Makefile                         |   4 +
>>>>    drivers/clk/meson/a1-pll.c                         |   1 +
>>>>    drivers/clk/meson/a4-peripherals.c                 | 764 ++++++++++++++++++
>>>>    drivers/clk/meson/a4-pll.c                         | 242 ++++++
>>>>    drivers/clk/meson/a5-peripherals.c                 | 883 +++++++++++++++++++++
>>>>    drivers/clk/meson/a5-pll.c                         | 476 +++++++++++
>>>>    drivers/clk/meson/clk-pll.c                        |  76 +-
>>>>    drivers/clk/meson/clk-pll.h                        |   2 +
>>>>    .../clock/amlogic,a4-peripherals-clkc.h            | 129 +++
>>>>    include/dt-bindings/clock/amlogic,a4-pll-clkc.h    |  15 +
>>>>    include/dt-bindings/clock/amlogic,a4-scmi-clkc.h   |  42 +
>>>>    .../clock/amlogic,a5-peripherals-clkc.h            | 132 +++
>>>>    include/dt-bindings/clock/amlogic,a5-pll-clkc.h    |  24 +
>>>>    include/dt-bindings/clock/amlogic,a5-scmi-clkc.h   |  44 +
>>>>    21 files changed, 3406 insertions(+), 28 deletions(-)
>>>> ---
>>>> base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
>>>> change-id: 20250928-a4_a5_add_clock_driver-2b7c9d695633
>>>>
>>>> Best regards,
>>> --
>>> Jerome
> --
> Jerome


From krzk at kernel.org  Thu Oct  9 19:42:25 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Fri, 10 Oct 2025 04:42:25 +0200
Subject: [PATCH 00/19] clk: amlogic: Add PLLs and peripheral clocks for A4
 and A5 SoCs
In-Reply-To: <7a5d3f57-4c0e-483c-9d6f-9556583180a7@amlogic.com>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>
 <b8105d25-112c-4406-9f3a-8fbbd0754b26@amlogic.com>
 <1jh5w84iat.fsf@starbuckisacylon.baylibre.com>
 <7a5d3f57-4c0e-483c-9d6f-9556583180a7@amlogic.com>
Message-ID: <c922430f-3efb-4c2a-8b10-b2f150db827f@kernel.org>

On 10/10/2025 04:38, Chuan Liu wrote:
> Hi Jerome,
> 
> 
> On 10/9/2025 3:59 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>> On Thu 09 Oct 2025 at 11:09, Chuan Liu <chuan.liu at amlogic.com> wrote:
>>
>>> Hi Jerome,
>>>
>>>      Thanks for your review, because the national day holidays did not
>>> timely feedback.
>>>
>>>
>>> On 10/1/2025 3:45 PM, Jerome Brunet wrote:
>>>> [ EXTERNAL EMAIL ]
>>>>
>>>> On Tue 30 Sep 2025 at 17:37, Chuan Liu via B4 Relay
>>>> <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>>>>
>>>>> This patch series includes changes related to the PLL and peripheral
>>>>> clocks for both the A4 and A5 SoCs.
>>>>>
>>>>> The patches for A5 were previously submitted up to V3 by Xianwei.
>>>>> https://lore.kernel.org/all/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com/
>>>>> After friendly coordination, I?ve taken over and continued the
>>>>> submission as part of this series. The dt-bindings patch retains Rob's
>>>>> original "Reviewed-by" tag, and I hope this hasn?t caused any
>>>>> additional confusion.
>>>> ... and yet you restart the versioning of the series making it harder
>>>> for people to follow that
>>>
>>> Sorry for the inconvenience caused. The main changes compared to the
>>> previous version by Xianwei are in the driver part.
>>>
>>> The dt-bindings part only has minor modifications in [PATCH 14/19].
>>>
>>> The driver part has relatively larger changes because it needs to be
>>> based on the code base you previously submitted.
>> I'm not seeing a justification for the mess introduced and I'm not
>> looking for one to be honest
> 
> 
> Previously, I provided a basic version of the A5 clock driver to
> Xianwei, and he helped improve it before submitting it.
> 
> Xianwei has been responsible for upstreaming many of our modules.
> Since clock drivers require significant effort, I?m sharing the
> workload by submitting some of the clock-related patches.
> 
> The three versions previously submitted by Xianwei mainly focused on
> improving the dt-bindings based on Rob?s feedback. The driver part
> remained unchanged.
> 
> The driver part in my current patch series has undergone relatively
> large modifications to adapt to the latest code base, so comparing it
> to the previous versions may not be very meaningful.
> 
> If it's more appropriate for the A5 clock-related patches to continue
> evolving based on Xianwei's earlier v3 series, please feel free to
> point it out. I will continue to assist Xianwei in completing the
> submission of the remaining A5 clock patches.
> 
> 
>>>>> Both A4 and A5 belong to the Audio series. Judging by their names, one
>>>>> might assume that A5 is an upgrade to A4, but in fact, A5 was released
>>>>> a year earlier than A4.
>>>>>
>>>>> Since there are differences in the PLLs and peripheral clocks between
>>>>> the A4 and A5 SoCs (especially the PLL), and taking into account factors
>>>>> such as memory footprint and maintainability, this series does not
>>>>> attempt to merge the two into a shared driver as was done for
>>>>> G12A/G12B/SM1.
>>>> ... and we end up with 19 patches series while it could be splitted into
>>>> manageable series, for each controller of each SoC
>>>
>>> I'm not sure if I understood you correctly.
>>>
>>> Do you mean that I should split this series of 19 patches into multiple
>>> patch series and send them separately? For example:
>>> serie 1: A4 SCMI clock controller (dt-bindings)
>>> serie 2: A4 PLL clock controller (dt-bindings, driver, dts)
>>> serie 3: A4 peripherals clock controller (dt-bindings, driver, dts)
>>> ... A5 similarly?
>> Things that do not actually depends on each other or which are not
>> merged through the same tree should not be sent together. There is
>> nothing new here. Same basic reminders on each submission.
> 
> 
> Sorry, but I'm still not quite sure if I understood you correctly.
> 
> This series of 19 patches mainly falls into three major categories:
> * Optimize PLL driver
> * PLLs and peripherals for A4
> * PLLs and peripherals for A5
> 
> Are you suggesting that the PLL driver part should be sent as a
> separate patch series, while the A4 and A5 parts should still follow
> the previous A5/C3-style submission?
> 

Please read submitting patches, soc maintainer profile and DT submitting
patches documents. You ask us to repeat same knowledge multiple times.
It's waste of our time, so we have documented it for your convenience.

Best regards,
Krzysztof


From lkp at intel.com  Thu Oct  9 21:21:07 2025
From: lkp at intel.com (kernel test robot)
Date: Fri, 10 Oct 2025 12:21:07 +0800
Subject: [PATCH 11/19] arm64: dts: amlogic: A4: Add peripherals clock
 controller node
In-Reply-To: <20250930-a4_a5_add_clock_driver-v1-11-a9acf7951589@amlogic.com>
References: <20250930-a4_a5_add_clock_driver-v1-11-a9acf7951589@amlogic.com>
Message-ID: <202510101124.3xwn3STp-lkp@intel.com>

Hi Chuan,

kernel test robot noticed the following build errors:

[auto build test ERROR on 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf]

url:    https://github.com/intel-lab-lkp/linux/commits/Chuan-Liu-via-B4-Relay/dt-bindings-clock-Add-Amlogic-A4-SCMI-clock-controller/20250930-174011
base:   01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
patch link:    https://lore.kernel.org/r/20250930-a4_a5_add_clock_driver-v1-11-a9acf7951589%40amlogic.com
patch subject: [PATCH 11/19] arm64: dts: amlogic: A4: Add peripherals clock controller node
config: arm64-allmodconfig (https://download.01.org/0day-ci/archive/20251010/202510101124.3xwn3STp-lkp at intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251010/202510101124.3xwn3STp-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510101124.3xwn3STp-lkp at intel.com/

All errors (new ones prefixed by >>):

   Error: arch/arm64/boot/dts/amlogic/amlogic-a4.dtsi:119.19-20 syntax error
>> FATAL ERROR: Unable to parse input tree

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From chuan.liu at amlogic.com  Thu Oct  9 23:15:21 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Fri, 10 Oct 2025 14:15:21 +0800
Subject: [PATCH 00/19] clk: amlogic: Add PLLs and peripheral clocks for A4
 and A5 SoCs
In-Reply-To: <c922430f-3efb-4c2a-8b10-b2f150db827f@kernel.org>
References: <20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589@amlogic.com>
 <1jv7kz3w1p.fsf@starbuckisacylon.baylibre.com>
 <b8105d25-112c-4406-9f3a-8fbbd0754b26@amlogic.com>
 <1jh5w84iat.fsf@starbuckisacylon.baylibre.com>
 <7a5d3f57-4c0e-483c-9d6f-9556583180a7@amlogic.com>
 <c922430f-3efb-4c2a-8b10-b2f150db827f@kernel.org>
Message-ID: <362b6daf-6b2c-4385-88b3-f2dda38f6612@amlogic.com>

Hi Krzysztof,

Sorry for bothering you unintentionally. I haven't fully understood
some of the details yet, I'll do my best to work through them.

Thanks again for your reminder.

On 10/10/2025 10:42 AM, Krzysztof Kozlowski wrote:
> [ EXTERNAL EMAIL ]
> 
> On 10/10/2025 04:38, Chuan Liu wrote:
>> Hi Jerome,
>>
>>
>> On 10/9/2025 3:59 PM, Jerome Brunet wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>> On Thu 09 Oct 2025 at 11:09, Chuan Liu <chuan.liu at amlogic.com> wrote:
>>>
>>>> Hi Jerome,
>>>>
>>>>       Thanks for your review, because the national day holidays did not
>>>> timely feedback.
>>>>
>>>>
>>>> On 10/1/2025 3:45 PM, Jerome Brunet wrote:
>>>>> [ EXTERNAL EMAIL ]
>>>>>
>>>>> On Tue 30 Sep 2025 at 17:37, Chuan Liu via B4 Relay
>>>>> <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>>>>>
>>>>>> This patch series includes changes related to the PLL and peripheral
>>>>>> clocks for both the A4 and A5 SoCs.
>>>>>>
>>>>>> The patches for A5 were previously submitted up to V3 by Xianwei.
>>>>>> https://lore.kernel.org/all/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com/
>>>>>> After friendly coordination, I?ve taken over and continued the
>>>>>> submission as part of this series. The dt-bindings patch retains Rob's
>>>>>> original "Reviewed-by" tag, and I hope this hasn?t caused any
>>>>>> additional confusion.
>>>>> ... and yet you restart the versioning of the series making it harder
>>>>> for people to follow that
>>>>
>>>> Sorry for the inconvenience caused. The main changes compared to the
>>>> previous version by Xianwei are in the driver part.
>>>>
>>>> The dt-bindings part only has minor modifications in [PATCH 14/19].
>>>>
>>>> The driver part has relatively larger changes because it needs to be
>>>> based on the code base you previously submitted.
>>> I'm not seeing a justification for the mess introduced and I'm not
>>> looking for one to be honest
>>
>>
>> Previously, I provided a basic version of the A5 clock driver to
>> Xianwei, and he helped improve it before submitting it.
>>
>> Xianwei has been responsible for upstreaming many of our modules.
>> Since clock drivers require significant effort, I?m sharing the
>> workload by submitting some of the clock-related patches.
>>
>> The three versions previously submitted by Xianwei mainly focused on
>> improving the dt-bindings based on Rob?s feedback. The driver part
>> remained unchanged.
>>
>> The driver part in my current patch series has undergone relatively
>> large modifications to adapt to the latest code base, so comparing it
>> to the previous versions may not be very meaningful.
>>
>> If it's more appropriate for the A5 clock-related patches to continue
>> evolving based on Xianwei's earlier v3 series, please feel free to
>> point it out. I will continue to assist Xianwei in completing the
>> submission of the remaining A5 clock patches.
>>
>>
>>>>>> Both A4 and A5 belong to the Audio series. Judging by their names, one
>>>>>> might assume that A5 is an upgrade to A4, but in fact, A5 was released
>>>>>> a year earlier than A4.
>>>>>>
>>>>>> Since there are differences in the PLLs and peripheral clocks between
>>>>>> the A4 and A5 SoCs (especially the PLL), and taking into account factors
>>>>>> such as memory footprint and maintainability, this series does not
>>>>>> attempt to merge the two into a shared driver as was done for
>>>>>> G12A/G12B/SM1.
>>>>> ... and we end up with 19 patches series while it could be splitted into
>>>>> manageable series, for each controller of each SoC
>>>>
>>>> I'm not sure if I understood you correctly.
>>>>
>>>> Do you mean that I should split this series of 19 patches into multiple
>>>> patch series and send them separately? For example:
>>>> serie 1: A4 SCMI clock controller (dt-bindings)
>>>> serie 2: A4 PLL clock controller (dt-bindings, driver, dts)
>>>> serie 3: A4 peripherals clock controller (dt-bindings, driver, dts)
>>>> ... A5 similarly?
>>> Things that do not actually depends on each other or which are not
>>> merged through the same tree should not be sent together. There is
>>> nothing new here. Same basic reminders on each submission.
>>
>>
>> Sorry, but I'm still not quite sure if I understood you correctly.
>>
>> This series of 19 patches mainly falls into three major categories:
>> * Optimize PLL driver
>> * PLLs and peripherals for A4
>> * PLLs and peripherals for A5
>>
>> Are you suggesting that the PLL driver part should be sent as a
>> separate patch series, while the A4 and A5 parts should still follow
>> the previous A5/C3-style submission?
>>
> 
> Please read submitting patches, soc maintainer profile and DT submitting
> patches documents. You ask us to repeat same knowledge multiple times.
> It's waste of our time, so we have documented it for your convenience.
> 
> Best regards,
> Krzysztof



From vignesh.raman at collabora.com  Sun Oct 12 23:02:10 2025
From: vignesh.raman at collabora.com (Vignesh Raman)
Date: Mon, 13 Oct 2025 11:32:10 +0530
Subject: [PATCH v1] drm/ci: disable broken MR check in sanity job
Message-ID: <20251013060212.14583-1-vignesh.raman@collabora.com>

GitLab recently changed the required permissions for the
are-developers-allowed-to-push-to-my-MR check:
https://gitlab.freedesktop.org/freedesktop/ci-templates/-/issues/81

Until that?s resolved, disable the check - it?s mostly obsolete anyway.

Based on https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37782

Signed-off-by: Vignesh Raman <vignesh.raman at collabora.com>
---
 drivers/gpu/drm/ci/gitlab-ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml
index d502d146b177..56638814bb28 100644
--- a/drivers/gpu/drm/ci/gitlab-ci.yml
+++ b/drivers/gpu/drm/ci/gitlab-ci.yml
@@ -280,7 +280,7 @@ sanity:
     GIT_STRATEGY: none
   script:
     # ci-fairy check-commits --junit-xml=check-commits.xml
-    - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request.xml
+    # - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request.xml
     - |
       set -eu
       image_tags=(
-- 
2.51.0



From devnull+xianwei.zhao.amlogic.com at kernel.org  Wed Oct 15 00:36:59 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 15 Oct 2025 15:36:59 +0800
Subject: [PATCH] spi: amlogic: fix spifc build error
Message-ID: <20251015-fix-spifc-a4-v1-1-08e0900e5b7e@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

There is an error building when
Compiler version: gcc (GCC) 14.3.0
Assembler version: GNU assembler (GNU Binutils) 2.44
"
 Error log:
 WARNING: modpost: missing MODULE_DESCRIPTION() in arch/arm/probes/kprobes/test-kprobes.o
 ERROR: modpost: "__ffsdi2" [drivers/spi/spi-amlogic-spifc-a4.ko] undefined!
"

Use __ffs API instead of __bf_shf to be safer.

Reported-by: Guenter Roeck <linux at roeck-us.net>
Closes: https://lore.kernel.org/all/f594c621-f9e1-49f2-af31-23fbcb176058 at roeck-us.net/
Fixes: 4670db6f32e9 ("spi: amlogic: add driver for Amlogic SPI Flash Controller")
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
Fix build err for spifc.
---
 drivers/spi/spi-amlogic-spifc-a4.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-amlogic-spifc-a4.c b/drivers/spi/spi-amlogic-spifc-a4.c
index 4338d00e56a6..35a7c4965e11 100644
--- a/drivers/spi/spi-amlogic-spifc-a4.c
+++ b/drivers/spi/spi-amlogic-spifc-a4.c
@@ -286,7 +286,7 @@ static int aml_sfc_set_bus_width(struct aml_sfc *sfc, u8 buswidth, u32 mask)
 
 	for (i = 0; i <= LANE_MAX; i++) {
 		if (buswidth == 1 << i) {
-			conf = i << __bf_shf(mask);
+			conf = i << __ffs(mask);
 			return regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG,
 						  mask, conf);
 		}
@@ -566,7 +566,7 @@ static int aml_sfc_raw_io_op(struct aml_sfc *sfc, const struct spi_mem_op *op)
 	if (!op->data.nbytes)
 		goto end_xfer;
 
-	conf = (op->data.nbytes >> RAW_SIZE_BW) << __bf_shf(RAW_EXT_SIZE);
+	conf = (op->data.nbytes >> RAW_SIZE_BW) << __ffs(RAW_EXT_SIZE);
 	ret = regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG, RAW_EXT_SIZE, conf);
 	if (ret)
 		goto err_out;

---
base-commit: 4412ab501677606436e5c49e41151a1e6eac7ac0
change-id: 20251015-fix-spifc-a4-0836ee1d0066

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From laurent.pinchart at ideasonboard.com  Wed Oct 15 00:53:23 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Wed, 15 Oct 2025 10:53:23 +0300
Subject: [PATCH v2 00/25] media: v4l2-mem2mem: Reduce cargo-cult
Message-ID: <20251015075353.22625-1-laurent.pinchart@ideasonboard.com>

Hello,

The v4l2_m2m_get_vq() function never returns NULL, but many mem2mem
drivers still check its return value and consider NULL as an error. This
may have originated a long time ago from valid checks when
v4l2_m2m_get_vq() could return NULL, with drivers then just copying the
checks. This series attempts to stop the cargo-cult behaviour.

Patch 01/25 starts by explicitly stating in kerneldoc that the
v4l2_m2m_get_vq() function never returns NULL. All the other patches
drop NULL checks from drivers.

I have carefully checked all patched locations in all drivers. They fall
in 3 categories:

- Checks in the VIDIOC_G_FMT, VIDIOC_TRY_FMT and VIDIOC_S_FMT handlers:
  Those may have been added to ensure that the format type has a valid
  value, but that is ensured by the V4L2 ioctl core before calling the
  handlers. The checks can be dropped without a need to replace them
  with proper type checks.

- Checks in the VIDIOC_S_SELECTION handler: The only location where this
  is performed has an explicit type check, so the NULL check can also be
  dropped.

- Checks in other locations where the type parameter to the
  v4l2_m2m_get_vq() function is hardcoded: The hardcoded type is valid,
  so the NULL check can't have been meant to check the type. It can also
  be removed.

There's no dependency between any of those patches so they can be merged
in any order.

Compared to v1, this version drops two more NULL checks, in the Mediatek
vcodec encoder get format handler (09/25) and the Qualcomm iris venc set
format handler (15/25).

Laurent Pinchart (25):
  media: v4l2-mem2mem: Document that v4l2_m2m_get_vq() never returns
    NULL
  media: allgro-dvt: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: meson-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: amphion: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: coda: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: imagination: e5010: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: m2m-deinterlace: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: mediatek: jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: mediatek: vcodec: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: dw100: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: imx-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: imx-pxp: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: nxp: imx8-isi: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: mx2_emmaprp: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: qcom: iris: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: qcom: venus: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: renesas: fdp1: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: rcar_jpu: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: platform: rga: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: samsung: s5p-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: samsung: s5p-jpeg: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: stm32: dma2d: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: ti: vpe: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: vicodec: Drop unneeded v4l2_m2m_get_vq() NULL check
  media: vim2m: Drop unneeded v4l2_m2m_get_vq() NULL check

 drivers/media/platform/allegro-dvt/allegro-core.c  |  2 --
 drivers/media/platform/amlogic/meson-ge2d/ge2d.c   |  5 -----
 drivers/media/platform/amphion/vdec.c              |  2 --
 drivers/media/platform/amphion/venc.c              |  2 --
 .../media/platform/chips-media/coda/coda-common.c  |  4 ----
 .../media/platform/imagination/e5010-jpeg-enc.c    |  4 ----
 drivers/media/platform/m2m-deinterlace.c           |  7 -------
 .../media/platform/mediatek/jpeg/mtk_jpeg_core.c   |  7 -------
 .../mediatek/vcodec/decoder/mtk_vcodec_dec.c       |  7 -------
 .../vcodec/decoder/vdec/vdec_av1_req_lat_if.c      |  2 --
 .../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c      |  2 --
 .../mediatek/vcodec/encoder/mtk_vcodec_enc.c       | 14 --------------
 drivers/media/platform/nxp/dw100/dw100.c           |  7 -------
 drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c     |  4 ----
 drivers/media/platform/nxp/imx-pxp.c               |  7 -------
 drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c |  2 --
 drivers/media/platform/nxp/mx2_emmaprp.c           |  7 -------
 drivers/media/platform/qcom/iris/iris_vdec.c       |  2 --
 drivers/media/platform/qcom/iris/iris_venc.c       |  2 --
 drivers/media/platform/qcom/venus/vdec.c           |  2 --
 drivers/media/platform/qcom/venus/venc.c           |  2 --
 drivers/media/platform/renesas/rcar_fdp1.c         |  3 ---
 drivers/media/platform/renesas/rcar_jpu.c          |  8 --------
 drivers/media/platform/rockchip/rga/rga.c          |  4 ----
 drivers/media/platform/samsung/s5p-g2d/g2d.c       |  4 ----
 .../media/platform/samsung/s5p-jpeg/jpeg-core.c    |  7 -------
 drivers/media/platform/st/stm32/dma2d/dma2d.c      |  5 -----
 drivers/media/platform/ti/vpe/vpe.c                |  7 -------
 drivers/media/test-drivers/vicodec/vicodec-core.c  |  7 -------
 drivers/media/test-drivers/vim2m.c                 | 12 ------------
 drivers/media/v4l2-core/v4l2-mem2mem.c             | 12 +-----------
 include/media/v4l2-mem2mem.h                       |  3 +++
 32 files changed, 4 insertions(+), 161 deletions(-)


base-commit: 082b86919b7a94de01d849021b4da820a6cb89dc
-- 
Regards,

Laurent Pinchart



From laurent.pinchart at ideasonboard.com  Wed Oct 15 00:53:26 2025
From: laurent.pinchart at ideasonboard.com (Laurent Pinchart)
Date: Wed, 15 Oct 2025 10:53:26 +0300
Subject: [PATCH v2 03/25] media: meson-g2d: Drop unneeded v4l2_m2m_get_vq() NULL check
In-Reply-To: <20251015075353.22625-1-laurent.pinchart@ideasonboard.com>
References: <20251015075353.22625-1-laurent.pinchart@ideasonboard.com>
Message-ID: <20251015075353.22625-4-laurent.pinchart@ideasonboard.com>

The v4l2_m2m_get_vq() function never returns NULL. The check was
probably intended to catch invalid format types, but that's not needed
as the V4L2 core picks the appropriate VIDIOC_G_FMT ioctl handler based
on the format type, so the type can't be incorrect. Drop the unneeded
return value check and, as the return value is not used for other
purposes and the function has no side effect, the function call as well.

Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>
---
 drivers/media/platform/amlogic/meson-ge2d/ge2d.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
index 5744853a4003..c51c6f4e41dc 100644
--- a/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
+++ b/drivers/media/platform/amlogic/meson-ge2d/ge2d.c
@@ -632,13 +632,8 @@ static int vidioc_s_fmt_cap(struct file *file, void *priv, struct v4l2_format *f
 static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
 	struct ge2d_ctx *ctx = file_to_ge2d_ctx(file);
-	struct vb2_queue *vq;
 	struct ge2d_frame *frm;
 
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-	if (!vq)
-		return -EINVAL;
-
 	frm = get_frame(ctx, f->type);
 
 	f->fmt.pix = frm->pix_fmt;
-- 
Regards,

Laurent Pinchart



From daniel at fooishbar.org  Wed Oct 15 05:03:53 2025
From: daniel at fooishbar.org (Daniel Stone)
Date: Wed, 15 Oct 2025 13:03:53 +0100
Subject: [PATCH v1 0/7] drm/ci: add new jobs, uprev IGT and mesa
In-Reply-To: <20250718105407.32878-1-vignesh.raman@collabora.com>
References: <20250718105407.32878-1-vignesh.raman@collabora.com>
Message-ID: <CAPj87rMRKdm4BvfD8gMmSF3jjeMK4nurzTKPOFY15V0tBr4pyw@mail.gmail.com>

Hi VIgnesh,

On Fri, 18 Jul 2025 at 11:54, Vignesh Raman <vignesh.raman at collabora.com> wrote:
> This series introduces new jobs to drm-ci for testing the following
> devices:
> - rk3588-rock-5b
> - mt8192-asurada-spherion-r0
>
> Other updates include:
> - Uprev IGT and updating test expectations accordingly.
> - Adapting to recent changes in Mesa CI, such as:
>    - LAVA overlay-based firmware handling
>    - Container/job rule separation
>    - Removal of the python-artifacts job
>    - Use of the Alpine container for LAVA jobs
>    - Various other CI improvements
> - Disabling bare-metal jobs for apq8016 and apq8096, as these devices
>   are being migrated to LAVA.
> - Updating the runner tag for i915: cml (switching from hatch to puff)
>   to improve device availability.
> - Adjusting parallelism in jobs (sm8350-hdk, amly) to better utilize
>   test resources.

Series is:
Reviewed-by: Daniel Stone <daniels at collabora.com>

Cheers,
Daniel


From daniel at fooishbar.org  Wed Oct 15 05:04:18 2025
From: daniel at fooishbar.org (Daniel Stone)
Date: Wed, 15 Oct 2025 13:04:18 +0100
Subject: [PATCH v1] drm/ci: disable broken MR check in sanity job
In-Reply-To: <20251013060212.14583-1-vignesh.raman@collabora.com>
References: <20251013060212.14583-1-vignesh.raman@collabora.com>
Message-ID: <CAPj87rPDppYBRuQ99mh=VqrsSErGKcw-ZRY+zPuGrDj77G5k6Q@mail.gmail.com>

Hi Vignesh,

On Mon, 13 Oct 2025 at 07:02, Vignesh Raman <vignesh.raman at collabora.com> wrote:
> GitLab recently changed the required permissions for the
> are-developers-allowed-to-push-to-my-MR check:
> https://gitlab.freedesktop.org/freedesktop/ci-templates/-/issues/81
>
> Until that?s resolved, disable the check - it?s mostly obsolete anyway.
>
> Based on https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37782

Thanks for fixing this.

Reviewed-by: Daniel Stone <daniels at collabora.com>

Cheers,
Daniel


From broonie at kernel.org  Wed Oct 15 11:40:41 2025
From: broonie at kernel.org (Mark Brown)
Date: Wed, 15 Oct 2025 19:40:41 +0100
Subject: [PATCH] spi: amlogic: fix spifc build error
In-Reply-To: <20251015-fix-spifc-a4-v1-1-08e0900e5b7e@amlogic.com>
References: <20251015-fix-spifc-a4-v1-1-08e0900e5b7e@amlogic.com>
Message-ID: <176055364173.227902.13691115706455809982.b4-ty@kernel.org>

On Wed, 15 Oct 2025 15:36:59 +0800, Xianwei Zhao wrote:
> There is an error building when
> Compiler version: gcc (GCC) 14.3.0
> Assembler version: GNU assembler (GNU Binutils) 2.44
> "
>  Error log:
>  WARNING: modpost: missing MODULE_DESCRIPTION() in arch/arm/probes/kprobes/test-kprobes.o
>  ERROR: modpost: "__ffsdi2" [drivers/spi/spi-amlogic-spifc-a4.ko] undefined!
> "
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: amlogic: fix spifc build error
      commit: 6b6e03106163458716c47df2baa9ad08ed4ddb0e

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



From rob.clark at oss.qualcomm.com  Thu Oct 16 07:52:23 2025
From: rob.clark at oss.qualcomm.com (Rob Clark)
Date: Thu, 16 Oct 2025 07:52:23 -0700
Subject: [PATCH v1 1/7] drm/ci: disable apq8016 and apq8096 bare-metal jobs
In-Reply-To: <20250718105407.32878-2-vignesh.raman@collabora.com>
References: <20250718105407.32878-1-vignesh.raman@collabora.com> <20250718105407.32878-2-vignesh.raman@collabora.com>
Message-ID: <CACSVV029ueL_4Y5irmmOwy_9QDQGqDe_1wCGUe22FdefQiNjkw@mail.gmail.com>

On Fri, Jul 18, 2025 at 3:54?AM Vignesh Raman
<vignesh.raman at collabora.com> wrote:
>
> These devices are being moved to LAVA. The jobs will be enabled and the
> job definitions will be updated once the move is complete.

fwiw, the runners are up and running in LAVA now

BR,
-R

> Signed-off-by: Vignesh Raman <vignesh.raman at collabora.com>
> ---
>  drivers/gpu/drm/ci/test.yml | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
> index 81147e86bfd0..53d19ffaaf61 100644
> --- a/drivers/gpu/drm/ci/test.yml
> +++ b/drivers/gpu/drm/ci/test.yml
> @@ -148,7 +148,9 @@ msm:sc7180-trogdor-kingoftown:
>      GPU_VERSION: ${DEVICE_TYPE}
>      RUNNER_TAG: mesa-ci-x86-64-lava-sc7180-trogdor-kingoftown
>
> -msm:apq8016:
> +# FIXME: Disable the bare-metal jobs. These devices are being moved to LAVA.
> +# Once the move is complete, update the job definitions accordingly.
> +.msm:apq8016:
>    extends:
>      - .baremetal-igt-arm64
>    stage: msm
> @@ -165,7 +167,7 @@ msm:apq8016:
>    script:
>      - ./install/bare-metal/fastboot.sh || exit $?
>
> -msm:apq8096:
> +.msm:apq8096:
>    extends:
>      - .baremetal-igt-arm64
>    stage: msm
> --
> 2.47.2
>


From vignesh.raman at collabora.com  Fri Oct 17 00:31:24 2025
From: vignesh.raman at collabora.com (Vignesh Raman)
Date: Fri, 17 Oct 2025 13:01:24 +0530
Subject: [PATCH v1 1/7] drm/ci: disable apq8016 and apq8096 bare-metal
 jobs
In-Reply-To: <CACSVV029ueL_4Y5irmmOwy_9QDQGqDe_1wCGUe22FdefQiNjkw@mail.gmail.com>
References: <20250718105407.32878-1-vignesh.raman@collabora.com>
 <20250718105407.32878-2-vignesh.raman@collabora.com>
 <CACSVV029ueL_4Y5irmmOwy_9QDQGqDe_1wCGUe22FdefQiNjkw@mail.gmail.com>
Message-ID: <6769d162-ab1c-4427-a0be-22c0b62673c3@collabora.com>

Hi Rob,

On 16/10/25 20:22, Rob Clark wrote:
> On Fri, Jul 18, 2025 at 3:54?AM Vignesh Raman
> <vignesh.raman at collabora.com> wrote:
>>
>> These devices are being moved to LAVA. The jobs will be enabled and the
>> job definitions will be updated once the move is complete.
> 
> fwiw, the runners are up and running in LAVA now

Thanks. I will enable them and send v2.

Regards,
Vignesh

> 
> BR,
> -R
> 
>> Signed-off-by: Vignesh Raman <vignesh.raman at collabora.com>
>> ---
>>   drivers/gpu/drm/ci/test.yml | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
>> index 81147e86bfd0..53d19ffaaf61 100644
>> --- a/drivers/gpu/drm/ci/test.yml
>> +++ b/drivers/gpu/drm/ci/test.yml
>> @@ -148,7 +148,9 @@ msm:sc7180-trogdor-kingoftown:
>>       GPU_VERSION: ${DEVICE_TYPE}
>>       RUNNER_TAG: mesa-ci-x86-64-lava-sc7180-trogdor-kingoftown
>>
>> -msm:apq8016:
>> +# FIXME: Disable the bare-metal jobs. These devices are being moved to LAVA.
>> +# Once the move is complete, update the job definitions accordingly.
>> +.msm:apq8016:
>>     extends:
>>       - .baremetal-igt-arm64
>>     stage: msm
>> @@ -165,7 +167,7 @@ msm:apq8016:
>>     script:
>>       - ./install/bare-metal/fastboot.sh || exit $?
>>
>> -msm:apq8096:
>> +.msm:apq8096:
>>     extends:
>>       - .baremetal-igt-arm64
>>     stage: msm
>> --
>> 2.47.2
>>



From vulab at iscas.ac.cn  Mon Oct 20 08:09:56 2025
From: vulab at iscas.ac.cn (Haotian Zhang)
Date: Mon, 20 Oct 2025 23:09:56 +0800
Subject: [PATCH] rtc: amlogic-a4: fix double free caused by devm
Message-ID: <20251020150956.491-1-vulab@iscas.ac.cn>

The clock obtained via devm_clk_get_enabled() is automatically managed
by devres and will be disabled and freed on driver detach. Manually
calling clk_disable_unprepare() in error path and remove function
causes double free.

Remove the redundant clk_disable_unprepare() calls from the probe
error path and aml_rtc_remove(), allowing the devm framework to
automatically manage the clock lifecycle.

Fixes: c89ac9182ee2 ("rtc: support for the Amlogic on-chip RTC")
Signed-off-by: Haotian Zhang <vulab at iscas.ac.cn>
---
 drivers/rtc/rtc-amlogic-a4.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
index 1928b29c1045..ed36b649c057 100644
--- a/drivers/rtc/rtc-amlogic-a4.c
+++ b/drivers/rtc/rtc-amlogic-a4.c
@@ -390,7 +390,6 @@ static int aml_rtc_probe(struct platform_device *pdev)
 
 	return 0;
 err_clk:
-	clk_disable_unprepare(rtc->sys_clk);
 	device_init_wakeup(dev, false);
 
 	return ret;
@@ -425,7 +424,6 @@ static void aml_rtc_remove(struct platform_device *pdev)
 {
 	struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
 
-	clk_disable_unprepare(rtc->sys_clk);
 	device_init_wakeup(&pdev->dev, false);
 }
 
-- 
2.25.1



From magdalena.koladczyk at zynotix.com  Tue Oct 21 00:40:46 2025
From: magdalena.koladczyk at zynotix.com (=?UTF-8?Q? Magdalena_Ko=C5=82adczyk ?=)
Date: Tue, 21 Oct 2025 07:40:46 GMT
Subject: =?UTF-8?Q?Informacja_z_ksi=C4=99gowo=C5=9Bci?=
Message-ID: <20251021084501-0.1.ck.uoi2.0.2k3d751fqt@zynotix.com>

Dzie? dobry,

prowadz? biuro ksi?gowe, kt?re specjalizuje si? w obs?udze biznesu Pa?stwa formatu.

Wraz z zespo?em zapewniamy wsparcie, kt?re wykracza daleko poza samo przygotowanie rozlicze? i procesowanie dokumentacji.

Redukujemy do minimum czas i ?rodki, jakie nasi Klienci przeznaczaj? na obs?ug? finansowo-ksi?gow? i kadrowo-p?acow?. 

Z racji mojego do?wiadczenia przy wsp??pracy z firmami o takim rodzaju dzia?alno?ci, chcia?abym przedstawi? kilka warto?ciowych i sprawdzonych rozwi?za?.

Czy mo?emy porozmawia? o obs?udze Pa?stwa firmy?

Pozdrawiam
Magdalena Ko?adczyk


From adrian.liszka at proventix.pl  Tue Oct 21 00:50:26 2025
From: adrian.liszka at proventix.pl (Adrian Liszka)
Date: Tue, 21 Oct 2025 07:50:26 GMT
Subject: =?UTF-8?Q?Prosz=C4=99_o_kontakt?=
Message-ID: <20251021084500-0.1.om.3jwmp.0.bg7tm840h5@proventix.pl>

Dzie? dobry,

Czy jest mo?liwo?? nawi?zania wsp??pracy z Pa?stwem?

Z ch?ci? porozmawiam z osob? zajmuj?c? si? dzia?aniami zwi?zanymi ze sprzeda??.

Pomagamy skutecznie pozyskiwa? nowych klient?w.

Zapraszam do kontaktu.


Z pozdrowieniami
Adrian Liszka


From lkp at intel.com  Tue Oct 21 02:29:38 2025
From: lkp at intel.com (kernel test robot)
Date: Tue, 21 Oct 2025 17:29:38 +0800
Subject: [PATCH] rtc: amlogic-a4: fix double free caused by devm
In-Reply-To: <20251020150956.491-1-vulab@iscas.ac.cn>
References: <20251020150956.491-1-vulab@iscas.ac.cn>
Message-ID: <202510211756.vnQ8ZIWo-lkp@intel.com>

Hi Haotian,

kernel test robot noticed the following build warnings:

[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on linus/master v6.18-rc2 next-20251021]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Haotian-Zhang/rtc-amlogic-a4-fix-double-free-caused-by-devm/20251020-231345
base:   https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
patch link:    https://lore.kernel.org/r/20251020150956.491-1-vulab%40iscas.ac.cn
patch subject: [PATCH] rtc: amlogic-a4: fix double free caused by devm
config: i386-buildonly-randconfig-002-20251021 (https://download.01.org/0day-ci/archive/20251021/202510211756.vnQ8ZIWo-lkp at intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251021/202510211756.vnQ8ZIWo-lkp at intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp at intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510211756.vnQ8ZIWo-lkp at intel.com/

All warnings (new ones prefixed by >>):

>> drivers/rtc/rtc-amlogic-a4.c:425:23: warning: unused variable 'rtc' [-Wunused-variable]
     425 |         struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
         |                              ^~~
   1 warning generated.


vim +/rtc +425 drivers/rtc/rtc-amlogic-a4.c

c89ac9182ee297 Yiting Deng  2024-11-12  419  
c89ac9182ee297 Yiting Deng  2024-11-12  420  static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
c89ac9182ee297 Yiting Deng  2024-11-12  421  			 aml_rtc_suspend, aml_rtc_resume);
c89ac9182ee297 Yiting Deng  2024-11-12  422  
c89ac9182ee297 Yiting Deng  2024-11-12  423  static void aml_rtc_remove(struct platform_device *pdev)
c89ac9182ee297 Yiting Deng  2024-11-12  424  {
c89ac9182ee297 Yiting Deng  2024-11-12 @425  	struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
c89ac9182ee297 Yiting Deng  2024-11-12  426  
8c28c4993f117e Wolfram Sang 2024-12-17  427  	device_init_wakeup(&pdev->dev, false);
c89ac9182ee297 Yiting Deng  2024-11-12  428  }
c89ac9182ee297 Yiting Deng  2024-11-12  429  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


From vulab at iscas.ac.cn  Tue Oct 21 03:35:59 2025
From: vulab at iscas.ac.cn (Haotian Zhang)
Date: Tue, 21 Oct 2025 18:35:59 +0800
Subject: [PATCH v2] rtc: amlogic-a4: fix double free caused by devm
In-Reply-To: <20251020150956.491-1-vulab@iscas.ac.cn>
References: <20251020150956.491-1-vulab@iscas.ac.cn>
Message-ID: <20251021103559.1903-1-vulab@iscas.ac.cn>

The clock obtained via devm_clk_get_enabled() is automatically managed
by devres and will be disabled and freed on driver detach. Manually
calling clk_disable_unprepare() in error path and remove function
causes double free.

Remove the redundant clk_disable_unprepare() calls from the probe
error path and aml_rtc_remove(), allowing the devm framework to
automatically manage the clock lifecycle.

Fixes: c89ac9182ee2 ("rtc: support for the Amlogic on-chip RTC")
Signed-off-by: Haotian Zhang <vulab at iscas.ac.cn>
---
v2: Also remove the now-unused local variable 'rtc' in aml_rtc_remove()
---
 drivers/rtc/rtc-amlogic-a4.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
index 1928b29c1045..a993d35e1d6b 100644
--- a/drivers/rtc/rtc-amlogic-a4.c
+++ b/drivers/rtc/rtc-amlogic-a4.c
@@ -390,7 +390,6 @@ static int aml_rtc_probe(struct platform_device *pdev)
 
 	return 0;
 err_clk:
-	clk_disable_unprepare(rtc->sys_clk);
 	device_init_wakeup(dev, false);
 
 	return ret;
@@ -423,9 +422,6 @@ static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
 
 static void aml_rtc_remove(struct platform_device *pdev)
 {
-	struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
-
-	clk_disable_unprepare(rtc->sys_clk);
 	device_init_wakeup(&pdev->dev, false);
 }
 
-- 
2.25.1



From neil.armstrong at linaro.org  Tue Oct 21 05:23:54 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 21 Oct 2025 14:23:54 +0200
Subject: [PATCH v3 2/2] dts: arm64: amlogic: add a5 pinctrl node
In-Reply-To: <6ebddeb4-b33f-4392-b5da-56501b38fd6d@amlogic.com>
References: <20250403-a5-pinctrl-v3-0-a8c067e22295@amlogic.com>
 <20250403-a5-pinctrl-v3-2-a8c067e22295@amlogic.com>
 <6ebddeb4-b33f-4392-b5da-56501b38fd6d@amlogic.com>
Message-ID: <263b86c9-61da-4d5e-af3d-4b9105112d82@linaro.org>

Hi,


On 9/5/25 05:19, Xianwei Zhao wrote:
> Hi Neil,
>  ?? Could you please take some time to review this submission?

Could you rebase on v6.18-rc1 ?

Thanks,
Neil

> 
> On 2025/4/3 16:33, Xianwei Zhao via B4 Relay wrote:
>> [ EXTERNAL EMAIL ]
>>
>> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>
>> Add pinctrl device to support Amlogic A5.
>>
>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>> ---
>> ? arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 90 +++++++++++++++++++++++++++++
>> ? 1 file changed, 90 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
>> index 32ed1776891b..844302db2133 100644
>> --- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
>> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
>> @@ -4,6 +4,7 @@
>> ?? */
>>
>> ? #include "amlogic-a4-common.dtsi"
>> +#include <dt-bindings/pinctrl/amlogic,pinctrl.h>
>> ? #include <dt-bindings/power/amlogic,a5-pwrc.h>
>> ? / {
>> ???????? cpus {
>> @@ -50,6 +51,95 @@ pwrc: power-controller {
>> ? };
>>
>> ? &apb {
>> +?????? periphs_pinctrl: pinctrl at 4000 {
>> +?????????????? compatible = "amlogic,pinctrl-a5",
>> +??????????????????????????? "amlogic,pinctrl-a4";
>> +?????????????? #address-cells = <2>;
>> +?????????????? #size-cells = <2>;
>> +?????????????? ranges = <0x0 0x0 0x0 0x4000 0x0 0x300>;
>> +
>> +?????????????? gpioz: gpio at c0 {
>> +?????????????????????? reg = <0x0 0xc0 0x0 0x40>,
>> +???????????????????????????? <0x0 0x18 0x0 0x8>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_Z<<8) 16>;
>> +?????????????? };
>> +
>> +?????????????? gpiox: gpio at 100 {
>> +?????????????????????? reg = <0x0 0x100 0x0 0x40>,
>> +???????????????????????????? <0x0 0xc?? 0x0 0xc>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_X<<8) 20>;
>> +?????????????? };
>> +
>> +?????????????? gpiot: gpio at 140 {
>> +?????????????????????? reg = <0x0 0x140 0x0 0x40>,
>> +???????????????????????????? <0x0 0x2c? 0x0 0x8>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_T<<8) 14>;
>> +?????????????? };
>> +
>> +?????????????? gpiod: gpio at 180 {
>> +?????????????????????? reg = <0x0 0x180 0x0 0x40>,
>> +???????????????????????????? <0x0 0x40? 0x0 0x8>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_D<<8) 16>;
>> +?????????????? };
>> +
>> +?????????????? gpioe: gpio at 1c0 {
>> +?????????????????????? reg = <0x0 0x1c0 0x0 0x40>,
>> +???????????????????????????? <0x0 0x48? 0x0 0x4>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_E<<8) 2>;
>> +?????????????? };
>> +
>> +?????????????? gpioc: gpio at 200 {
>> +?????????????????????? reg = <0x0 0x200 0x0 0x40>,
>> +???????????????????????????? <0x0 0x24? 0x0 0x8>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_C<<8) 11>;
>> +?????????????? };
>> +
>> +?????????????? gpiob: gpio at 240 {
>> +?????????????????????? reg = <0x0 0x240 0x0 0x40>,
>> +???????????????????????????? <0x0 0x0?? 0x0 0x8>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_B<<8) 14>;
>> +?????????????? };
>> +
>> +?????????????? gpioh: gpio at 280 {
>> +?????????????????????? reg = <0x0 0x280 0x0 0x40>,
>> +???????????????????????????? <0x0 0x4c? 0x0 0x4>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_H<<8) 5>;
>> +?????????????? };
>> +
>> +?????????????? gpio_test_n: gpio at 2c0 {
>> +?????????????????????? reg = <0x0 0x2c0 0x0 0x40>,
>> +???????????????????????????? <0x0 0x3c? 0x0 0x4>;
>> +?????????????????????? reg-names = "gpio", "mux";
>> +?????????????????????? gpio-controller;
>> +?????????????????????? #gpio-cells = <2>;
>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_TEST_N<<8) 1>;
>> +?????????????? };
>> +?????? };
>> +
>> ???????? gpio_intc: interrupt-controller at 4080 {
>> ???????????????? compatible = "amlogic,a5-gpio-intc",
>> ????????????????????????????? "amlogic,meson-gpio-intc";
>>
>> -- 
>> 2.37.1
>>
>>



From neil.armstrong at linaro.org  Tue Oct 21 05:29:33 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 21 Oct 2025 14:29:33 +0200
Subject: [PATCH 0/2] soc: amlogic: canvas: fix device leak on lookup
In-Reply-To: <20250926142454.5929-1-johan@kernel.org>
References: <20250926142454.5929-1-johan@kernel.org>
Message-ID: <176104977371.3063512.7347854086347476606.b4-ty@linaro.org>

Hi,

On Fri, 26 Sep 2025 16:24:52 +0200, Johan Hovold wrote:
> This series fixes a device leak in the canvas lookup helper and
> simplifies the lookup error handling somewhat.
> 
> Johan
> 
> 
> Johan Hovold (2):
>   soc: amlogic: canvas: fix device leak on lookup
>   soc: amlogic: canvas: simplify lookup error handling
> 
> [...]

Thanks, Applied to https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git (v6.19/drivers)

[1/2] soc: amlogic: canvas: fix device leak on lookup
      https://git.kernel.org/amlogic/c/32200f4828de9d7e6db379909898e718747f4e18
[2/2] soc: amlogic: canvas: simplify lookup error handling
      https://git.kernel.org/amlogic/c/075daf22641870e435a16ec2129bfd3b3134c487

These changes has been applied on the intermediate git tree [1].

The v6.19/drivers branch will then be sent via a formal Pull Request to the Linux SoC maintainers
for inclusion in their intermediate git branches in order to be sent to Linus during
the next merge window, or sooner if it's a set of fixes.

In the cases of fixes, those will be merged in the current release candidate
kernel and as soon they appear on the Linux master branch they will be
backported to the previous Stable and Long-Stable kernels [2].

The intermediate git branches are merged daily in the linux-next tree [3],
people are encouraged testing these pre-release kernels and report issues on the
relevant mailing-lists.

If problems are discovered on those changes, please submit a signed-off-by revert
patch followed by a corrective changeset.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
[3] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

-- 
Neil



From neil.armstrong at linaro.org  Tue Oct 21 05:29:44 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 21 Oct 2025 14:29:44 +0200
Subject: [PATCH 1/2] dt-bindings: arm: amlogic: add support for Tanix
 TX9 Pro
In-Reply-To: <20250927125006.824293-1-christianshewitt@gmail.com>
References: <20250927125006.824293-1-christianshewitt@gmail.com>
Message-ID: <176104978445.3075289.8934335794181531302.b4-ty@linaro.org>

Hi,

On Sat, 27 Sep 2025 12:50:05 +0000, Christian Hewitt wrote:
> The Oranth Tanix TX9 Pro is an Android STB using the Amlogic S912 chip
> 
> 

Thanks, Applied to https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git (v6.19/arm64-dt)

[1/2] dt-bindings: arm: amlogic: add support for Tanix TX9 Pro
      https://git.kernel.org/amlogic/c/beaea75ddc2a483e7b2b08a040d418f323510316
[2/2] arm64: dts: meson: add initial device-tree for Tanix TX9 Pro
      https://git.kernel.org/amlogic/c/afd1e16c6d3f53810ea29b5269dfcfc233e9b6b9

These changes has been applied on the intermediate git tree [1].

The v6.19/arm64-dt branch will then be sent via a formal Pull Request to the Linux SoC maintainers
for inclusion in their intermediate git branches in order to be sent to Linus during
the next merge window, or sooner if it's a set of fixes.

In the cases of fixes, those will be merged in the current release candidate
kernel and as soon they appear on the Linux master branch they will be
backported to the previous Stable and Long-Stable kernels [2].

The intermediate git branches are merged daily in the linux-next tree [3],
people are encouraged testing these pre-release kernels and report issues on the
relevant mailing-lists.

If problems are discovered on those changes, please submit a signed-off-by revert
patch followed by a corrective changeset.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
[3] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

-- 
Neil



From neil.armstrong at linaro.org  Tue Oct 21 05:29:45 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 21 Oct 2025 14:29:45 +0200
Subject: [PATCH RESEND] dts: arm64: amlogic: Add ISP related nodes for
 C3
In-Reply-To: <20250918-b4-c3isp-v1-1-5f48db6516c9@amlogic.com>
References: <20250918-b4-c3isp-v1-1-5f48db6516c9@amlogic.com>
Message-ID: <176104978523.3075289.16180550527361572624.b4-ty@linaro.org>

Hi,

On Thu, 18 Sep 2025 16:35:09 +0800, Keke Li wrote:
> Add the IMX290 sensor node description to the device tree file,
> which will be controlled via I2C bus with image data transmission
> through MIPI CSI-2 interface.
> 
> Add CSI-2, adapter and ISP nodes for C3 family.
> 
> 
> [...]

Thanks, Applied to https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git (v6.19/arm64-dt)

[1/1] dts: arm64: amlogic: Add ISP related nodes for C3
      https://git.kernel.org/amlogic/c/63aa70a1f84f5dfabbac28d60e12949705876648

These changes has been applied on the intermediate git tree [1].

The v6.19/arm64-dt branch will then be sent via a formal Pull Request to the Linux SoC maintainers
for inclusion in their intermediate git branches in order to be sent to Linus during
the next merge window, or sooner if it's a set of fixes.

In the cases of fixes, those will be merged in the current release candidate
kernel and as soon they appear on the Linux master branch they will be
backported to the previous Stable and Long-Stable kernels [2].

The intermediate git branches are merged daily in the linux-next tree [3],
people are encouraged testing these pre-release kernels and report issues on the
relevant mailing-lists.

If problems are discovered on those changes, please submit a signed-off-by revert
patch followed by a corrective changeset.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
[3] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

-- 
Neil



From xianwei.zhao at amlogic.com  Tue Oct 21 19:09:53 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Wed, 22 Oct 2025 10:09:53 +0800
Subject: [PATCH v3 2/2] dts: arm64: amlogic: add a5 pinctrl node
In-Reply-To: <263b86c9-61da-4d5e-af3d-4b9105112d82@linaro.org>
References: <20250403-a5-pinctrl-v3-0-a8c067e22295@amlogic.com>
 <20250403-a5-pinctrl-v3-2-a8c067e22295@amlogic.com>
 <6ebddeb4-b33f-4392-b5da-56501b38fd6d@amlogic.com>
 <263b86c9-61da-4d5e-af3d-4b9105112d82@linaro.org>
Message-ID: <5d8e439a-9ad0-4d2e-b106-d6e65a3e4638@amlogic.com>

Hi Neil,
    Thanks for your reply.

On 2025/10/21 20:23, Neil Armstrong wrote:
> [ EXTERNAL EMAIL ]
> 
> Hi,
> 
> 
> On 9/5/25 05:19, Xianwei Zhao wrote:
>> Hi Neil,
>> ??? Could you please take some time to review this submission?
> 
> Could you rebase on v6.18-rc1 ?
> 

Will do.

> Thanks,
> Neil
> 
>>
>> On 2025/4/3 16:33, Xianwei Zhao via B4 Relay wrote:
>>> [ EXTERNAL EMAIL ]
>>>
>>> From: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>>
>>> Add pinctrl device to support Amlogic A5.
>>>
>>> Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
>>> ---
>>> ? arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 90 
>>> +++++++++++++++++++++++++++++
>>> ? 1 file changed, 90 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi 
>>> b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
>>> index 32ed1776891b..844302db2133 100644
>>> --- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
>>> +++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
>>> @@ -4,6 +4,7 @@
>>> ?? */
>>>
>>> ? #include "amlogic-a4-common.dtsi"
>>> +#include <dt-bindings/pinctrl/amlogic,pinctrl.h>
>>> ? #include <dt-bindings/power/amlogic,a5-pwrc.h>
>>> ? / {
>>> ???????? cpus {
>>> @@ -50,6 +51,95 @@ pwrc: power-controller {
>>> ? };
>>>
>>> ? &apb {
>>> +?????? periphs_pinctrl: pinctrl at 4000 {
>>> +?????????????? compatible = "amlogic,pinctrl-a5",
>>> +??????????????????????????? "amlogic,pinctrl-a4";
>>> +?????????????? #address-cells = <2>;
>>> +?????????????? #size-cells = <2>;
>>> +?????????????? ranges = <0x0 0x0 0x0 0x4000 0x0 0x300>;
>>> +
>>> +?????????????? gpioz: gpio at c0 {
>>> +?????????????????????? reg = <0x0 0xc0 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x18 0x0 0x8>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_Z<<8) 16>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpiox: gpio at 100 {
>>> +?????????????????????? reg = <0x0 0x100 0x0 0x40>,
>>> +???????????????????????????? <0x0 0xc?? 0x0 0xc>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_X<<8) 20>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpiot: gpio at 140 {
>>> +?????????????????????? reg = <0x0 0x140 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x2c? 0x0 0x8>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_T<<8) 14>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpiod: gpio at 180 {
>>> +?????????????????????? reg = <0x0 0x180 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x40? 0x0 0x8>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_D<<8) 16>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpioe: gpio at 1c0 {
>>> +?????????????????????? reg = <0x0 0x1c0 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x48? 0x0 0x4>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_E<<8) 2>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpioc: gpio at 200 {
>>> +?????????????????????? reg = <0x0 0x200 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x24? 0x0 0x8>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_C<<8) 11>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpiob: gpio at 240 {
>>> +?????????????????????? reg = <0x0 0x240 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x0?? 0x0 0x8>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_B<<8) 14>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpioh: gpio at 280 {
>>> +?????????????????????? reg = <0x0 0x280 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x4c? 0x0 0x4>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_H<<8) 5>;
>>> +?????????????? };
>>> +
>>> +?????????????? gpio_test_n: gpio at 2c0 {
>>> +?????????????????????? reg = <0x0 0x2c0 0x0 0x40>,
>>> +???????????????????????????? <0x0 0x3c? 0x0 0x4>;
>>> +?????????????????????? reg-names = "gpio", "mux";
>>> +?????????????????????? gpio-controller;
>>> +?????????????????????? #gpio-cells = <2>;
>>> +?????????????????????? gpio-ranges = <&periphs_pinctrl 0 
>>> (AMLOGIC_GPIO_TEST_N<<8) 1>;
>>> +?????????????? };
>>> +?????? };
>>> +
>>> ???????? gpio_intc: interrupt-controller at 4080 {
>>> ???????????????? compatible = "amlogic,a5-gpio-intc",
>>> ????????????????????????????? "amlogic,meson-gpio-intc";
>>>
>>> -- 
>>> 2.37.1
>>>
>>>
> 


From devnull+xianwei.zhao.amlogic.com at kernel.org  Tue Oct 21 22:04:48 2025
From: devnull+xianwei.zhao.amlogic.com at kernel.org (Xianwei Zhao via B4 Relay)
Date: Wed, 22 Oct 2025 13:04:48 +0800
Subject: [PATCH v4] dts: arm64: amlogic: add a5 pinctrl node
Message-ID: <20251022-a5-pinctrl-node-v4-1-a71911852c4b@amlogic.com>

From: Xianwei Zhao <xianwei.zhao at amlogic.com>

Add pinctrl device to support Amlogic A5.

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
Add A5 pinctrl compatible string and device node.
---
Changes in v4:
- Rebase dts.
- Binding has already be accepted. This submission does not include this part.
- Link to v3: https://lore.kernel.org/all/20250403-a5-pinctrl-v3-0-a8c067e22295 at amlogic.com

Changes in v3:
- Remain blank line.
- Link to v2: https://lore.kernel.org/r/20250401-a5-pinctrl-v2-0-a136c1058379 at amlogic.com

Changes in v2:
- Modify bindings according to Conor's suggestion.
- Link to v1: https://lore.kernel.org/r/20250327-a5-pinctrl-v1-0-49320349c463 at amlogic.com
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 90 +++++++++++++++++++++++++++++
 1 file changed, 90 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index b1da8cbaa25a..2b12d8284594 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -5,6 +5,7 @@
 
 #include "amlogic-a4-common.dtsi"
 #include "amlogic-a5-reset.h"
+#include <dt-bindings/pinctrl/amlogic,pinctrl.h>
 #include <dt-bindings/power/amlogic,a5-pwrc.h>
 / {
 	cpus {
@@ -58,6 +59,95 @@ reset: reset-controller at 2000 {
 		#reset-cells = <1>;
 	};
 
+	periphs_pinctrl: pinctrl at 4000 {
+		compatible = "amlogic,pinctrl-a5",
+			     "amlogic,pinctrl-a4";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x0 0x0 0x0 0x4000 0x0 0x300>;
+
+		gpioz: gpio at c0 {
+			reg = <0x0 0xc0 0x0 0x40>,
+			      <0x0 0x18 0x0 0x8>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_Z<<8) 16>;
+		};
+
+		gpiox: gpio at 100 {
+			reg = <0x0 0x100 0x0 0x40>,
+			      <0x0 0xc   0x0 0xc>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_X<<8) 20>;
+		};
+
+		gpiot: gpio at 140 {
+			reg = <0x0 0x140 0x0 0x40>,
+			      <0x0 0x2c  0x0 0x8>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_T<<8) 14>;
+		};
+
+		gpiod: gpio at 180 {
+			reg = <0x0 0x180 0x0 0x40>,
+			      <0x0 0x40  0x0 0x8>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_D<<8) 16>;
+		};
+
+		gpioe: gpio at 1c0 {
+			reg = <0x0 0x1c0 0x0 0x40>,
+			      <0x0 0x48  0x0 0x4>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_E<<8) 2>;
+		};
+
+		gpioc: gpio at 200 {
+			reg = <0x0 0x200 0x0 0x40>,
+			      <0x0 0x24  0x0 0x8>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_C<<8) 11>;
+		};
+
+		gpiob: gpio at 240 {
+			reg = <0x0 0x240 0x0 0x40>,
+			      <0x0 0x0   0x0 0x8>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_B<<8) 14>;
+		};
+
+		gpioh: gpio at 280 {
+			reg = <0x0 0x280 0x0 0x40>,
+			      <0x0 0x4c  0x0 0x4>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_H<<8) 5>;
+		};
+
+		gpio_test_n: gpio at 2c0 {
+			reg = <0x0 0x2c0 0x0 0x40>,
+			      <0x0 0x3c  0x0 0x4>;
+			reg-names = "gpio", "mux";
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&periphs_pinctrl 0 (AMLOGIC_GPIO_TEST_N<<8) 1>;
+		};
+	};
+
 	gpio_intc: interrupt-controller at 4080 {
 		compatible = "amlogic,a5-gpio-intc",
 			     "amlogic,meson-gpio-intc";

---
base-commit: ea528a07aae07a764babc0d92db55e2c0d68d414
change-id: 20251022-a5-pinctrl-node-89d647ba2916

Best regards,
-- 
Xianwei Zhao <xianwei.zhao at amlogic.com>




From xianwei.zhao at amlogic.com  Tue Oct 21 22:48:02 2025
From: xianwei.zhao at amlogic.com (Xianwei Zhao)
Date: Wed, 22 Oct 2025 13:48:02 +0800
Subject: [PATCH v2] rtc: amlogic-a4: fix double free caused by devm
In-Reply-To: <20251021103559.1903-1-vulab@iscas.ac.cn>
References: <20251020150956.491-1-vulab@iscas.ac.cn>
 <20251021103559.1903-1-vulab@iscas.ac.cn>
Message-ID: <126bce2b-d899-40e8-ae45-07dfd1e3f8c7@amlogic.com>

Reviewed-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
On 2025/10/21 18:35, Haotian Zhang wrote:
> [Some people who received this message don't often get email from vulab at iscas.ac.cn. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
> 
> [ EXTERNAL EMAIL ]
> 
> The clock obtained via devm_clk_get_enabled() is automatically managed
> by devres and will be disabled and freed on driver detach. Manually
> calling clk_disable_unprepare() in error path and remove function
> causes double free.
> 
> Remove the redundant clk_disable_unprepare() calls from the probe
> error path and aml_rtc_remove(), allowing the devm framework to
> automatically manage the clock lifecycle.
> 
> Fixes: c89ac9182ee2 ("rtc: support for the Amlogic on-chip RTC")
> Signed-off-by: Haotian Zhang <vulab at iscas.ac.cn>
> ---
> v2: Also remove the now-unused local variable 'rtc' in aml_rtc_remove()
> ---
>   drivers/rtc/rtc-amlogic-a4.c | 4 ----
>   1 file changed, 4 deletions(-)
> 
> diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
> index 1928b29c1045..a993d35e1d6b 100644
> --- a/drivers/rtc/rtc-amlogic-a4.c
> +++ b/drivers/rtc/rtc-amlogic-a4.c
> @@ -390,7 +390,6 @@ static int aml_rtc_probe(struct platform_device *pdev)
> 
>          return 0;
>   err_clk:
> -       clk_disable_unprepare(rtc->sys_clk);
>          device_init_wakeup(dev, false);
> 
>          return ret;
> @@ -423,9 +422,6 @@ static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
> 
>   static void aml_rtc_remove(struct platform_device *pdev)
>   {
> -       struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
> -
> -       clk_disable_unprepare(rtc->sys_clk);
>          device_init_wakeup(&pdev->dev, false);
>   }
> 
> --
> 2.25.1
> 


From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 21 23:58:53 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Wed, 22 Oct 2025 14:58:53 +0800
Subject: [PATCH 3/3] clk: amlogic: Correct l_detect bit control
In-Reply-To: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
Message-ID: <20251022-optimize_pll_driver-v1-3-a275722fb6f4@amlogic.com>

From: Chuan Liu <chuan.liu at 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 at 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




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 21 23:58:50 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Wed, 22 Oct 2025 14:58:50 +0800
Subject: [PATCH 0/3] clk: amlogic: optimize the PLL driver
Message-ID: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>

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 at 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 at amlogic.com>




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 21 23:58:51 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Wed, 22 Oct 2025 14:58:51 +0800
Subject: [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting
In-Reply-To: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
Message-ID: <20251022-optimize_pll_driver-v1-1-a275722fb6f4@amlogic.com>

From: Chuan Liu <chuan.liu at 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 at 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




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 21 23:58:52 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Wed, 22 Oct 2025 14:58:52 +0800
Subject: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
Message-ID: <20251022-optimize_pll_driver-v1-2-a275722fb6f4@amlogic.com>

From: Chuan Liu <chuan.liu at 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 at 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




From neil.armstrong at linaro.org  Wed Oct 22 00:13:37 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Wed, 22 Oct 2025 09:13:37 +0200
Subject: [PATCH v4] dts: arm64: amlogic: add a5 pinctrl node
In-Reply-To: <20251022-a5-pinctrl-node-v4-1-a71911852c4b@amlogic.com>
References: <20251022-a5-pinctrl-node-v4-1-a71911852c4b@amlogic.com>
Message-ID: <176111721718.2414958.3337470167774710768.b4-ty@linaro.org>

Hi,

On Wed, 22 Oct 2025 13:04:48 +0800, Xianwei Zhao wrote:
> Add pinctrl device to support Amlogic A5.
> 
> 

Thanks, Applied to https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git (v6.19/arm64-dt)

[1/1] dts: arm64: amlogic: add a5 pinctrl node
      https://git.kernel.org/amlogic/c/a8b41683186d1465c06aabfee6e66ae0bb29f5fe

These changes has been applied on the intermediate git tree [1].

The v6.19/arm64-dt branch will then be sent via a formal Pull Request to the Linux SoC maintainers
for inclusion in their intermediate git branches in order to be sent to Linus during
the next merge window, or sooner if it's a set of fixes.

In the cases of fixes, those will be merged in the current release candidate
kernel and as soon they appear on the Linux master branch they will be
backported to the previous Stable and Long-Stable kernels [2].

The intermediate git branches are merged daily in the linux-next tree [3],
people are encouraged testing these pre-release kernels and report issues on the
relevant mailing-lists.

If problems are discovered on those changes, please submit a signed-off-by revert
patch followed by a corrective changeset.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/amlogic/linux.git
[2] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
[3] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

-- 
Neil



From jbrunet at baylibre.com  Wed Oct 22 04:57:39 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Wed, 22 Oct 2025 13:57:39 +0200
Subject: [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting
In-Reply-To: <20251022-optimize_pll_driver-v1-1-a275722fb6f4@amlogic.com>
	(Chuan Liu via's message of "Wed, 22 Oct 2025 14:58:51 +0800")
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
	<20251022-optimize_pll_driver-v1-1-a275722fb6f4@amlogic.com>
Message-ID: <1j8qh34098.fsf@starbuckisacylon.baylibre.com>

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

> From: Chuan Liu <chuan.liu at 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 at 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


From jbrunet at baylibre.com  Wed Oct 22 05:01:05 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Wed, 22 Oct 2025 14:01:05 +0200
Subject: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <20251022-optimize_pll_driver-v1-2-a275722fb6f4@amlogic.com>
	(Chuan Liu via's message of "Wed, 22 Oct 2025 14:58:52 +0800")
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
	<20251022-optimize_pll_driver-v1-2-a275722fb6f4@amlogic.com>
Message-ID: <1j347b403i.fsf@starbuckisacylon.baylibre.com>

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

> From: Chuan Liu <chuan.liu at 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 at 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


From chuan.liu at amlogic.com  Wed Oct 22 06:50:47 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Wed, 22 Oct 2025 21:50:47 +0800
Subject: [PATCH 1/3] clk: amlogic: Fix out-of-range PLL frequency setting
In-Reply-To: <1j8qh34098.fsf@starbuckisacylon.baylibre.com>
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
 <20251022-optimize_pll_driver-v1-1-a275722fb6f4@amlogic.com>
 <1j8qh34098.fsf@starbuckisacylon.baylibre.com>
Message-ID: <7be1f72e-00b1-4e86-88b2-260200b10480@amlogic.com>

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 at kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu at 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 at 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



From chuan.liu at amlogic.com  Wed Oct 22 07:07:43 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Wed, 22 Oct 2025 22:07:43 +0800
Subject: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <1j347b403i.fsf@starbuckisacylon.baylibre.com>
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
 <20251022-optimize_pll_driver-v1-2-a275722fb6f4@amlogic.com>
 <1j347b403i.fsf@starbuckisacylon.baylibre.com>
Message-ID: <61c2738d-7291-4a45-aa73-f18528c81ba8@amlogic.com>

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 at kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu at 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 at 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



From linnaea-von-lavia at live.com  Thu Oct 23 04:33:07 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Thu, 23 Oct 2025 11:33:07 +0000
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
Message-ID: <DM4PR05MB102707B8CDF84D776C39F22F2C7F0A@DM4PR05MB10270.namprd05.prod.outlook.com>

Hi all,

I'm getting the following in dmesg after installing 6.18-rc1 on a VIM3 board.

[    5.391324] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.411265] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.415323] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.422278] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.442280] [     T50] meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
[    5.449631] [     T50] meson-pcie fc000000.pcie: Add PCIe port failed, -16
[    5.458779] [     T50] meson-pcie fc000000.pcie: probe with driver meson-pcie failed with error -16

I think the problem is related to c96992a24bec("PCI: dwc: Add support for ELBI resource mapping")
and 2f2cea1ea70a("PCI: dwc/meson: Rework PCI config and DW port logic register accesses"), as they're
both trying to map ELBI/DBI registers.

From helgaas at kernel.org  Thu Oct 23 09:42:05 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 23 Oct 2025 11:42:05 -0500
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <DM4PR05MB102707B8CDF84D776C39F22F2C7F0A@DM4PR05MB10270.namprd05.prod.outlook.com>
Message-ID: <20251023164205.GA1299816@bhelgaas>

[+cc Meson folks, Krishna, author of c96992a24bec]

On Thu, Oct 23, 2025 at 11:33:07AM +0000, Linnaea Lavia wrote:
> I'm getting the following in dmesg after installing 6.18-rc1 on a VIM3 board.
> 
> [    5.391324] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
> [    5.411265] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
> [    5.415323] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
> [    5.422278] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
> [    5.442280] [     T50] meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
> [    5.449631] [     T50] meson-pcie fc000000.pcie: Add PCIe port failed, -16
> [    5.458779] [     T50] meson-pcie fc000000.pcie: probe with driver meson-pcie failed with error -16
> 
> I think the problem is related to c96992a24bec("PCI: dwc: Add
> support for ELBI resource mapping") and 2f2cea1ea70a("PCI:
> dwc/meson: Rework PCI config and DW port logic register accesses"),
> as they're both trying to map ELBI/DBI registers.

Thanks for the report!  Can you post complete dmesg logs for working
and broken boots, e.g., v6.17 and v6.18-rc1?

#regzbot ^introduced: v6.18-rc1


From linnaea-von-lavia at live.com  Thu Oct 23 20:27:49 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Fri, 24 Oct 2025 11:27:49 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <20251023164205.GA1299816@bhelgaas>
References: <20251023164205.GA1299816@bhelgaas>
Message-ID: <DM4PR05MB102709E0A9C0CF0D62AEC3524C7F1A@DM4PR05MB10270.namprd05.prod.outlook.com>

On 10/24/2025 12:42 AM, Bjorn Helgaas wrote:
> [+cc Meson folks, Krishna, author of c96992a24bec]
> 
> On Thu, Oct 23, 2025 at 11:33:07AM +0000, Linnaea Lavia wrote:
>> I'm getting the following in dmesg after installing 6.18-rc1 on a VIM3 board.
>>
>> [    5.391324] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
>> [    5.411265] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
>> [    5.415323] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
>> [    5.422278] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
>> [    5.442280] [     T50] meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
>> [    5.449631] [     T50] meson-pcie fc000000.pcie: Add PCIe port failed, -16
>> [    5.458779] [     T50] meson-pcie fc000000.pcie: probe with driver meson-pcie failed with error -16
>>
>> I think the problem is related to c96992a24bec("PCI: dwc: Add
>> support for ELBI resource mapping") and 2f2cea1ea70a("PCI:
>> dwc/meson: Rework PCI config and DW port logic register accesses"),
>> as they're both trying to map ELBI/DBI registers.
> 
> Thanks for the report!  Can you post complete dmesg logs for working
> and broken boots, e.g., v6.17 and v6.18-rc1?
> 

On 6.17.4

[    0.000000] [      T0] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] [      T0] Linux version 6.17.4 (geeko at buildhost) (gcc (SUSE Linux) 15.1.1 20250714, GNU ld (GNU Binutils; SUSE Linux 16) 2.43.1.20241209-160000.2) #1 SMP PREEMPT_DYNAMIC Mon Oct 20 09:22:09 UTC 2025 (b07233b)
[    0.000000] [      T0] KASLR enabled
[    0.000000] [      T0] Machine model: Khadas VIM3
[    0.000000] [      T0] efi: EFI v2.10 by Das U-Boot
[    0.000000] [      T0] efi: RTPROP=0xefed5040 SMBIOS=0xefefc000 RNG=0xedc4d040 MEMRESERVE=0xe7d51040
[    0.000000] [      T0] random: crng init done
[    0.000000] [      T0] Reserved memory: created CMA memory pool at 0x00000000c9800000, size 480 MiB
[    0.000000] [      T0] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
[    0.000000] [      T0] OF: reserved mem: 0x00000000c9800000..0x00000000e77fffff (491520 KiB) map reusable linux,cma
[    0.000000] [      T0] OF: reserved mem: 0x0000000005000000..0x00000000052fffff (3072 KiB) nomap non-reusable secmon at 5000000
[    0.000000] [      T0] OF: reserved mem: 0x0000000005300000..0x00000000072fffff (32768 KiB) nomap non-reusable secmon at 5300000
[    0.000000] [      T0] Zone ranges:
[    0.000000] [      T0]   DMA      [mem 0x0000000000000000-0x00000000f4ffffff]
[    0.000000] [      T0]   DMA32    empty
[    0.000000] [      T0]   Normal   empty
[    0.000000] [      T0]   Device   empty
[    0.000000] [      T0] Movable zone start for each node
[    0.000000] [      T0] Early memory node ranges
[    0.000000] [      T0]   node   0: [mem 0x0000000000000000-0x0000000004ffffff]
[    0.000000] [      T0]   node   0: [mem 0x0000000005000000-0x00000000072fffff]
[    0.000000] [      T0]   node   0: [mem 0x0000000007300000-0x00000000efed4fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed5000-0x00000000efed5fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed6000-0x00000000efed6fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed7000-0x00000000efed8fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed9000-0x00000000efed9fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efeda000-0x00000000efef9fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efefa000-0x00000000efefbfff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efefc000-0x00000000efefcfff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efefd000-0x00000000f2f0ffff]
[    0.000000] [      T0]   node   0: [mem 0x00000000f2f10000-0x00000000f2f1ffff]
[    0.000000] [      T0]   node   0: [mem 0x00000000f2f20000-0x00000000f4e5afff]
[    0.000000] [      T0]   node   0: [mem 0x00000000f4e5b000-0x00000000f4ffffff]
[    0.000000] [      T0] Initmem setup node 0 [mem 0x0000000000000000-0x00000000f4ffffff]
[    0.000000] [      T0] On node 0, zone DMA: 12288 pages in unavailable ranges
[    0.000000] [      T0] psci: probing for conduit method from DT.
[    0.000000] [      T0] psci: PSCIv1.0 detected in firmware.
[    0.000000] [      T0] psci: Using standard PSCI v0.2 function IDs
[    0.000000] [      T0] psci: MIGRATE_INFO_TYPE not supported.
[    0.000000] [      T0] psci: SMC Calling Convention v1.1
[    0.000000] [      T0] RME: RMM doesn't support RSI version 1.0. Supported range: 1.0-0.0
[    0.000000] [      T0] percpu: Embedded 56 pages/cpu s103704 r8192 d117480 u229376
[    0.000000] [      T0] pcpu-alloc: s103704 r8192 d117480 u229376 alloc=56*4096
[    0.000000] [      T0] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5
[    0.000000] [      T0] Detected VIPT I-cache on CPU0
[    0.000000] [      T0] CPU features: kernel page table isolation forced ON by KASLR
[    0.000000] [      T0] CPU features: detected: Kernel page table isolation (KPTI)
[    0.000000] [      T0] alternatives: applying boot alternatives
[    0.000000] [      T0] Kernel command line: BOOT_IMAGE=/boot/Image-6.17.4 root=UUID=6a42b9d0-571c-4394-9ebb-c9a490151bba rd.timeout=15 mitigations=off delayacct
[    0.000000] [      T0] printk: log_buf_len individual max cpu contribution: 32768 bytes
[    0.000000] [      T0] printk: log_buf_len total cpu_extra contributions: 163840 bytes
[    0.000000] [      T0] printk: log_buf_len min size: 262144 bytes
[    0.000000] [      T0] printk: log buffer data + meta data: 524288 + 1835008 = 2359296 bytes
[    0.000000] [      T0] printk: early log buf free: 258728(98%)
[    0.000000] [      T0] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes, linear)
[    0.000000] [      T0] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[    0.000000] [      T0] software IO TLB: SWIOTLB bounce buffer size adjusted to 3MB
[    0.000000] [      T0] software IO TLB: area num 8.
[    0.000000] [      T0] software IO TLB: mapped [mem 0x00000000f3894000-0x00000000f3c94000] (4MB)
[    0.000000] [      T0] Built 1 zonelists, mobility grouping on.  Total pages: 1003520
[    0.000000] [      T0] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] [      T0] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=6, Nodes=1
[    0.000000] [      T0] ftrace: allocating 46334 entries in 182 pages
[    0.000000] [      T0] ftrace: allocated 182 pages with 5 groups
[    0.000000] [      T0] Dynamic Preempt: voluntary
[    0.000000] [      T0] rcu: Preemptible hierarchical RCU implementation.
[    0.000000] [      T0] rcu:  RCU event tracing is enabled.
[    0.000000] [      T0] rcu:  RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=6.
[    0.000000] [      T0]       Trampoline variant of Tasks RCU enabled.
[    0.000000] [      T0]       Rude variant of Tasks RCU enabled.
[    0.000000] [      T0]       Tracing variant of Tasks RCU enabled.
[    0.000000] [      T0] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] [      T0] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=6
[    0.000000] [      T0] RCU Tasks: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=6.
[    0.000000] [      T0] RCU Tasks Rude: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=6.
[    0.000000] [      T0] RCU Tasks Trace: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=6.
[    0.000000] [      T0] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] [      T0] Root IRQ handler: gic_handle_irq
[    0.000000] [      T0] GIC: Using split EOI/Deactivate mode
[    0.000000] [      T0] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] [      T0] arch_timer: cp15 timer(s) running at 24.00MHz (phys).
[    0.000000] [      T0] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
[    0.000001] [      T0] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
[    0.000494] [      T0] Console: colour dummy device 80x25
[    0.000510] [      T0] printk: legacy console [tty0] enabled
[    0.001397] [      T0] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=96000)
[    0.001426] [      T0] pid_max: default: 32768 minimum: 301
[    0.001619] [      T0] LSM: initializing lsm=capability,apparmor,bpf,ima,evm
[    0.002014] [      T0] AppArmor: AppArmor initialized
[    0.002512] [      T0] LSM support for eBPF active
[    0.002820] [      T0] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.002858] [      T0] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.004129] [      T0] spectre-v4 mitigation disabled by command-line option
[    0.005933] [      T1] rcu: Hierarchical SRCU implementation.
[    0.005974] [      T1] rcu:  Max phase no-delay instances is 1000.
[    0.006236] [      T1] Timer migration: 1 hierarchy levels; 8 children per group; 1 crossnode level
[    0.007605] [      T1] Remapping and enabling EFI services.
[    0.008167] [      T1] smp: Bringing up secondary CPUs ...
[    0.008999] [      T0] Detected VIPT I-cache on CPU1
[    0.009196] [      T0] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[    0.010553] [      T0] CPU features: detected: Spectre-v2
[    0.010569] [      T0] CPU features: detected: Spectre-v4
[    0.010573] [      T0] CPU features: detected: Spectre-BHB
[    0.010577] [      T0] CPU features: detected: ARM erratum 858921
[    0.010588] [      T0] Detected VIPT I-cache on CPU2
[    0.010714] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.010732] [      T0] arch_timer: CPU2: Trapping CNTVCT access
[    0.010743] [      T0] CPU2: Booted secondary processor 0x0000000100 [0x410fd092]
[    0.011514] [      T0] Detected VIPT I-cache on CPU3
[    0.011610] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.011620] [      T0] arch_timer: CPU3: Trapping CNTVCT access
[    0.011627] [      T0] CPU3: Booted secondary processor 0x0000000101 [0x410fd092]
[    0.012468] [      T0] Detected VIPT I-cache on CPU4
[    0.012564] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.012574] [      T0] arch_timer: CPU4: Trapping CNTVCT access
[    0.012581] [      T0] CPU4: Booted secondary processor 0x0000000102 [0x410fd092]
[    0.013318] [      T0] Detected VIPT I-cache on CPU5
[    0.013416] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.013426] [      T0] arch_timer: CPU5: Trapping CNTVCT access
[    0.013433] [      T0] CPU5: Booted secondary processor 0x0000000103 [0x410fd092]
[    0.013524] [      T1] smp: Brought up 1 node, 6 CPUs
[    0.013770] [      T1] SMP: Total of 6 processors activated.
[    0.013783] [      T1] CPU: All CPU(s) started at EL2
[    0.013808] [      T1] CPU features: detected: 32-bit EL0 Support
[    0.013821] [      T1] CPU features: detected: 32-bit EL1 Support
[    0.013838] [      T1] CPU features: detected: CRC32 instructions
[    0.013860] [      T1] CPU features: detected: PMUv3
[    0.013937] [      T1] alternatives: applying system-wide alternatives
[    0.015142] [      T1] CPU features: emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching
[    0.037577] [     T47] node 0 deferred pages initialised in 20ms
[    0.037659] [      T1] Memory: 3332424K/4014080K available (14848K kernel code, 2598K rwdata, 11596K rodata, 7424K init, 721K bss, 184396K reserved, 491520K cma-reserved)
[    0.038637] [      T1] devtmpfs: initialized
[    0.048887] [      T1] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.048957] [      T1] posixtimers hash table entries: 4096 (order: 4, 65536 bytes, linear)
[    0.049023] [      T1] futex hash table entries: 2048 (131072 bytes on 1 NUMA nodes, total 128 KiB, linear).
[    0.052878] [      T1] 2G module region forced by RANDOMIZE_MODULE_REGION_FULL
[    0.052910] [      T1] 0 pages in range for non-PLT usage
[    0.052914] [      T1] 514928 pages in range for PLT usage
[    0.053198] [      T1] pinctrl core: initialized pinctrl subsystem
[    0.053877] [      T1] SMBIOS 3.0 present.
[    0.053899] [      T1] DMI: khadas VIM3/VIM3, BIOS 2024.01-rc4-00039-gce25ceb939 01/01/2024
[    0.053921] [      T1] DMI: Memory slots populated: 0/0
[    0.055931] [      T1] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.056798] [      T1] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic allocations
[    0.057055] [      T1] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.057356] [      T1] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.057416] [      T1] audit: initializing netlink subsys (disabled)
[    0.057566] [     T58] audit: type=2000 audit(0.056:1): state=initialized audit_enabled=0 res=1
[    0.058816] [      T1] thermal_sys: Registered thermal governor 'fair_share'
[    0.058822] [      T1] thermal_sys: Registered thermal governor 'bang_bang'
[    0.058836] [      T1] thermal_sys: Registered thermal governor 'step_wise'
[    0.058847] [      T1] thermal_sys: Registered thermal governor 'user_space'
[    0.058857] [      T1] thermal_sys: Registered thermal governor 'power_allocator'
[    0.058903] [      T1] cpuidle: using governor ladder
[    0.058945] [      T1] cpuidle: using governor menu
[    0.059085] [      T1] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.059205] [      T1] ASID allocator initialised with 32768 entries
[    0.059400] [      T1] Serial: AMBA PL011 UART driver
[    0.066121] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.066511] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.066563] [      T1] /soc/vpu at ff900000: Fixed dependency cycle(s) with /soc/bus at ff600000/hdmi-tx at 0
[    0.066591] [      T1] /soc/interrupt-controller at ffc01000: Fixed dependency cycle(s) with /soc/interrupt-controller at ffc01000
[    0.066677] [      T1] /soc/usb at ffe09000: Fixed dependency cycle(s) with /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector
[    0.067279] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.067684] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.072817] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.074031] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.074537] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.074603] [      T1] /soc/vpu at ff900000: Fixed dependency cycle(s) with /soc/bus at ff600000/hdmi-tx at 0
[    0.076836] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.076907] [      T1] /soc/usb at ffe09000: Fixed dependency cycle(s) with /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector
[    0.079911] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /hdmi-connector
[    0.079985] [      T1] /hdmi-connector: Fixed dependency cycle(s) with /soc/bus at ff600000/hdmi-tx at 0
[    0.081962] [      T1] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
[    0.081986] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 1.00 GiB page
[    0.081999] [      T1] HugeTLB: registered 32.0 MiB page size, pre-allocated 0 pages
[    0.082011] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 32.0 MiB page
[    0.082023] [      T1] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
[    0.082034] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 2.00 MiB page
[    0.082045] [      T1] HugeTLB: registered 64.0 KiB page size, pre-allocated 0 pages
[    0.082057] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 64.0 KiB page
[    0.083745] [      T1] fbcon: Taking over console
[    0.084330] [      T1] iommu: Default domain type: Translated
[    0.084349] [      T1] iommu: DMA domain TLB invalidation policy: strict mode
[    0.086812] [      T1] pps_core: LinuxPPS API ver. 1 registered
[    0.086827] [      T1] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    0.086850] [      T1] PTP clock support registered
[    0.086882] [      T1] EDAC MC: Ver: 3.0.0
[    0.086977] [      T1] EDAC DEBUG: edac_mc_sysfs_init: device mc created
[    0.087116] [      T1] scmi_core: SCMI protocol bus registered
[    0.087263] [      T1] efivars: Registered efivars operations
[    0.088323] [      T1] NetLabel: Initializing
[    0.088337] [      T1] NetLabel:  domain hash size = 128
[    0.088348] [      T1] NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO
[    0.088416] [      T1] NetLabel:  unlabeled traffic allowed by default
[    0.088437] [      T1] mctp: management component transport protocol core
[    0.088447] [      T1] NET: Registered PF_MCTP protocol family
[    0.088690] [      T1] vgaarb: loaded
[    0.088973] [      T1] clocksource: Switched to clocksource arch_sys_counter
[    0.089462] [      T1] VFS: Disk quotas dquot_6.6.0
[    0.089502] [      T1] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.090167] [      T1] AppArmor: AppArmor Filesystem Enabled
[    0.095274] [      T1] NET: Registered PF_INET protocol family
[    0.095477] [      T1] IP idents hash table entries: 65536 (order: 7, 524288 bytes, linear)
[    0.129172] [      T1] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes, linear)
[    0.129234] [      T1] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.129308] [      T1] TCP established hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.129483] [      T1] TCP bind hash table entries: 32768 (order: 8, 1048576 bytes, linear)
[    0.129804] [      T1] TCP: Hash tables configured (established 32768 bind 32768)
[    0.130059] [      T1] MPTCP token hash table entries: 4096 (order: 4, 98304 bytes, linear)
[    0.130156] [      T1] UDP hash table entries: 2048 (order: 5, 131072 bytes, linear)
[    0.130242] [      T1] UDP-Lite hash table entries: 2048 (order: 5, 131072 bytes, linear)
[    0.130482] [      T1] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.130523] [      T1] NET: Registered PF_XDP protocol family
[    0.130580] [      T1] PCI: CLS 0 bytes, default 64
[    0.130785] [     T50] Trying to unpack rootfs image as initramfs...
[    0.135620] [      T1] kvm [1]: nv: 567 coarse grained trap handlers
[    0.135994] [      T1] kvm [1]: IPA Size Limit: 40 bits
[    0.137875] [      T1] kvm [1]: vgic interrupt IRQ9
[    0.137932] [      T1] kvm [1]: Hyp nVHE mode initialized successfully
[    0.142901] [      T1] Initialise system trusted keyrings
[    0.142954] [      T1] Key type blacklist registered
[    0.143126] [      T1] workingset: timestamp_bits=46 max_order=20 bucket_order=0
[    0.144262] [      T1] integrity: Platform Keyring initialized
[    0.144300] [      T1] integrity: Machine keyring initialized
[    0.144311] [      T1] Allocating IMA blacklist keyring.
[    0.184509] [      T1] Key type asymmetric registered
[    0.184541] [      T1] Asymmetric key parser 'x509' registered
[    0.184668] [      T1] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
[    0.184859] [      T1] io scheduler mq-deadline registered
[    0.184878] [      T1] io scheduler kyber registered
[    0.184961] [      T1] io scheduler bfq registered
[    0.186166] [      T1] irq_meson_gpio: 100 to 8 gpio interrupt mux initialized
[    0.192182] [      T1] ledtrig-cpu: registered to indicate activity on CPUs
[    0.201900] [      T1] soc soc0: Amlogic Meson G12B (A311D) Revision 29:b (10:2) Detected
[    0.203287] [      T1] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
[    0.211113] [      T1] Serial: AMBA driver
[    0.212016] [      T1] ff803000.serial: ttyAML0 at MMIO 0xff803000 (irq = 14, base_baud = 1500000) is a meson_uart
[    0.212065] [      T1] printk: legacy console [ttyAML0] enabled
[    0.580368] [     T50] Freeing initrd memory: 23008K
[    0.593808] [      T1] ffd24000.serial: ttyAML6 at MMIO 0xffd24000 (irq = 15, base_baud = 1500000) is a meson_uart
[    1.823937] [      T1] serial serial0: tty port ttyAML6 registered
[    1.830386] [      T1] msm_serial: driver initialized
[    1.837522] [      T1] mousedev: PS/2 mouse device common for all mice
[    1.841715] [      T1] meson-sm: secure-monitor enabled
[    1.845501] [      T1] hid: raw HID events driver (C) Jiri Kosina
[    1.851993] [     T77] watchdog: NMI not fully supported
[    1.856165] [     T77] watchdog: Hard watchdog permanently disabled
[    1.857393] [      T1] drop_monitor: Initializing network drop monitor service
[    1.869376] [      T1] NET: Registered PF_INET6 protocol family
[    1.875534] [      T1] Segment Routing with IPv6
[    1.879052] [      T1] RPL Segment Routing with IPv6
[    1.883742] [      T1] In-situ OAM (IOAM) with IPv6
[    1.893603] [      T1] registered taskstats version 1
[    1.924118] [      T1] zswap: loaded using pool zstd/zsmalloc
[    1.924229] [      T1] page_owner is disabled
[    1.928369] [      T1] Key type .fscrypt registered
[    1.932706] [      T1] Key type fscrypt-provisioning registered
[    1.938847] [      T1] Key type big_key registered
[    1.998514] [      T1] Key type encrypted registered
[    1.998575] [      T1] AppArmor: AppArmor sha256 policy hashing enabled
[    2.004095] [      T1] ima: secureboot mode disabled
[    2.008618] [      T1] ima: No TPM chip found, activating TPM-bypass!
[    2.030640] [      T1] ima: Allocated hash algorithm: sha256
[    2.036044] [      T1] ima: No architecture policies found
[    2.041236] [      T1] evm: Initialising EVM extended attributes:
[    2.046998] [      T1] evm: security.selinux
[    2.050982] [      T1] evm: security.SMACK64 (disabled)
[    2.055921] [      T1] evm: security.SMACK64EXEC (disabled)
[    2.061208] [      T1] evm: security.SMACK64TRANSMUTE (disabled)
[    2.066928] [      T1] evm: security.SMACK64MMAP (disabled)
[    2.072214] [      T1] evm: security.apparmor
[    2.076287] [      T1] evm: security.ima
[    2.079927] [      T1] evm: security.capability
[    2.084174] [      T1] evm: HMAC attrs: 0x1
[    2.101071] [     T50] simple-framebuffer f4e5b000.framebuffer: [drm] Registered 1 planes with drm panic
[    2.104670] [     T50] [drm] Initialized simpledrm 1.0.0 for f4e5b000.framebuffer on minor 0
[    2.115234] [     T50] Console: switching to colour frame buffer device 90x36
[    2.120593] [     T50] simple-framebuffer f4e5b000.framebuffer: [drm] fb0: simpledrmdrmfb frame buffer device
[    2.162151] [      T1] clk: Disabling unused clocks
[    2.162525] [      T1] PM: genpd: Disabling unused power domains
[    2.176852] [      T1] Freeing unused kernel memory: 7424K
[    2.221979] [      T1] Checked W+X mappings: passed, no W+X pages found
[    2.222888] [      T1] Run /init as init process
[    2.227078] [      T1]   with arguments:
[    2.227085] [      T1]     /init
[    2.227090] [      T1]   with environment:
[    2.227094] [      T1]     HOME=/
[    2.227098] [      T1]     TERM=linux
[    2.241253] [      T1] systemd[1]: System time advanced to built-in epoch: Thu 2025-07-31 14:32:25 UTC
[    2.280011] [      T1] systemd[1]: Successfully made /usr/ read-only.
[    2.289042] [      T1] systemd[1]: systemd 257.7+suse.19.ga0dfd5de4c running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +IPE -SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK -BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE)
[    2.324212] [      T1] systemd[1]: Detected architecture arm64.
[    2.325827] [      T1] systemd[1]: Running in initrd.
[    2.353290] [      T1] systemd[1]: Hostname set to <linux-g12b>.
[    2.570749] [      T1] systemd[1]: Queued start job for default target Initrd Default Target.
[    2.606120] [      T1] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    2.625192] [      T1] systemd[1]: Expecting device /dev/disk/by-uuid/6a42b9d0-571c-4394-9ebb-c9a490151bba...
[    2.645084] [      T1] systemd[1]: Expecting device /dev/disk/by-uuid/CE59-EAEA...
[    2.661228] [      T1] systemd[1]: Reached target Initrd /usr File System.
[    2.677189] [      T1] systemd[1]: Reached target Path Units.
[    2.689160] [      T1] systemd[1]: Reached target Slice Units.
[    2.701238] [      T1] systemd[1]: Reached target Swaps.
[    2.713187] [      T1] systemd[1]: Reached target Timer Units.
[    2.725695] [      T1] systemd[1]: Listening on Journal Socket (/dev/log).
[    2.741532] [      T1] systemd[1]: Listening on Journal Sockets.
[    2.753585] [      T1] systemd[1]: Listening on udev Control Socket.
[    2.769399] [      T1] systemd[1]: Listening on udev Kernel Socket.
[    2.789219] [      T1] systemd[1]: Reached target Socket Units.
[    2.804616] [      T1] systemd[1]: Starting Create List of Static Device Nodes...
[    2.855446] [      T1] systemd[1]: Starting Journal Service...
[    2.875713] [      T1] systemd[1]: Starting Load Kernel Modules...
[    2.898878] [      T1] systemd[1]: Starting Virtual Console Setup...
[    2.919643] [      T1] systemd[1]: Finished Create List of Static Device Nodes.
[    2.940780] [      T1] systemd[1]: Starting Create Static Device Nodes in /dev gracefully...
[    2.953107] [    T152] systemd-journald[152]: Collecting audit messages is disabled.
[    2.971443] [    T153] zram: Added device: zram0
[    2.975736] [      T1] systemd[1]: Finished Load Kernel Modules.
[    2.980599] [      T1] systemd[1]: Starting Apply Kernel Variables...
[    2.986763] [      T1] systemd[1]: Started Journal Service.
[    3.628979] [    T274] raid6: neonx8   gen()  2660 MB/s
[    3.696978] [    T274] raid6: neonx4   gen()  2924 MB/s
[    3.764973] [    T274] raid6: neonx2   gen()  2343 MB/s
[    3.832981] [    T274] raid6: neonx1   gen()  1780 MB/s
[    3.900987] [    T274] raid6: int64x8  gen()  1201 MB/s
[    3.968984] [    T274] raid6: int64x4  gen()  1407 MB/s
[    4.036989] [    T274] raid6: int64x2  gen()  1358 MB/s
[    4.104979] [    T274] raid6: int64x1  gen()  1093 MB/s
[    4.105736] [    T274] raid6: using algorithm neonx4 gen() 2924 MB/s
[    4.176975] [    T274] raid6: .... xor() 2182 MB/s, rmw enabled
[    4.177616] [    T274] raid6: using neon recovery algorithm
[    4.187998] [    T274] xor: measuring software checksum speed
[    4.189640] [    T274]    8regs           :  3978 MB/sec
[    4.194347] [    T274]    32regs          :  4201 MB/sec
[    4.199544] [    T274]    arm64_neon      :  3107 MB/sec
[    4.203471] [    T274] xor: using function: 32regs (4201 MB/sec)
[    4.470939] [    T274] Btrfs loaded, assert=on, zoned=yes, fsverity=yes
[    5.163979] [    T306] input: gpio-keys-polled as /devices/platform/gpio-keys-polled/input/input0
[    5.249320] [    T338] meson-gx-mmc ffe07000.mmc: allocated mmc-pwrseq
[    5.252896] [    T307] pca953x 0-0020: using no AI
[    5.259129] [     T45] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.260109] [    T303] meson-vrtc ff8000a8.rtc: registered as rtc1
[    5.273053] [    T307] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    5.274684] [     T45] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.289867] [     T45] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.297925] [     T45] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.307114] [     T45] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.352480] [    T302] meson-drm ff900000.vpu: Queued 1 outputs on vpu
[    5.353749] [    T313] dwc3-meson-g12a ffe09000.usb: USB2 ports: 2
[    5.355846] [     T45] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.359076] [    T313] dwc3-meson-g12a ffe09000.usb: USB3 ports: 0
[    5.379709] [     T45] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.382559] [     T45] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.388871] [     T45] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.396188] [     T45] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.402825] [    T290] Console: switching to colour dummy device 80x25
[    5.402870] [     T45] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.415578] [     T45] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.423485] [     T45] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.430349] [     T45] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.436191] [     T45] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.442955] [     T45] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.450406] [     T45] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.458363] [     T45] pci 0000:00:00.0: supports D1
[    5.463040] [     T45] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.474323] [     T45] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.480785] [     T45] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.487467] [     T28] mmc1: new HS200 MMC card at address 0001
[    5.487771] [     T45] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.502681] [     T45] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.510581] [     T45] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.526115] [    T290] meson-drm ff900000.vpu: CVBS Output connector not available
[    5.526498] [     T45] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.533861] [    T291] rtc-hym8563 0-0051: registered as rtc0
[    5.540761] [     T45] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.540796] [     T45] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.552322] [    T291] rtc-hym8563 0-0051: setting system clock to 2025-10-23T16:12:22 UTC (1761235942)
[    5.554001] [     T45] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.556100] [    T295] mmcblk1: mmc1:0001 BJTD4R 29.1 GiB
[    5.558738] [    T311] usbcore: registered new interface driver usbfs
[    5.558784] [    T311] usbcore: registered new interface driver hub
[    5.558827] [    T311] usbcore: registered new device driver usb
[    5.563157] [    T295]  mmcblk1: p1 p2 p3
[    5.571003] [     T45] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    5.571018] [     T45] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    5.577056] [    T290] meson-dw-hdmi ff600000.hdmi-tx: Detected HDMI TX controller v2.01a with HDCP (meson_dw_hdmi_phy)
[    5.582037] [     T45] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    5.584045] [    T295] mmcblk1boot0: mmc1:0001 BJTD4R 4.00 MiB
[    5.589372] [    T290] meson-dw-hdmi ff600000.hdmi-tx: registered DesignWare HDMI I2C bus driver
[    5.594140] [     T45] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    5.594943] [     T45] pcieport 0000:00:00.0: PME: Signaling with IRQ 22
[    5.598866] [    T295] mmcblk1boot1: mmc1:0001 BJTD4R 4.00 MiB
[    5.603023] [    T290] meson-drm ff900000.vpu: bound ff600000.hdmi-tx (ops meson_dw_hdmi_ops [meson_dw_hdmi])
[    5.603247] [    T295] mmcblk1rpmb: mmc1:0001 BJTD4R 4.00 MiB, chardev (234:0)
[    5.608166] [     T45] pcieport 0000:00:00.0: AER: enabled with IRQ 22
[    5.612195] [    T290] meson-drm ff900000.vpu: DSI transceiver device is disabled
[    5.628176] [     T48] meson-gx-mmc ffe05000.mmc: Got CD GPIO
[    5.637133] [    T290] [drm] Initialized meson 1.0.0 for ff900000.vpu on minor 1
[    5.637694] [    T311] dwc2 ff400000.usb: supply vusb_d not found, using dummy regulator
[    5.637799] [    T311] dwc2 ff400000.usb: supply vusb_a not found, using dummy regulator
[    5.649999] [    T311] dwc2 ff400000.usb: EPs: 7, dedicated fifos, 712 entries in SPRAM
[    5.666878] [     T49] meson-gx-mmc ffe03000.mmc: allocated mmc-pwrseq
[    5.786590] [    T354] mmc0: new UHS-I speed SDR104 SDXC card at address 1388
[    5.788294] [    T354] mmcblk0: mmc0:1388 Stora 466 GiB
[    5.818458] [    T295] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller
[    5.818494] [    T295] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus number 1
[    5.818800] [    T295] xhci-hcd xhci-hcd.2.auto: hcc params 0x0228fe64 hci version 0x110 quirks 0x0000808000000010
[    5.818851] [    T295] xhci-hcd xhci-hcd.2.auto: irq 26, io mem 0xff500000
[    5.819142] [    T295] xhci-hcd xhci-hcd.2.auto: xHCI Host Controller
[    5.819157] [    T295] xhci-hcd xhci-hcd.2.auto: new USB bus registered, assigned bus number 2
[    5.819173] [    T295] xhci-hcd xhci-hcd.2.auto: Host supports USB 3.0 SuperSpeed
[    5.819330] [    T295] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.17
[    5.819339] [    T295] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    5.819345] [    T295] usb usb1: Product: xHCI Host Controller
[    5.819349] [    T295] usb usb1: Manufacturer: Linux 6.17.4 xhci-hcd
[    5.819354] [    T295] usb usb1: SerialNumber: xhci-hcd.2.auto
[    5.820255] [    T295] hub 1-0:1.0: USB hub found
[    5.820415] [    T295] hub 1-0:1.0: 2 ports detected
[    5.901768] [    T290] Console: switching to colour frame buffer device 128x48
[    5.907292] [     T86] mmc2: new UHS-I speed SDR104 SDIO card at address 0001
[    6.037459] [    T290] meson-drm ff900000.vpu: [drm] fb0: mesondrmfb frame buffer device
[    6.053559] [    T295] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[    6.059877] [    T295] usb usb2: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.17
[    6.068675] [    T295] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    6.076555] [    T295] usb usb2: Product: xHCI Host Controller
[    6.082088] [    T295] usb usb2: Manufacturer: Linux 6.17.4 xhci-hcd
[    6.090666] [    T295] usb usb2: SerialNumber: xhci-hcd.2.auto
[    6.096741] [    T295] hub 2-0:1.0: USB hub found
[    6.100657] [    T295] hub 2-0:1.0: 1 port detected
[    6.348249] [    T381] BTRFS: device fsid 6a42b9d0-571c-4394-9ebb-c9a490151bba devid 1 transid 289466 /dev/mmcblk1p3 (179:3) scanned by mount (381)
[    6.358236] [    T381] BTRFS info (device mmcblk1p3): first mount of filesystem 6a42b9d0-571c-4394-9ebb-c9a490151bba
[    6.366811] [    T381] BTRFS info (device mmcblk1p3): using crc32c (crc32c-lib) checksum algorithm
[    6.391884] [    T381] BTRFS info (device mmcblk1p3): enabling ssd optimizations
[    6.394315] [    T381] BTRFS info (device mmcblk1p3): enabling free space tree
[    7.201146] [    T152] systemd-journald[152]: Received SIGTERM from PID 1 (systemd).
[    7.537061] [      T1] systemd[1]: systemd 257.7+suse.19.ga0dfd5de4c running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +IPE -SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK -BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE)
[    7.570687] [      T1] systemd[1]: Detected architecture arm64.
[    7.937815] [      T1] systemd[1]: bpf-restrict-fs: LSM BPF program attached
[    8.248007] [      T1] systemd[1]: /usr/lib/systemd/system/frr.service:30: PIDFile= references a path below legacy directory /var/run/, updating /var/run/frr/watchfrr.pid ? /run/frr/watchfrr.pid; please update the unit file accordingly.
[    8.532291] [      T1] systemd[1]: initrd-switch-root.service: Deactivated successfully.
[    8.535896] [      T1] systemd[1]: Stopped Switch Root.
[    8.555279] [      T1] systemd[1]: systemd-journald.service: Scheduled restart job, restart counter is at 1.
[    8.562763] [      T1] systemd[1]: Created slice Slice /system/getty.
[    8.586734] [      T1] systemd[1]: Created slice Slice /system/openvpn.
[    8.602667] [      T1] systemd[1]: Created slice Slice /system/serial-getty.
[    8.622699] [      T1] systemd[1]: Created slice Slice /system/systemd-fsck.
[    8.641679] [      T1] systemd[1]: Created slice User and Session Slice.
[    8.657304] [      T1] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    8.677614] [      T1] systemd[1]: Set up automount Arbitrary Executable File Formats File System Automount Point.
[    8.705092] [      T1] systemd[1]: Expecting device /dev/disk/by-uuid/CE59-EAEA...
[    8.721042] [      T1] systemd[1]: Expecting device /dev/ttyAML0...
[    8.733073] [      T1] systemd[1]: Reached target Local Encrypted Volumes.
[    8.753115] [      T1] systemd[1]: Stopped target Switch Root.
[    8.765092] [      T1] systemd[1]: Stopped target Initrd File Systems.
[    8.785065] [      T1] systemd[1]: Stopped target Initrd Root File System.
[    8.805095] [      T1] systemd[1]: Reached target Local Integrity Protected Volumes.
[    8.821170] [      T1] systemd[1]: Reached target Remote File Systems.
[    8.841068] [      T1] systemd[1]: Reached target Slice Units.
[    8.853111] [      T1] systemd[1]: Reached target Swaps.
[    8.865105] [      T1] systemd[1]: Reached target Local Verity Protected Volumes.
[    8.881359] [      T1] systemd[1]: Listening on Device-mapper event daemon FIFOs.
[    8.897357] [      T1] systemd[1]: Listening on LVM2 poll daemon socket.
[    8.927348] [      T1] systemd[1]: Listening on Process Core Dump Socket.
[    8.943952] [      T1] systemd[1]: Listening on Credential Encryption/Decryption.
[    8.961554] [      T1] systemd[1]: Listening on Network Service Netlink Socket.
[    8.977330] [      T1] systemd[1]: Listening on udev Control Socket.
[    8.997255] [      T1] systemd[1]: Listening on udev Kernel Socket.
[    9.022028] [      T1] systemd[1]: Mounting Huge Pages File System...
[    9.069543] [      T1] systemd[1]: Mounting POSIX Message Queue File System...
[    9.087790] [      T1] systemd[1]: Mounting Kernel Debug File System...
[    9.104852] [      T1] systemd[1]: Mounting Kernel Trace File System...
[    9.126835] [      T1] systemd[1]: Starting Create List of Static Device Nodes...
[    9.150033] [      T1] systemd[1]: Starting Load Kernel Module configfs...
[    9.174126] [      T1] systemd[1]: Starting Load Kernel Module dm_mod...
[    9.198077] [      T1] systemd[1]: Starting Load Kernel Module drm...
[    9.222216] [      T1] systemd[1]: Starting Load Kernel Module fuse...
[    9.232683] [    T435] device-mapper: uevent: version 1.0.3
[    9.234539] [    T435] device-mapper: ioctl: 4.50.0-ioctl (2025-04-28) initialised: dm-devel at lists.linux.dev
[    9.279631] [      T1] systemd[1]: Starting Load Kernel Module loop...
[    9.297691] [      T1] systemd[1]: Clear Stale Hibernate Storage Info was skipped because of an unmet condition check (ConditionPathExists=/sys/firmware/efi/efivars/HibernateLocation-8cf2644b-4b0b-428f-9387-6d876050dc67).
[    9.318760] [    T437] fuse: init (API version 7.44)
[    9.320076] [    T438] loop: module loaded
[    9.325469] [      T1] systemd[1]: Starting Journal Service...
[    9.344839] [      T1] systemd[1]: Starting Load Kernel Modules...
[    9.370932] [      T1] systemd[1]: Starting Generate network units from Kernel command line...
[    9.392510] [      T1] systemd[1]: Starting Remount Root and Kernel File Systems...
[    9.416457] [      T1] systemd[1]: Starting Load udev Rules from Credentials...
[    9.432769] [    T439] systemd-journald[439]: Collecting audit messages is disabled.
[    9.444571] [    T447] BTRFS info (device mmcblk1p3 state M): use zstd compression, level 2
[    9.469779] [      T1] systemd[1]: Starting Coldplug All udev Devices...
[    9.496192] [      T1] systemd[1]: Started Journal Service.
[    9.760089] [    T439] systemd-journald[439]: Received client request to flush runtime journal.
[   10.745740] [    T526] cpu cpu0: EM: created perf domain
[   10.761734] [    T526] cpufreq: cpufreq_policy_online: CPU2: Running at unlisted initial frequency: 999999 kHz, changing to: 1000000 kHz
[   10.769578] [    T526] cpu cpu2: EM: created perf domain
[   10.773795] [    T526] energy_model: updating cpu0 cpu_cap=449 old capacity=512
[   10.794887] [    T520] mc: Linux media interface: v0.10
[   10.833439] [    T512] etnaviv etnaviv: bound ff100000.npu (ops gpu_ops [etnaviv])
[   10.835679] [    T512] etnaviv-gpu ff100000.npu: model: GC8000, revision: 7120
[   10.842505] [    T512] etnaviv-gpu ff100000.npu: etnaviv has been instantiated on a NPU, for which the UAPI is still experimental
[   10.847890] [    T520] videodev: Linux video capture interface: v2.00
[   10.872540] [    T512] [drm] Initialized etnaviv 1.4.0 for etnaviv on minor 0
[   10.905517] [    T526] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[   10.909149] [    T526] Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[   10.915637] [    T526] Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600'
[   10.925158] [     T82] faux_driver regulatory: Direct firmware load for regulatory.db failed with error -2
[   10.937797] [     T82] cfg80211: failed to load regulatory.db
[   10.945546] [    T491] meson8b-dwmac ff3f0000.ethernet: IRQ eth_wake_irq not found
[   10.947964] [    T491] meson8b-dwmac ff3f0000.ethernet: IRQ eth_lpi not found
[   10.954941] [    T491] meson8b-dwmac ff3f0000.ethernet: IRQ sfty not found
[   10.964383] [    T491] meson8b-dwmac ff3f0000.ethernet: PTP uses main clock
[   10.968306] [    T491] meson8b-dwmac ff3f0000.ethernet: User ID: 0x11, Synopsys ID: 0x37
[   10.975667] [    T491] meson8b-dwmac ff3f0000.ethernet:      DWMAC1000
[   10.981521] [    T491] meson8b-dwmac ff3f0000.ethernet: DMA HW capability register supported
[   10.989684] [    T491] meson8b-dwmac ff3f0000.ethernet: RX Checksum Offload Engine supported
[   10.997769] [    T491] meson8b-dwmac ff3f0000.ethernet: COE Type 2
[   11.003620] [    T491] meson8b-dwmac ff3f0000.ethernet: TX Checksum insertion supported
[   11.011341] [    T491] meson8b-dwmac ff3f0000.ethernet: Wake-Up On Lan supported
[   11.018568] [    T491] meson8b-dwmac ff3f0000.ethernet: Normal descriptors
[   11.021177] [    T540] debugfs: 'ff800280.cec' already exists in 'regmap'
[   11.024631] [    T491] meson8b-dwmac ff3f0000.ethernet: Ring mode enabled
[   11.027298] [    T520] meson_vdec: module is from the staging directory, the quality is unknown, you have been warned.
[   11.039744] [    T526] iwlwifi 0000:01:00.0: enabling device (0000 -> 0002)
[   11.048030] [    T491] meson8b-dwmac ff3f0000.ethernet: Enable RX Mitigation via HW Watchdog Timer
[   11.067621] [    T526] iwlwifi 0000:01:00.0: Detected crf-id 0x400410, cnv-id 0x400410 wfpm id 0x80000000
[   11.073131] [    T526] iwlwifi 0000:01:00.0: PCI dev 2725/0024, rev=0x420, rfid=0x10d000
[   11.080985] [    T526] iwlwifi 0000:01:00.0: Detected Intel(R) Wi-Fi 6E AX210 160MHz
[   11.102253] [    T523] panfrost ffe40000.gpu: clock rate = 24000000
[   11.103448] [    T523] panfrost ffe40000.gpu: error -ENODEV: _opp_set_regulators: no regulator (mali) found
[   11.134370] [    T523] panfrost ffe40000.gpu: mali-g52 id 0x7212 major 0x0 minor 0x0 status 0x0
[   11.137986] [    T523] panfrost ffe40000.gpu: features: 00000000,00000df7, issues: 00000000,00000400
[   11.146805] [    T523] panfrost ffe40000.gpu: Features: L2:0x07110206 Shader:0x00000000 Tiler:0x00000809 Mem:0x1 MMU:0x00002830 AS:0xff JS:0x7
[   11.159425] [    T466] iwlwifi 0000:01:00.0: loaded firmware version 89.af655058.0 ty-a0-gf-a0-89.ucode op_mode iwlmvm
[   11.160187] [    T523] panfrost ffe40000.gpu: shader_present=0x3 l2_present=0x1
[   11.220516] [    T523] [drm] Initialized panfrost 1.4.0 for ffe40000.gpu on minor 2

On 6.18-rc2 iwlwifi never gets probed

[    0.000000] [      T0] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] [      T0] Linux version 6.18.0-rc2 (geeko at buildhost) (gcc (SUSE Linux) 15.1.1 20250714, GNU ld (GNU Binutils; SUSE Linux 16) 2.43.1.20241209-160000.2) #1 SMP PREEMPT_DYNAMIC Mon Oct 20 05:45:13 UTC 2025 (f43c94d)
[    0.000000] [      T0] KASLR enabled
[    0.000000] [      T0] Machine model: Khadas VIM3
[    0.000000] [      T0] efi: EFI v2.10 by Das U-Boot
[    0.000000] [      T0] efi: RTPROP=0xefed5040 SMBIOS=0xefefc000 RNG=0xedc4d040 MEMRESERVE=0xe7d43040
[    0.000000] [      T0] random: crng init done
[    0.000000] [      T0] Reserved memory: created CMA memory pool at 0x00000000c9800000, size 480 MiB
[    0.000000] [      T0] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
[    0.000000] [      T0] OF: reserved mem: 0x00000000c9800000..0x00000000e77fffff (491520 KiB) map reusable linux,cma
[    0.000000] [      T0] OF: reserved mem: 0x0000000005000000..0x00000000052fffff (3072 KiB) nomap non-reusable secmon at 5000000
[    0.000000] [      T0] OF: reserved mem: 0x0000000005300000..0x00000000072fffff (32768 KiB) nomap non-reusable secmon at 5300000
[    0.000000] [      T0] Zone ranges:
[    0.000000] [      T0]   DMA      [mem 0x0000000000000000-0x00000000f4ffffff]
[    0.000000] [      T0]   DMA32    empty
[    0.000000] [      T0]   Normal   empty
[    0.000000] [      T0]   Device   empty
[    0.000000] [      T0] Movable zone start for each node
[    0.000000] [      T0] Early memory node ranges
[    0.000000] [      T0]   node   0: [mem 0x0000000000000000-0x0000000004ffffff]
[    0.000000] [      T0]   node   0: [mem 0x0000000005000000-0x00000000072fffff]
[    0.000000] [      T0]   node   0: [mem 0x0000000007300000-0x00000000efed4fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed5000-0x00000000efed5fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed6000-0x00000000efed6fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed7000-0x00000000efed8fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efed9000-0x00000000efed9fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efeda000-0x00000000efef9fff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efefa000-0x00000000efefbfff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efefc000-0x00000000efefcfff]
[    0.000000] [      T0]   node   0: [mem 0x00000000efefd000-0x00000000f2f0ffff]
[    0.000000] [      T0]   node   0: [mem 0x00000000f2f10000-0x00000000f2f1ffff]
[    0.000000] [      T0]   node   0: [mem 0x00000000f2f20000-0x00000000f4e5afff]
[    0.000000] [      T0]   node   0: [mem 0x00000000f4e5b000-0x00000000f4ffffff]
[    0.000000] [      T0] Initmem setup node 0 [mem 0x0000000000000000-0x00000000f4ffffff]
[    0.000000] [      T0] On node 0, zone DMA: 12288 pages in unavailable ranges
[    0.000000] [      T0] psci: probing for conduit method from DT.
[    0.000000] [      T0] psci: PSCIv1.0 detected in firmware.
[    0.000000] [      T0] psci: Using standard PSCI v0.2 function IDs
[    0.000000] [      T0] psci: MIGRATE_INFO_TYPE not supported.
[    0.000000] [      T0] psci: SMC Calling Convention v1.1
[    0.000000] [      T0] RME: RMM doesn't support RSI version 1.0. Supported range: 1.0-0.0
[    0.000000] [      T0] percpu: Embedded 56 pages/cpu s103768 r8192 d117416 u229376
[    0.000000] [      T0] pcpu-alloc: s103768 r8192 d117416 u229376 alloc=56*4096
[    0.000000] [      T0] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 [0] 4 [0] 5
[    0.000000] [      T0] Detected VIPT I-cache on CPU0
[    0.000000] [      T0] CPU features: kernel page table isolation forced ON by KASLR
[    0.000000] [      T0] CPU features: detected: Kernel page table isolation (KPTI)
[    0.000000] [      T0] alternatives: applying boot alternatives
[    0.000000] [      T0] Kernel command line: BOOT_IMAGE=/boot/Image-6.18.0-rc2 root=UUID=6a42b9d0-571c-4394-9ebb-c9a490151bba rd.timeout=15 mitigations=off delayacct
[    0.000000] [      T0] printk: log_buf_len individual max cpu contribution: 32768 bytes
[    0.000000] [      T0] printk: log_buf_len total cpu_extra contributions: 163840 bytes
[    0.000000] [      T0] printk: log_buf_len min size: 262144 bytes
[    0.000000] [      T0] printk: log buffer data + meta data: 524288 + 1835008 = 2359296 bytes
[    0.000000] [      T0] printk: early log buf free: 258624(98%)
[    0.000000] [      T0] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes, linear)
[    0.000000] [      T0] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[    0.000000] [      T0] software IO TLB: SWIOTLB bounce buffer size adjusted to 3MB
[    0.000000] [      T0] software IO TLB: area num 8.
[    0.000000] [      T0] software IO TLB: mapped [mem 0x00000000f389f000-0x00000000f3c9f000] (4MB)
[    0.000000] [      T0] Built 1 zonelists, mobility grouping on.  Total pages: 1003520
[    0.000000] [      T0] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] [      T0] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=6, Nodes=1
[    0.000000] [      T0] ftrace: allocating 46541 entries in 182 pages
[    0.000000] [      T0] ftrace: allocated 182 pages with 5 groups
[    0.000000] [      T0] Dynamic Preempt: voluntary
[    0.000000] [      T0] rcu: Preemptible hierarchical RCU implementation.
[    0.000000] [      T0] rcu:  RCU event tracing is enabled.
[    0.000000] [      T0] rcu:  RCU restricting CPUs from NR_CPUS=16 to nr_cpu_ids=6.
[    0.000000] [      T0]       Trampoline variant of Tasks RCU enabled.
[    0.000000] [      T0]       Rude variant of Tasks RCU enabled.
[    0.000000] [      T0]       Tracing variant of Tasks RCU enabled.
[    0.000000] [      T0] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] [      T0] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=6
[    0.000000] [      T0] RCU Tasks: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=6.
[    0.000000] [      T0] RCU Tasks Rude: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=6.
[    0.000000] [      T0] RCU Tasks Trace: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=6.
[    0.000000] [      T0] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] [      T0] Root IRQ handler: gic_handle_irq
[    0.000000] [      T0] GIC: Using split EOI/Deactivate mode
[    0.000000] [      T0] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] [      T0] arch_timer: cp15 timer running at 24.00MHz (phys).
[    0.000000] [      T0] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
[    0.000000] [      T0] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
[    0.000503] [      T0] Console: colour dummy device 80x25
[    0.000521] [      T0] printk: legacy console [tty0] enabled
[    0.001411] [      T0] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=96000)
[    0.001439] [      T0] pid_max: default: 32768 minimum: 301
[    0.001648] [      T0] LSM: initializing lsm=capability,apparmor,bpf,ima,evm
[    0.002019] [      T0] AppArmor: AppArmor initialized
[    0.002483] [      T0] LSM support for eBPF active
[    0.002778] [      T0] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.002817] [      T0] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.004111] [      T0] spectre-v4 mitigation disabled by command-line option
[    0.005905] [      T1] rcu: Hierarchical SRCU implementation.
[    0.005946] [      T1] rcu:  Max phase no-delay instances is 1000.
[    0.006191] [      T1] Timer migration: 1 hierarchy levels; 8 children per group; 1 crossnode level
[    0.007612] [      T1] Remapping and enabling EFI services.
[    0.008163] [      T1] smp: Bringing up secondary CPUs ...
[    0.008977] [      T0] Detected VIPT I-cache on CPU1
[    0.009184] [      T0] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[    0.010567] [      T0] CPU features: detected: Spectre-v2
[    0.010583] [      T0] CPU features: detected: Spectre-v4
[    0.010589] [      T0] CPU features: detected: Spectre-BHB
[    0.010593] [      T0] CPU features: detected: ARM erratum 858921
[    0.010603] [      T0] Detected VIPT I-cache on CPU2
[    0.010737] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.010755] [      T0] arch_timer: CPU2: Trapping CNTVCT access
[    0.010766] [      T0] CPU2: Booted secondary processor 0x0000000100 [0x410fd092]
[    0.011540] [      T0] Detected VIPT I-cache on CPU3
[    0.011638] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.011648] [      T0] arch_timer: CPU3: Trapping CNTVCT access
[    0.011655] [      T0] CPU3: Booted secondary processor 0x0000000101 [0x410fd092]
[    0.012468] [      T0] Detected VIPT I-cache on CPU4
[    0.012568] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.012578] [      T0] arch_timer: CPU4: Trapping CNTVCT access
[    0.012585] [      T0] CPU4: Booted secondary processor 0x0000000102 [0x410fd092]
[    0.013322] [      T0] Detected VIPT I-cache on CPU5
[    0.013423] [      T0] arch_timer: Enabling local workaround for ARM erratum 858921
[    0.013433] [      T0] arch_timer: CPU5: Trapping CNTVCT access
[    0.013440] [      T0] CPU5: Booted secondary processor 0x0000000103 [0x410fd092]
[    0.013531] [      T1] smp: Brought up 1 node, 6 CPUs
[    0.013774] [      T1] SMP: Total of 6 processors activated.
[    0.013788] [      T1] CPU: All CPU(s) started at EL2
[    0.013814] [      T1] CPU features: detected: 32-bit EL0 Support
[    0.013828] [      T1] CPU features: detected: 32-bit EL1 Support
[    0.013844] [      T1] CPU features: detected: CRC32 instructions
[    0.013867] [      T1] CPU features: detected: PMUv3
[    0.013944] [      T1] alternatives: applying system-wide alternatives
[    0.015167] [      T1] CPU features: emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching
[    0.034628] [     T47] node 0 deferred pages initialised in 16ms
[    0.034707] [      T1] Memory: 3332448K/4014080K available (14912K kernel code, 2590K rwdata, 11620K rodata, 7360K init, 725K bss, 184416K reserved, 491520K cma-reserved)
[    0.035701] [      T1] devtmpfs: initialized
[    0.046066] [      T1] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.046136] [      T1] posixtimers hash table entries: 4096 (order: 4, 65536 bytes, linear)
[    0.046203] [      T1] futex hash table entries: 2048 (131072 bytes on 1 NUMA nodes, total 128 KiB, linear).
[    0.050044] [      T1] 2G module region forced by RANDOMIZE_MODULE_REGION_FULL
[    0.050075] [      T1] 0 pages in range for non-PLT usage
[    0.050079] [      T1] 514928 pages in range for PLT usage
[    0.050369] [      T1] pinctrl core: initialized pinctrl subsystem
[    0.051042] [      T1] SMBIOS 3.0 present.
[    0.051064] [      T1] DMI: khadas VIM3/VIM3, BIOS 2024.01-rc4-00039-gce25ceb939 01/01/2024
[    0.051086] [      T1] DMI: Memory slots populated: 0/0
[    0.053164] [      T1] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.054039] [      T1] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic allocations
[    0.054296] [      T1] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.054596] [      T1] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.054660] [      T1] audit: initializing netlink subsys (disabled)
[    0.054823] [     T58] audit: type=2000 audit(0.052:1): state=initialized audit_enabled=0 res=1
[    0.056121] [      T1] thermal_sys: Registered thermal governor 'fair_share'
[    0.056128] [      T1] thermal_sys: Registered thermal governor 'bang_bang'
[    0.056142] [      T1] thermal_sys: Registered thermal governor 'step_wise'
[    0.056153] [      T1] thermal_sys: Registered thermal governor 'user_space'
[    0.056164] [      T1] thermal_sys: Registered thermal governor 'power_allocator'
[    0.056212] [      T1] cpuidle: using governor ladder
[    0.056255] [      T1] cpuidle: using governor menu
[    0.056405] [      T1] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
[    0.056525] [      T1] ASID allocator initialised with 32768 entries
[    0.056737] [      T1] Serial: AMBA PL011 UART driver
[    0.063459] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.063859] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.063912] [      T1] /soc/vpu at ff900000: Fixed dependency cycle(s) with /soc/bus at ff600000/hdmi-tx at 0
[    0.063949] [      T1] /soc/interrupt-controller at ffc01000: Fixed dependency cycle(s) with /soc/interrupt-controller at ffc01000
[    0.064038] [      T1] /soc/usb at ffe09000: Fixed dependency cycle(s) with /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector
[    0.064659] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.065076] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.070294] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.071521] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.072052] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /soc/vpu at ff900000
[    0.072120] [      T1] /soc/vpu at ff900000: Fixed dependency cycle(s) with /soc/bus at ff600000/hdmi-tx at 0
[    0.074369] [      T1] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    0.074440] [      T1] /soc/usb at ffe09000: Fixed dependency cycle(s) with /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector
[    0.077573] [      T1] /soc/bus at ff600000/hdmi-tx at 0: Fixed dependency cycle(s) with /hdmi-connector
[    0.077650] [      T1] /hdmi-connector: Fixed dependency cycle(s) with /soc/bus at ff600000/hdmi-tx at 0
[    0.079566] [      T1] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
[    0.079589] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 1.00 GiB page
[    0.079602] [      T1] HugeTLB: registered 32.0 MiB page size, pre-allocated 0 pages
[    0.079614] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 32.0 MiB page
[    0.079626] [      T1] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
[    0.079637] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 2.00 MiB page
[    0.079648] [      T1] HugeTLB: registered 64.0 KiB page size, pre-allocated 0 pages
[    0.079659] [      T1] HugeTLB: 0 KiB vmemmap can be freed for a 64.0 KiB page
[    0.081445] [      T1] fbcon: Taking over console
[    0.082252] [      T1] iommu: Default domain type: Translated
[    0.082274] [      T1] iommu: DMA domain TLB invalidation policy: strict mode
[    0.084675] [      T1] pps_core: LinuxPPS API ver. 1 registered
[    0.084692] [      T1] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti at linux.it>
[    0.084714] [      T1] PTP clock support registered
[    0.084750] [      T1] EDAC MC: Ver: 3.0.0
[    0.084846] [      T1] EDAC DEBUG: edac_mc_sysfs_init: device mc created
[    0.084983] [      T1] scmi_core: SCMI protocol bus registered
[    0.085130] [      T1] efivars: Registered efivars operations
[    0.086205] [      T1] NetLabel: Initializing
[    0.086219] [      T1] NetLabel:  domain hash size = 128
[    0.086229] [      T1] NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO
[    0.086306] [      T1] NetLabel:  unlabeled traffic allowed by default
[    0.086327] [      T1] mctp: management component transport protocol core
[    0.086337] [      T1] NET: Registered PF_MCTP protocol family
[    0.086640] [      T1] vgaarb: loaded
[    0.087009] [      T1] clocksource: Switched to clocksource arch_sys_counter
[    0.087671] [      T1] VFS: Disk quotas dquot_6.6.0
[    0.087717] [      T1] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
[    0.088417] [      T1] AppArmor: AppArmor Filesystem Enabled
[    0.093700] [      T1] NET: Registered PF_INET protocol family
[    0.093915] [      T1] IP idents hash table entries: 65536 (order: 7, 524288 bytes, linear)
[    0.127773] [      T1] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes, linear)
[    0.127835] [      T1] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.127915] [      T1] TCP established hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.128089] [      T1] TCP bind hash table entries: 32768 (order: 8, 1048576 bytes, linear)
[    0.128411] [      T1] TCP: Hash tables configured (established 32768 bind 32768)
[    0.128657] [      T1] MPTCP token hash table entries: 4096 (order: 4, 98304 bytes, linear)
[    0.128752] [      T1] UDP hash table entries: 2048 (order: 5, 131072 bytes, linear)
[    0.128829] [      T1] UDP-Lite hash table entries: 2048 (order: 5, 131072 bytes, linear)
[    0.129104] [      T1] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.129148] [      T1] NET: Registered PF_XDP protocol family
[    0.129205] [      T1] PCI: CLS 0 bytes, default 64
[    0.129396] [     T48] Trying to unpack rootfs image as initramfs...
[    0.138099] [      T1] kvm [1]: nv: 568 coarse grained trap handlers
[    0.138500] [      T1] kvm [1]: IPA Size Limit: 40 bits
[    0.140404] [      T1] kvm [1]: vgic interrupt IRQ9
[    0.140465] [      T1] kvm [1]: Hyp nVHE mode initialized successfully
[    0.144840] [      T1] Initialise system trusted keyrings
[    0.144905] [      T1] Key type blacklist registered
[    0.145156] [      T1] workingset: timestamp_bits=46 max_order=20 bucket_order=0
[    0.145904] [      T1] integrity: Platform Keyring initialized
[    0.145930] [      T1] integrity: Machine keyring initialized
[    0.145941] [      T1] Allocating IMA blacklist keyring.
[    0.186578] [      T1] Key type asymmetric registered
[    0.186611] [      T1] Asymmetric key parser 'x509' registered
[    0.186720] [      T1] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
[    0.186931] [      T1] io scheduler mq-deadline registered
[    0.186949] [      T1] io scheduler kyber registered
[    0.187064] [      T1] io scheduler bfq registered
[    0.187831] [      T1] irq_meson_gpio: 100 to 8 gpio interrupt mux initialized
[    0.193712] [      T1] ledtrig-cpu: registered to indicate activity on CPUs
[    0.200362] [      T1] soc soc0: Amlogic Meson G12B (A311D) Revision 29:b (10:2) Detected
[    0.201799] [      T1] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled
[    0.210450] [      T1] Serial: AMBA driver
[    0.211406] [      T1] ff803000.serial: ttyAML0 at MMIO 0xff803000 (irq = 14, base_baud = 1500000) is a meson_uart
[    0.211454] [      T1] printk: legacy console [ttyAML0] enabled
[    0.579974] [     T48] Freeing initrd memory: 23072K
[    0.596452] [      T1] ffd24000.serial: ttyAML6 at MMIO 0xffd24000 (irq = 15, base_baud = 1500000) is a meson_uart
[    1.833547] [      T1] serial serial0: tty port ttyAML6 registered
[    1.839565] [      T1] msm_serial: driver initialized
[    1.847374] [      T1] mousedev: PS/2 mouse device common for all mice
[    1.851410] [      T1] meson-sm: secure-monitor enabled
[    1.855333] [      T1] hid: raw HID events driver (C) Jiri Kosina
[    1.861687] [     T82] watchdog: NMI not fully supported
[    1.865872] [     T82] watchdog: Hard watchdog permanently disabled
[    1.867408] [      T1] drop_monitor: Initializing network drop monitor service
[    1.879113] [      T1] NET: Registered PF_INET6 protocol family
[    1.885448] [      T1] Segment Routing with IPv6
[    1.888755] [      T1] RPL Segment Routing with IPv6
[    1.893446] [      T1] In-situ OAM (IOAM) with IPv6
[    1.903427] [      T1] registered taskstats version 1
[    1.934253] [      T1] zswap: loaded using pool zstd
[    1.934369] [      T1] page_owner is disabled
[    1.937734] [      T1] Key type .fscrypt registered
[    1.942017] [      T1] Key type fscrypt-provisioning registered
[    1.948232] [      T1] Key type big_key registered
[    2.008936] [      T1] Key type encrypted registered
[    2.008992] [      T1] AppArmor: AppArmor sha256 policy hashing enabled
[    2.014525] [      T1] ima: secureboot mode disabled
[    2.019050] [      T1] ima: No TPM chip found, activating TPM-bypass!
[    2.040795] [      T1] ima: Allocated hash algorithm: sha256
[    2.046192] [      T1] ima: No architecture policies found
[    2.051424] [      T1] evm: Initialising EVM extended attributes:
[    2.057166] [      T1] evm: security.selinux
[    2.061149] [      T1] evm: security.SMACK64 (disabled)
[    2.066090] [      T1] evm: security.SMACK64EXEC (disabled)
[    2.071375] [      T1] evm: security.SMACK64TRANSMUTE (disabled)
[    2.077095] [      T1] evm: security.SMACK64MMAP (disabled)
[    2.082382] [      T1] evm: security.apparmor
[    2.086454] [      T1] evm: security.ima
[    2.090094] [      T1] evm: security.capability
[    2.094341] [      T1] evm: HMAC attrs: 0x1
[    2.111082] [     T48] simple-framebuffer f4e5b000.framebuffer: [drm] Registered 1 planes with drm panic
[    2.114682] [     T48] [drm] Initialized simpledrm 1.0.0 for f4e5b000.framebuffer on minor 0
[    2.125198] [     T48] Console: switching to colour frame buffer device 90x36
[    2.130606] [     T48] simple-framebuffer f4e5b000.framebuffer: [drm] fb0: simpledrmdrmfb frame buffer device
[    2.172492] [      T1] clk: Disabling unused clocks
[    2.172879] [      T1] PM: genpd: Disabling unused power domains
[    2.187117] [      T1] Freeing unused kernel memory: 7360K
[    2.232240] [      T1] Checked W+X mappings: passed, no W+X pages found
[    2.233150] [      T1] Run /init as init process
[    2.237331] [      T1]   with arguments:
[    2.237337] [      T1]     /init
[    2.237342] [      T1]   with environment:
[    2.237346] [      T1]     HOME=/
[    2.237350] [      T1]     TERM=linux
[    2.251522] [      T1] systemd[1]: System time advanced to built-in epoch: Thu 2025-07-31 14:32:25 UTC
[    2.310633] [      T1] systemd[1]: Successfully made /usr/ read-only.
[    2.319091] [      T1] systemd[1]: systemd 257.7+suse.19.ga0dfd5de4c running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +IPE -SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK -BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE)
[    2.354231] [      T1] systemd[1]: Detected architecture arm64.
[    2.356597] [      T1] systemd[1]: Running in initrd.
[    2.379214] [      T1] systemd[1]: Hostname set to <linux-g12b>.
[    2.600479] [      T1] systemd[1]: Queued start job for default target Initrd Default Target.
[    2.644193] [      T1] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    2.663166] [      T1] systemd[1]: Expecting device /dev/disk/by-uuid/6a42b9d0-571c-4394-9ebb-c9a490151bba...
[    2.683135] [      T1] systemd[1]: Expecting device /dev/disk/by-uuid/CE59-EAEA...
[    2.699227] [      T1] systemd[1]: Reached target Initrd /usr File System.
[    2.715232] [      T1] systemd[1]: Reached target Path Units.
[    2.727239] [      T1] systemd[1]: Reached target Slice Units.
[    2.739272] [      T1] systemd[1]: Reached target Swaps.
[    2.751224] [      T1] systemd[1]: Reached target Timer Units.
[    2.763657] [      T1] systemd[1]: Listening on Journal Socket (/dev/log).
[    2.779645] [      T1] systemd[1]: Listening on Journal Sockets.
[    2.795577] [      T1] systemd[1]: Listening on udev Control Socket.
[    2.811440] [      T1] systemd[1]: Listening on udev Kernel Socket.
[    2.831237] [      T1] systemd[1]: Reached target Socket Units.
[    2.846782] [      T1] systemd[1]: Starting Create List of Static Device Nodes...
[    2.897543] [      T1] systemd[1]: Starting Journal Service...
[    2.917894] [      T1] systemd[1]: Starting Load Kernel Modules...
[    2.948938] [      T1] systemd[1]: Starting Virtual Console Setup...
[    2.965662] [      T1] systemd[1]: Finished Create List of Static Device Nodes.
[    2.991297] [      T1] systemd[1]: Starting Create Static Device Nodes in /dev gracefully...
[    2.999627] [    T150] systemd-journald[150]: Collecting audit messages is disabled.
[    3.030974] [      T1] systemd[1]: Finished Create Static Device Nodes in /dev gracefully.
[    3.036695] [      T1] systemd[1]: Started Journal Service.
[    3.043247] [    T151] zram: Added device: zram0
[    3.703012] [    T273] raid6: neonx8   gen()  2657 MB/s
[    3.771010] [    T273] raid6: neonx4   gen()  2949 MB/s
[    3.839009] [    T273] raid6: neonx2   gen()  2357 MB/s
[    3.907012] [    T273] raid6: neonx1   gen()  1784 MB/s
[    3.975012] [    T273] raid6: int64x8  gen()  1209 MB/s
[    4.043013] [    T273] raid6: int64x4  gen()  1409 MB/s
[    4.111019] [    T273] raid6: int64x2  gen()  1364 MB/s
[    4.179018] [    T273] raid6: int64x1  gen()  1092 MB/s
[    4.179812] [    T273] raid6: using algorithm neonx4 gen() 2949 MB/s
[    4.251008] [    T273] raid6: .... xor() 2265 MB/s, rmw enabled
[    4.251704] [    T273] raid6: using neon recovery algorithm
[    4.265918] [    T273] xor: measuring software checksum speed
[    4.267560] [    T273]    8regs           :  4038 MB/sec
[    4.272284] [    T273]    32regs          :  4199 MB/sec
[    4.277491] [    T273]    arm64_neon      :  3107 MB/sec
[    4.281410] [    T273] xor: using function: 32regs (4199 MB/sec)
[    4.551724] [    T273] Btrfs loaded, assert=on, zoned=yes, fsverity=yes
[    5.263494] [    T293] input: gpio-keys-polled as /devices/platform/gpio-keys-polled/input/input0
[    5.274235] [    T301] pca953x 0-0020: using no AI
[    5.317556] [    T331] meson-gx-mmc ffe07000.mmc: allocated mmc-pwrseq
[    5.317948] [    T301] /soc/bus at ff800000/i2c at 5000/usb-typec at 22/connector: Fixed dependency cycle(s) with /soc/usb at ffe09000
[    5.371526] [    T309] meson-vrtc ff8000a8.rtc: registered as rtc1
[    5.391114] [    T306] dwc3-meson-g12a ffe09000.usb: USB2 ports: 2
[    5.391324] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.391413] [    T306] dwc3-meson-g12a ffe09000.usb: USB3 ports: 0
[    5.411265] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.415323] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.419906] [     T51] meson-gx-mmc ffe05000.mmc: Got CD GPIO
[    5.422278] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.442280] [     T50] meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
[    5.449631] [     T50] meson-pcie fc000000.pcie: Add PCIe port failed, -16
[    5.458779] [     T50] meson-pcie fc000000.pcie: probe with driver meson-pcie failed with error -16
[    5.503260] [    T317] rtc-hym8563 0-0051: registered as rtc0
[    5.506592] [    T317] rtc-hym8563 0-0051: setting system clock to 2025-10-23T08:55:45 UTC (1761209745)
[    5.522820] [    T295] meson-drm ff900000.vpu: Queued 1 outputs on vpu
[    5.580230] [     T51] meson-gx-mmc ffe03000.mmc: allocated mmc-pwrseq
[    5.589512] [    T157] mmc0: new UHS-I speed SDR104 SDXC card at address 1388
[    5.597129] [    T301] usbcore: registered new interface driver usbfs
[    5.599821] [    T301] usbcore: registered new interface driver hub
[    5.605003] [    T301] usbcore: registered new device driver usb
[    5.613310] [    T305] Console: switching to colour dummy device 80x25
[    5.625728] [    T290] mmcblk0: mmc0:1388 Stora 466 GiB
[    5.649562] [    T305] meson-drm ff900000.vpu: CVBS Output connector not available
[    5.654702] [    T318] dwc2 ff400000.usb: supply vusb_d not found, using dummy regulator
[    5.659365] [    T318] dwc2 ff400000.usb: supply vusb_a not found, using dummy regulator
[    5.663437] [     T10] mmc1: new HS200 MMC card at address 0001
[    5.667212] [    T318] dwc2 ff400000.usb: EPs: 7, dedicated fifos, 712 entries in SPRAM
[    5.674331] [     T10] mmcblk1: mmc1:0001 BJTD4R 29.1 GiB
[    5.680403] [    T305] meson-dw-hdmi ff600000.hdmi-tx: Detected HDMI TX controller v2.01a with HDCP (meson_dw_hdmi_phy)
[    5.688828] [     T10]  mmcblk1: p1 p2 p3
[    5.696297] [    T305] meson-dw-hdmi ff600000.hdmi-tx: registered DesignWare HDMI I2C bus driver
[    5.701094] [     T10] mmcblk1boot0: mmc1:0001 BJTD4R 4.00 MiB
[    5.708375] [    T305] meson-drm ff900000.vpu: bound ff600000.hdmi-tx (ops meson_dw_hdmi_ops [meson_dw_hdmi])
[    5.718988] [     T10] mmcblk1boot1: mmc1:0001 BJTD4R 4.00 MiB
[    5.723360] [    T305] meson-drm ff900000.vpu: DSI transceiver device is disabled
[    5.734431] [     T10] mmcblk1rpmb: mmc1:0001 BJTD4R 4.00 MiB, chardev (234:0)
[    5.736610] [    T305] [drm] Initialized meson 1.0.0 for ff900000.vpu on minor 1
[    5.754254] [    T291] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller
[    5.756542] [    T291] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 1
[    5.764698] [    T291] xhci-hcd xhci-hcd.1.auto: hcc params 0x0228fe64 hci version 0x110 quirks 0x0000808000000010
[    5.774703] [    T291] xhci-hcd xhci-hcd.1.auto: irq 23, io mem 0xff500000
[    5.781503] [    T291] xhci-hcd xhci-hcd.1.auto: xHCI Host Controller
[    5.787362] [    T291] xhci-hcd xhci-hcd.1.auto: new USB bus registered, assigned bus number 2
[    5.795599] [    T291] xhci-hcd xhci-hcd.1.auto: Host supports USB 3.0 SuperSpeed
[    5.803035] [    T291] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 6.18
[    5.811695] [    T291] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    5.818262] [     T28] mmc2: new UHS-I speed SDR104 SDIO card at address 0001
[    5.819566] [    T291] usb usb1: Product: xHCI Host Controller
[    5.831981] [    T291] usb usb1: Manufacturer: Linux 6.18.0-rc2 xhci-hcd
[    5.840026] [    T291] usb usb1: SerialNumber: xhci-hcd.1.auto
[    5.846082] [    T291] hub 1-0:1.0: USB hub found
[    5.850042] [    T291] hub 1-0:1.0: 2 ports detected
[    6.347749] [    T305] Console: switching to colour frame buffer device 160x45
[    6.373623] [    T305] meson-drm ff900000.vpu: [drm] fb0: mesondrmfb frame buffer device
[    6.387572] [    T291] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[    6.396074] [    T291] usb usb2: New USB device found, idVendor=1d6b, idProduct=0003, bcdDevice= 6.18
[    6.404869] [    T291] usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[    6.412742] [    T291] usb usb2: Product: xHCI Host Controller
[    6.418243] [    T291] usb usb2: Manufacturer: Linux 6.18.0-rc2 xhci-hcd
[    6.426335] [    T291] usb usb2: SerialNumber: xhci-hcd.1.auto
[    6.432370] [    T291] hub 2-0:1.0: USB hub found
[    6.436358] [    T291] hub 2-0:1.0: 1 port detected
[    6.842476] [    T385] BTRFS: device fsid 6a42b9d0-571c-4394-9ebb-c9a490151bba devid 1 transid 288771 /dev/mmcblk1p3 (179:11) scanned by mount (385)
[    6.850883] [    T385] BTRFS info (device mmcblk1p3): first mount of filesystem 6a42b9d0-571c-4394-9ebb-c9a490151bba
[    6.860228] [    T385] BTRFS info (device mmcblk1p3): using crc32c (crc32c-lib) checksum algorithm
[    6.885833] [    T385] BTRFS info (device mmcblk1p3): enabling ssd optimizations
[    6.887408] [    T385] BTRFS info (device mmcblk1p3): turning on async discard
[    6.894334] [    T385] BTRFS info (device mmcblk1p3): enabling free space tree
[    7.640767] [    T150] systemd-journald[150]: Received SIGTERM from PID 1 (systemd).
[    7.971200] [      T1] systemd[1]: systemd 257.7+suse.19.ga0dfd5de4c running in system mode (+PAM +AUDIT +SELINUX -APPARMOR +IMA +IPE -SMACK +SECCOMP +GCRYPT +GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBCRYPTSETUP_PLUGINS +LIBFDISK +PCRE2 +PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD +BPF_FRAMEWORK -BTF -XKBCOMMON -UTMP +SYSVINIT +LIBARCHIVE)
[    8.001508] [      T1] systemd[1]: Detected architecture arm64.
[    8.312796] [     T28] usb usb1-port1: attempt power cycle
[    8.381404] [      T1] systemd[1]: bpf-restrict-fs: LSM BPF program attached
[    8.694777] [      T1] systemd[1]: /usr/lib/systemd/system/frr.service:30: PIDFile= references a path below legacy directory /var/run/, updating /var/run/frr/watchfrr.pid ? /run/frr/watchfrr.pid; please update the unit file accordingly.
[    8.981248] [      T1] systemd[1]: initrd-switch-root.service: Deactivated successfully.
[    8.983956] [      T1] systemd[1]: Stopped Switch Root.
[    9.001520] [      T1] systemd[1]: systemd-journald.service: Scheduled restart job, restart counter is at 1.
[    9.007980] [      T1] systemd[1]: Created slice Slice /system/getty.
[    9.028751] [      T1] systemd[1]: Created slice Slice /system/openvpn.
[    9.044710] [      T1] systemd[1]: Created slice Slice /system/serial-getty.
[    9.065445] [      T1] systemd[1]: Created slice Slice /system/systemd-fsck.
[    9.087714] [      T1] systemd[1]: Created slice User and Session Slice.
[    9.107334] [      T1] systemd[1]: Started Dispatch Password Requests to Console Directory Watch.
[    9.131647] [      T1] systemd[1]: Set up automount Arbitrary Executable File Formats File System Automount Point.
[    9.155119] [      T1] systemd[1]: Expecting device /dev/disk/by-uuid/CE59-EAEA...
[    9.171074] [      T1] systemd[1]: Expecting device /dev/ttyAML0...
[    9.183121] [      T1] systemd[1]: Reached target Local Encrypted Volumes.
[    9.199147] [      T1] systemd[1]: Stopped target Switch Root.
[    9.211120] [      T1] systemd[1]: Stopped target Initrd File Systems.
[    9.227092] [      T1] systemd[1]: Stopped target Initrd Root File System.
[    9.243125] [      T1] systemd[1]: Reached target Local Integrity Protected Volumes.
[    9.259179] [      T1] systemd[1]: Reached target Remote File Systems.
[    9.275122] [      T1] systemd[1]: Reached target Slice Units.
[    9.287134] [      T1] systemd[1]: Reached target Swaps.
[    9.299157] [      T1] systemd[1]: Reached target Local Verity Protected Volumes.
[    9.315389] [      T1] systemd[1]: Listening on Device-mapper event daemon FIFOs.
[    9.332129] [      T1] systemd[1]: Listening on LVM2 poll daemon socket.
[    9.357417] [      T1] systemd[1]: Listening on Process Core Dump Socket.
[    9.373958] [      T1] systemd[1]: Listening on Credential Encryption/Decryption.
[    9.391545] [      T1] systemd[1]: Listening on Network Service Netlink Socket.
[    9.407374] [      T1] systemd[1]: Listening on udev Control Socket.
[    9.423269] [      T1] systemd[1]: Listening on udev Kernel Socket.
[    9.444022] [      T1] systemd[1]: Mounting Huge Pages File System...
[    9.495565] [      T1] systemd[1]: Mounting POSIX Message Queue File System...
[    9.513869] [      T1] systemd[1]: Mounting Kernel Debug File System...
[    9.529792] [      T1] systemd[1]: Mounting Kernel Trace File System...
[    9.547040] [      T1] systemd[1]: Starting Create List of Static Device Nodes...
[    9.566497] [      T1] systemd[1]: Starting Load Kernel Module configfs...
[    9.582624] [      T1] systemd[1]: Starting Load Kernel Module dm_mod...
[    9.602495] [      T1] systemd[1]: Starting Load Kernel Module drm...
[    9.622512] [      T1] systemd[1]: Starting Load Kernel Module fuse...
[    9.640413] [    T437] device-mapper: uevent: version 1.0.3
[    9.640826] [    T437] device-mapper: ioctl: 4.50.0-ioctl (2025-04-28) initialised: dm-devel at lists.linux.dev
[    9.642643] [      T1] systemd[1]: Starting Load Kernel Module loop...
[    9.656512] [      T1] systemd[1]: Clear Stale Hibernate Storage Info was skipped because of an unmet condition check (ConditionPathExists=/sys/firmware/efi/efivars/HibernateLocation-8cf2644b-4b0b-428f-9387-6d876050dc67).
[    9.681553] [      T1] systemd[1]: Starting Journal Service...
[    9.690178] [    T439] fuse: init (API version 7.45)
[    9.703177] [      T1] systemd[1]: Starting Load Kernel Modules...
[    9.723457] [    T440] loop: module loaded
[    9.742587] [      T1] systemd[1]: Starting Generate network units from Kernel command line...
[    9.762697] [      T1] systemd[1]: Starting Remount Root and Kernel File Systems...
[    9.779256] [    T441] systemd-journald[441]: Collecting audit messages is disabled.
[    9.823789] [      T1] systemd[1]: Starting Load udev Rules from Credentials...
[    9.844530] [    T449] BTRFS info (device mmcblk1p3 state M): use zstd compression, level 2
[    9.846675] [      T1] systemd[1]: Starting Coldplug All udev Devices...
[    9.883173] [      T1] systemd[1]: Started Journal Service.
[   10.143680] [    T441] systemd-journald[441]: Received client request to flush runtime journal.
[   10.156809] [     T28] usb usb1-port1: unable to enumerate USB device
[   11.176960] [    T533] cpu cpu0: EM: created perf domain
[   11.210657] [    T533] cpufreq: cpufreq_policy_online: CPU2: Running at unlisted initial frequency: 999999 kHz, changing to: 1000000 kHz
[   11.218947] [    T533] cpu cpu2: EM: created perf domain
[   11.222707] [    T519] mc: Linux media interface: v0.10
[   11.223758] [    T533] energy_model: updating cpu0 cpu_cap=449 old capacity=512
[   11.241127] [    T523] debugfs: 'ff800280.cec' already exists in 'regmap'
[   11.246579] [    T528] etnaviv etnaviv: bound ff100000.npu (ops gpu_ops [etnaviv])
[   11.250561] [    T528] etnaviv-gpu ff100000.npu: model: GC8000, revision: 7120
[   11.257284] [    T528] etnaviv-gpu ff100000.npu: etnaviv has been instantiated on a NPU, for which the UAPI is still experimental
[   11.291630] [    T528] [drm] Initialized etnaviv 1.4.0 for etnaviv on minor 0
[   11.292742] [    T519] videodev: Linux video capture interface: v2.00
[   11.332791] [    T496] meson8b-dwmac ff3f0000.ethernet: IRQ eth_wake_irq not found
[   11.341193] [    T496] meson8b-dwmac ff3f0000.ethernet: IRQ eth_lpi not found
[   11.347988] [    T496] meson8b-dwmac ff3f0000.ethernet: IRQ sfty not found
[   11.354652] [    T496] meson8b-dwmac ff3f0000.ethernet: PTP uses main clock
[   11.361595] [    T496] meson8b-dwmac ff3f0000.ethernet: User ID: 0x11, Synopsys ID: 0x37
[   11.369044] [    T496] meson8b-dwmac ff3f0000.ethernet:      DWMAC1000
[   11.374855] [    T496] meson8b-dwmac ff3f0000.ethernet: DMA HW capability register supported
[   11.383131] [    T496] meson8b-dwmac ff3f0000.ethernet: RX Checksum Offload Engine supported
[   11.391216] [    T496] meson8b-dwmac ff3f0000.ethernet: COE Type 2
[   11.397151] [    T496] meson8b-dwmac ff3f0000.ethernet: TX Checksum insertion supported
[   11.404729] [    T496] meson8b-dwmac ff3f0000.ethernet: Wake-Up On Lan supported
[   11.416508] [    T496] meson8b-dwmac ff3f0000.ethernet: Normal descriptors
[   11.421082] [    T496] meson8b-dwmac ff3f0000.ethernet: Ring mode enabled
[   11.427520] [    T496] meson8b-dwmac ff3f0000.ethernet: Enable RX Mitigation via HW Watchdog Timer
[   11.453415] [    T515] panfrost ffe40000.gpu: clock rate = 24000000
[   11.454903] [    T515] panfrost ffe40000.gpu: error -ENODEV: _opp_set_regulators: no regulator (mali) found
[   11.460690] [    T519] meson_vdec: module is from the staging directory, the quality is unknown, you have been warned.
[   11.507684] [    T515] panfrost ffe40000.gpu: mali-g52 id 0x7212 major 0x0 minor 0x0 status 0x0
[   11.511590] [    T515] panfrost ffe40000.gpu: features: 00000000,00000df7, issues: 00000000,00000400
[   11.520313] [    T515] panfrost ffe40000.gpu: Features: L2:0x07110206 Shader:0x00000000 Tiler:0x00000809 Mem:0x1 MMU:0x00002830 AS:0xff JS:0x7
[   11.532868] [    T515] panfrost ffe40000.gpu: shader_present=0x3 l2_present=0x1
[   11.589314] [    T497] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[   11.589976] [    T515] [drm] Initialized panfrost 1.4.0 for ffe40000.gpu on minor 2

I then made some changes to the meson glue driver so it won't try to map the ELBI registers.

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 787469d1b396..404c4d9e1900 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -109,10 +109,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
  {
  	struct dw_pcie *pci = &mp->pci;
  
-	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi");
-	if (IS_ERR(pci->dbi_base))
-		return PTR_ERR(pci->dbi_base);
-
  	mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg");
  	if (IS_ERR(mp->cfg_base))
  		return PTR_ERR(mp->cfg_base);

And to the device tree so the designware driver would handle the DBI registers (I know this breaks DT bindings, but it's for testing).

diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index dcc927a9da80..ca455f634834 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -138,7 +138,7 @@ pcie: pcie at fc000000 {
  			reg = <0x0 0xfc000000 0x0 0x400000>,
  			      <0x0 0xff648000 0x0 0x2000>,
  			      <0x0 0xfc400000 0x0 0x200000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
  			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
  			#interrupt-cells = <1>;
  			interrupt-map-mask = <0 0 0 0>;

With the patch on 6.18-rc2 it fails later with ASPM.

[    5.362080] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.400163] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.421350] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.428902] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.436367] [     T50] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.485658] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.491449] [     T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.512122] [     T50] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.515375] [     T50] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.521523] [     T50] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.528847] [     T50] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.536237] [     T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.543415] [     T50] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.543432] [     T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.543441] [     T50] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.543448] [     T50] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.569461] [     T50] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.587641] [     T50] pci 0000:00:00.0: supports D1
[    5.591578] [     T50] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.603775] [     T50] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.614373] [     T50] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.621353] [     T50] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.621374] [     T50] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.623252] [     T50] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.651205] [     T50] pci 0000:01:00.0: ASPM: DT platform, enabling L0s-up L0s-dw L1 ASPM-L1.1 ASPM-L1.2 PCI-PM-L1.1 PCI-PM-L1.2
[    5.664912] [     T50] pci 0000:01:00.0: ASPM: DT platform, enabling ClockPM
[    5.706596] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.748181] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.796864] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.798178] [     T50] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.806100] [     T50] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.806382] [     T50] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.863079] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.904553] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.946013] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.987492] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.987517] [     T50] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
[    6.028979] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    6.080320] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    6.081421] [     T50] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)
[    6.131210] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    6.132324] [     T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    6.138215] [     T50] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    6.145683] [     T50] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    6.151953] [     T50] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    6.165037] [     T50] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    6.165782] [     T50] pcieport 0000:00:00.0: PME: Signaling with IRQ 25
[    6.181556] [     T50] pcieport 0000:00:00.0: AER: enabled with IRQ 25
[   11.500464] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.543334] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.544875] [    T491] iwlwifi 0000:01:00.0: of_irq_parse_pci: failed with rc=134
[   11.593524] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.636355] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.680033] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.721230] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.722728] [    T491] iwlwifi 0000:01:00.0: Unable to change power state from D3cold to D0, device inaccessible
[   11.773976] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.816771] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.859334] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.901868] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.944393] [    T491] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.945931] [    T491] iwlwifi 0000:01:00.0: HW_REV=0xFFFFFFFF, PCI issues?
[   11.952685] [    T491] iwlwifi 0000:01:00.0: probe with driver iwlwifi failed with error -5

Booting with the patch and pcie_aspm=off made the PCIe card work again.

[    0.000000] [      T0] Kernel command line: BOOT_IMAGE=/boot/Image-6.18.0-rc2-160001.218-default root=UUID=6a42b9d0-571c-4394-9ebb-c9a490151bba rd.timeout=15 mitigations=off delayacct pcie_aspm=off
[    5.306734] [     T48] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.316622] [     T48] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.321311] [     T48] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.331124] [     T48] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.340136] [     T48] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.389671] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.395682] [     T48] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.408784] [     T48] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.412271] [     T48] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.419606] [     T48] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.426684] [     T48] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.434093] [     T48] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.441392] [     T48] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.448118] [     T48] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.453979] [     T48] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.460845] [     T48] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.467161] [     T48] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.467973] [     T48] pci 0000:00:00.0: supports D1
[    5.486588] [     T48] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.539676] [     T48] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.543309] [     T48] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.543367] [     T48] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.543384] [     T48] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.549364] [     T48] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.581794] [     T48] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.613019] [     T48] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.616489] [     T48] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.628803] [     T48] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.634557] [     T48] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    5.649790] [     T48] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    5.663909] [     T48] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    5.663917] [     T48] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    5.664513] [     T48] pcieport 0000:00:00.0: PME: Signaling with IRQ 24
[    5.692363] [     T48] pcieport 0000:00:00.0: AER: enabled with IRQ 24
[   11.233785] [    T523] iwlwifi 0000:01:00.0: enabling device (0000 -> 0002)
[   11.261273] [    T523] iwlwifi 0000:01:00.0: Detected crf-id 0x400410, cnv-id 0x400410 wfpm id 0x80000000
[   11.271641] [    T523] iwlwifi 0000:01:00.0: PCI dev 2725/0024, rev=0x420, rfid=0x10d000
[   11.271658] [    T523] iwlwifi 0000:01:00.0: Detected Intel(R) Wi-Fi 6E AX210 160MHz
[   11.421478] [     T43] iwlwifi 0000:01:00.0: loaded firmware version 89.af655058.0 ty-a0-gf-a0-89.ucode op_mode iwlmvm

> #regzbot ^introduced: v6.18-rc1



From sashal at kernel.org  Sun Oct 26 07:48:49 2025
From: sashal at kernel.org (Sasha Levin)
Date: Sun, 26 Oct 2025 10:48:49 -0400
Subject: [PATCH AUTOSEL 6.17-5.10] ASoC: meson: aiu-encoder-i2s: fix bit clock polarity
In-Reply-To: <20251026144958.26750-1-sashal@kernel.org>
References: <20251026144958.26750-1-sashal@kernel.org>
Message-ID: <20251026144958.26750-11-sashal@kernel.org>

From: Valerio Setti <vsetti at baylibre.com>

[ Upstream commit 4c4ed5e073a923fb3323022e1131cb51ad8df7a0 ]

According to I2S specs audio data is sampled on the rising edge of the
clock and it can change on the falling one. When operating in normal mode
this SoC behaves the opposite so a clock polarity inversion is required
in this case.

This was tested on an OdroidC2 (Amlogic S905 SoC) board.

Signed-off-by: Valerio Setti <vsetti at baylibre.com>
Reviewed-by: Jerome Brunet <jbrunet at baylibre.com>
Tested-by: Jerome Brunet <jbrunet at baylibre.com>
Link: https://patch.msgid.link/20251007-fix-i2s-polarity-v1-1-86704d9cda10 at baylibre.com
Signed-off-by: Mark Brown <broonie at kernel.org>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---

LLM Generated explanations, may be completely bogus:

YES ? this change fixes a long-standing functional bug with the Meson
AIU I?S encoder and is low risk to backport.
- The updated `aiu_encoder_i2s_set_fmt()` now inverts the bit clock
  whenever the DAI format requests the normal (non-inverted) polarity
  (`SND_SOC_DAIFMT_NB_*`), matching the hardware quirk described in the
  new comment (`sound/soc/meson/aiu-encoder-i2s.c:239-245`). Without
  this inversion, the CPU-side master drives BCLK so that data toggles
  on the rising edge, which makes all mainline DT users (e.g. Odroid C2)
  sample on the wrong edge and yields audible corruption.
- Frames (`LRCLK`) are still handled exactly as before, and the fix only
  flips which `inv` combinations set `AIU_CLK_CTRL_AOCLK_INVERT`, so
  `IB_*` formats continue to work as they already matched the SoC?s
  ?inverted? default.
- The change is tightly scoped to one helper in the Meson AIU encoder
  driver, leaves register programming and clock sequencing untouched,
  and has been validated on real hardware per the commit log.
- Mainline device trees for this DAI all rely on the default `NB_NF`
  format, so the bug is user-visible today; there are no dependency or
  API concerns blocking stable backporting.

Suggested follow-up: 1) Run a quick playback sanity test on an Odroid C2
(or any Meson GX board using the AIU encoder) after backporting to
confirm audio becomes clean.

 sound/soc/meson/aiu-encoder-i2s.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sound/soc/meson/aiu-encoder-i2s.c b/sound/soc/meson/aiu-encoder-i2s.c
index a0dd914c8ed13..3b4061508c180 100644
--- a/sound/soc/meson/aiu-encoder-i2s.c
+++ b/sound/soc/meson/aiu-encoder-i2s.c
@@ -236,8 +236,12 @@ static int aiu_encoder_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	    inv == SND_SOC_DAIFMT_IB_IF)
 		val |= AIU_CLK_CTRL_LRCLK_INVERT;
 
-	if (inv == SND_SOC_DAIFMT_IB_NF ||
-	    inv == SND_SOC_DAIFMT_IB_IF)
+	/*
+	 * The SoC changes data on the rising edge of the bitclock
+	 * so an inversion of the bitclock is required in normal mode
+	 */
+	if (inv == SND_SOC_DAIFMT_NB_NF ||
+	    inv == SND_SOC_DAIFMT_NB_IF)
 		val |= AIU_CLK_CTRL_AOCLK_INVERT;
 
 	/* Signal skew */
@@ -328,4 +332,3 @@ const struct snd_soc_dai_ops aiu_encoder_i2s_dai_ops = {
 	.startup	= aiu_encoder_i2s_startup,
 	.shutdown	= aiu_encoder_i2s_shutdown,
 };
-
-- 
2.51.0



From devnull+zhentao.guo.amlogic.com at kernel.org  Sun Oct 26 22:42:38 2025
From: devnull+zhentao.guo.amlogic.com at kernel.org (Zhentao Guo via B4 Relay)
Date: Mon, 27 Oct 2025 13:42:38 +0800
Subject: [PATCH 2/3] dts: decoder: Support V4L2 stateless decoder dt node
 for S4
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
Message-ID: <20251027-b4-s4-vdec-upstream-v1-2-620401813b5d@amlogic.com>

From: Zhentao Guo <zhentao.guo at amlogic.com>

Add vcodec_dec to the s4 dtsi for the V4L2 stateless decoder driver

Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/meson-s4.dtsi | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
index 9d99ed2994df..028566f7423d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-s4.dtsi
@@ -853,5 +853,29 @@ emmc: mmc at fe08c000 {
 			no-sd;
 			status = "disabled";
 		};
+
+		video-codec at fe320000 {
+			compatible = "amlogic,s4-vcodec-dec";
+			reg = <0x0 0xfe320000 0x0 0x10000>,
+			      <0x0 0xfe036000 0x0 0x2000>;
+			reg-names = "dosbus",
+				    "dmcbus";
+			interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 92 IRQ_TYPE_EDGE_RISING>,
+				     <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "mailbox_0",
+					  "mailbox_1",
+					  "mailbox_2";
+			clocks = <&clkc_periphs CLKID_DOS>,
+				 <&clkc_periphs CLKID_VDEC_SEL>,
+				 <&clkc_periphs CLKID_HEVCF_SEL>;
+			clock-names = "vdec",
+				      "clk_vdec_mux",
+				      "clk_hevcf_mux";
+			power-domains = <&pwrc PWRC_S4_DOS_VDEC_ID>,
+					<&pwrc PWRC_S4_DOS_HEVC_ID>;
+			power-domain-names = "pwrc-vdec",
+					     "pwrc-hevc";
+		};
 	};
 };

-- 
2.42.0




From devnull+zhentao.guo.amlogic.com at kernel.org  Sun Oct 26 22:42:37 2025
From: devnull+zhentao.guo.amlogic.com at kernel.org (Zhentao Guo via B4 Relay)
Date: Mon, 27 Oct 2025 13:42:37 +0800
Subject: [PATCH 1/3] dt-bindings: vdec: Add binding document of Amlogic
 decoder accelerator
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
Message-ID: <20251027-b4-s4-vdec-upstream-v1-1-620401813b5d@amlogic.com>

From: Zhentao Guo <zhentao.guo at amlogic.com>

Add dt-binding of the Amlogic hardware decoder accelerator.

Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
---
 .../bindings/media/amlogic,vcodec-dec.yaml         | 96 ++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml b/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
new file mode 100644
index 000000000000..6cea8af72639
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2025 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/amlogic,vcodec-dec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Video Decode Accelerator
+
+maintainers:
+  - Zhentao Guo <zhentao.guo at amlogic.com>
+
+description: |
+  The Video Decoder Accelerator present on Amlogic SOCs.
+  It supports stateless h264 decoding.
+
+properties:
+  compatible:
+    const: amlogic,s4-vcodec-dec
+
+  reg:
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: dosbus
+      - const: dmcbus
+
+  interrupts:
+    maxItems: 3
+
+  interrupt-names:
+    items:
+      - const: mailbox_0
+      - const: mailbox_1
+      - const: mailbox_2
+
+  clocks:
+    maxItems: 3
+
+  clock-names:
+    items:
+      - const: vdec
+      - const: clk_vdec_mux
+      - const: clk_hevcf_mux
+
+  power-domains:
+    maxItems: 2
+
+  power-domain-names:
+    items:
+      - const: pwrc-vdec
+      - const: pwrc-hevc
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - interrupt-names
+  - clocks
+  - clock-names
+  - power-domains
+  - power-domain-names
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
+    #include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
+    #include <dt-bindings/power/meson-s4-power.h>
+    video-codec at fe320000 {
+      compatible = "amlogic,s4-vcodec-dec";
+      reg = <0xfe320000 0x10000>,
+            <0xfe036000 0x2000>;
+      reg-names = "dosbus",
+                  "dmcbus";
+      interrupts = <GIC_SPI 91 IRQ_TYPE_EDGE_RISING>,
+                   <GIC_SPI 92 IRQ_TYPE_EDGE_RISING>,
+                   <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
+      interrupt-names = "mailbox_0",
+                        "mailbox_1",
+                        "mailbox_2";
+      clocks = <&clkc_periphs CLKID_DOS>,
+               <&clkc_periphs CLKID_VDEC_SEL>,
+               <&clkc_periphs CLKID_HEVCF_SEL>;
+      clock-names = "vdec",
+                    "clk_vdec_mux",
+                    "clk_hevcf_mux";
+      power-domains = <&pwrc PWRC_S4_DOS_VDEC_ID>,
+                      <&pwrc PWRC_S4_DOS_HEVC_ID>;
+      power-domain-names = "pwrc-vdec",
+                           "pwrc-hevc";
+    };

-- 
2.42.0




From devnull+zhentao.guo.amlogic.com at kernel.org  Sun Oct 26 22:42:36 2025
From: devnull+zhentao.guo.amlogic.com at kernel.org (Zhentao Guo via B4 Relay)
Date: Mon, 27 Oct 2025 13:42:36 +0800
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
Message-ID: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>

Introduce initial driver support for Amlogic's new video acceleration
hardware architecture, designed for video stream decoding.

Compared to the current Amlogic video decoder hardware architecture,
this new implementation eliminates the Esparser hardware component,
enabling direct vb2 buffer input. The driver is designed to support
the V4L2 M2M stateless decoder API. The initial phase includes support
for H.264 decoding on Amlogic S805X2 platform.

The driver is capable of:
- Supporting stateless H.264 decoding up to a resolution 1920x1088(on the S805X2 platform).
- Supporting I/P/B frame handling.
- Supporting vb2 mmap and dma-buf modes.
- Supporting frame-based decode mode. (Note that some H.264 bitstreams require
  DPB reordering to generate reference lists, the stateless decoder driver
  cannot access reordered reference lists in this mode, requiring the driver
  to perform reference list reordering itself)
- Supporting NV12/NV21 output.
- Supporting Annex B start codes.

This driver is tested with Gstreamer.
Example:
gst-launch-1.0 filesrc location=/tmp/video_640x360_mp4_hevc_450kbps_no_b.mp4 !
parsebin ! v4l2slh264dec ! filesink location=/tmp/output.yuv

The driver passes v4l2 compliance test, test reports :
v4l2-compliance 1.30.1, 64 bits, 64-bit time_t

Compliance test for aml-vdec-drv device /dev/video0:

Driver Info:
        Driver name      : aml-vdec-drv
        Card type        : platform:aml-vdec-drv
        Bus info         : platform:fe320000.video-codec
        Driver version   : 6.16.0
        Capabilities     : 0x84204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
                Device Capabilities
        Device Caps      : 0x04204000
                Video Memory-to-Memory Multiplanar
                Streaming
                Extended Pix Format
        Detected Stateless Decoder
Media Driver Info:
        Driver name      : aml-vdec-drv
        Model            : aml-vdec-drv
        Serial           :
        Bus info         : platform:fe320000.video-codec
        Media version    : 6.16.0
        Hardware revision: 0x00000000 (0)
        Driver version   : 6.16.0
Interface Info:
        ID               : 0x0300000c
        Type             : V4L Video
Entity Info:
        ID               : 0x00000001 (1)
        Name             : aml_dev_drv-source
        Function         : V4L2 I/O
        Pad 0x01000002   : 0: Source
          Link 0x02000008: to remote pad 0x1000004 of entity 'aml_dev_drv-proc' (Video Decoder): Data, Enabled, Immutable

Required ioctls:
        test MC information (see 'Media Driver Info' above): OK
        test VIDIOC_QUERYCAP: OK
        test invalid ioctls: OK

Allow for multiple opens:
        test second /dev/video0 open: OK
        test VIDIOC_QUERYCAP: OK
        test VIDIOC_G/S_PRIORITY: OK
        test for unlimited opens: OK

Debug ioctls:
        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
        test VIDIOC_LOG_STATUS: OK (Not Supported)

Input ioctls:
        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
        test VIDIOC_ENUMAUDIO: OK (Not Supported)
        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDIO: OK (Not Supported)
        Inputs: 0 Audio Inputs: 0 Tuners: 0

Output ioctls:
        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
        Outputs: 0 Audio Outputs: 0 Modulators: 0

Input/Output configuration ioctls:
        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
        test VIDIOC_G/S_EDID: OK (Not Supported)

Control ioctls:
        test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
        test VIDIOC_QUERYCTRL: OK
        test VIDIOC_G/S_CTRL: OK
        test VIDIOC_G/S/TRY_EXT_CTRLS: OK
        test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
        test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
        Standard Controls: 6 Private Controls: 0
        Standard Compound Controls: 4 Private Compound Controls: 0

Format ioctls:
        test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
        test VIDIOC_G/S_PARM: OK (Not Supported)
        test VIDIOC_G_FBUF: OK (Not Supported)
        test VIDIOC_G_FMT: OK
        test VIDIOC_TRY_FMT: OK
        test VIDIOC_S_FMT: OK
        test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
        test Cropping: OK (Not Supported)
        test Composing: OK (Not Supported)
        test Scaling: OK (Not Supported)

Codec ioctls:
        test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
        test VIDIOC_G_ENC_INDEX: OK (Not Supported)
        test VIDIOC_(TRY_)DECODER_CMD: OK

Buffer ioctls:
        test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
        test CREATE_BUFS maximum buffers: OK
        test VIDIOC_REMOVE_BUFS: OK
        test VIDIOC_EXPBUF: OK
        test Requests: OK
        test blocking wait: OK

Total for aml-vdec-drv device /dev/video0: 49, Succeeded: 49, Failed: 0, Warnings: 0

Some Fluster test cases are still failing. We will publish the final results
once all these Fluster test failures have been resolved.

Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
---
Zhentao Guo (3):
      dt-bindings: vdec: Add binding document of Amlogic decoder accelerator
      dts: decoder: Support V4L2 stateless decoder dt node for S4
      decoder: Add V4L2 stateless H.264 decoder driver

 .../bindings/media/amlogic,vcodec-dec.yaml         |   96 ++
 MAINTAINERS                                        |    7 +
 arch/arm64/boot/dts/amlogic/meson-s4.dtsi          |   24 +
 drivers/media/platform/amlogic/Kconfig             |    2 +
 drivers/media/platform/amlogic/Makefile            |    1 +
 drivers/media/platform/amlogic/vdec/Kconfig        |   15 +
 drivers/media/platform/amlogic/vdec/Makefile       |    4 +
 drivers/media/platform/amlogic/vdec/aml_vdec.c     |  759 +++++++++
 drivers/media/platform/amlogic/vdec/aml_vdec.h     |   31 +
 .../platform/amlogic/vdec/aml_vdec_canvas_utils.c  |  154 ++
 .../platform/amlogic/vdec/aml_vdec_canvas_utils.h  |   22 +
 drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |  263 +++
 drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |  194 +++
 drivers/media/platform/amlogic/vdec/aml_vdec_hw.c  |  652 +++++++
 drivers/media/platform/amlogic/vdec/aml_vdec_hw.h  |  182 ++
 .../platform/amlogic/vdec/aml_vdec_platform.c      |   37 +
 .../platform/amlogic/vdec/aml_vdec_platform.h      |   62 +
 drivers/media/platform/amlogic/vdec/h264.c         | 1790 ++++++++++++++++++++
 drivers/media/platform/amlogic/vdec/h264.h         |  300 ++++
 drivers/media/platform/amlogic/vdec/reg_defines.h  |  175 ++
 20 files changed, 4770 insertions(+)
---
base-commit: 72fb0170ef1f45addf726319c52a0562b6913707
change-id: 20251027-b4-s4-vdec-upstream-0603c1a4c84a

Best regards,
-- 
Zhentao Guo <zhentao.guo at amlogic.com>




From devnull+zhentao.guo.amlogic.com at kernel.org  Sun Oct 26 22:42:39 2025
From: devnull+zhentao.guo.amlogic.com at kernel.org (Zhentao Guo via B4 Relay)
Date: Mon, 27 Oct 2025 13:42:39 +0800
Subject: [PATCH 3/3] decoder: Add V4L2 stateless H.264 decoder driver
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
Message-ID: <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>

From: Zhentao Guo <zhentao.guo at amlogic.com>

This patch introduces initial driver support for Amlogic's new
video acceleration hardware architecture, designed for video
stream decoding. The driver is designed to support the
V4L2 M2M stateless decoder API. In phase 1, it supports H.264
bitstreams decoding.

Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
---
 MAINTAINERS                                        |    7 +
 drivers/media/platform/amlogic/Kconfig             |    2 +
 drivers/media/platform/amlogic/Makefile            |    1 +
 drivers/media/platform/amlogic/vdec/Kconfig        |   15 +
 drivers/media/platform/amlogic/vdec/Makefile       |    4 +
 drivers/media/platform/amlogic/vdec/aml_vdec.c     |  759 +++++++++
 drivers/media/platform/amlogic/vdec/aml_vdec.h     |   31 +
 .../platform/amlogic/vdec/aml_vdec_canvas_utils.c  |  154 ++
 .../platform/amlogic/vdec/aml_vdec_canvas_utils.h  |   22 +
 drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |  263 +++
 drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |  194 +++
 drivers/media/platform/amlogic/vdec/aml_vdec_hw.c  |  652 +++++++
 drivers/media/platform/amlogic/vdec/aml_vdec_hw.h  |  182 ++
 .../platform/amlogic/vdec/aml_vdec_platform.c      |   37 +
 .../platform/amlogic/vdec/aml_vdec_platform.h      |   62 +
 drivers/media/platform/amlogic/vdec/h264.c         | 1790 ++++++++++++++++++++
 drivers/media/platform/amlogic/vdec/h264.h         |  300 ++++
 drivers/media/platform/amlogic/vdec/reg_defines.h  |  175 ++
 18 files changed, 4650 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5ea78444f035..f400b5dabf30 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1352,6 +1352,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/spi/amlogic,a4-spisg.yaml
 F:	drivers/spi/spi-amlogic-spisg.c
 
+AMLOGIC VCODEC DRIVER
+M:	Zhentao Guo <zhentao.guo at amlogic.com>
+L:	linux-media at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
+F:	drivers/media/platform/amlogic/vdec/
+
 AMPHENOL CHIPCAP 2 DRIVER
 M:	Javier Carrasco <javier.carrasco.cruz at gmail.com>
 L:	linux-hwmon at vger.kernel.org
diff --git a/drivers/media/platform/amlogic/Kconfig b/drivers/media/platform/amlogic/Kconfig
index 458acf3d5fa8..8132f5b9282b 100644
--- a/drivers/media/platform/amlogic/Kconfig
+++ b/drivers/media/platform/amlogic/Kconfig
@@ -4,3 +4,5 @@ comment "Amlogic media platform drivers"
 
 source "drivers/media/platform/amlogic/c3/Kconfig"
 source "drivers/media/platform/amlogic/meson-ge2d/Kconfig"
+
+source "drivers/media/platform/amlogic/vdec/Kconfig"
diff --git a/drivers/media/platform/amlogic/Makefile b/drivers/media/platform/amlogic/Makefile
index c744afcd1b9e..7409de674c0b 100644
--- a/drivers/media/platform/amlogic/Makefile
+++ b/drivers/media/platform/amlogic/Makefile
@@ -2,3 +2,4 @@
 
 obj-y += c3/
 obj-y += meson-ge2d/
+obj-y += vdec/
diff --git a/drivers/media/platform/amlogic/vdec/Kconfig b/drivers/media/platform/amlogic/vdec/Kconfig
new file mode 100644
index 000000000000..05c4568e058b
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/Kconfig
@@ -0,0 +1,15 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+
+config VIDEO_AMLOGIC_VCODEC
+    tristate "Amlogic Video Codec Driver"
+    depends on ARCH_MESON || COMPILE_TEST
+    depends on VIDEO_DEV
+    depends on V4L_MEM2MEM_DRIVERS
+    select VIDEOBUF2_DMA_CONTIG
+    select V4L2_H264
+    select V4L2_MEM2MEM_DEV
+    help
+      This is a v4l2 driver for Amlogic video codec driver.
+	  This driver is designed to support V4L2 M2M STATELESS
+	  interface.
+      To compile this driver as a module choose m here.
diff --git a/drivers/media/platform/amlogic/vdec/Makefile b/drivers/media/platform/amlogic/vdec/Makefile
new file mode 100644
index 000000000000..f645f7ca5e2d
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+aml-vdec-drv-objs := aml_vdec.o aml_vdec_drv.o aml_vdec_hw.o aml_vdec_platform.o h264.o aml_vdec_canvas_utils.o\
+
+obj-$(CONFIG_VIDEO_AMLOGIC_VCODEC) += aml-vdec-drv.o
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec.c b/drivers/media/platform/amlogic/vdec/aml_vdec.c
new file mode 100644
index 000000000000..e8a66bde0397
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec.c
@@ -0,0 +1,759 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "aml_vdec.h"
+#include "aml_vdec_hw.h"
+#include "aml_vdec_platform.h"
+
+#define VCODEC_DRV_NAME "aml-vdec-drv"
+
+static const struct aml_vdec_v4l2_ctrl controls[] = {
+	{
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_STATELESS_H264_SPS,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_STATELESS_H264_PPS,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_STATELESS_H264_DECODE_MODE,
+			.min = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
+			.def = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
+			.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_STATELESS_H264_START_CODE,
+			.min = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
+			.def = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
+			.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
+		},
+	}, {
+		.codec_type = CODEC_TYPE_H264,
+		.cfg = {
+			.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+			.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
+			.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+			.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN,
+		},
+	}
+};
+
+static struct aml_video_fmt aml_video_formats[] = {
+	{
+		.name = "H.264",
+		.fourcc = V4L2_PIX_FMT_H264_SLICE,
+		.type = AML_FMT_DEC,
+		.codec_type = CODEC_TYPE_H264,
+		.num_planes = 1,
+		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
+			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
+	},
+	{
+		.name = "NV21M",
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.type = AML_FMT_FRAME,
+		.codec_type = CODEC_TYPE_FRAME,
+		.num_planes = 2,
+		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
+			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
+	},
+	{
+		.name = "NV21",
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.type = AML_FMT_FRAME,
+		.codec_type = CODEC_TYPE_FRAME,
+		.num_planes = 1,
+		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
+			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
+	},
+	{
+		.name = "NV12M",
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.type = AML_FMT_FRAME,
+		.codec_type = CODEC_TYPE_FRAME,
+		.num_planes = 2,
+		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
+			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
+
+	},
+	{
+		.name = "NV12",
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.type = AML_FMT_FRAME,
+		.codec_type = CODEC_TYPE_FRAME,
+		.num_planes = 1,
+		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
+			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
+	},
+};
+
+void aml_vdec_set_default_params(struct aml_vdec_ctx *ctx)
+{
+	struct aml_q_data *q_data = NULL;
+
+	ctx->m2m_ctx->q_lock = &ctx->v4l2_intf_lock;
+
+	ctx->pic_info.colorspace = V4L2_COLORSPACE_DEFAULT;
+	ctx->pic_info.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->pic_info.quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->pic_info.xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	q_data = &ctx->q_data[AML_Q_DATA_SRC];
+	memset(q_data, 0, sizeof(struct aml_q_data));
+	q_data->visible_width = AML_VDEC_MIN_W;
+	q_data->visible_height = AML_VDEC_MIN_H;
+	q_data->coded_width = AML_VDEC_MIN_W;
+	q_data->coded_height = AML_VDEC_MIN_H;
+	q_data->filed_flag = V4L2_FIELD_NONE;
+	q_data->bytesperline[0] = 0;
+	q_data->sizeimage[0] = (1024 * 1024);
+	q_data->fmt = &aml_video_formats[DEFAULT_OUT_IDX];
+
+	q_data = &ctx->q_data[AML_Q_DATA_DST];
+	memset(q_data, 0, sizeof(struct aml_q_data));
+	q_data->visible_width = AML_VDEC_MIN_W;
+	q_data->visible_height = AML_VDEC_MIN_H;
+	q_data->coded_width = AML_VDEC_MIN_W;
+	q_data->coded_height = AML_VDEC_MIN_H;
+	q_data->filed_flag = V4L2_FIELD_NONE;
+	q_data->bytesperline[0] = q_data->coded_width;
+	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
+	q_data->bytesperline[1] = q_data->coded_width;
+	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
+	q_data->fmt = &aml_video_formats[DEFAULT_CAP_IDX];
+}
+
+int aml_vdec_ctrls_setup(struct aml_vdec_ctx *ctx)
+{
+	int i;
+	int ctrls_size = sizeof(controls) / sizeof(struct aml_vdec_v4l2_ctrl);
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_handler, ctrls_size);
+	for (i = 0; i < ctrls_size; i++) {
+		v4l2_ctrl_new_custom(&ctx->ctrl_handler, &controls[i].cfg, NULL);
+		if (ctx->ctrl_handler.error) {
+			pr_debug("add ctrl for (%d) failed%d\n",
+				 controls[i].cfg.id, ctx->ctrl_handler.error);
+			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+			return ctx->ctrl_handler.error;
+		}
+	}
+	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+	return v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+}
+
+static void m2mops_vdec_device_run(void *m2m_priv)
+{
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)m2m_priv;
+	struct aml_vdec_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *src, *dst;
+	struct media_request *src_req;
+	const char *fw_path = dev->pvdec_data->fw_path[ctx->curr_dec_type];
+
+	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	pr_debug("device run : src buf : %d dst buf %d\n", src->vb2_buf.index, dst->vb2_buf.index);
+
+	src_req = src->vb2_buf.req_obj.req;
+	if (src_req)
+		v4l2_ctrl_request_setup(src_req, &ctx->ctrl_handler);
+
+	dos_enable();
+	/* incase of bus hang in stop_streaming */
+	ctx->dos_clk_en = 1;
+	aml_vdec_reset_core();
+	load_firmware(dev->dec_hw, fw_path);
+
+	if (ctx->codec_ops->run)
+		ctx->codec_ops->run(ctx);
+
+	v4l2_m2m_buf_copy_metadata(src, dst);
+	if (src_req)
+		v4l2_ctrl_request_complete(src_req, &ctx->ctrl_handler);
+
+	v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx, VB2_BUF_STATE_DONE);
+}
+
+const struct v4l2_m2m_ops aml_vdec_m2m_ops = {
+	.device_run = m2mops_vdec_device_run,
+};
+
+static int vidioc_vdec_querycap(struct file *file, void *priv,
+				struct v4l2_capability *cap)
+{
+	strscpy(cap->driver, VCODEC_DRV_NAME, sizeof(cap->driver));
+	strscpy(cap->card, "platform:" VCODEC_DRV_NAME, sizeof(cap->card));
+
+	return 0;
+}
+
+static int vidioc_vdec_enum_fmt(struct v4l2_fmtdesc *f, bool is_output)
+{
+	struct aml_video_fmt *fmt;
+	int fmt_size = sizeof(aml_video_formats) / sizeof(struct aml_video_fmt);
+	int i = 0, j = 0;
+
+	for (; i < fmt_size; i++) {
+		fmt = &aml_video_formats[i];
+		if (is_output && fmt->type != AML_FMT_DEC)
+			continue;
+		if (!is_output && fmt->type != AML_FMT_FRAME)
+			continue;
+
+		if (j == f->index) {
+			f->pixelformat = fmt->fourcc;
+			strscpy(f->description, fmt->name,
+				sizeof(f->description));
+			if (strlen(fmt->name) >= sizeof(f->description)) {
+				pr_err("fmt name string is too long!\n");
+				f->description[sizeof(f->description) - 1] = '\0';
+			}
+			return 0;
+		}
+		++j;
+	}
+	return -EINVAL;
+}
+
+static struct aml_q_data *aml_vdec_get_qdata_by_type(struct aml_vdec_ctx *ctx,
+						     enum v4l2_buf_type type)
+{
+	if (V4L2_TYPE_IS_OUTPUT(type))
+		return &ctx->q_data[AML_Q_DATA_SRC];
+
+	return &ctx->q_data[AML_Q_DATA_DST];
+}
+
+static struct aml_video_fmt *aml_vdec_get_video_fmt(u32 format)
+{
+	struct aml_video_fmt *fmt;
+	unsigned int k;
+
+	for (k = 0; k < (sizeof(aml_video_formats) / sizeof(struct aml_video_fmt)); k++) {
+		fmt = &aml_video_formats[k];
+		if (fmt->fourcc == format)
+			return fmt;
+	}
+
+	return NULL;
+}
+
+static int aml_vdec_init_dec_inst(struct aml_vdec_ctx *ctx,
+				  struct aml_video_fmt *fmt_out)
+{
+	struct aml_vdec_dev *dev = ctx->dev;
+	int ret = -1;
+
+	if (!fmt_out)
+		return ret;
+
+	if (fmt_out->codec_type == CODEC_TYPE_FRAME) {
+		pr_debug("capture type no need to set\n");
+		return 0;
+	}
+
+	ctx->codec_ops = &dev->pvdec_data->codec_ops[fmt_out->codec_type];
+	if (ctx->codec_ops->init) {
+		ret = ctx->codec_ops->init(ctx);
+		if (ret < 0)
+			return ret;
+	}
+	ctx->curr_dec_type = fmt_out->codec_type;
+	pr_info("%s set curr_dec_type = %d\n", __func__, ctx->curr_dec_type);
+
+	return ret;
+}
+
+static void set_pic_info(struct aml_vdec_ctx *ctx,
+			 struct v4l2_pix_format_mplane *pix_mp,
+			 enum v4l2_buf_type type)
+{
+	struct aml_q_data *q_data;
+
+	q_data = aml_vdec_get_qdata_by_type(ctx, type);
+
+	ctx->pic_info.colorspace = pix_mp->colorspace;
+	ctx->pic_info.ycbcr_enc = pix_mp->ycbcr_enc;
+	ctx->pic_info.quantization = pix_mp->quantization;
+	ctx->pic_info.xfer_func = pix_mp->xfer_func;
+
+	if (V4L2_TYPE_IS_OUTPUT(type)) {
+		q_data->sizeimage[0] = pix_mp->plane_fmt[0].sizeimage;
+		ctx->pic_info.output_pix_fmt = pix_mp->pixelformat;
+		ctx->pic_info.coded_width = ALIGN(pix_mp->width, 64);
+		ctx->pic_info.coded_height = ALIGN(pix_mp->height, 64);
+		ctx->pic_info.fb_size[0] =
+		    ctx->pic_info.coded_width * ctx->pic_info.coded_height;
+		ctx->pic_info.fb_size[1] = ctx->pic_info.fb_size[0] / 2;
+		ctx->pic_info.plane_num = 1;
+	} else {
+		ctx->pic_info.plane_num = q_data->fmt->num_planes;
+		ctx->pic_info.cap_pix_fmt = pix_mp->pixelformat;
+		q_data->coded_width = ctx->pic_info.coded_width;
+		q_data->coded_height = ctx->pic_info.coded_height;
+		q_data->sizeimage[0] = ctx->pic_info.fb_size[0];
+		q_data->bytesperline[0] = ctx->pic_info.coded_width;
+		if (q_data->fmt->num_planes > 1) {
+			q_data->sizeimage[1] = ctx->pic_info.fb_size[1];
+			q_data->bytesperline[1] = ctx->pic_info.coded_width;
+		} else {
+			q_data->sizeimage[0] += ctx->pic_info.fb_size[1];
+		}
+	}
+}
+
+static int vidioc_vdec_enum_framesizes(struct file *file, void *priv,
+				       struct v4l2_frmsizeenum *fsize)
+{
+	struct aml_video_fmt *fmt;
+	struct aml_vdec_dev *dev = video_drvdata(file);
+	u32 max_h, max_w;
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	max_h = dev->pvdec_data->dec_fmt->max_height;
+	max_w = dev->pvdec_data->dec_fmt->max_width;
+
+	fmt = aml_vdec_get_video_fmt(fsize->pixel_format);
+	if (!fmt)
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise = fmt->stepwise;
+	fsize->stepwise.max_height = max_h;
+	fsize->stepwise.max_width = max_w;
+
+	return 0;
+}
+
+static int vdec_try_fmt_mp(struct aml_vdec_ctx *ctx, struct v4l2_format *f,
+			   const struct aml_video_fmt *fmt_mp)
+{
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct aml_q_data *q_data;
+	struct aml_vdec_dev *dev = ctx->dev;
+	u32 max_h, max_w;
+	int i;
+
+	max_h = dev->pvdec_data->dec_fmt->max_height;
+	max_w = dev->pvdec_data->dec_fmt->max_width;
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	q_data = aml_vdec_get_qdata_by_type(ctx, f->type);
+
+	pix_mp->height = clamp(pix_mp->height, AML_VDEC_MIN_H, max_h);
+	pix_mp->width = clamp(pix_mp->width, AML_VDEC_MIN_H, max_w);
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+	} else {
+		v4l2_fill_pixfmt_mp(pix_mp, fmt_mp->fourcc, pix_mp->width,
+				    pix_mp->height);
+	}
+
+	for (i = 0; i < pix_mp->num_planes; i++)
+		memset(&pix_mp->plane_fmt[i].reserved[0], 0x0,
+		       sizeof(pix_mp->plane_fmt[0].reserved));
+
+	memset(pix_mp->reserved, 0x0, sizeof(pix_mp->reserved));
+	pix_mp->flags = 0;
+
+	return 0;
+}
+
+static int vdec_s_fmt(struct aml_vdec_ctx *ctx, struct v4l2_format *f)
+{
+	struct aml_q_data *q_data;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct aml_video_fmt *fmt =
+	    aml_vdec_get_video_fmt(f->fmt.pix_mp.pixelformat);
+
+	q_data = aml_vdec_get_qdata_by_type(ctx, f->type);
+
+	if (fmt)	/* default fmt was set in fopen */
+		q_data->fmt = fmt;
+
+	vdec_try_fmt_mp(ctx, f, q_data->fmt);
+	set_pic_info(ctx, pix_mp, f->type);
+
+	return 0;
+}
+
+static int vdec_g_fmt(struct aml_vdec_ctx *ctx, struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct aml_q_data *q_data;
+
+	q_data = aml_vdec_get_qdata_by_type(ctx, f->type);
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->colorspace = ctx->pic_info.colorspace;
+	pix_mp->ycbcr_enc = ctx->pic_info.ycbcr_enc;
+	pix_mp->quantization = ctx->pic_info.quantization;
+	pix_mp->xfer_func = ctx->pic_info.xfer_func;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		pix_mp->height = q_data->coded_height;
+		pix_mp->width = q_data->coded_width;
+		pix_mp->pixelformat = q_data->fmt->fourcc;
+		pix_mp->num_planes = q_data->fmt->num_planes;
+		pix_mp->plane_fmt[0].bytesperline = q_data->bytesperline[0];
+		pix_mp->plane_fmt[0].sizeimage = q_data->sizeimage[0];
+	} else {
+		if (ctx->pic_info.coded_width != 0 && ctx->pic_info.coded_height != 0) {
+			pix_mp->width = ctx->pic_info.coded_width;
+			pix_mp->height = ctx->pic_info.coded_height;
+		} else {
+			pix_mp->height = q_data->coded_height;
+			pix_mp->width = q_data->coded_height;
+		}
+		v4l2_fill_pixfmt_mp(pix_mp, q_data->fmt->fourcc, pix_mp->width,
+				    pix_mp->height);
+	}
+
+	return 0;
+}
+
+static int vidioc_try_fmt_cap_mplane(struct file *file, void *priv,
+				     struct v4l2_format *f)
+{
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(priv);
+	const struct aml_video_fmt *fmt_mp;
+	struct aml_q_data *q_data;
+
+	q_data = aml_vdec_get_qdata_by_type(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+	fmt_mp = aml_vdec_get_video_fmt(f->fmt.pix_mp.pixelformat);
+	if (!fmt_mp)
+		fmt_mp = q_data->fmt;
+
+	return vdec_try_fmt_mp(ctx, f, fmt_mp);
+}
+
+static int vidioc_try_fmt_out_mplane(struct file *file, void *priv,
+				     struct v4l2_format *f)
+{
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(priv);
+	const struct aml_video_fmt *fmt_mp;
+	struct aml_q_data *q_data = aml_vdec_get_qdata_by_type(ctx,
+							       V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+	fmt_mp = aml_vdec_get_video_fmt(f->fmt.pix_mp.pixelformat);
+	if (!fmt_mp)
+		fmt_mp = q_data->fmt;
+
+	return vdec_try_fmt_mp(ctx, f, fmt_mp);
+}
+
+static int vidioc_vdec_s_fmt_out_mplane(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(priv);
+
+	return vdec_s_fmt(ctx, f);
+}
+
+static int vidioc_vdec_s_fmt_cap_mplane(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(priv);
+
+	return vdec_s_fmt(ctx, f);
+}
+
+static int vidioc_vdec_g_fmt_out_mplane(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(priv);
+
+	return vdec_g_fmt(ctx, f);
+}
+
+static int vidioc_vdec_g_fmt_cap_mplane(struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(priv);
+
+	return vdec_g_fmt(ctx, f);
+}
+
+static int vidioc_vdec_enum_fmt_out_mplane(struct file *file,
+					   void *priv, struct v4l2_fmtdesc *f)
+{
+	return vidioc_vdec_enum_fmt(f, 1);
+}
+
+static int vidioc_vdec_enum_fmt_cap_mplane(struct file *file,
+					   void *priv, struct v4l2_fmtdesc *f)
+{
+	return vidioc_vdec_enum_fmt(f, 0);
+}
+
+const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
+	.vidioc_querycap = vidioc_vdec_querycap,
+	.vidioc_enum_framesizes = vidioc_vdec_enum_framesizes,
+
+	.vidioc_enum_fmt_vid_cap = vidioc_vdec_enum_fmt_cap_mplane,
+	.vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt_cap_mplane,
+	.vidioc_s_fmt_vid_cap_mplane = vidioc_vdec_s_fmt_cap_mplane,
+	.vidioc_g_fmt_vid_cap_mplane = vidioc_vdec_g_fmt_cap_mplane,
+
+	.vidioc_enum_fmt_vid_out = vidioc_vdec_enum_fmt_out_mplane,
+	.vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt_out_mplane,
+	.vidioc_s_fmt_vid_out_mplane = vidioc_vdec_s_fmt_out_mplane,
+	.vidioc_g_fmt_vid_out_mplane = vidioc_vdec_g_fmt_out_mplane,
+
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_decoder_cmd = v4l2_m2m_ioctl_stateless_decoder_cmd,
+	.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_stateless_try_decoder_cmd,
+
+	.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+};
+
+static void aml_vdec_release_instance(struct aml_vdec_ctx *ctx)
+{
+	if (ctx->codec_ops && ctx->codec_ops->exit)
+		ctx->codec_ops->exit(ctx);
+}
+
+static int vb2ops_vdec_queue_setup(struct vb2_queue *vq,
+				   unsigned int *nbuffers,
+				   unsigned int *nplanes,
+				   unsigned int sizes[],
+				   struct device *alloc_devs[])
+{
+	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct aml_q_data *q_data;
+	unsigned int i;
+
+	q_data = aml_vdec_get_qdata_by_type(ctx, vq->type);
+	if (!q_data) {
+		pr_err("not supported vq type\n");
+		return -EINVAL;
+	}
+
+	if (*nplanes) {
+		if (*nplanes != q_data->fmt->num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < q_data->sizeimage[i]) {
+				pr_err("not supported sizeimage\n");
+				return -EINVAL;
+			}
+			alloc_devs[i] = &ctx->dev->plat_dev->dev;
+		}
+	} else {
+		if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+			*nplanes = q_data->fmt->num_planes;
+		else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+			*nplanes = 1;
+
+		for (i = 0; i < *nplanes; i++) {
+			alloc_devs[i] = &ctx->dev->plat_dev->dev;
+			sizes[i] = q_data->sizeimage[i];
+		}
+	}
+
+	if (*nplanes) {
+		pr_debug("type: %d, plane: %d, buf cnt: %d, size: [Y: %u, C: %u]\n",
+			 vq->type, *nplanes, *nbuffers, sizes[0], sizes[1]);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int vb2ops_vdec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct aml_q_data *q_data;
+	unsigned int sizeimage = 0;
+	int i;
+
+	q_data = aml_vdec_get_qdata_by_type(ctx, vb->type);
+	if (!q_data) {
+		pr_err("not supported vq type\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < q_data->fmt->num_planes; i++) {
+		sizeimage = q_data->sizeimage[i];
+		if (vb2_plane_size(vb, i) < sizeimage)
+			return -EINVAL;
+
+		if (V4L2_TYPE_IS_CAPTURE(vb->type))
+			vb2_set_plane_payload(vb, i, q_data->sizeimage[i]);
+	}
+
+	return 0;
+}
+
+static int vb2_ops_vdec_buf_init(struct vb2_buffer *vb)
+{
+	return 0;
+}
+
+static void vb2_ops_vdec_buf_queue(struct vb2_buffer *vb)
+{
+	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vb2_v4l2 = to_vb2_v4l2_buffer(vb);
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb2_v4l2);
+}
+
+static void vb2_ops_vdec_buf_finish(struct vb2_buffer *vb)
+{
+}
+
+static int vb2ops_vdec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(q);
+	struct aml_q_data *q_data;
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		ctx->is_output_streamon = 1;
+		q_data = aml_vdec_get_qdata_by_type(ctx, q->type);
+		if (aml_vdec_init_dec_inst(ctx, q_data->fmt) < 0)
+			return -EINVAL;
+	} else {
+		ctx->is_cap_streamon = 1;
+	}
+
+	return 0;
+}
+
+static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
+{
+	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(q);
+	struct vb2_v4l2_buffer *src_buf = NULL, *dst_buf = NULL;
+
+	aml_vdec_release_instance(ctx);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		while ((src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
+			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+		ctx->is_output_streamon = 0;
+	} else {
+		while ((dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)))
+			v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+		ctx->is_cap_streamon = 0;
+	}
+}
+
+static int vb2ops_vdec_out_buf_validate(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+	vbuf->field = V4L2_FIELD_NONE;
+	return 0;
+}
+
+static void vb2ops_vdec_buf_request_complete(struct vb2_buffer *vb)
+{
+	struct aml_vdec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->ctrl_handler);
+}
+
+static const struct vb2_ops aml_vdec_vb2_ops = {
+	.queue_setup = vb2ops_vdec_queue_setup,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = vb2ops_vdec_start_streaming,
+	.stop_streaming = vb2ops_vdec_stop_streaming,
+
+	.buf_init = vb2_ops_vdec_buf_init,
+	.buf_prepare = vb2ops_vdec_buf_prepare,
+	.buf_out_validate = vb2ops_vdec_out_buf_validate,
+	.buf_queue = vb2_ops_vdec_buf_queue,
+	.buf_finish = vb2_ops_vdec_buf_finish,
+	.buf_request_complete = vb2ops_vdec_buf_request_complete,
+};
+
+int aml_vdec_queue_init(void *priv, struct vb2_queue *src_vq,
+			struct vb2_queue *dst_vq)
+{
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
+	struct aml_vdec_dev *dev = ctx->dev;
+	int ret = 0;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->drv_priv = ctx;
+	src_vq->ops = &aml_vdec_vb2_ops;
+	src_vq->lock = &ctx->v4l2_intf_lock;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	src_vq->supports_requests = true;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	ret = vb2_queue_init(src_vq);
+	if (ret) {
+		v4l2_info(&dev->v4l2_dev,
+			  "Failed to initialize videobuf2 queue(output)");
+		return ret;
+	}
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->ops = &aml_vdec_vb2_ops;
+	dst_vq->lock = &ctx->v4l2_intf_lock;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		v4l2_info(&dev->v4l2_dev,
+			  "Failed to initialize videobuf2 queue(capture)");
+		vb2_queue_release(src_vq);
+	}
+
+	return ret;
+}
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec.h b/drivers/media/platform/amlogic/vdec/aml_vdec.h
new file mode 100644
index 000000000000..a9ff93f25043
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef _AML_VDEC_H_
+#define _AML_VDEC_H_
+
+#include "aml_vdec_drv.h"
+
+#define DEFAULT_OUT_IDX  0	/* set default output format to h264 type */
+#define DEFAULT_CAP_IDX  2	/* set default capture format to NV21 */
+
+/**
+ * struct aml_vdec_v4l2_ctrl - helper type to declare supported ctrls
+ * @codec_type: codec id this control belong to (CODEC_TYPE_H264, etc.)
+ * @cfg: control configuration
+ */
+struct aml_vdec_v4l2_ctrl {
+	unsigned int codec_type;
+	struct v4l2_ctrl_config cfg;
+};
+
+extern const struct v4l2_m2m_ops aml_vdec_m2m_ops;
+extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops;
+
+int aml_vdec_ctrls_setup(struct aml_vdec_ctx *ctx);
+int aml_vdec_queue_init(void *priv, struct vb2_queue *src_vq,
+			struct vb2_queue *dst_vq);
+void aml_vdec_set_default_params(struct aml_vdec_ctx *ctx);
+#endif
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c
new file mode 100644
index 000000000000..066958118b00
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#include "aml_vdec_canvas_utils.h"
+
+#define CANVAS_REG_OFFSET   (0x12 << 2)
+
+/*
+ * DMC_CAV_LUT_DATAL/DMC_CAV_LUT_DATAH
+ * high 32bits of canvas data which need to be configured
+ * to canvas memory.
+ * 64bits CANVAS look up table
+ * bit 61 : 58   Endian control.
+ * bit 61 :  1 : switch 2 64bits data inside 128bits boundary.
+ * 0 : no change.
+ * bit 60 :  1 : switch 2 32bits data inside 64bits data boundary.
+ * 0 : no change.
+ * bit 59 :  1 : switch 2 16bits data inside 32bits data boundary.
+ * 0 : no change.
+ * bit 58 :  1 : switch 2 8bits data  inside 16bits data boundary.
+ * 0 : no change.
+ * bit 57 : 56.   Canvas block mode.  2 : 64x32, 1: 32x32;
+ *  0 : linear mode.
+ * bit 55 :      canvas Y direction wrap control.
+ * 1: wrap back in y.  0: not wrap back.
+ * bit 54 :      canvas X direction wrap control.
+ * 1: wrap back in X.  0: not wrap back.
+ * bit 53 : 41.   canvas Hight.
+ * bit 40 : 29.   canvas Width, unit: 8bytes. must in 32bytes boundary.
+ * that means last 2 bits must be 0.
+ * bit 28 : 0.    canvas start address.   unit. 8 bytes. must be in
+ * 32bytes boundary. that means last 2bits must be 0.
+ */
+
+#define CANVAS_WADDR_LBIT       0
+#define CANVAS_WIDTH_LBIT       29
+#define CANVAS_HEIGHT_HBIT      (41 - 32)
+#define CANVAS_WRAPX_HBIT       (54 - 32)
+#define CANVAS_WRAPY_HBIT       (55 - 32)
+#define CANVAS_BLKMODE_HBIT     (56 - 32)
+#define CANVAS_ENDIAN_HBIT      (58 - 32)
+
+/* canvas regs */
+#define DC_CAV_LUT_DATAL        0x12
+#define DC_CAV_LUT_DATAH        0x13
+#define DC_CAV_LUT_ADDR         0x14
+#define DC_CAV_LUT_RDATAL       0x15
+#define DC_CAV_LUT_RDATAH       0x16
+
+#define CANVAS_ADDR_LMASK       0x1fffffff
+#define CANVAS_WIDTH_LMASK      0x7
+#define CANVAS_WIDTH_LWID       3
+#define CANVAS_WIDTH_HMASK      0x1ff
+#define CANVAS_WIDTH_HBIT       0
+#define CANVAS_HEIGHT_MASK      0x1fff
+#define CANVAS_HEIGHT_BIT       9
+#define CANVAS_ADDR_NOWRAP      0x00
+#define CANVAS_ADDR_WRAPX       0x01
+#define CANVAS_ADDR_WRAPY       0x02
+#define CANVAS_BLKMODE_MASK     0x03
+
+#define CANVAS_BLKMODE_LINEAR   0x00
+#define CANVAS_BLKMODE_32X32    0x01
+#define CANVAS_BLKMODE_64X32    0x02
+
+#define CANVAS_LUT_WR_EN   (0x2 << 8)
+#define CANVAS_LUT_RD_EN   (0x1 << 8)
+
+#define CANVAS_ADDR_BITS_MASK		GENMASK(28, 0)
+#define CANVAS_WIDTH_L_MASK		GENMASK(31, 29)
+#define CANVAS_WIDTH_H_MASK		GENMASK(8, 0)
+#define CANVAS_HEIGHT_H_MASK		GENMASK(21, 9)
+#define CANVAS_WRAP_H_MASK		GENMASK(23, 23)
+#define CANVAS_BLOCK_H_MASK		GENMASK(25, 24)
+#define CANVAS_BITS_CTRL_MASK		GENMASK(29, 26)
+
+static struct vdec_canvas_s canvas;
+
+static void write_canvas_reg(u32 addr, u32 val)
+{
+	int offset = -DC_CAV_LUT_DATAL;
+
+	return writel(val, canvas.regs_base + ((addr + offset) << 2));
+}
+
+static int aml_vdec_canvas_alloc(u8 *canvas_index)
+{
+	int i;
+	unsigned long flags;
+
+	*canvas_index = -1;
+	spin_lock_irqsave(&canvas.canvas_lock, flags);
+	for (i = 0; i < CANVAS_MAX_SIZE; i++) {
+		if (i >= 0x10 && i <= 0x15)	/* 0x10~0x15 is used by RDMA */
+			continue;
+		if (canvas.canvas_used[i] == 0) {
+			*canvas_index = i;
+			canvas.canvas_used[i] = 1;
+			spin_unlock_irqrestore(&canvas.canvas_lock, flags);
+			return 0;
+		}
+	}
+	spin_unlock_irqrestore(&canvas.canvas_lock, flags);
+
+	return -1;
+}
+
+static void aml_vdec_canvas_free(u8 canvas_index)
+{
+	unsigned long flags;
+
+	if (canvas_index < 0 || canvas_index > CANVAS_MAX_SIZE)
+		return;
+
+	spin_lock_irqsave(&canvas.canvas_lock, flags);
+	if (canvas.canvas_used[canvas_index])
+		canvas.canvas_used[canvas_index] = 0;
+
+	spin_unlock_irqrestore(&canvas.canvas_lock, flags);
+}
+
+static void aml_vdec_config_canvas(u8 canvas_index,
+				   ulong addr, u32 width, u32 height,
+				   u32 wrap, u32 blkmode, u32 endian)
+{
+	u32 data_h, data_l;
+
+	data_h = FIELD_PREP(CANVAS_WIDTH_H_MASK,
+			    (((width + 7) >> 3) >> CANVAS_WIDTH_LWID)) |
+		FIELD_PREP(CANVAS_HEIGHT_H_MASK, height) |
+		FIELD_PREP(CANVAS_WRAP_H_MASK, wrap) |
+		FIELD_PREP(CANVAS_BLOCK_H_MASK, blkmode) |
+		FIELD_PREP(CANVAS_BITS_CTRL_MASK, endian);
+
+	data_l = FIELD_PREP(CANVAS_ADDR_BITS_MASK, ((addr + 7) >> 3)) |
+		FIELD_PREP(CANVAS_WIDTH_L_MASK, ((width + 7) >> 3));
+
+	write_canvas_reg(DC_CAV_LUT_DATAL, data_l);
+	write_canvas_reg(DC_CAV_LUT_DATAH, data_h);
+	write_canvas_reg(DC_CAV_LUT_ADDR, CANVAS_LUT_WR_EN | canvas_index);
+}
+
+void aml_vdec_canvas_register(struct aml_vdec_hw *hw)
+{
+	canvas.regs_base = hw->regs[DMC_BUS] + CANVAS_REG_OFFSET;
+	memset(canvas.canvas_used, 0, CANVAS_MAX_SIZE);
+	spin_lock_init(&canvas.canvas_lock);
+
+	hw->hw_ops.canvas_alloc = aml_vdec_canvas_alloc;
+	hw->hw_ops.canvas_free = aml_vdec_canvas_free;
+	hw->hw_ops.config_canvas = aml_vdec_config_canvas;
+}
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.h b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.h
new file mode 100644
index 000000000000..55757fe5f95d
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+#include "reg_defines.h"
+#include "aml_vdec_hw.h"
+
+#define CANVAS_MAX_SIZE 63
+
+/**
+ * struct vdec_canvas_s - helper to decoder canvas, which config the w/h, buffer addr of frames
+ * @regs_base: base addr of canvas regs.
+ * @canvas_used: used flag.
+ * @canvas_lock: spinlock for canvas.
+ */
+struct vdec_canvas_s {
+	void __iomem *regs_base;
+	u8 canvas_used[CANVAS_MAX_SIZE];
+	spinlock_t canvas_lock;
+};
+
+void aml_vdec_canvas_register(struct aml_vdec_hw *hw);
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
new file mode 100644
index 000000000000..ef2c779839d8
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+
+#include "aml_vdec.h"
+#include "aml_vdec_hw.h"
+#include "aml_vdec_platform.h"
+
+#define AML_VDEC_DRV_NAME "aml-vdec-drv"
+
+static int fops_vcodec_open(struct file *file)
+{
+	struct aml_vdec_dev *dec_dev = video_drvdata(file);
+	struct aml_vdec_ctx *ctx = NULL;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	mutex_lock(&dec_dev->dev_mutex);
+	dec_dev->dec_ctx = ctx;
+	ctx->dev = dec_dev;
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh, file);
+	dec_dev->filp = file;
+	mutex_init(&ctx->v4l2_intf_lock);
+	init_waitqueue_head(&ctx->queue);
+	ctx->int_cond = 0;
+
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dec_dev->m2m_dev_dec, ctx,
+					 &aml_vdec_queue_init);
+	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
+		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
+		v4l2_err(&dec_dev->v4l2_dev, "Failed to v4l2_m2m_ctx_init() (%d)", ret);
+		goto err_m2m_ctx_init;
+	}
+
+	ctx->fh.m2m_ctx = ctx->m2m_ctx;
+	ret = aml_vdec_ctrls_setup(ctx);
+	if (ret) {
+		v4l2_err(&dec_dev->v4l2_dev, "Failed to init all ctrls (%d)", ret);
+		goto err_ctrls_setup;
+	}
+
+	aml_vdec_set_default_params(ctx);
+	mutex_unlock(&dec_dev->dev_mutex);
+
+	return ret;
+
+err_ctrls_setup:
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+err_m2m_ctx_init:
+	v4l2_fh_del(&ctx->fh, file);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dec_dev->dev_mutex);
+
+	return ret;
+}
+
+static int fops_vcodec_release(struct file *file)
+{
+	struct aml_vdec_dev *dec_dev = video_drvdata(file);
+	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(file->private_data);
+
+	mutex_lock(&dec_dev->dev_mutex);
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
+	v4l2_fh_del(&ctx->fh, file);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dec_dev->dev_mutex);
+
+	return 0;
+}
+
+static const struct v4l2_file_operations aml_vdec_fops = {
+	.owner        = THIS_MODULE,
+	.open        = fops_vcodec_open,
+	.release    = fops_vcodec_release,
+	.poll        = v4l2_m2m_fop_poll,
+	.unlocked_ioctl    = video_ioctl2,
+	.mmap        = v4l2_m2m_fop_mmap,
+};
+
+static const struct video_device dec_dev = {
+	.name = "aml_dev_drv",
+	.fops = &aml_vdec_fops,
+	.ioctl_ops = &aml_vdec_ioctl_ops,
+	.release = video_device_release,
+	.vfl_dir = VFL_DIR_M2M,
+	.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
+};
+
+static const struct media_device_ops aml_m2m_media_ops = {
+	.req_validate = vb2_request_validate,
+	.req_queue = v4l2_m2m_request_queue,
+};
+
+static int aml_vdec_drv_probe(struct platform_device *pdev)
+{
+	struct aml_vdec_dev *dev;
+	struct video_device *vfd_dec;
+	struct aml_vdec_hw *hw;
+	int ret = 0;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->plat_dev = pdev;
+	mutex_init(&dev->dev_mutex);
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret, "v4l2_device_register err\n");
+
+	vfd_dec = video_device_alloc();
+	if (!vfd_dec) {
+		v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
+		ret = -ENOMEM;
+		goto err_device_alloc;
+	}
+	*vfd_dec = dec_dev;
+	vfd_dec->v4l2_dev = &dev->v4l2_dev;
+	vfd_dec->lock = &dev->dev_mutex;
+	video_set_drvdata(vfd_dec, dev);
+	dev->vfd = vfd_dec;
+	platform_set_drvdata(pdev, dev);
+
+	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+	if (!hw) {
+		ret = -ENOMEM;
+		goto err_dec_mem_init;
+	}
+	dev->dec_hw = hw;
+
+	dev->pvdec_data = of_device_get_match_data(&pdev->dev);
+	ret = dev->pvdec_data->req_hw_resource(dev);
+	if (ret < 0)
+		goto err_hw_init;
+
+	dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
+	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
+		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem dec device\n");
+		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
+		goto err_hw_init;
+	}
+
+	ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to register video device");
+		goto err_vid_dev_register;
+	}
+
+	v4l2_info(&dev->v4l2_dev, "Registered %s as /dev/%s\n",
+		  vfd_dec->name, video_device_node_name(vfd_dec));
+
+	dev->mdev.dev = &pdev->dev;
+	strscpy(dev->mdev.model, AML_VDEC_DRV_NAME, sizeof(dev->mdev.model));
+	media_device_init(&dev->mdev);
+	dev->mdev.ops = &aml_m2m_media_ops;
+	dev->v4l2_dev.mdev = &dev->mdev;
+
+	ret = v4l2_m2m_register_media_controller(dev->m2m_dev_dec, vfd_dec,
+						 MEDIA_ENT_F_PROC_VIDEO_DECODER);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
+		goto error_m2m_mc_register;
+	}
+
+	ret = media_device_register(&dev->mdev);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to register media device");
+		goto err_media_dev_register;
+	}
+	vdec_enable(dev->dec_hw);
+	return 0;
+
+err_media_dev_register:
+	v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
+error_m2m_mc_register:
+	media_device_cleanup(&dev->mdev);
+err_vid_dev_register:
+	v4l2_m2m_release(dev->m2m_dev_dec);
+err_hw_init:
+	kfree(hw);
+	dev->dec_hw = NULL;
+err_dec_mem_init:
+	video_device_release(vfd_dec);
+err_device_alloc:
+	v4l2_device_unregister(&dev->v4l2_dev);
+	return ret;
+}
+
+static void aml_vdec_drv_remove(struct platform_device *pdev)
+{
+	struct aml_vdec_dev *dev = platform_get_drvdata(pdev);
+
+	vdec_disable(dev->dec_hw);
+
+	if (media_devnode_is_registered(dev->mdev.devnode)) {
+		media_device_unregister(&dev->mdev);
+		media_device_cleanup(&dev->mdev);
+	}
+
+	if (dev->m2m_dev_dec)
+		v4l2_m2m_release(dev->m2m_dev_dec);
+	if (dev->vfd)
+		video_unregister_device(dev->vfd);
+	if (dev->dec_hw)
+		dev->pvdec_data->destroy_hw_resource(dev);
+
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+	pr_debug("aml v4l2 decoder driver remove\n");
+}
+
+static const struct of_device_id aml_vdec_match[] = {
+	{.compatible = "amlogic,s4-vcodec-dec", .data = &aml_vdec_s4_pdata},
+	{},
+};
+
+static struct platform_driver aml_vcodec_dec_driver = {
+	.probe    = aml_vdec_drv_probe,
+	.remove    = aml_vdec_drv_remove,
+	.driver    = {
+		.name    = AML_VDEC_DRV_NAME,
+		.of_match_table = aml_vdec_match,
+	},
+};
+
+static int __init aml_vdec_init(void)
+{
+	pr_debug("aml v4l2 decoder module init\n");
+
+	if (platform_driver_register(&aml_vcodec_dec_driver)) {
+		pr_err("failed to register aml v4l2 decoder\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit aml_vdec_exit(void)
+{
+	pr_debug("aml v4l2 decoder module exit\n");
+	platform_driver_unregister(&aml_vcodec_dec_driver);
+}
+
+module_init(aml_vdec_init);
+module_exit(aml_vdec_exit);
+
+MODULE_DESCRIPTION("Amlogic V4L2 decoder driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h
new file mode 100644
index 000000000000..f3318cceff3f
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h
@@ -0,0 +1,194 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef _AML_VDEC_DRV_H_
+#define _AML_VDEC_DRV_H_
+
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/clk.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define AML_VCODEC_MAX_PLANES 3
+#define AML_VDEC_MIN_W    64U
+#define AML_VDEC_MIN_H    64U
+#define AML_VDEC_1080P_MAX_H  1088U
+#define AML_VDEC_1080P_MAX_W  1920U
+
+struct aml_vdec_ctx;
+/**
+ * enum aml_fmt_type - Type of format type
+ */
+enum aml_fmt_type {
+	AML_FMT_DEC = 0,
+	AML_FMT_FRAME = 1,
+};
+
+/**
+ * enum aml_codec_type - Type of codec format
+ */
+enum aml_codec_type {
+	CODEC_TYPE_H264 = 0,
+	CODEC_TYPE_FRAME,
+};
+
+/**
+ * enum aml_q_type - Type of queue : cap or output
+ */
+enum aml_q_type {
+	AML_Q_DATA_SRC = 0,
+	AML_Q_DATA_DST = 1,
+};
+
+/**
+ * struct aml_video_fmt - aml video decoder fmt information
+ * @fourcc: FourCC code of the format. See V4L2_PIX_FMT_*.
+ * @type: Curr queue type: capture or output.
+ * @codec_type: Codec mode related. See aml_codec_type.
+ * @num_planes: Num planes of the format.
+ * @name: Name of the format.
+ * @stepwise: Supported range of frame sizes (only for bitstream formats).
+ */
+struct aml_video_fmt {
+	u32 fourcc;
+	enum aml_fmt_type type;
+	enum aml_codec_type codec_type;
+	u32 num_planes;
+	const u8 *name;
+	struct v4l2_frmsize_stepwise stepwise;
+};
+
+/**
+ * struct aml_q_data - aml video queue information
+ * @visible_width: Width for display.
+ * @visible_height: Height for display.
+ * @coded_width: Width for decode, which is 64/32 aligned.
+ * @coded_height: Height for decode, which is 64/32 aligned.
+ * @filed_flag: Field pic flag.
+ * @bytesperline: Byte num of each pixel line.
+ * @sizeimage: Size of frame in bytes.
+ * @fmt: Format for curr queue. See struct aml_video_fmt.
+ */
+struct aml_q_data {
+	u32 visible_width;
+	u32 visible_height;
+	u32 coded_width;
+	u32 coded_height;
+	u32 filed_flag;
+	u32 bytesperline[AML_VCODEC_MAX_PLANES];
+	u32 sizeimage[AML_VCODEC_MAX_PLANES];
+	struct aml_video_fmt *fmt;
+};
+
+/**
+ * struct aml_vdec_dev - driver data
+ * @plat_dev: Platform device for the current driver.
+ * @v4l2_dev: V4L2 device to register video devices for.
+ * @m2m_dev_dec: Mem2mem device associated to this device.
+ * @vfd: Video_device associated to this device.
+ * @mdev: Media_device associated to this device.
+ * @dec_ctx: Decoder context. See struct aml_vdec_ctx.
+ * @dec_hw: Decoder hardware resources. See struct aml_vdec_hw.
+ * @pvdec_data: Decoder platform data. See struct aml_dev_platform_data.
+ * @dev_mutex: video_device lock.
+ * @filp: v4l2 file handle pointer.
+ */
+struct aml_vdec_dev {
+	struct platform_device *plat_dev;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_m2m_dev *m2m_dev_dec;
+	struct video_device *vfd;
+	struct media_device mdev;
+
+	struct aml_vdec_ctx *dec_ctx;
+	struct aml_vdec_hw *dec_hw;
+	const struct aml_dev_platform_data *pvdec_data;
+
+	struct mutex dev_mutex;
+	struct file *filp;
+};
+
+/**
+ * struct dec_pic_info - pic information description
+ * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
+ * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
+ * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
+ * @quantization: enum v4l2_quantization, colorspace quantization
+ * @cap_pix_fmt: Pixel format for capture queue.
+ * @output_pix_fmt: Pixel format for output queue.
+ * @coded_width: Width for decode.
+ * @coded_height: Height for decode.
+ * @fb_size: Frame buffer size for Y or UV.
+ * @plane_num: Num for planes for curr format.
+ */
+struct dec_pic_info {
+	enum v4l2_colorspace colorspace;
+	enum v4l2_ycbcr_encoding ycbcr_enc;
+	enum v4l2_xfer_func xfer_func;
+	enum v4l2_quantization quantization;
+	u32 cap_pix_fmt;
+	u32 output_pix_fmt;
+	u32 coded_width;
+	u32 coded_height;
+	u32 fb_size[2];
+	u32 plane_num;
+};
+
+/**
+ * struct aml_vdec_ctx - driver instance context
+ * @dev: pointer to the aml_vdec_dev of the device.
+ * @fh: struct v4l2 fh.
+ * @m2m_ctx: pointer to v4l2_m2m_ctx context.
+ * @ctrl_handler: V4L2 ctrl handler.
+ * @v4l2_intf_lock: Mutex lock for v4l2 interface.
+ * @codec_ops: Codec operation functions. See struct aml_codec_ops.
+ * @int_cond: Variable used by the waitqueue.
+ * @queue: Waitqueue to wait for the current decode context finish.
+ * @q_data: feature supported by the current decoder instance.
+ * @is_cap_streamon: indicates if the current capture stream is on.
+ * @is_output_streamon: indicates if the current output stream is on.
+ * @dos_clk_en: indicates if dos clk is enabled.
+ * @pic_info: Pic information for curr decoder context. See struct dec_pic_info.
+ * @curr_dec_type: Current decoder type. (CODEC_TYPE_H264, etc.)
+ * @codec_priv: Pointer to current decoder instance.
+ */
+struct aml_vdec_ctx {
+	struct aml_vdec_dev *dev;
+	struct v4l2_fh fh;
+	struct v4l2_m2m_ctx *m2m_ctx;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct mutex v4l2_intf_lock;
+
+	const struct aml_codec_ops *codec_ops;
+	int int_cond;
+	wait_queue_head_t queue;
+	struct aml_q_data q_data[2];
+
+	bool is_cap_streamon;
+	bool is_output_streamon;
+	bool dos_clk_en;
+
+	struct dec_pic_info pic_info;
+	u32 curr_dec_type;
+	void *codec_priv;
+};
+
+static inline struct aml_vdec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct aml_vdec_ctx, fh);
+}
+
+static inline struct aml_vdec_ctx *ctrl_to_dec_ctx(struct v4l2_ctrl_handler *ctrl)
+{
+	return container_of(ctrl, struct aml_vdec_ctx, ctrl_handler);
+}
+
+#endif
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
new file mode 100644
index 000000000000..4db0e3076761
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
@@ -0,0 +1,652 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+
+#include "aml_vdec_drv.h"
+#include "aml_vdec_hw.h"
+#include "aml_vdec_platform.h"
+#include "aml_vdec_canvas_utils.h"
+
+#define MHz     (1000000)
+#define MC_SIZE (4096 * 16)
+
+static void __iomem *reg_base[MAX_REG_BUS];
+
+static struct pm_pd_s vdec_domain_data[] = {
+	[VDEC_1] = {.name = "pwrc-vdec", },
+	[VDEC_HEVC] = {.name = "pwrc-hevc", },
+};
+
+u32 read_dos_reg(u32 addr)
+{
+	return readl(reg_base[DOS_BUS] + (addr << 2));
+}
+
+void write_dos_reg(u32 addr, int val)
+{
+	writel(val, reg_base[DOS_BUS] + (addr << 2));
+}
+
+u32 read_dmc_reg(u32 addr)
+{
+	return readl(reg_base[DMC_BUS] + (addr << 2));
+}
+
+void write_dmc_reg(u32 addr, int val)
+{
+	writel(val, reg_base[DMC_BUS] + (addr << 2));
+}
+
+void dos_reg_set_mask(u32 addr, u32 mask)
+{
+	u32 r;
+
+	r = read_dos_reg(addr);
+	write_dos_reg(addr, (r | mask));
+}
+
+void dos_reg_clear_mask(u32 addr, u32 mask)
+{
+	u32 r;
+
+	r = read_dos_reg(addr);
+	write_dos_reg(addr, (r & (~mask)));
+}
+
+void dos_reg_write_bits(u32 reg, u32 val, int start, int len)
+{
+	u32 to_val = read_dos_reg(reg);
+	u32 mask = (((1L << (len)) - 1) << (start));
+
+	to_val &= ~mask;
+	to_val |= (val << start) & mask;
+	write_dos_reg(reg, to_val);
+}
+
+void dos_enable(void)
+{
+	WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10);
+
+	WRITE_VREG(GCLK_EN, 0x3ff);
+
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 31));
+}
+
+void aml_vdec_reset_core(void)
+{
+	unsigned int mask = 0;
+
+	mask = (1 << 21);
+
+	write_dmc_reg(0x0, (read_dmc_reg(0x0) & ~mask));
+	usleep_range(60, 70);
+	WRITE_VREG(DOS_SW_RESET0, (1 << 3) | (1 << 4) |
+		   (1 << 5) | (1 << 7) | (1 << 8) | (1 << 9));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+	CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
+	CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
+	WRITE_VREG(MDEC_EXTIF_CFG1, 0);
+
+	write_dmc_reg(0x0, (read_dmc_reg(0x0) | mask));
+}
+
+void aml_start_vdec_hw(void)
+{
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(MPSR, 0x0001);
+}
+
+void aml_stop_vdec_hw(void)
+{
+	ulong timeout = jiffies + HZ / 10;
+
+	WRITE_VREG(MPSR, 0);
+	WRITE_VREG(CPSR, 0);
+
+	while (RD_VREG(IMEM_DMA_CTRL) & 0x8000) {
+		if (time_after(jiffies, timeout))
+			break;
+	}
+
+	timeout = jiffies + HZ / 10;
+	while (RD_VREG(LMEM_DMA_CTRL) & 0x8000) {
+		if (time_after(jiffies, timeout))
+			break;
+	}
+
+	timeout = jiffies + HZ / 80;
+	while (RD_VREG(WRRSP_LMEM) & 0xfff) {
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s, ctrl %x, rsp %x, pc %x status %x,%x\n",
+			       __func__, RD_VREG(LMEM_DMA_CTRL),
+			       RD_VREG(WRRSP_LMEM), RD_VREG(MPC_E),
+			       RD_VREG(AV_SCRATCH_J), RD_VREG(AV_SCRATCH_9));
+			break;
+		}
+	}
+
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+
+	WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+	RD_VREG(DOS_SW_RESET0);
+}
+
+int load_firmware(struct aml_vdec_hw *hw, const char *path)
+{
+	const struct firmware *fw;
+	struct device *dev = hw->dev;
+	static u8 *mc_addr;
+	static dma_addr_t mc_addr_map;
+	int fw_head_len;
+	ulong timeout;
+	int ret;
+
+	ret = request_firmware(&fw, path, dev);
+	if (ret < 0) {
+		pr_info("request_firmware %s failed ret %d\n", path, ret);
+		return -EINVAL;
+	}
+
+	if (fw->size > MC_SIZE) {
+		pr_info("fw %s oversize\n", path);
+		ret = -EINVAL;
+		goto release_firmware;
+	}
+
+	fw_head_len = 512;
+	mc_addr = dma_alloc_coherent(dev, MC_SIZE, &mc_addr_map, GFP_KERNEL);
+	if (!mc_addr) {
+		pr_info("no mem for fw %s\n", path);
+		ret = -ENOMEM;
+		goto release_firmware;
+	}
+	memset(mc_addr, 0, MC_SIZE);
+	memcpy(mc_addr, ((u8 *)fw->data + fw_head_len),
+	       (fw->size - fw_head_len));
+
+	WRITE_VREG(MPSR, 0);
+	WRITE_VREG(CPSR, 0);
+
+	timeout = RD_VREG(MPSR);
+	timeout = RD_VREG(MPSR);
+	timeout = jiffies + HZ;
+
+	WRITE_VREG(IMEM_DMA_ADR, mc_addr_map);
+	WRITE_VREG(IMEM_DMA_COUNT, 0x1000);
+	WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
+
+	while (RD_VREG(IMEM_DMA_CTRL) & 0x8000) {
+		if (time_before(jiffies, timeout)) {
+			schedule();
+		} else {
+			pr_info("vdec load mc error\n");
+			ret = -EBUSY;
+			break;
+		}
+	}
+
+	/* Only h264 needs this step */
+	if (hw->hw_ops.load_firmware_ex) {
+		ret = hw->hw_ops.load_firmware_ex(hw->curr_ctx,
+						  mc_addr,
+						  (fw->size - fw_head_len));
+		if (ret < 0) {
+			ret = -EINVAL;
+			goto free_dma_mem;
+		}
+	}
+
+free_dma_mem:
+	dma_free_coherent(dev, MC_SIZE, mc_addr, mc_addr_map);
+release_firmware:
+	release_firmware(fw);
+	return ret;
+}
+
+static int vdec_clock_gate_init(struct aml_vdec_hw *hw)
+{
+	int i;
+
+	hw->gates[VDEC].name = "vdec";
+	hw->gates[VDEC_MUX].name = "clk_vdec_mux";
+	hw->gates[HEVCF_MUX].name = "clk_hevcf_mux";
+
+	for (i = 0; i < DOS_CLK_MAX; i++) {
+		hw->gates[i].clk = devm_clk_get(hw->dev, hw->gates[i].name);
+		hw->gates[i].ref_count = 0;
+		mutex_init(&hw->gates[i].mutex);
+	}
+
+	return 0;
+}
+
+static int vdec_gate_clk(struct gate_switch_node *gate_node, bool enable)
+{
+	int ret = 0;
+
+	mutex_lock(&gate_node->mutex);
+	if (enable) {
+		gate_node->ref_count++;
+		if (gate_node->ref_count == 1) {
+			ret = clk_prepare_enable(gate_node->clk);
+			pr_debug("the %-15s clock on, ref cnt: %d ret = %d\n",
+				 gate_node->name, gate_node->ref_count, ret);
+		}
+	} else {
+		gate_node->ref_count--;
+		if (!gate_node->ref_count) {
+			clk_disable_unprepare(gate_node->clk);
+			pr_debug("the %-15s clock off, ref cnt: %d ret = %d\n",
+				 gate_node->name, gate_node->ref_count, ret);
+		}
+	}
+	mutex_unlock(&gate_node->mutex);
+
+	return 0;
+}
+
+static int vdec_switch_gate(struct aml_vdec_hw *hw,
+			    const char *name, bool enable)
+{
+	int i;
+
+	for (i = 0; i < DOS_CLK_MAX; i++) {
+		if (!strcmp(name, hw->gates[i].name)) {
+			if (hw->gates[i].clk)
+				vdec_gate_clk(&hw->gates[i], enable);
+			else
+				return -ENODEV;
+		}
+	}
+	return 0;
+}
+
+static int vdec_set_rate(struct aml_vdec_hw *hw,
+			 const char *name, unsigned long hz)
+{
+	int i;
+
+	for (i = 0; i < DOS_CLK_MAX; i++) {
+		if (!strcmp(name, hw->gates[i].name)) {
+			if (hw->gates[i].clk && hw->gates[i].ref_count) {
+				clk_set_rate(hw->gates[i].clk, hz);
+				pr_debug("after set, vdec mux clock is %lu Hz\n",
+					 clk_get_rate(hw->gates[i].clk));
+			} else {
+				return -ENODEV;
+			}
+		}
+	}
+	return 0;
+}
+
+static void pm_vdec_clock_switch(struct aml_vdec_hw *hw, int id, bool on)
+{
+	int ret = 0;
+
+	if (id == VDEC_1) {
+		ret = vdec_switch_gate(hw, "clk_vdec_mux", on);
+		vdec_set_rate(hw, "clk_vdec_mux", 499999992);
+	} else if (id == VDEC_HEVC) {
+		/* enable hevc clock */
+		ret = vdec_switch_gate(hw, "clk_hevcf_mux", on);
+		if (ret == -ENODEV)
+			ret = vdec_switch_gate(hw, "clk_hevc_mux", on);
+	}
+
+	if (ret < 0)
+		pr_debug("clk %d, unreachable ret %d\n", id, ret);
+}
+
+static void pm_vdec_power_switch(struct pm_pd_s *pd, int id, bool on)
+{
+	struct device *dev = pd[id].dev;
+	int ret;
+
+	if (!dev) {
+		pr_debug("no dev %d, maybe always on\n", id);
+		return;
+	}
+
+	if (on)
+		ret = pm_runtime_get_sync(dev);
+	else
+		ret = pm_runtime_put_sync(dev);
+
+	pr_debug("dev: %p link %p the %-15s power %s ret %d\n",
+		 dev, pd[id].link, pd[id].name, on ? "on" : "off", ret);
+}
+
+static int pm_vdec_power_domain_init(struct aml_vdec_hw *hw)
+{
+	int i, err;
+	const struct power_manager_s *pm = hw->pm;
+	struct pm_pd_s *pd = pm->pd_data;
+
+	mutex_init(&hw->pm_mutex);
+
+	for (i = 0; i < VDEC_MAX; i++) {
+		pd[i].dev = dev_pm_domain_attach_by_name(hw->dev, pd[i].name);
+		if (IS_ERR_OR_NULL(pd[i].dev)) {
+			err = PTR_ERR(pd[i].dev);
+			pr_debug("Get %s failed, pm-domain: %d\n",
+				 pd[i].name, err);
+			continue;
+		}
+
+		pd[i].link = device_link_add(hw->dev, pd[i].dev,
+					     DL_FLAG_PM_RUNTIME |
+					     DL_FLAG_STATELESS);
+		if (IS_ERR_OR_NULL(pd[i].link)) {
+			pr_err("Adding %s device link failed!\n", pd[i].name);
+			return -ENODEV;
+		}
+
+		pr_debug("power domain: name: %s, dev: %p, link: %p\n",
+			 pd[i].name, pd[i].dev, pd[i].link);
+	}
+
+	return 0;
+}
+
+static void pm_vdec_power_domain_release(struct aml_vdec_hw *hw)
+{
+	int i;
+	const struct power_manager_s *pm = hw->pm;
+	struct pm_pd_s *pd = pm->pd_data;
+
+	for (i = 0; i < VDEC_MAX; i++) {
+		if (!IS_ERR_OR_NULL(pd[i].link))
+			device_link_del(pd[i].link);
+
+		if (!IS_ERR_OR_NULL(pd[i].dev))
+			dev_pm_domain_detach(pd[i].dev, true);
+	}
+}
+
+static void dos_local_config(bool is_on, int id)
+{
+	if (is_on) {
+		usleep_range(20, 100);
+
+		switch (id) {
+		case VDEC_1:
+			WRITE_VREG(DOS_MEM_PD_VDEC, 0);
+			WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_SW_RESET0, 0);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_MEM_PD_VDEC, 0);
+			break;
+		case VDEC_HEVC:
+			WRITE_VREG(DOS_MEM_PD_HEVC, 0);
+			WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_SW_RESET3, 0);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_MEM_PD_HEVC, 0);
+			break;
+		default:
+			pr_debug("%s on, not found id %d\n", __func__, id);
+			break;
+		}
+	} else {
+		switch (id) {
+		case VDEC_1:
+			WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_SW_RESET0, 0);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
+			break;
+		case VDEC_HEVC:
+			WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_SW_RESET3, 0);
+			usleep_range(20, 100);
+			WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
+			break;
+		default:
+			pr_debug("%s off, not found id %d\n", __func__, id);
+			break;
+		}
+	}
+
+	pr_debug("%s end, id %d, is_on %d\n", __func__, id, is_on);
+}
+
+static void pm_vdec_power_domain_power_on(struct aml_vdec_hw *hw, int id)
+{
+	const struct power_manager_s *pm = hw->pm;
+
+	pm_vdec_clock_switch(hw, id, true);
+	pm_vdec_power_switch(pm->pd_data, id, true);
+
+	dos_local_config(1, id);
+}
+
+static void pm_vdec_power_domain_power_off(struct aml_vdec_hw *hw, int id)
+{
+	const struct power_manager_s *pm = hw->pm;
+
+	dos_local_config(0, id);
+
+	pm_vdec_clock_switch(hw, id, false);
+	pm_vdec_power_switch(pm->pd_data, id, false);
+}
+
+static bool pm_vdec_power_domain_power_state(struct aml_vdec_hw *hw, int id)
+{
+	if (hw->pm->pd_data[id].dev)
+		return pm_runtime_active(hw->pm->pd_data[id].dev);
+	else
+		return false;
+}
+
+static void vdec_poweron(struct aml_vdec_hw *hw, enum vdec_type_e core)
+{
+	if (core >= VDEC_MAX)
+		return;
+
+	mutex_lock(&hw->pm_mutex);
+	if (!hw->pm->pd_data[core].dev)
+		goto out;
+
+	hw->pm->pd_data[core].ref_count++;
+	if (hw->pm->pd_data[core].ref_count > 1)
+		goto out;
+
+	if (hw->pm->power_state(hw, core))
+		goto out;
+
+	hw->pm->power_on(hw, core);
+
+out:
+	mutex_unlock(&hw->pm_mutex);
+}
+
+static void vdec_poweroff(struct aml_vdec_hw *hw, enum vdec_type_e core)
+{
+	if (core >= VDEC_MAX)
+		return;
+
+	mutex_lock(&hw->pm_mutex);
+	if (hw->pm->pd_data[core].ref_count == 0)
+		goto out;
+
+	hw->pm->pd_data[core].ref_count--;
+	if (hw->pm->pd_data[core].ref_count > 0)
+		goto out;
+
+	hw->pm->power_off(hw, core);
+
+out:
+	mutex_unlock(&hw->pm_mutex);
+}
+
+int vdec_enable(struct aml_vdec_hw *hw)
+{
+	vdec_switch_gate(hw, "vdec", 1);
+	vdec_poweron(hw, VDEC_1);
+
+	return 0;
+}
+
+int vdec_disable(struct aml_vdec_hw *hw)
+{
+	vdec_poweroff(hw, VDEC_1);
+	vdec_switch_gate(hw, "vdec", 0);
+
+	return 0;
+}
+
+static const struct power_manager_s pm[] = {
+	[AML_PM_PD] = {
+		.pd_data    = vdec_domain_data,
+		.init        = pm_vdec_power_domain_init,
+		.release    = pm_vdec_power_domain_release,
+		.power_on    = pm_vdec_power_domain_power_on,
+		.power_off    = pm_vdec_power_domain_power_off,
+		.power_state = pm_vdec_power_domain_power_state,
+	},
+};
+
+static irqreturn_t vdec_irq_handler(int irq, void *priv)
+{
+	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
+	struct aml_vdec_hw *hw = dev->dec_hw;
+	irqreturn_t ret;
+
+	if (hw->hw_ops.irq_handler)
+		ret = hw->hw_ops.irq_handler(irq, priv);
+
+	return ret;
+}
+
+static irqreturn_t vdec_threaded_isr_handler(int irq, void *priv)
+{
+	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
+	struct aml_vdec_hw *hw = dev->dec_hw;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	if (hw->hw_ops.irq_threaded_func)
+		ret = hw->hw_ops.irq_threaded_func(irq, priv);
+
+	return ret;
+}
+
+struct aml_vdec_hw *vdec_get_hw(void *priv)
+{
+	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
+
+	return dev->dec_hw;
+}
+
+int dev_request_hw_resources(void *priv)
+{
+	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
+	struct aml_vdec_hw *hw;
+	struct platform_device *pdev;
+	struct resource res;
+	u32 res_size;
+	int i;
+	int ret = -1;
+
+	if (!dev || !dev->dec_hw) {
+		pr_err("%s param invalid\n", __func__);
+		return -1;
+	}
+	pdev = dev->plat_dev;
+	hw = dev->dec_hw;
+	hw->dev = &pdev->dev;
+
+	hw->dec_irq = platform_get_irq(pdev, VDEC_IRQ_1);
+	if (hw->dec_irq < 0) {
+		dev_err(&pdev->dev, "get irq failed\n");
+		return hw->dec_irq;
+	}
+	ret = devm_request_threaded_irq(&pdev->dev, hw->dec_irq, vdec_irq_handler,
+					vdec_threaded_isr_handler, IRQF_ONESHOT,
+					"vdec-1", dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to install irq %d (%d)",
+			hw->dec_irq, ret);
+		return -1;
+	}
+
+	for (i = 0; i < MAX_REG_BUS; i++) {
+		if (of_address_to_resource(pdev->dev.of_node, i, &res)) {
+			pr_err("of_address_to_resource %d failed\n", i);
+			return -EINVAL;
+		}
+
+		res_size = resource_size(&res);
+		hw->regs[i] = ioremap(res.start, res_size);
+		reg_base[i] = hw->regs[i];
+
+		pr_debug("%s, res start %llx, end %llx, iomap: %p\n",
+			 __func__, (unsigned long long)res.start,
+			 (unsigned long long)res.end, reg_base[i]);
+	}
+
+	hw->pm = &pm[dev->pvdec_data->power_type];
+	if (hw->pm->init) {
+		ret = hw->pm->init(hw);
+		if (ret < 0) {
+			pr_err("power mgr init failed!\n");
+			return ret;
+		}
+	}
+	vdec_clock_gate_init(hw);
+
+	aml_vdec_canvas_register(hw);
+
+	pr_debug("##Amlogic hw resource init OK##\n");
+
+	return 0;
+}
+
+void dev_destroy_hw_resources(void *priv)
+{
+	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
+	struct aml_vdec_hw *hw;
+
+	if (!dev || !dev->dec_hw) {
+		pr_err("%s param invalid\n", __func__);
+		return;
+	}
+	hw = dev->dec_hw;
+
+	if (hw->pm->release)
+		hw->pm->release(hw);
+
+	kfree(hw);
+	dev->dec_hw = NULL;
+	pr_debug("##Amlogic hw resource release OK##\n");
+}
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h
new file mode 100644
index 000000000000..ad1e613a2cf8
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef _AML_VDEC_HW_H_
+#define _AML_VDEC_HW_H_
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/interrupt.h>
+#include "reg_defines.h"
+
+#define VDEC_FIFO_ALIGN     8
+#define VLD_PADDING_SIZE    1024
+
+#define RD_VREG(addr) read_dos_reg(addr)
+#define WRITE_VREG(addr, val) write_dos_reg(addr, val)
+#define WRITE_VREG_BITS(r, val, start, len) dos_reg_write_bits(r, val, start, len)
+#define CLEAR_VREG_MASK(r, mask) dos_reg_clear_mask(r, mask)
+#define SET_VREG_MASK(r, mask) dos_reg_set_mask(r, mask)
+
+/**
+ * struct aml_vdec_hw_ops - codec mode specific operations for hw
+ * @load_firmware_ex: Load firmware for current dec specific.
+ * @irq_handler: mandatory call when the ISR triggers
+ * @irq_threaded_func: mandatory call for the threaded ISR
+ * @canvas_alloc: Alloc canvas for curr frame
+ * @canvas_free: Release canvas.
+ * @config_canvas: Config for curr frame, such as w/h, Y/UV start addr etc.
+ */
+struct aml_vdec_hw_ops {
+	int (*load_firmware_ex)(void *priv, const u8 *data, u32 len);
+	irqreturn_t (*irq_handler)(int irq, void *priv);
+	irqreturn_t (*irq_threaded_func)(int irq, void *priv);
+	int (*canvas_alloc)(u8 *canvas_index);
+	void (*canvas_free)(u8 canvas_index);
+	void (*config_canvas)(u8 canvas_index,
+			      ulong addr, u32 width, u32 height,
+			      u32 wrap, u32 blkmode, u32 endian);
+};
+
+/**
+ * enum vdec_type_e - Type of decoder hardware.
+ */
+enum vdec_type_e {
+	VDEC_1 = 0,
+	VDEC_HEVC,
+	VDEC_MAX,
+};
+
+/**
+ * enum vdec_irq_num - Definition of the irq.
+ */
+enum vdec_irq_num {
+	VDEC_IRQ_0 = 0,
+	VDEC_IRQ_1,
+	VDEC_IRQ_2,
+	VDEC_IRQ_MAX,
+};
+
+/**
+ * enum vdec_type_e - Type of decoder clock.
+ */
+enum clk_type_e {
+	VDEC = 0,
+	VDEC_MUX,
+	HEVCF_MUX,
+	DOS_CLK_MAX,
+};
+
+/**
+ * enum aml_power_type_e - Type of decoder power.
+ */
+enum aml_power_type_e {
+	AML_PM_PD = 0,
+};
+
+/**
+ * enum mm_bus_e - Type of decoder hardware bus.
+ */
+enum mm_bus_e {
+	DOS_BUS = 0,
+	DMC_BUS,
+	MAX_REG_BUS
+};
+
+/**
+ * struct gate_switch_node - clock node definition
+ * @clk: Pointer to clk instance.
+ * @name: Clock name used.
+ * @mutex: Mutex lock for multi decoder instance.
+ * @ref_count: Curr clk instance ref count.
+ */
+struct gate_switch_node {
+	struct clk *clk;
+	const char *name;
+	struct mutex mutex;
+	int ref_count;
+};
+
+/**
+ * struct pm_pd_s - power domain definition
+ * @name: Power domain name.
+ * @dev: Pointer to device structure.
+ * @mutex: Pointer to device_link structure.
+ * @ref_count: Curr power domain instance ref count.
+ */
+struct pm_pd_s {
+	u8 *name;
+	struct device *dev;
+	struct device_link *link;
+	int ref_count;
+};
+
+/**
+ * struct aml_vdec_hw - decoder hardware resources definition
+ * @pdev: Pointer to struct platform_device.
+ * @dev: Pointer to struct device.
+ * @regs: Reg base for dos/dmc hardware.
+ * @pm_mutex: Mutex for pm->pd_data.
+ * @pm: Pointer to struct power_manager_s.
+ * @hw_ops: Hardware resource operation functions. See struct aml_vdec_hw_ops.
+ * @gates: Clk instance used by curr decoder context.
+ * @dec_irq: Irq registered.
+ * @curr_ctx: Pointer to curr decoder context.
+ */
+struct aml_vdec_hw {
+	struct platform_device *pdev;
+	struct device *dev;
+	void __iomem *regs[MAX_REG_BUS];
+	struct mutex pm_mutex;
+	const struct power_manager_s *pm;
+	struct aml_vdec_hw_ops hw_ops;
+	struct gate_switch_node gates[DOS_CLK_MAX];
+	int dec_irq;
+	void *curr_ctx;
+};
+
+/**
+ * struct power_manager_s - Power manager & opertion function
+ * @pd_data: Pointer to struct pm_pd_s
+ * @init: Power manager init.
+ * @release: Power manager release.
+ * @power_on: Power on for decoder hw.
+ * @power_off: Power off for decoder hw.
+ * @power_state: Query the power state.
+ */
+struct power_manager_s {
+	struct pm_pd_s *pd_data;
+	int (*init)(struct aml_vdec_hw *hw);
+	void (*release)(struct aml_vdec_hw *hw);
+	void (*power_on)(struct aml_vdec_hw *hw, int id);
+	void (*power_off)(struct aml_vdec_hw *hw, int id);
+	bool (*power_state)(struct aml_vdec_hw *hw, int id);
+};
+
+int dev_request_hw_resources(void *priv);
+void dev_destroy_hw_resources(void *priv);
+struct aml_vdec_hw *vdec_get_hw(void *priv);
+u32 read_dos_reg(u32 reg_addr);
+void write_dos_reg(u32 addr, int val);
+void dos_reg_write_bits(u32 reg, u32 val, int start, int len);
+void dos_reg_clear_mask(u32 addr, u32 mask);
+void dos_reg_set_mask(u32 addr, u32 mask);
+u32 read_dmc_reg(u32 addr);
+void write_dmc_reg(u32 addr, int val);
+int vdec_enable(struct aml_vdec_hw *hw);
+int vdec_disable(struct aml_vdec_hw *hw);
+void dos_enable(void);
+void aml_start_vdec_hw(void);
+void aml_stop_vdec_hw(void);
+int load_firmware(struct aml_vdec_hw *hw, const char *path);
+void aml_vdec_reset_core(void);
+
+#endif
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c
new file mode 100644
index 000000000000..f1f8ba1f4ff6
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#include "aml_vdec_platform.h"
+#include "aml_vdec_drv.h"
+#include "aml_vdec_hw.h"
+#include "h264.h"
+
+#define VIDEO_DEC_H264  "s4_h264_multi.bin"
+
+const struct aml_codec_ops aml_S4_dec_ops[] = {
+	[CODEC_TYPE_H264] = {
+		.init = aml_h264_init,
+		.exit = aml_h264_exit,
+		.run = aml_h264_dec_run,
+	},
+};
+
+static const struct aml_video_dec_fmt aml_S4_dec_fmts = {
+	.max_height = AML_VDEC_1080P_MAX_H,
+	.max_width = AML_VDEC_1080P_MAX_W,
+	.align = 32,
+	.is_10_bit_support = 0,
+};
+
+const struct aml_dev_platform_data aml_vdec_s4_pdata = {
+	.dec_fmt = &aml_S4_dec_fmts,
+	.codec_ops = aml_S4_dec_ops,
+	.power_type = AML_PM_PD,
+	.req_hw_resource = dev_request_hw_resources,
+	.destroy_hw_resource = dev_destroy_hw_resources,
+	.fw_path = {
+		VIDEO_DEC_H264,
+	},
+};
diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h
new file mode 100644
index 000000000000..ff0933f6f074
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef AML_VDEC_PLATFORM_H_
+#define AML_VDEC_PLATFORM_H_
+
+#include <linux/videodev2.h>
+
+#define MAX_DEC_FORMAT 3
+
+/**
+ * struct aml_codec_ops - codec mode specific operations
+ * @init: Used for decoder initialization.
+ * @exit: If needed, can be used to undo the .init phase.
+ * @run: Start a single decoding job. Called from atomic context.
+ * Caller should ensure that a pair of buffers is ready and the
+ * hardware is powered on and clk is enabled. Returns zero if OK,
+ * a negative value in error cases.
+ */
+struct aml_codec_ops {
+	int (*init)(void *priv);
+	void (*exit)(void *priv);
+	int (*run)(void *priv);
+};
+
+/**
+ * struct aml_video_dec_fmt - codec format required by platform
+ * @max_height: Max decode frame height of current platform.
+ * @max_width: Max decode frame width of current platform.
+ * @align: Align requirement of the current platform.
+ * @is_10_bit_support: Whether the platform supports 10 bit.
+ */
+struct aml_video_dec_fmt {
+	u32 max_height;
+	u32 max_width;
+	int align;
+	int is_10_bit_support;
+};
+
+/**
+ * struct aml_dev_platform_data - compatible data for each chip.
+ * @dec_fmt: Support dec format.
+ * @codec_ops: Codec operation function.
+ * @req_hw_resource: Operation function to request the hardware resource.
+ * @destroy_hw_resource: Operation function to release the hardware resource.
+ * @power_type: Type of power that the current chip need. See aml_power_type_e.
+ * @fw_path: Path of the firmware.bin.
+ */
+struct aml_dev_platform_data {
+	const struct aml_video_dec_fmt *dec_fmt;
+	const struct aml_codec_ops *codec_ops;
+	int (*req_hw_resource)(void *priv);
+	void (*destroy_hw_resource)(void *priv);
+	int power_type;
+	const char *fw_path[MAX_DEC_FORMAT];
+};
+
+extern const struct aml_dev_platform_data aml_vdec_s4_pdata;
+
+#endif
diff --git a/drivers/media/platform/amlogic/vdec/h264.c b/drivers/media/platform/amlogic/vdec/h264.c
new file mode 100644
index 000000000000..ebfd10885eaa
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/h264.c
@@ -0,0 +1,1790 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#include <media/v4l2-h264.h>
+#include <linux/vmalloc.h>
+#include "aml_vdec.h"
+#include "aml_vdec_hw.h"
+#include "h264.h"
+
+#define INVALID_POC 0xffffffff
+
+#define H264_SLICE_HEADER_DONE		0x1
+#define H264_SLICE_DATA_DONE		0x2
+
+#define DECODER_TIMEOUT_MS			500
+
+#define COL_BUFFER_MARGIN			2
+
+struct vdec_h264_stateless_ctrl_ref {
+	const struct v4l2_ctrl_h264_decode_params *decode;
+	const struct v4l2_ctrl_h264_scaling_matrix *scaling;
+	const struct v4l2_ctrl_h264_sps *sps;
+	const struct v4l2_ctrl_h264_pps *pps;
+};
+
+enum SliceType {
+	P_SLICE = 0,
+	B_SLICE = 1,
+	I_SLICE = 2,
+	SP_SLICE = 3,
+	SI_SLICE = 4,
+	MAX_SLICE_TYPES = 5
+};
+
+/* Used by firmware */
+union param {
+	struct {
+		unsigned short data[RPM_END - RPM_BEGIN];
+	} l;
+	struct {
+		unsigned short dump[DPB_OFFSET];
+		unsigned short dpb_base[FRAME_IN_DPB << 3];
+
+		unsigned short dpb_max_buffer_frame;
+		unsigned short actual_dpb_size;
+
+		unsigned short colocated_buf_status;
+
+		unsigned short num_forward_short_term_reference_pic;
+		unsigned short num_short_term_reference_pic;
+		unsigned short num_reference_pic;
+
+		unsigned short current_dpb_index;
+		unsigned short current_decoded_frame_num;
+		unsigned short current_reference_frame_num;
+
+		unsigned short l0_size;
+		unsigned short l1_size;
+		/**
+		 * [6:5] : nal_ref_idc
+		 * [4:0] : nal_unit_type
+		 */
+		unsigned short NAL_info_mmco;
+		/**
+		 * [1:0] : 00 - top field, 01 - bottom field,
+		 *         10 - frame, 11 - mbaff frame
+		 */
+		unsigned short picture_structure_mmco;
+		unsigned short frame_num;
+		unsigned short pic_order_cnt_lsb;
+
+		unsigned short num_ref_idx_l0_active_minus1;
+		unsigned short num_ref_idx_l1_active_minus1;
+
+		unsigned short PrevPicOrderCntLsb;
+		unsigned short PreviousFrameNum;
+
+		/* 32 bits variables */
+		unsigned short delta_pic_order_cnt_bottom[2];
+		unsigned short delta_pic_order_cnt_0[2];
+		unsigned short delta_pic_order_cnt_1[2];
+
+		unsigned short PrevPicOrderCntMsb[2];
+		unsigned short PrevFrameNumOffset[2];
+
+		unsigned short frame_pic_order_cnt[2];
+		unsigned short top_field_pic_order_cnt[2];
+		unsigned short bottom_field_pic_order_cnt[2];
+
+		unsigned short colocated_mv_addr_start[2];
+		unsigned short colocated_mv_addr_end[2];
+		unsigned short colocated_mv_wr_addr[2];
+	} dpb;
+	struct {
+		unsigned short dump[MMCO_OFFSET];
+
+		/* array base address for offset_for_ref_frame */
+		unsigned short offset_for_ref_frame_base[128];
+
+		/**
+		 * 0 - Index in DPB
+		 * 1 - Picture Flag
+		 *  [2] : 0 - short term reference,
+		 *			1 - long term reference
+		 *  [1] : bottom field
+		 *  [0] : top field
+		 * 2 - Picture Number (short term or long term) low 16 bits
+		 * 3 - Picture Number (short term or long term) high 16 bits
+		 */
+		unsigned short reference_base[128];
+
+		/* command and parameter, until command is 3 */
+		unsigned short l0_reorder_cmd[REORDER_CMD_MAX];
+		unsigned short l1_reorder_cmd[REORDER_CMD_MAX];
+
+		/* command and parameter, until command is 0 */
+		unsigned short mmco_cmd[44];
+
+		unsigned short l0_base[40];
+		unsigned short l1_base[40];
+	} mmco;
+	struct {
+		/* from ucode lmem, do not change this struct */
+	} p;
+};
+
+struct h264_decode_buf_spec {
+	struct v4l2_h264_dpb_entry *dpb;
+	u32 canvas_pos;
+	u32 dpb_index;
+	u32 poc;
+	int col_buf_index;
+	u8 y_canvas_index;
+	u8 u_canvas_index;
+	u8 v_canvas_index;
+	u8 used;
+	u8 long_term_flag;
+	dma_addr_t y_dma_addr;
+	dma_addr_t c_dma_addr;
+};
+
+#define REORDERING_COMMAND_MAX_SIZE	33
+struct slice {
+	int frame_num;
+	/*modification */
+	int slice_type;
+	int num_ref_idx_l0;
+	int num_ref_idx_l1;
+	int ref_pic_list_reordering_flag[2];
+	int modification_of_pic_nums_idc[2][REORDERING_COMMAND_MAX_SIZE];
+	int abs_diff_pic_num_minus1[2][REORDERING_COMMAND_MAX_SIZE];
+	int long_term_pic_idx[2][REORDERING_COMMAND_MAX_SIZE];
+	unsigned char dec_ref_pic_marking_buffer_valid;
+};
+
+struct aml_h264_ctx {
+	struct aml_vdec_ctx *v4l2_ctx;
+	u8 init_flag;
+	u8 new_pic_flag;
+	u8 mc_cpu_loaded;
+	u8 param_set;
+	u8 colocated_buf_num;
+	u8 reg_iqidct_control_init_flag;
+	u32 reg_iqidct_control;
+	u32 reg_vcop_ctrl_reg;
+	u32 reg_rv_ai_mb_count;
+	u32 vld_dec_control;
+	u32 save_avscratch_f;
+	u32 seq_info;
+	u32 decode_pic_count;
+	union param dpb_param;
+	u32 dec_status;
+	struct slice mslice;
+	struct h264_decode_buf_spec curr_spec;
+	struct h264_decode_buf_spec ref_list0[V4L2_H264_NUM_DPB_ENTRIES + 1];
+	struct h264_decode_buf_spec ref_list1[V4L2_H264_NUM_DPB_ENTRIES + 1];
+	struct h264_decode_buf_spec ref_list0_unreordered[V4L2_H264_NUM_DPB_ENTRIES + 1];
+	struct h264_decode_buf_spec ref_list1_unreordered[V4L2_H264_NUM_DPB_ENTRIES + 1];
+	u8 list_size[2];
+	dma_addr_t lmem_phy_addr;
+	void *lmem_addr;
+	dma_addr_t mc_cpu_paddr;
+	void *mc_cpu_vaddr;
+	dma_addr_t cma_alloc_addr;
+	void *cma_alloc_vaddr;
+	dma_addr_t collated_cma_addr;
+	dma_addr_t collated_cma_addr_end;
+	void *collated_cma_vaddr;
+	dma_addr_t workspace_offset;
+	void *workspace_vaddr;
+	u32 col_buf_alloc_size;
+	u32 one_col_buf_size;
+	u32 colocated_buf_map;
+	int colocated_buf_poc[32];
+
+	u32 frame_width;
+	u32 frame_height;
+	u32 mb_width;
+	u32 mb_height;
+	u32 mb_total;
+	u32 max_num_ref_frames;
+
+	struct vdec_h264_stateless_ctrl_ref ctrl_ref;
+};
+
+static inline int get_flag(u32 flag, u32 mask)
+{
+	return (flag & mask) ? 1 : 0;
+}
+
+static inline void write_lmem(unsigned short *base, u32 offset, u32 value)
+{
+	base[offset] = value;
+}
+
+static inline uint32_t spec2canvas(struct h264_decode_buf_spec *buf_spec)
+{
+	return (buf_spec->v_canvas_index << 16) |
+		(buf_spec->u_canvas_index << 8) |
+		(buf_spec->y_canvas_index << 0);
+}
+
+static struct h264_decode_buf_spec *find_spec_by_dpb_index(struct aml_h264_ctx *h264_ctx, int index)
+{
+	int i;
+
+	for (i = 0; i < h264_ctx->list_size[0]; i++) {
+		if (index == h264_ctx->ref_list0[i].dpb_index)
+			return &h264_ctx->ref_list0[i];
+	}
+
+	for (i = 0; i < h264_ctx->list_size[1]; i++) {
+		if (index == h264_ctx->ref_list1[i].dpb_index)
+			return &h264_ctx->ref_list1[i];
+	}
+	return NULL;
+}
+
+static int h264_prepare_input(struct aml_vdec_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *src;
+	struct vb2_buffer *vb;
+	dma_addr_t src_dma;
+	u32 payload_size;
+	int dummy;
+
+	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	if (!src) {
+		pr_info("no input buffer available!\n");
+		return -1;
+	}
+	vb = &src->vb2_buf;
+	payload_size = vb2_get_plane_payload(vb, 0);
+	src_dma = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
+	/* reset VLD fifo for all vdec */
+	WRITE_VREG(DOS_SW_RESET0, (1 << 5) | (1 << 4) | (1 << 3));
+	WRITE_VREG(DOS_SW_RESET0, 0);
+	WRITE_VREG(POWER_CTL_VLD, 1 << 4);
+
+	WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, src_dma);
+	WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, (src_dma + payload_size));
+	WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
+		   round_down(src_dma, VDEC_FIFO_ALIGN));
+
+	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
+	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
+	WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
+
+	WRITE_VREG(VLD_MEM_VIFIFO_RP,
+		   round_down(src_dma, VDEC_FIFO_ALIGN));
+	dummy = payload_size + VLD_PADDING_SIZE;
+	WRITE_VREG(VLD_MEM_VIFIFO_WP,
+		   round_down((src_dma + dummy), VDEC_FIFO_ALIGN));
+
+	WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3);
+	WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
+
+	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
+		   (0x11 << 16) | (1 << 10) | (7 << 3));
+
+	WRITE_VREG(AV_SCRATCH_1, 0x0);
+	WRITE_VREG(H264_DECODE_INFO, (1 << 13));
+	WRITE_VREG(H264_DECODE_SIZE, payload_size);
+	WRITE_VREG(VIFF_BIT_CNT, payload_size * 8);
+
+	return 0;
+}
+
+static void config_sps_params(struct aml_h264_ctx *h264_ctx,
+			      unsigned short *sps_base,
+			      const struct v4l2_ctrl_h264_sps *sps)
+{
+	u32 cfg_tmp = 0;
+	u32 frame_size;
+	u32 offset = 0;
+	unsigned short data_tmp[0x100];
+	int i, ii;
+
+	memset(sps_base, 0, 0x100);
+
+	h264_ctx->frame_width = (sps->pic_width_in_mbs_minus1 + 1) << 4;
+	h264_ctx->frame_height = (sps->pic_height_in_map_units_minus1 + 1) << 4;
+
+	data_tmp[offset] = PARAM_BASE_VAL;
+	offset += 2;
+
+	data_tmp[offset++] = GET_SPS_PROFILE_IDC(sps->profile_idc);
+
+	data_tmp[offset++] = GET_SPS_SEQ_PARAM_SET_ID(sps->seq_parameter_set_id) |
+	    GET_SPS_LEVEL_IDC(sps->level_idc);
+
+	if (sps->profile_idc >= 100) {
+		data_tmp[offset++] = GET_SPS_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
+
+		data_tmp[offset++] = ((sps->chroma_format_idc ^ 1) << 1);
+	}
+
+	data_tmp[offset++] = GET_SPS_LOG2_MAX_FRAME_NUM(sps->log2_max_frame_num_minus4);
+	data_tmp[offset++] = GET_SPS_PIC_ORDER_TYPE(sps->pic_order_cnt_type);
+
+	if (sps->pic_order_cnt_type == 0) {
+		data_tmp[offset++] =
+			GET_SPS_PIC_ORDER_CNT_LSB(sps->log2_max_pic_order_cnt_lsb_minus4);
+	} else if (sps->pic_order_cnt_type == 1) {
+		data_tmp[offset++] =
+			get_flag(sps->flags,
+				 V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO);
+		data_tmp[offset++] =
+			GET_SPS_OFFSET_FOR_NONREF_PIC_LOW(sps->offset_for_non_ref_pic);
+		data_tmp[offset++] =
+			GET_SPS_OFFSET_FOR_NONREF_PIC_HIGH(sps->offset_for_non_ref_pic);
+		data_tmp[offset++] =
+			GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_LOW(sps->offset_for_top_to_bottom_field);
+		data_tmp[offset++] =
+			GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_HIGH(sps->offset_for_top_to_bottom_field);
+		data_tmp[offset++] = sps->num_ref_frames_in_pic_order_cnt_cycle;
+	}
+
+	data_tmp[offset++] = GET_SPS_NUM_REF_FRAMES(sps->max_num_ref_frames) |
+	    GET_SPS_GAPS_ALLOWED_FLAG(get_flag(sps->flags,
+					       V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED));
+
+	data_tmp[offset++] = GET_SPS_PIC_WIDTH_IN_MBS(sps->pic_width_in_mbs_minus1);
+
+	data_tmp[offset++] = GET_SPS_PIC_HEIGHT_IN_MBS(sps->pic_height_in_map_units_minus1);
+	data_tmp[offset++] =
+		GET_SPS_DIRECT_8X8_FLAGS
+				(get_flag(sps->flags,
+					  V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) |
+		GET_SPS_MB_ADAPTIVE_FRAME_FIELD_FLAGS
+				(get_flag(sps->flags,
+					  V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) |
+		GET_SPS_FRAME_MBS_ONLY_FLAGS
+				(get_flag(sps->flags,
+					  V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY));
+
+	for (i = 0; i < 0x100; i += 4) {
+		for (ii = 0; ii < 4; ii++)
+			sps_base[i + 3 - ii] = data_tmp[i + ii];
+	}
+
+	frame_size = (sps->pic_width_in_mbs_minus1 + 1) * (sps->pic_height_in_map_units_minus1 + 1);
+	cfg_tmp = (get_flag(sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) << 31) |
+				(sps->max_num_ref_frames << 24) | (frame_size << 8) |
+				(sps->pic_width_in_mbs_minus1 + 1);
+	WRITE_VREG(AV_SCRATCH_1, cfg_tmp);
+	h264_ctx->seq_info = cfg_tmp;
+
+	cfg_tmp = 0;
+	cfg_tmp = (get_flag(sps->flags, V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) << 15) |
+				(sps->chroma_format_idc);
+	WRITE_VREG(AV_SCRATCH_2, cfg_tmp);
+
+	cfg_tmp = 0;
+	cfg_tmp = (sps->max_num_ref_frames << 8) | (sps->level_idc);
+	WRITE_VREG(AV_SCRATCH_B, cfg_tmp);
+
+	cfg_tmp = ((sps->level_idc & 0xff) << 7) |
+	    (get_flag(sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) << 2);
+	WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) | cfg_tmp);
+
+	h264_ctx->mb_width = (sps->pic_width_in_mbs_minus1 + 4) & 0xfffffffc;
+	h264_ctx->mb_height = (sps->pic_height_in_map_units_minus1 + 4) & 0xfffffffc;
+	h264_ctx->mb_total = h264_ctx->mb_width * h264_ctx->mb_height;
+	h264_ctx->max_num_ref_frames = sps->max_num_ref_frames;
+}
+
+static void config_pps_params(struct aml_h264_ctx *h264_ctx,
+			      unsigned short *pps_base,
+			      const struct v4l2_ctrl_h264_pps *pps)
+{
+	u32 offset = 0;
+	unsigned short data_tmp[0x100];
+	u32 max_reference_size = V4L2_H264_NUM_DPB_ENTRIES;
+	u32 max_list_size;
+	int i, ii;
+
+	memset(pps_base, 0, 0x100);
+
+	data_tmp[offset++] = PARAM_BASE_VAL;
+
+	data_tmp[offset++] =
+		GET_PPS_PIC_PARAM_SET_ID(pps->pic_parameter_set_id) |
+	    GET_PPS_SEQ_PARAM_SET_ID(pps->seq_parameter_set_id) |
+	    GET_PPS_ENTROPY_CODING_MODE_FLAG
+			(get_flag(pps->flags,
+				  V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)) |
+	    GET_PPS_PIC_ORDER_PRESENT_FLAG
+			(get_flag(pps->flags,
+				  V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT));
+
+	data_tmp[offset++] =
+		GET_PPS_WEIGHTED_BIPRED_IDC(pps->weighted_bipred_idc) |
+		GET_PPS_WEIGHTED_PRED_FLAG(get_flag(pps->flags,
+						    V4L2_H264_PPS_FLAG_WEIGHTED_PRED)) |
+		GET_PPS_NUM_IDX_REF_L1_MINUS1(pps->num_ref_idx_l1_default_active_minus1) |
+		GET_PPS_NUM_IDX_REF_L0_MINUS1(pps->num_ref_idx_l0_default_active_minus1);
+
+	data_tmp[offset++] = GET_PPS_INIT_QS_MINUS26(pps->pic_init_qs_minus26) |
+	    GET_PPS_INIT_QP_MINUS26(pps->pic_init_qp_minus26);
+
+	data_tmp[offset] =
+	    GET_PPS_CHROMA_QP_INDEX_OFFSET(pps->chroma_qp_index_offset) |
+	    GET_PPS_DEBLOCK_FILTER_CTRL_PRESENT_FLAG
+				(get_flag(pps->flags,
+					  V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)) |
+	    GET_PPS_CONSTRAIN_INTRA_PRED_FLAG
+				(get_flag(pps->flags,
+					  V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)) |
+	    GET_PPS_REDUNDANT_PIC_CNT_PRESENT_FLAG
+				(get_flag(pps->flags,
+					  V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT));
+	if (get_flag
+	    (pps->flags,
+	     V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE |
+	     V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
+		data_tmp[offset] |= (1 << 11);
+	offset++;
+
+	data_tmp[offset++] =
+	    GET_PPS_SCALING_MATRIX_PRESENT_FLAG(get_flag
+						(pps->flags,
+						 V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) |
+	    GET_PPS_TRANSFORM_8X8_FLAG(get_flag
+				       (pps->flags,
+					V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE));
+
+	data_tmp[offset++] =
+		GET_PPS_GET_SECOND_CHROMA_QP_OFFSET(pps->second_chroma_qp_index_offset);
+
+	max_list_size = (pps->num_ref_idx_l1_default_active_minus1 + 1) +
+	    (pps->num_ref_idx_l0_default_active_minus1 + 1);
+
+	h264_ctx->max_num_ref_frames = max_list_size > h264_ctx->max_num_ref_frames ?
+						max_list_size : h264_ctx->max_num_ref_frames;
+
+	WRITE_VREG(AV_SCRATCH_0, ((h264_ctx->max_num_ref_frames + 1) << 24) |
+		   (max_reference_size << 16) | (max_reference_size << 8));
+
+	for (i = 0; i < 0x100; i += 4) {
+		for (ii = 0; ii < 4; ii++)
+			pps_base[i + 3 - ii] = data_tmp[i + ii];
+	}
+}
+
+static void h264_config_params(struct aml_vdec_ctx *ctx)
+{
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
+	unsigned short *p_sps_base, *p_pps_base;
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+	const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
+	const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
+
+	p_sps_base = (unsigned short *)(h264_ctx->workspace_vaddr +
+		MEM_SPS_BASE + sps->seq_parameter_set_id * 0x400);
+	p_pps_base = (unsigned short *)(h264_ctx->workspace_vaddr +
+		MEM_PPS_BASE + pps->pic_parameter_set_id * 0x200);
+
+	config_sps_params(h264_ctx, p_sps_base, sps);
+	config_pps_params(h264_ctx, p_pps_base, pps);
+}
+
+static void config_decode_canvas(struct aml_vdec_hw *hw,
+				 struct h264_decode_buf_spec *buf_spec,
+				 u32 mb_width, u32 mb_height)
+{
+	int canvas_alloc_result = 0;
+	int blkmode = 0x0;
+
+	canvas_alloc_result = hw->hw_ops.canvas_alloc(&buf_spec->y_canvas_index);
+	canvas_alloc_result = hw->hw_ops.canvas_alloc(&buf_spec->u_canvas_index);
+	buf_spec->v_canvas_index = buf_spec->u_canvas_index;
+
+	if (!canvas_alloc_result) {
+		/* config y canvas */
+		hw->hw_ops.config_canvas(buf_spec->y_canvas_index,
+					 buf_spec->y_dma_addr, mb_width << 4,
+					 mb_height << 4, 0, blkmode, 7);
+		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, (1 << 11) |	/* canvas_blk32_wr */
+			   (blkmode << 10) |	/* canvas_blk32 */
+			   (1 << 8) |	/* canvas_index_wr */
+			   (buf_spec->y_canvas_index << 0)	/* canvas index */
+		    );
+
+		/* config uv canvas */
+		hw->hw_ops.config_canvas(buf_spec->u_canvas_index,
+					 buf_spec->c_dma_addr, mb_width << 4,
+					 mb_height << 3, 0, blkmode, 7);
+		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, (1 << 11) |	/* canvas_blk32_wr */
+			   (blkmode << 10) |	/* canvas_blk32 */
+			   (1 << 8) |	/* canvas_index_wr */
+			   (buf_spec->u_canvas_index << 0)	/* canvas index */
+		    );
+
+		WRITE_VREG(ANC0_CANVAS_ADDR + buf_spec->canvas_pos,
+			   spec2canvas(buf_spec));
+	}
+}
+
+static int allocate_colocate_buf(struct aml_h264_ctx *h264_ctx, int poc)
+{
+	int i;
+
+	for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
+		if (((h264_ctx->colocated_buf_map >> i) & 0x1) == 0) {
+			h264_ctx->colocated_buf_map |= (1 << i);
+			break;
+		}
+	}
+
+	if (i == h264_ctx->colocated_buf_num)
+		return -1;
+
+	h264_ctx->colocated_buf_poc[i] = poc;
+	pr_debug("%s colocated_buf_index %d poc %d\n", __func__, i,
+		 h264_ctx->colocated_buf_poc[i]);
+
+	return i;
+}
+
+static void release_colocate_buf(struct aml_h264_ctx *h264_ctx, int index)
+{
+	if (index >= 0) {
+		if (index >= h264_ctx->colocated_buf_num) {
+			pr_debug
+			    ("%s error, index %d is bigger than buf count %d\n",
+			     __func__, index, h264_ctx->max_num_ref_frames);
+		} else {
+			if (((h264_ctx->colocated_buf_map >> index) & 0x1) == 0x1) {
+				h264_ctx->colocated_buf_map &= (~(1 << index));
+				pr_debug
+				    ("%s colocated_buf_index %d released poc %d\n",
+				     __func__, index,
+				     h264_ctx->colocated_buf_poc[index]);
+			}
+			h264_ctx->colocated_buf_poc[index] = INVALID_POC;
+		}
+	}
+}
+
+static int get_col_buf_index_by_poc(struct aml_h264_ctx *h264_ctx, int poc)
+{
+	int idx;
+
+	for (idx = 0; idx < h264_ctx->colocated_buf_num; idx++) {
+		if (h264_ctx->colocated_buf_poc[idx] == poc)
+			break;
+	}
+
+	if (idx == h264_ctx->colocated_buf_num)
+		idx = -1;
+
+	return idx;
+}
+
+static int alloc_colocate_cma(struct aml_h264_ctx *h264_ctx,
+			      struct aml_vdec_ctx *ctx)
+{
+	int alloc_size = 0;
+	int i;
+	struct aml_vdec_hw *hw;
+
+	if (h264_ctx->collated_cma_vaddr)
+		return 0;
+
+	hw = vdec_get_hw(ctx->dev);
+	if (!hw)
+		return -1;
+
+	/* 96 :col buf size for each mb */
+	h264_ctx->one_col_buf_size = h264_ctx->mb_total * 96;
+	alloc_size = PAGE_ALIGN(h264_ctx->one_col_buf_size *
+			(h264_ctx->max_num_ref_frames + COL_BUFFER_MARGIN));
+	h264_ctx->collated_cma_vaddr = dma_alloc_coherent(hw->dev, alloc_size,
+							  &h264_ctx->collated_cma_addr, GFP_KERNEL);
+	if (!h264_ctx->collated_cma_vaddr)
+		return -ENOMEM;
+
+	pr_debug
+	    ("collated_cma_addr = 0x%llx, one_col_buf_size = %x alloc_size = %x\n",
+	     h264_ctx->collated_cma_addr, h264_ctx->one_col_buf_size,
+	     alloc_size);
+	h264_ctx->collated_cma_addr_end =
+	    h264_ctx->collated_cma_addr + alloc_size;
+	memset(h264_ctx->collated_cma_vaddr, 0, alloc_size);
+	h264_ctx->col_buf_alloc_size = alloc_size;
+	h264_ctx->colocated_buf_map = 0;
+	h264_ctx->colocated_buf_num = h264_ctx->max_num_ref_frames + COL_BUFFER_MARGIN;
+
+	/* 32 : max index of co-locate buffer */
+	for (i = 0; i < 32; i++)
+		h264_ctx->colocated_buf_poc[i] = INVALID_POC;
+
+	return 0;
+}
+
+static void config_p_reflist(struct aml_h264_ctx *h264_ctx,
+			     struct v4l2_h264_reference *v4l2_p0_reflist,
+			     u32 list_size)
+{
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+	struct v4l2_ctrl_h264_decode_params *decode =
+	    (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
+	struct v4l2_h264_dpb_entry *dpb = decode->dpb;
+	u8 index;
+	int i;
+
+	for (i = 0; i < list_size; i++) {
+		index = v4l2_p0_reflist[i].index;
+		h264_ctx->ref_list0[i].used = 1;
+		h264_ctx->ref_list0[i].dpb = &dpb[index];
+		h264_ctx->ref_list0[i].poc = dpb[index].top_field_order_cnt;
+		h264_ctx->ref_list0[i].long_term_flag =
+		    dpb[index].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
+		h264_ctx->ref_list0[i].dpb_index = index;
+	}
+	h264_ctx->list_size[0] = i;
+}
+
+static void config_b_reflist(struct aml_h264_ctx *h264_ctx,
+			     struct v4l2_h264_reference *v4l2_b0_reflist,
+			     struct v4l2_h264_reference *v4l2_b1_reflist,
+			     u32 list_size)
+{
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+	struct v4l2_ctrl_h264_decode_params *decode =
+	    (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
+	struct v4l2_h264_dpb_entry *dpb = decode->dpb;
+	u8 index;
+	int i, j;
+
+	for (i = 0; i < list_size; i++) {
+		index = v4l2_b0_reflist[i].index;
+		if (dpb[index].top_field_order_cnt > decode->top_field_order_cnt) {
+			h264_ctx->list_size[0] = i;
+			break;
+		}
+		h264_ctx->ref_list0[i].used = 1;
+		h264_ctx->ref_list0[i].dpb = &dpb[index];
+		h264_ctx->ref_list0[i].poc = dpb[index].top_field_order_cnt;
+		h264_ctx->ref_list0[i].long_term_flag =
+		    dpb[index].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
+		h264_ctx->ref_list0[i].col_buf_index =
+			get_col_buf_index_by_poc(h264_ctx, dpb[index].top_field_order_cnt);
+		h264_ctx->ref_list0[i].dpb_index = index;
+	}
+
+	for (j = 0; j < list_size; j++) {
+		index = v4l2_b1_reflist[j].index;
+		if (dpb[index].top_field_order_cnt < decode->top_field_order_cnt) {
+			h264_ctx->list_size[1] = j;
+			break;
+		}
+		h264_ctx->ref_list1[j].used = 1;
+		h264_ctx->ref_list1[j].dpb = &dpb[index];
+		h264_ctx->ref_list1[j].poc = dpb[index].top_field_order_cnt;
+		h264_ctx->ref_list1[j].long_term_flag =
+		    dpb[index].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
+		h264_ctx->ref_list1[j].col_buf_index =
+			get_col_buf_index_by_poc(h264_ctx, dpb[index].top_field_order_cnt);
+		h264_ctx->ref_list1[j].dpb_index = index;
+	}
+
+	if ((h264_ctx->list_size[1] + h264_ctx->list_size[0]) < list_size)
+		pr_info("ref list incorrect list0 %d list0 %d list_size%d\n",
+			h264_ctx->list_size[0], h264_ctx->list_size[1], list_size);
+}
+
+static int poc_is_in_dpb(int poc, const struct v4l2_h264_dpb_entry *dpb)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
+		if (poc == dpb[i].top_field_order_cnt) {
+			ret = 1;
+			pr_debug("%s find poc %d col index %x inDPB\n", __func__, poc, i);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int get_ref_list_size(struct aml_h264_ctx *h264_ctx, int cur_list)
+{
+	unsigned short override_flag = h264_ctx->dpb_param.l.data[REF_IDC_OVERRIDE_FLAG];
+	int num_ref_idx_lx_active_minus1;
+
+	if (cur_list == 0) {
+		num_ref_idx_lx_active_minus1 =
+			h264_ctx->ctrl_ref.pps->num_ref_idx_l0_default_active_minus1;
+		if (override_flag)
+			num_ref_idx_lx_active_minus1 =
+				h264_ctx->dpb_param.dpb.num_ref_idx_l0_active_minus1;
+	} else {
+		num_ref_idx_lx_active_minus1 =
+			h264_ctx->ctrl_ref.pps->num_ref_idx_l1_default_active_minus1;
+	}
+	pr_debug("%s get list %d size %d\n", __func__, cur_list, num_ref_idx_lx_active_minus1 + 1);
+
+	return num_ref_idx_lx_active_minus1 + 1;
+}
+
+static int get_refidx_by_picnum(struct aml_h264_ctx *h264_ctx, int pic_num,
+				int curr_list)
+{
+	int i;
+	struct h264_decode_buf_spec *ref_list;
+
+	if (curr_list == 0)
+		ref_list = &h264_ctx->ref_list0[0];
+	else
+		ref_list = &h264_ctx->ref_list1[0];
+
+	for (i = 0; ref_list[i].dpb; i++) {
+		if (pic_num == ref_list[i].dpb->pic_num)
+			return i;
+	}
+
+	return -1;
+}
+
+static struct h264_decode_buf_spec *get_st_refpic_by_num(struct aml_h264_ctx *h264_ctx,
+							 int pic_num, int curr_list)
+{
+	int i;
+	struct h264_decode_buf_spec *ref_list;
+
+	if (curr_list == 0)
+		ref_list = &h264_ctx->ref_list0_unreordered[0];
+	else
+		ref_list = &h264_ctx->ref_list1_unreordered[0];
+
+	for (i = 0; ref_list[i].dpb; i++) {
+		if (pic_num == ref_list[i].dpb->pic_num && ref_list[i].long_term_flag == 0)
+			return &ref_list[i];
+	}
+
+	return NULL;
+}
+
+static struct h264_decode_buf_spec *get_lt_refpic_by_num(struct aml_h264_ctx *h264_ctx,
+							 int pic_num, int curr_list)
+{
+	int i;
+	struct h264_decode_buf_spec *ref_list;
+
+	if (curr_list == 0)
+		ref_list = &h264_ctx->ref_list0_unreordered[0];
+	else
+		ref_list = &h264_ctx->ref_list1_unreordered[0];
+
+	for (i = 0; ref_list[i].dpb; i++) {
+		if (pic_num == ref_list[i].dpb->pic_num && ref_list[i].long_term_flag == 1)
+			return &ref_list[i];
+	}
+
+	return NULL;
+}
+
+static void reorder_short_term(struct slice *curr_slice, int cur_list,
+			       int pic_num_lx, int *ref_idx_lx)
+{
+	struct aml_h264_ctx *h264_ctx = container_of(curr_slice, struct aml_h264_ctx, mslice);
+	int c_idx, n_idx;
+	int num_ref_idx_lx_active;
+	struct h264_decode_buf_spec *pic_lx = NULL;
+	struct h264_decode_buf_spec *ref_list_reordered;
+
+	if (cur_list == 0)
+		ref_list_reordered = &h264_ctx->ref_list0[0];
+	else
+		ref_list_reordered = &h264_ctx->ref_list1[0];
+
+	num_ref_idx_lx_active = get_ref_list_size(h264_ctx, cur_list);
+
+	/* find short-term ref frame with pic_num is pic_num_lx */
+	pic_lx = get_st_refpic_by_num(h264_ctx, pic_num_lx, cur_list);
+	if (!pic_lx) {
+		pr_debug("cannot find st pic_lx for %d\n", pic_num_lx);
+		return;
+	}
+
+	if (*ref_idx_lx == get_refidx_by_picnum(h264_ctx, pic_num_lx, cur_list)) {
+		pr_debug("no need to move pic lx %d\n", *ref_idx_lx);
+		*ref_idx_lx = *ref_idx_lx + 1;
+		return;
+	}
+
+	for (c_idx = num_ref_idx_lx_active; c_idx > *ref_idx_lx; c_idx--)
+		memcpy(&ref_list_reordered[c_idx], &ref_list_reordered[c_idx - 1],
+		       sizeof(struct h264_decode_buf_spec));
+
+	memcpy(&ref_list_reordered[*ref_idx_lx], pic_lx, sizeof(struct h264_decode_buf_spec));
+	pr_debug("%s 1 : RefPicListX[%d ] = pic %p pic_num(%d)\n", __func__,
+		 *ref_idx_lx, pic_lx, ref_list_reordered[*ref_idx_lx].dpb->pic_num);
+	*ref_idx_lx = *ref_idx_lx + 1;
+
+	n_idx = *ref_idx_lx;
+	for (c_idx = *ref_idx_lx; c_idx <= num_ref_idx_lx_active; c_idx++) {
+		if (ref_list_reordered[c_idx].long_term_flag || !ref_list_reordered[c_idx].dpb ||
+		    ref_list_reordered[c_idx].dpb->pic_num != pic_num_lx)
+			memcpy(&ref_list_reordered[n_idx++], &ref_list_reordered[c_idx],
+			       sizeof(struct h264_decode_buf_spec));
+	}
+
+	h264_ctx->list_size[cur_list] = num_ref_idx_lx_active;
+}
+
+static void reorder_long_term(struct slice *curr_slice, int cur_list,
+			      int lt_pic_num, int *ref_idx_lx)
+{
+	struct aml_h264_ctx *h264_ctx = container_of(curr_slice, struct aml_h264_ctx, mslice);
+	int num_ref_idx_lx_active;
+	int c_idx, n_idx;
+	struct h264_decode_buf_spec *ref_list;
+	struct h264_decode_buf_spec *pic_lt = NULL;
+
+	if (cur_list == 0)
+		ref_list = &h264_ctx->ref_list0[0];
+	else
+		ref_list = &h264_ctx->ref_list1[0];
+
+	num_ref_idx_lx_active = get_ref_list_size(h264_ctx, cur_list);
+
+	/* find long-term ref frame with pic_num is lt_pic_num */
+	pic_lt = get_lt_refpic_by_num(h264_ctx, lt_pic_num, cur_list);
+	if (!pic_lt) {
+		pr_debug("cannot find lt pic_lx for %d\n", lt_pic_num);
+		return;
+	}
+
+	if (*ref_idx_lx == get_refidx_by_picnum(h264_ctx, lt_pic_num, cur_list)) {
+		pr_debug("no need to move pic lx %d\n", *ref_idx_lx);
+		*ref_idx_lx = *ref_idx_lx + 1;
+		return;
+	}
+
+	for (c_idx = num_ref_idx_lx_active; c_idx > *ref_idx_lx; c_idx--)
+		memcpy(&ref_list[c_idx], &ref_list[c_idx - 1], sizeof(struct h264_decode_buf_spec));
+
+	memcpy(&ref_list[*ref_idx_lx], pic_lt, sizeof(struct h264_decode_buf_spec));
+	pr_debug("%s 1 : RefPicListX[%d ] = pic %p pic_num(%d)\n", __func__,
+		 *ref_idx_lx, pic_lt, ref_list[*ref_idx_lx].dpb->pic_num);
+	*ref_idx_lx = *ref_idx_lx + 1;
+
+	n_idx = *ref_idx_lx;
+	/* Pointer dpb is NULL means this is a dummy frame store */
+	for (c_idx = *ref_idx_lx; c_idx <= num_ref_idx_lx_active; c_idx++) {
+		if (!ref_list[c_idx].long_term_flag || !ref_list[c_idx].dpb ||
+		    ref_list[c_idx].dpb->pic_num != lt_pic_num)
+			memcpy(&ref_list[n_idx++], &ref_list[c_idx],
+			       sizeof(struct h264_decode_buf_spec));
+	}
+
+	h264_ctx->list_size[cur_list] = num_ref_idx_lx_active;
+}
+
+static void get_modification_cmd(unsigned short *reorder_cmd, struct slice *curr_slice, int list)
+{
+	int i, j, val;
+
+	val = curr_slice->ref_pic_list_reordering_flag[list];
+	if (val) {
+		i = 0;
+		j = 0;
+		do {
+			curr_slice->modification_of_pic_nums_idc[list][i] =
+				reorder_cmd[j++];
+			if (j >= REORDER_CMD_MAX) {
+				curr_slice->modification_of_pic_nums_idc[list][i] = 0;
+				break;
+			}
+
+			val = curr_slice->modification_of_pic_nums_idc[list][i];
+			if (val == 0 || val == 1)
+				curr_slice->abs_diff_pic_num_minus1[list][i] = reorder_cmd[j++];
+			else if (val == 2)
+				curr_slice->long_term_pic_idx[list][i] = reorder_cmd[j++];
+
+			i++;
+
+			if (i >= REORDERING_COMMAND_MAX_SIZE) {
+				curr_slice->ref_pic_list_reordering_flag[list] = 0;
+				break;
+			};
+			if (j > REORDER_CMD_MAX) {
+				curr_slice->ref_pic_list_reordering_flag[list] = 0;
+				break;
+			};
+		} while (val != 3);
+	}
+}
+
+static void reorder_pics(struct aml_h264_ctx *h264_ctx, struct slice *curr_slice, int cur_list)
+{
+	int *modification_of_pic_nums_idc =
+		curr_slice->modification_of_pic_nums_idc[cur_list];
+	int *abs_diff_pic_num_minus1 =
+		curr_slice->abs_diff_pic_num_minus1[cur_list];
+	int *long_term_pic_idx = curr_slice->long_term_pic_idx[cur_list];
+	int pic_num_lx_nowarp, pic_num_lx_pred, pic_num_lx;
+	int curr_pic_num = curr_slice->frame_num;
+	int max_pic_num = 1 << (4 + h264_ctx->ctrl_ref.sps->log2_max_frame_num_minus4);
+	int ref_idx_lx = 0;
+	int nowarp_tmp = 0;
+	int i;
+
+	pic_num_lx_pred = curr_pic_num;
+	for (i = 0; i < REORDERING_COMMAND_MAX_SIZE && modification_of_pic_nums_idc[i] != 3; i++) {
+		if (modification_of_pic_nums_idc[i] > 3) {
+			pr_info("error, Invalid modification_of_pic_nums_idc command\n");
+			break;
+		}
+
+		if (modification_of_pic_nums_idc[i] < 2) {
+			if (modification_of_pic_nums_idc[i] == 0) {
+				nowarp_tmp = pic_num_lx_pred - (abs_diff_pic_num_minus1[i] + 1);
+				pic_num_lx_nowarp = nowarp_tmp + (nowarp_tmp < 0 ? max_pic_num : 0);
+			} else if (modification_of_pic_nums_idc[i] == 1) {
+				nowarp_tmp = pic_num_lx_pred + (abs_diff_pic_num_minus1[i] + 1);
+				pic_num_lx_nowarp = nowarp_tmp -
+					(nowarp_tmp > max_pic_num ? max_pic_num : 0);
+			}
+			pic_num_lx_pred = pic_num_lx_nowarp;
+			if (pic_num_lx_nowarp > curr_pic_num)
+				pic_num_lx = pic_num_lx_nowarp - max_pic_num;
+			else
+				pic_num_lx = pic_num_lx_nowarp;
+
+			reorder_short_term(curr_slice, cur_list, pic_num_lx, &ref_idx_lx);
+		} else {
+			reorder_long_term(curr_slice, cur_list, long_term_pic_idx[i], &ref_idx_lx);
+		}
+	}
+}
+
+static void copy_ref_list(struct aml_h264_ctx *h264_ctx, int curr_list)
+{
+	if (curr_list == 0)
+		memcpy(h264_ctx->ref_list0_unreordered, h264_ctx->ref_list0,
+		       sizeof(h264_ctx->ref_list0));
+	else
+		memcpy(h264_ctx->ref_list1_unreordered, h264_ctx->ref_list0,
+		       sizeof(h264_ctx->ref_list1));
+}
+
+static void h264_reorder_reflists(struct aml_h264_ctx *h264_ctx)
+{
+	unsigned short *reorder_cmd;
+	struct slice *curr_slice = &h264_ctx->mslice;
+
+	memset(curr_slice, 0, sizeof(struct slice));
+	/* parsed by ucode */
+	curr_slice->slice_type = h264_ctx->dpb_param.l.data[SLICE_TYPE];
+	curr_slice->num_ref_idx_l0 = h264_ctx->dpb_param.dpb.num_ref_idx_l0_active_minus1 + 1;
+	curr_slice->num_ref_idx_l1 = h264_ctx->dpb_param.dpb.num_ref_idx_l1_active_minus1 + 1;
+	curr_slice->frame_num = h264_ctx->ctrl_ref.decode->frame_num;
+
+	if (curr_slice->slice_type != I_SLICE && curr_slice->slice_type != SI_SLICE) {
+		reorder_cmd = &h264_ctx->dpb_param.mmco.l0_reorder_cmd[0];
+		/* 3:parsed by ucode, means no reorder needed */
+		if (reorder_cmd[0] != 3)
+			curr_slice->ref_pic_list_reordering_flag[0] = 1;
+		else
+			curr_slice->ref_pic_list_reordering_flag[0] = 0;
+
+		get_modification_cmd(reorder_cmd, curr_slice, 0);
+	}
+
+	if (curr_slice->slice_type == B_SLICE) {
+		reorder_cmd = &h264_ctx->dpb_param.mmco.l1_reorder_cmd[0];
+		/* 3:parsed by ucode, means no reorder needed */
+		if (reorder_cmd[0] != 3)
+			curr_slice->ref_pic_list_reordering_flag[1] = 1;
+		else
+			curr_slice->ref_pic_list_reordering_flag[1] = 0;
+
+		get_modification_cmd(reorder_cmd, curr_slice, 1);
+	}
+
+	if (curr_slice->slice_type != I_SLICE &&
+	    curr_slice->slice_type != SI_SLICE &&
+	    curr_slice->ref_pic_list_reordering_flag[0] != 0) {
+		copy_ref_list(h264_ctx, 0);
+		reorder_pics(h264_ctx, curr_slice, 0);
+	}
+
+	if (curr_slice->slice_type == B_SLICE && curr_slice->ref_pic_list_reordering_flag[1] != 0) {
+		copy_ref_list(h264_ctx, 1);
+		reorder_pics(h264_ctx, curr_slice, 1);
+	}
+}
+
+static void h264_config_ref_lists(struct aml_vdec_ctx *ctx)
+{
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+	struct v4l2_ctrl_h264_decode_params *decode =
+		(struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
+	struct v4l2_ctrl_h264_sps *sps = (struct v4l2_ctrl_h264_sps *)ctrls->sps;
+	const struct v4l2_h264_dpb_entry *dpb = decode->dpb;
+	struct v4l2_h264_reflist_builder builder;
+	struct v4l2_h264_reference v4l2_p0_reflist[V4L2_H264_REF_LIST_LEN];
+	struct v4l2_h264_reference v4l2_b0_reflist[V4L2_H264_REF_LIST_LEN];
+	struct v4l2_h264_reference v4l2_b1_reflist[V4L2_H264_REF_LIST_LEN];
+
+	if (decode->flags == V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC)
+		return;
+
+	v4l2_h264_init_reflist_builder(&builder, decode, sps, dpb);
+	pr_debug("%s num_valid = %d", __func__, builder.num_valid);
+
+	if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_PFRAME) {
+		v4l2_h264_build_p_ref_list(&builder, v4l2_p0_reflist);
+		config_p_reflist(h264_ctx, v4l2_p0_reflist, builder.num_valid);
+	} else if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BFRAME) {
+		v4l2_h264_build_b_ref_lists(&builder, v4l2_b0_reflist, v4l2_b1_reflist);
+		config_b_reflist(h264_ctx, v4l2_b0_reflist, v4l2_b1_reflist, builder.num_valid);
+	}
+}
+
+static void clear_unused_col_buf(struct aml_h264_ctx *h264_ctx,
+				 struct v4l2_ctrl_h264_decode_params *decode)
+{
+	int i, col_poc;
+
+	/* flush all col buffers when IDR */
+	if (decode->flags == V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) {
+		/* 32 : max index of co-locate buffer */
+		for (i = 0; i < 32; i++)
+			release_colocate_buf(h264_ctx, i);
+		return;
+	}
+
+	for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
+		col_poc = h264_ctx->colocated_buf_poc[i];
+		if (col_poc != INVALID_POC && (poc_is_in_dpb(col_poc, decode->dpb) != 1))
+			release_colocate_buf(h264_ctx, i);
+	}
+}
+
+static void h264_config_decode_spec(struct aml_vdec_hw *hw, struct aml_vdec_ctx *ctx)
+{
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)hw->curr_ctx;
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+	struct v4l2_ctrl_h264_decode_params *decode =
+		(struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
+	struct h264_decode_buf_spec *buf_spec;
+	struct vb2_buffer *vb;
+	struct vb2_v4l2_buffer *vb2_v4l2;
+	struct vb2_queue *vq;
+	int i;
+
+	clear_unused_col_buf(h264_ctx, decode);
+
+	vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+	vb = &vb2_v4l2->vb2_buf;
+
+	h264_ctx->curr_spec.y_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+	if (ctx->pic_info.plane_num > 1)
+		h264_ctx->curr_spec.c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
+	else
+		h264_ctx->curr_spec.c_dma_addr =
+				h264_ctx->curr_spec.y_dma_addr + ctx->pic_info.fb_size[0];
+	h264_ctx->curr_spec.canvas_pos = 0;
+	h264_ctx->curr_spec.col_buf_index =
+		allocate_colocate_buf(h264_ctx, decode->top_field_order_cnt);
+	h264_ctx->curr_spec.poc = decode->top_field_order_cnt;
+	config_decode_canvas(hw, &h264_ctx->curr_spec, h264_ctx->mb_width, h264_ctx->mb_height);
+
+	h264_config_ref_lists(ctx);
+
+	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+	for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
+		struct v4l2_h264_dpb_entry *dpb = &decode->dpb[i];
+
+		if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
+			continue;
+
+		buf_spec = find_spec_by_dpb_index(h264_ctx, i);
+		if (buf_spec) {
+			buf_spec->canvas_pos = i + 1;
+			vb = vb2_find_buffer(vq, dpb->reference_ts);
+			if (!vb) {
+				pr_err("ref pic for ts %llu lost\n", dpb->reference_ts);
+				continue;
+			}
+
+			buf_spec->y_dma_addr =
+				vb2_dma_contig_plane_dma_addr(vb, 0);
+			if (ctx->pic_info.plane_num > 1)
+				buf_spec->c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
+			else
+				buf_spec->c_dma_addr =
+					buf_spec->y_dma_addr + ctx->pic_info.fb_size[0];
+			config_decode_canvas(hw, buf_spec, h264_ctx->mb_width, h264_ctx->mb_height);
+			pr_debug
+			    ("config canvas for poc %d canvas %d y_dma_addr 0x%llx\n",
+			     buf_spec->dpb->top_field_order_cnt,
+			     buf_spec->canvas_pos, buf_spec->y_dma_addr);
+		}
+	}
+
+	h264_reorder_reflists(h264_ctx);
+}
+
+static int h264_config_decode_buf(struct aml_vdec_hw *hw, struct aml_vdec_ctx *ctx)
+{
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)hw->curr_ctx;
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+	struct v4l2_ctrl_h264_decode_params *decode =
+		(struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
+	unsigned long canvas_adr;
+	unsigned int ref_cfg;
+	unsigned int ref_cfg_once = 0;
+	unsigned int type_cfg = 0x3; /* 0x3: frame type */
+	unsigned int colocate_adr_offset, colocate_wr_adr;
+	unsigned int info0;
+	unsigned int info1;
+	unsigned int info2;
+	int i, j;
+	int h264_buffer_info_data_write_count;
+	u8 canvas_pos;
+	u8 use_mode_8x8_flag;
+
+	WRITE_VREG(H264_CURRENT_POC_IDX_RESET, 0);
+	WRITE_VREG(H264_CURRENT_POC, decode->top_field_order_cnt);
+	WRITE_VREG(H264_CURRENT_POC, decode->top_field_order_cnt);
+	WRITE_VREG(H264_CURRENT_POC, decode->bottom_field_order_cnt);
+	WRITE_VREG(CURR_CANVAS_CTRL, h264_ctx->curr_spec.canvas_pos << 24);
+	canvas_adr = RD_VREG(CURR_CANVAS_CTRL) & 0xffffff;
+	pr_debug("canvas_pos = %d canvas_adr 0x%lx\n", h264_ctx->curr_spec.canvas_pos, canvas_adr);
+
+	WRITE_VREG(REC_CANVAS_ADDR, canvas_adr);
+	WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr);
+	WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr);
+
+	WRITE_VREG(H264_BUFFER_INFO_INDEX, 16);
+	info0 = 0xf480;
+	info1 = decode->top_field_order_cnt;
+	info2 = decode->bottom_field_order_cnt;
+	if (decode->bottom_field_order_cnt < decode->top_field_order_cnt)
+		info0 |= 0x100;
+
+	WRITE_VREG(H264_BUFFER_INFO_DATA, info0 | 0xf);
+	WRITE_VREG(H264_BUFFER_INFO_DATA, info1);
+	WRITE_VREG(H264_BUFFER_INFO_DATA, info2);
+
+	for (j = 0; j < V4L2_H264_NUM_DPB_ENTRIES; j++) {
+		struct v4l2_h264_dpb_entry *dpb = &decode->dpb[j];
+
+		info0 = 0;
+		info1 = 0;
+		info2 = 0;
+		if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
+			info0 = 0xf480;
+			if (decode->bottom_field_order_cnt < decode->top_field_order_cnt)
+				info0 |= 0x100;
+			info1 = dpb->top_field_order_cnt;
+			info2 = dpb->bottom_field_order_cnt;
+			if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
+				info0 |= ((1 << 5) | (1 << 4));
+		}
+		WRITE_VREG(H264_BUFFER_INFO_DATA, info0);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, info1);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, info2);
+	}
+
+	WRITE_VREG(H264_BUFFER_INFO_INDEX, 0);
+	/* when frame width <= 256, Disable DDR_BYTE64_CACHE */
+	if (ctx->pic_info.coded_width <= 256) {
+		SET_VREG_MASK(IQIDCT_CONTROL, (1 << 16));
+		WRITE_VREG(DCAC_DDR_BYTE64_CTL,
+			   (RD_VREG(DCAC_DDR_BYTE64_CTL) & (~0xf)) | 0xa);
+	} else {
+		CLEAR_VREG_MASK(IQIDCT_CONTROL, (1 << 16));
+	}
+
+	ref_cfg = 0;
+	j = 0;
+
+	if (h264_ctx->list_size[0] > 0) {
+		for (i = 0; i < h264_ctx->list_size[0]; i++) {
+			canvas_pos = h264_ctx->ref_list0[i].canvas_pos;
+			/* bit 0:3 canvas_pos bit 5:6 frame struct cfg */
+			ref_cfg_once = (canvas_pos & 0x1f) | (type_cfg << 5);
+			ref_cfg <<= 8;
+			ref_cfg |= ref_cfg_once;
+			j++;
+
+			if (j == 4) {
+				WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
+				pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
+				h264_buffer_info_data_write_count++;
+				j = 0;
+			}
+		}
+
+		if (j != 0) {
+			while (j != 4) {
+				ref_cfg <<= 8;
+				ref_cfg |= ref_cfg_once;
+				j++;
+			}
+			WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
+			pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
+			h264_buffer_info_data_write_count++;
+		}
+		ref_cfg = (ref_cfg_once << 24) | (ref_cfg_once << 16) |
+			(ref_cfg_once << 8) | ref_cfg_once;
+		for (j = h264_buffer_info_data_write_count; j < 8; j++)
+			WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
+	}
+
+	WRITE_VREG(H264_BUFFER_INFO_INDEX, 8);
+	j = 0;
+	ref_cfg = 0;
+
+	if (h264_ctx->list_size[1] > 0) {
+		for (i = 0; i < h264_ctx->list_size[1]; i++) {
+			canvas_pos = h264_ctx->ref_list1[i].canvas_pos;
+			ref_cfg_once = (canvas_pos & 0x1f) | (type_cfg << 5);
+			ref_cfg <<= 8;
+			ref_cfg |= ref_cfg_once;
+			j++;
+
+			if (j == 4) {
+				WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
+				pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
+				j = 0;
+			}
+		}
+	}
+
+	if (j != 0) {
+		while (j != 4) {
+			ref_cfg <<= 8;
+			ref_cfg |= ref_cfg_once;
+			j++;
+		}
+		pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
+		WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
+	}
+
+	if (get_flag(ctrls->sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
+	    get_flag(ctrls->sps->flags, V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
+		use_mode_8x8_flag = 1;
+	else
+		use_mode_8x8_flag = 0;
+
+	while ((RD_VREG(H264_CO_MB_RW_CTL) >> 11) & 0x1)
+		continue;
+
+	/* col buf for curr frame */
+	colocate_adr_offset = 0;
+	if (h264_ctx->curr_spec.col_buf_index >= 0 &&
+	    h264_ctx->curr_spec.col_buf_index < h264_ctx->colocated_buf_num) {
+		colocate_wr_adr = h264_ctx->collated_cma_addr +
+			((h264_ctx->one_col_buf_size * h264_ctx->curr_spec.col_buf_index) >>
+			(use_mode_8x8_flag ? 2 : 0));
+		if (colocate_wr_adr + h264_ctx->one_col_buf_size >
+		    h264_ctx->collated_cma_addr_end) {
+			pr_err
+			    ("Error, colocate buf is not enough, index is %d\n",
+			     h264_ctx->curr_spec.col_buf_index);
+			return -1;
+		}
+		WRITE_VREG(H264_CO_MB_WR_ADDR,
+			   (colocate_wr_adr + colocate_adr_offset));
+		pr_debug("col buffer addr = 0x%x col_buf_index %d\n",
+			 (colocate_wr_adr + colocate_adr_offset),
+			 h264_ctx->curr_spec.col_buf_index);
+	} else {
+		WRITE_VREG(H264_CO_MB_WR_ADDR, 0xffffffff);
+		pr_debug("col buffer addr = 0xffffffff\n");
+	}
+
+	if (h264_ctx->list_size[1] > 0) {
+		struct h264_decode_buf_spec *colocate_pic = &h264_ctx->ref_list1[0];
+		struct h264_decode_buf_spec *curr_pic = &h264_ctx->curr_spec;
+		int l10_structure = 2; /* for pic struct == FRAME, default to 2 */
+		int cur_colocate_ref_type;
+		unsigned int colocate_rd_adr;
+		unsigned int colocate_rd_adr_offset = 0;
+		unsigned int val;
+
+		cur_colocate_ref_type =
+			(abs(curr_pic->poc - colocate_pic->dpb->top_field_order_cnt) <
+			abs(curr_pic->poc - colocate_pic->dpb->bottom_field_order_cnt)) ?
+			0 : 1;
+
+		if (colocate_pic->col_buf_index >= 0 &&
+		    colocate_pic->col_buf_index < h264_ctx->colocated_buf_num) {
+			colocate_rd_adr = h264_ctx->collated_cma_addr +
+				((h264_ctx->one_col_buf_size * colocate_pic->col_buf_index) >>
+				(use_mode_8x8_flag ? 2 : 0));
+			if (colocate_rd_adr + h264_ctx->one_col_buf_size >
+			    h264_ctx->collated_cma_addr_end) {
+				pr_err
+				    ("Error, colocate rd buf is not enough, index is %d\n",
+				     colocate_pic->col_buf_index);
+				return -1;
+			}
+			val  = ((colocate_rd_adr_offset + colocate_rd_adr) >> 3) |
+				(cur_colocate_ref_type << 29) |
+				(l10_structure << 30);
+			WRITE_VREG(H264_CO_MB_RD_ADDR, val);
+		} else {
+			pr_err
+			    ("Error, reference pic has no colocated buf poc %d\n",
+			     curr_pic->poc);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static void h264_release_decode_spec(struct aml_vdec_hw *hw, struct aml_vdec_ctx *ctx)
+{
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)hw->curr_ctx;
+	int i;
+	struct h264_decode_buf_spec *buf;
+
+	hw->hw_ops.canvas_free(h264_ctx->curr_spec.y_canvas_index);
+	hw->hw_ops.canvas_free(h264_ctx->curr_spec.v_canvas_index);
+
+	if (h264_ctx->list_size[0] > 0) {
+		for (i = 0; i < h264_ctx->list_size[0]; i++) {
+			buf = &h264_ctx->ref_list0[i];
+			if (buf->used) {
+				buf->canvas_pos = 0;
+				buf->dpb = NULL;
+				hw->hw_ops.canvas_free(buf->y_canvas_index);
+				hw->hw_ops.canvas_free(buf->u_canvas_index);
+				buf->used = 0;
+			}
+		}
+		h264_ctx->list_size[0] = 0;
+	}
+
+	if (h264_ctx->list_size[1] > 0) {
+		for (i = 0; i < h264_ctx->list_size[1]; i++) {
+			buf = &h264_ctx->ref_list1[i];
+			if (buf->used) {
+				buf->canvas_pos = 0;
+				buf->dpb = NULL;
+				hw->hw_ops.canvas_free(buf->y_canvas_index);
+				hw->hw_ops.canvas_free(buf->u_canvas_index);
+				buf->used = 0;
+			}
+		}
+		h264_ctx->list_size[1] = 0;
+	}
+}
+
+static void save_reg_status(struct aml_h264_ctx *h264_ctx)
+{
+	h264_ctx->reg_iqidct_control = RD_VREG(IQIDCT_CONTROL);
+	h264_ctx->reg_iqidct_control_init_flag = 1;
+	h264_ctx->reg_vcop_ctrl_reg = RD_VREG(VCOP_CTRL_REG);
+	h264_ctx->reg_rv_ai_mb_count = RD_VREG(RV_AI_MB_COUNT);
+	h264_ctx->vld_dec_control = RD_VREG(VLD_DECODE_CONTROL);
+}
+
+static irqreturn_t h264_isr(int irq, void *priv)
+{
+	WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t h264_threaded_isr_func(int irq, void *priv)
+{
+	int dec_status = RD_VREG(DPB_STATUS_REG);
+	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)dev->dec_hw->curr_ctx;
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)dev->dec_ctx;
+	struct aml_vdec_hw *hw = (struct aml_vdec_hw *)dev->dec_hw;
+	unsigned short *p = (unsigned short *)h264_ctx->lmem_addr;
+	int i, ii;
+
+	h264_ctx->dec_status = dec_status;
+	pr_debug
+	    ("%s, dec_status 0x%x VIFF_BIT_CNT 0x%x MBY_MBX 0x%x VLD_SHIFT_STATUS 0x%x\n",
+	     __func__, dec_status, RD_VREG(VIFF_BIT_CNT), RD_VREG(MBY_MBX),
+	     RD_VREG(VLD_SHIFT_STATUS));
+
+	h264_ctx->save_avscratch_f = RD_VREG(AV_SCRATCH_F);
+
+	switch (dec_status) {
+	case H264_SLICE_HEADER_DONE:
+		for (i = 0; i < 0x400; i += 4)
+			for (ii = 0; ii < 4; ii++)
+				h264_ctx->dpb_param.l.data[i + ii] = p[i + 3 - ii];
+		save_reg_status(h264_ctx);
+		if (h264_ctx->new_pic_flag == 1)
+			h264_config_decode_spec(hw, ctx);
+
+		if (h264_config_decode_buf(hw, ctx) < 0) {
+			h264_release_decode_spec(hw, ctx);
+			ctx->int_cond = 1;
+			wake_up_interruptible(&ctx->queue);
+			goto irq_handled;
+		}
+		if (h264_ctx->new_pic_flag == 1) {
+			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_NEWPIC);
+			pr_debug("action decode new pic\n");
+			h264_ctx->new_pic_flag = 0;
+		} else {
+			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_SLICE);
+			pr_debug("action decode new slice\n");
+		}
+		break;
+	case H264_SLICE_DATA_DONE:
+		h264_release_decode_spec(hw, ctx);
+		h264_ctx->decode_pic_count++;
+		ctx->int_cond = 1;
+		wake_up_interruptible(&ctx->queue);
+		break;
+	default:
+		h264_release_decode_spec(hw, ctx);
+		ctx->int_cond = 1;
+		wake_up_interruptible(&ctx->queue);
+		break;
+	}
+irq_handled:
+	return IRQ_HANDLED;
+}
+
+static int h264_restore_hw_ctx(struct aml_vdec_ctx *ctx)
+{
+	struct aml_h264_ctx *h264_ctx =
+		(struct aml_h264_ctx *)ctx->codec_priv;
+
+	WRITE_VREG(POWER_CTL_VLD,
+		   (RD_VREG(POWER_CTL_VLD) | (0 << 10) | (1 << 9) | (1 << 6)));
+
+	WRITE_VREG(PSCALE_CTRL, 0);
+
+	/* clear mailbox interrupt */
+	WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
+
+	/* enable mailbox interrupt */
+	WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 1);
+
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 17));
+	if (ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21 ||
+	    ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)
+		SET_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 16));
+	else
+		CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 16));
+
+	SET_VREG_MASK(MDEC_PIC_DC_CTRL, (0xbf << 24));
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (0xbf << 24));
+	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 31));
+
+	CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
+	WRITE_VREG(MDEC_EXTIF_CFG1, 0);
+	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
+
+	WRITE_VREG(DPB_STATUS_REG, 0);
+
+	WRITE_VREG(LMEM_DUMP_ADR, h264_ctx->lmem_phy_addr);
+	WRITE_VREG(FRAME_COUNTER_REG, h264_ctx->decode_pic_count);
+	WRITE_VREG(AV_SCRATCH_8, h264_ctx->workspace_offset);
+	WRITE_VREG(AV_SCRATCH_G, h264_ctx->mc_cpu_paddr);
+
+	WRITE_VREG(AV_SCRATCH_F, ((h264_ctx->save_avscratch_f & 0xffffffc3) | (1 << 4)));
+	CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6);
+
+	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
+
+	if (h264_ctx->reg_iqidct_control_init_flag == 0)
+		WRITE_VREG(IQIDCT_CONTROL, 0x200);
+
+	if (h264_ctx->reg_iqidct_control)
+		WRITE_VREG(IQIDCT_CONTROL, h264_ctx->reg_iqidct_control);
+
+	if (h264_ctx->reg_vcop_ctrl_reg)
+		WRITE_VREG(VCOP_CTRL_REG, h264_ctx->reg_vcop_ctrl_reg);
+
+	if (h264_ctx->vld_dec_control)
+		WRITE_VREG(VLD_DECODE_CONTROL, h264_ctx->vld_dec_control);
+
+	pr_debug
+	    ("IQIDCT_CONTROL = 0x%x, VCOP_CTRL_REG 0x%x VLD_DECODE_CONTROL 0x%x\n",
+	     RD_VREG(IQIDCT_CONTROL), RD_VREG(VCOP_CTRL_REG),
+	     RD_VREG(VLD_DECODE_CONTROL));
+
+	return 0;
+}
+
+static void *aml_h264_get_ctrl(struct v4l2_ctrl_handler *hdl, u32 id)
+{
+	struct v4l2_ctrl *ctrl;
+
+	ctrl = v4l2_ctrl_find(hdl, id);
+	return ctrl ? ctrl->p_cur.p : NULL;
+}
+
+static int aml_h264_get_stateless_ctrl_ref(struct aml_h264_ctx *h264_ctx)
+{
+	struct aml_vdec_ctx *ctx = h264_ctx->v4l2_ctx;
+	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
+
+	ctrls->sps =
+		(struct v4l2_ctrl_h264_sps *)aml_h264_get_ctrl(&ctx->ctrl_handler,
+			V4L2_CID_STATELESS_H264_SPS);
+	if (WARN_ON(!ctrls->sps))
+		return -EINVAL;
+
+	ctrls->pps =
+		(struct v4l2_ctrl_h264_pps *)aml_h264_get_ctrl(&ctx->ctrl_handler,
+			V4L2_CID_STATELESS_H264_PPS);
+	if (WARN_ON(!ctrls->pps))
+		return -EINVAL;
+
+	ctrls->decode =
+		(struct v4l2_ctrl_h264_decode_params *)aml_h264_get_ctrl(&ctx->ctrl_handler,
+			V4L2_CID_STATELESS_H264_DECODE_PARAMS);
+	if (WARN_ON(!ctrls->decode))
+		return -EINVAL;
+
+	ctrls->scaling =
+		(struct v4l2_ctrl_h264_scaling_matrix *)aml_h264_get_ctrl(&ctx->ctrl_handler,
+			V4L2_CID_STATELESS_H264_SCALING_MATRIX);
+	if (WARN_ON(!ctrls->scaling))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void copy_mc_cpu_fw(void *mc_cpu_addr, const u8 *data)
+{
+	/*header */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_HEADER,
+	       data + 0x4000, MC_SWAP_SIZE);
+	/*data */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_DATA,
+	       data + 0x2000, MC_SWAP_SIZE);
+	/*mmco */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MMCO,
+	       data + 0x6000, MC_SWAP_SIZE);
+	/*list */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_LIST,
+	       data + 0x3000, MC_SWAP_SIZE);
+	/*slice */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_SLICE,
+	       data + 0x5000, MC_SWAP_SIZE);
+	/*main */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN, data, 0x2000);
+	/*data */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN + 0x2000,
+	       data + 0x2000, 0x1000);
+	/*slice */
+	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN + 0x3000,
+	       data + 0x5000, 0x1000);
+}
+
+static int aml_h264_load_fw_ext(void *priv, const u8 *data, u32 len)
+{
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)priv;
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)h264_ctx->v4l2_ctx;
+	struct aml_vdec_hw *dec_hw;
+
+	if (h264_ctx->mc_cpu_loaded)
+		return 0;
+
+	dec_hw = vdec_get_hw(ctx->dev);
+	if (!dec_hw)
+		return -1;
+
+	if (len > MC_TOTAL_SIZE) {
+		pr_info("size of mc_cpu_fw id invalid\n");
+		return -1;
+	}
+
+	h264_ctx->mc_cpu_vaddr = dma_alloc_coherent(dec_hw->dev, MC_TOTAL_SIZE,
+						    &h264_ctx->mc_cpu_paddr,
+						    GFP_KERNEL);
+	if (!h264_ctx->mc_cpu_vaddr)
+		return -ENOMEM;
+
+	copy_mc_cpu_fw(h264_ctx->mc_cpu_vaddr, data);
+
+	h264_ctx->mc_cpu_loaded = true;
+
+	pr_debug("h264 mccpu fw loaded\n");
+
+	return 0;
+}
+
+int aml_h264_init(void *priv)
+{
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
+	struct aml_vdec_hw *dec_hw;
+	struct aml_h264_ctx *h264_ctx;
+	int ret = 0;
+
+	h264_ctx = kzalloc(sizeof(*h264_ctx), GFP_KERNEL);
+	if (!h264_ctx)
+		return -ENOMEM;
+
+	h264_ctx->v4l2_ctx = ctx;
+	dec_hw = vdec_get_hw(ctx->dev);
+	if (!dec_hw)
+		return -1;
+
+	h264_ctx->mc_cpu_loaded = false;
+	dec_hw->hw_ops.irq_handler = h264_isr;
+	dec_hw->hw_ops.irq_threaded_func = h264_threaded_isr_func;
+	dec_hw->hw_ops.load_firmware_ex = aml_h264_load_fw_ext;
+
+	h264_ctx->lmem_addr = dma_alloc_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
+						 &h264_ctx->lmem_phy_addr,
+						 GFP_KERNEL);
+	if (!h264_ctx->lmem_addr) {
+		ret = -ENOMEM;
+		goto err_alloc_lmem;
+	}
+
+	h264_ctx->cma_alloc_vaddr =
+	    dma_alloc_coherent(dec_hw->dev, V_BUF_ADDR_OFFSET,
+			       &h264_ctx->cma_alloc_addr, GFP_KERNEL);
+	if (!h264_ctx->cma_alloc_vaddr) {
+		ret = -ENOMEM;
+		goto err_alloc_workspace;
+	}
+
+	h264_ctx->workspace_offset = h264_ctx->cma_alloc_addr + DCAC_READ_MARGIN;
+	h264_ctx->workspace_vaddr = h264_ctx->cma_alloc_vaddr + DCAC_READ_MARGIN;
+
+	ctx->codec_priv = h264_ctx;
+	dec_hw->curr_ctx = h264_ctx;
+	h264_ctx->col_buf_alloc_size = 0;
+	h264_ctx->init_flag = 0;
+	h264_ctx->new_pic_flag = 0;
+	h264_ctx->param_set = 0;
+	h264_ctx->reg_iqidct_control_init_flag = 0;
+	h264_ctx->decode_pic_count = 0;
+
+	return 0;
+
+err_alloc_workspace:
+	dma_free_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
+			  h264_ctx->lmem_addr, h264_ctx->lmem_phy_addr);
+err_alloc_lmem:
+	kfree(h264_ctx);
+
+	return ret;
+}
+
+void aml_h264_exit(void *priv)
+{
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
+	struct aml_vdec_hw *dec_hw;
+
+	if (!h264_ctx) {
+		pr_info("h264 decoder is already destroyed or not created!\n");
+		return;
+	}
+	dec_hw = vdec_get_hw(ctx->dev);
+	h264_ctx->param_set = 0;
+
+	if (ctx->dos_clk_en)
+		aml_stop_vdec_hw();
+
+	if (h264_ctx->collated_cma_vaddr) {
+		dma_free_coherent(dec_hw->dev, h264_ctx->col_buf_alloc_size,
+				  h264_ctx->collated_cma_vaddr,
+				  h264_ctx->collated_cma_addr);
+		h264_ctx->col_buf_alloc_size = 0;
+	}
+
+	if (h264_ctx->mc_cpu_vaddr) {
+		dma_free_coherent(dec_hw->dev, MC_TOTAL_SIZE,
+				  h264_ctx->mc_cpu_vaddr,
+				  h264_ctx->mc_cpu_paddr);
+		h264_ctx->mc_cpu_loaded = false;
+	}
+
+	if (h264_ctx->lmem_addr)
+		dma_free_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
+				  h264_ctx->lmem_addr, h264_ctx->lmem_phy_addr);
+
+	if (h264_ctx->cma_alloc_vaddr)
+		dma_free_coherent(dec_hw->dev, V_BUF_ADDR_OFFSET,
+				  h264_ctx->cma_alloc_vaddr,
+				  h264_ctx->cma_alloc_addr);
+
+	kfree(ctx->codec_priv);
+	dec_hw->curr_ctx = NULL;
+	ctx->codec_priv = NULL;
+}
+
+static void config_decode_mode(struct aml_h264_ctx *h264_ctx)
+{
+	WRITE_VREG(H264_DECODE_MODE, 0x1);  /*decode mode framebase*/
+	WRITE_VREG(HEAD_PADDING_REG, 0);
+	WRITE_VREG(H264_DECODE_SEQINFO, h264_ctx->seq_info);
+	WRITE_VREG(INIT_FLAG_REG, 1);
+}
+
+int aml_h264_dec_run(void *priv)
+{
+	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
+	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
+	int ret = -1;
+	int i;
+
+	ret = aml_h264_get_stateless_ctrl_ref(h264_ctx);
+	if (ret < 0) {
+		pr_err("not ctrl ref for h264 decoder\n");
+		return ret;
+	}
+
+	h264_config_params(ctx);
+
+	if (h264_prepare_input(ctx) < 0)
+		return ret;
+
+	if (alloc_colocate_cma(h264_ctx, ctx) < 0)
+		return ret;
+
+	h264_restore_hw_ctx(ctx);
+
+	config_decode_mode(h264_ctx);
+	/* enable stream input hardware */
+	SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1 << 2) | (1 << 1));
+	/* enable hardware timer */
+	WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) | (1 << 16));
+	WRITE_VREG(MDEC_EXTIF_CFG2, RD_VREG(MDEC_EXTIF_CFG2) | 0x20);
+	WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) & (~0x2));
+	CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
+
+	aml_start_vdec_hw();
+	h264_ctx->init_flag = 1;
+	h264_ctx->new_pic_flag = 1;
+
+	WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD);
+
+	ret = wait_event_interruptible_timeout(ctx->queue, ctx->int_cond,
+					       msecs_to_jiffies(DECODER_TIMEOUT_MS));
+	ctx->int_cond = 0;
+	if (!ret) {
+		ret = -1;
+		pr_err("dec timeout=%u\n", DECODER_TIMEOUT_MS);
+		for (i = 0; i < 16; i++) {	/* 16 : show ucode PC 16 times when timeout */
+			pr_info("decoder timeout, pc 0x%x\n", RD_VREG(MPC_E));
+			usleep_range(10, 20);
+		}
+	} else if (-ERESTARTSYS == ret) {
+		ret = -1;
+		pr_err("dec inter fail\n");
+	}
+
+	aml_stop_vdec_hw();
+	h264_ctx->init_flag = 0;
+
+	return ret;
+}
diff --git a/drivers/media/platform/amlogic/vdec/h264.h b/drivers/media/platform/amlogic/vdec/h264.h
new file mode 100644
index 000000000000..3d3a35a641c9
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/h264.h
@@ -0,0 +1,300 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+#ifndef _H264_H_
+#define _H264_H_
+
+#define RPM_BEGIN           0x0
+#define FRAME_IN_DPB        24
+#define RPM_END             0x400
+#define DPB_OFFSET          0x100
+#define MMCO_OFFSET         0x200
+#define SPS_OFFSET          0x100
+#define PPS_OFFSET          0x300
+#define PARAM_BASE_VAL      0x414d
+#define MEM_MMCO_BASE       0x01c3000
+#define MEM_SPS_BASE        0x01c3c00
+#define MEM_PPS_BASE        0x01cbc00
+#define MC_TOTAL_SIZE       ((20 + 16) * SZ_1K)
+#define MC_SWAP_SIZE        (4 * SZ_1K)
+#define LMEM_DUMP_SIZE      4096
+#define V_BUF_ADDR_OFFSET   (0x200000 + 0x8000 + 0x20000 + 0x1000)
+#define DCAC_READ_MARGIN    (64 * 1024)
+#define MC_OFFSET_HEADER    0x0000
+#define MC_OFFSET_DATA      0x1000
+#define MC_OFFSET_MMCO      0x2000
+#define MC_OFFSET_LIST      0x3000
+#define MC_OFFSET_SLICE     0x4000
+#define MC_OFFSET_MAIN      0x5000
+
+/* Rename the dos regs */
+#define H264_DECODE_INFO    M4_CONTROL_REG
+#define INIT_FLAG_REG       AV_SCRATCH_2
+#define HEAD_PADDING_REG     AV_SCRATCH_3
+#define UCODE_WATCHDOG_REG   AV_SCRATCH_7
+#define LMEM_DUMP_ADR       AV_SCRATCH_L
+#define DEBUG_REG1          AV_SCRATCH_M
+#define DEBUG_REG2          AV_SCRATCH_N
+#define FRAME_COUNTER_REG       AV_SCRATCH_I
+#define RPM_CMD_REG          AV_SCRATCH_A
+#define H264_DECODE_SIZE    AV_SCRATCH_E
+#define H264_DECODE_MODE    AV_SCRATCH_4
+#define H264_DECODE_SEQINFO    AV_SCRATCH_5
+/**
+ * NAL_SEARCH_CTL: bit 0, enable itu_t35
+ * NAL_SEARCH_CTL: bit 1, enable mmu
+ * NAL_SEARCH_CTL: bit 2, detect frame_mbs_only_flag whether switch resolution
+ * NAL_SEARCH_CTL: bit 3, recover the correct sps pps
+ * NAL_SEARCH_CTL: bit 7-14,level_idc
+ * NAL_SEARCH_CTL: bit 15,bitstream_restriction_flag
+ */
+#define NAL_SEARCH_CTL      AV_SCRATCH_9
+#define DPB_STATUS_REG      AV_SCRATCH_J
+#define ERROR_STATUS_REG    AV_SCRATCH_9
+
+#define H264_BUFFER_INFO_INDEX      PMV3_X	/* 0xc24 */
+#define H264_BUFFER_INFO_DATA       PMV2_X	/* 0xc22 */
+#define H264_CURRENT_POC_IDX_RESET  LAST_SLICE_MV_ADDR	/* 0xc30 */
+#define H264_CURRENT_POC            LAST_MVY	/* 0xc32 shared with conceal MV */
+#define H264_CO_MB_WR_ADDR          VLD_C38
+#define H264_CO_MB_RD_ADDR          VLD_C39
+#define H264_CO_MB_RW_CTL           VLD_C3D
+#define MBY_MBX                     MB_MOTION_MODE
+
+#define H264_ACTION_SEARCH_HEAD     0xf0
+#define H264_ACTION_DECODE_SLICE    0xf1
+#define H264_ACTION_CONFIG_DONE     0xf2
+#define H264_ACTION_DECODE_NEWPIC   0xf3
+#define H264_ACTION_DECODE_START    0xff
+
+/* RPM memory definition */
+#define FIXED_FRAME_RATE_FLAG						0X21
+#define OFFSET_DELIMITER_LO						0x2f
+#define OFFSET_DELIMITER_HI						0x30
+#define REF_IDC_OVERRIDE_FLAG						0x35
+#define SLICE_IPONLY_BREAK						0X5C
+#define PREV_MAX_REFERENCE_FRAME_NUM					0X5D
+#define EOS								0X5E
+#define FRAME_PACKING_TYPE						0X5F
+#define OLD_POC_PAR_1							0X60
+#define OLD_POC_PAR_2							0X61
+#define PREV_MBX							0X62
+#define PREV_MBY							0X63
+#define ERROR_SKIP_MB_NUM						0X64
+#define ERROR_MB_STATUS							0X65
+#define L0_PIC0_STATUS							0X66
+#define TIMEOUT_COUNTER							0X67
+#define BUFFER_SIZE							0X68
+#define BUFFER_SIZE_HI							0X69
+#define CROPPING_LEFT_RIGHT						0X6A
+#define CROPPING_TOP_BOTTOM						0X6B
+/**
+ * sps_flags2:
+ * bit 3, bitstream_restriction_flag
+ * bit 2, pic_struct_present_flag
+ * bit 1, vcl_hrd_parameters_present_flag
+ * bit 0, nal_hrd_parameters_present_flag
+ */
+#define SPS_FLAGS2							0x6C
+#define NUM_REORDER_FRAMES						0x6D
+#define MAX_BUFFER_FRAME						0X6E
+
+#define NON_CONFORMING_STREAM						0X70
+#define RECOVERY_POINT							0X71
+#define POST_CANVAS							0X72
+#define POST_CANVAS_H							0X73
+#define SKIP_PIC_COUNT							0X74
+#define TARGET_NUM_SCALING_LIST						0X75
+#define FF_POST_ONE_FRAME						0X76
+#define PREVIOUS_BIT_CNT						0X77
+#define MB_NOT_SHIFT_COUNT						0X78
+#define PIC_STATUS							0X79
+#define FRAME_COUNTER							0X7A
+#define NEW_SLICE_TYPE							0X7B
+#define NEW_PICTURE_STRUCTURE						0X7C
+#define NEW_FRAME_NUM							0X7D
+#define NEW_IDR_PIC_ID							0X7E
+#define IDR_PIC_ID							0X7F
+
+/* h264 LOCAL */
+#define NAL_UNIT_TYPE							0X80
+#define NAL_REF_IDC							0X81
+#define SLICE_TYPE							0X82
+#define LOG2_MAX_FRAME_NUM						0X83
+#define FRAME_MBS_ONLY_FLAG						0X84
+#define PIC_ORDER_CNT_TYPE						0X85
+#define LOG2_MAX_PIC_ORDER_CNT_LSB					0X86
+#define PIC_ORDER_PRESENT_FLAG						0X87
+#define REDUNDANT_PIC_CNT_PRESENT_FLAG					0X88
+#define PIC_INIT_QP_MINUS26						0X89
+#define DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG				0X8A
+#define NUM_SLICE_GROUPS_MINUS1						0X8B
+#define MODE_8X8_FLAGS							0X8C
+#define ENTROPY_CODING_MODE_FLAG					0X8D
+#define SLICE_QUANT							0X8E
+#define TOTAL_MB_HEIGHT							0X8F
+#define PICTURE_STRUCTURE						0X90
+#define TOP_INTRA_TYPE							0X91
+#define RV_AI_STATUS							0X92
+#define AI_READ_START							0X93
+#define AI_WRITE_START							0X94
+#define AI_CUR_BUFFER							0X95
+#define AI_DMA_BUFFER							0X96
+#define AI_READ_OFFSET							0X97
+#define AI_WRITE_OFFSET							0X98
+#define AI_WRITE_OFFSET_SAVE						0X99
+#define RV_AI_BUFF_START						0X9A
+#define I_PIC_MB_COUNT							0X9B
+#define AI_WR_DCAC_DMA_CTRL						0X9C
+#define SLICE_MB_COUNT							0X9D
+#define PICTYPE								0X9E
+#define SLICE_GROUP_MAP_TYPE						0X9F
+#define MB_TYPE								0XA0
+#define MB_AFF_ADDED_DMA						0XA1
+#define PREVIOUS_MB_TYPE						0XA2
+#define WEIGHTED_PRED_FLAG						0XA3
+#define WEIGHTED_BIPRED_IDC						0XA4
+/* bit 3:2 - PICTURE_STRUCTURE
+ * bit 1 - MB_ADAPTIVE_FRAME_FIELD_FLAG
+ * bit 0 - FRAME_MBS_ONLY_FLAG
+ */
+#define MBFF_INFO							0XA5
+#define TOP_INTRA_TYPE_TOP						0XA6
+#define RV_AI_BUFF_INC							0xA7
+#define DEFAULT_MB_INFO_LO						0xA8
+/* 0 -- no need to read
+ * 1 -- need to wait Left
+ * 2 -- need to read Intra
+ * 3 -- need to read back MV
+ */
+#define NEED_READ_TOP_INFO						0xA9
+/* 0 -- idle
+ * 1 -- wait Left
+ * 2 -- reading top Intra
+ * 3 -- reading back MV
+ */
+#define READ_TOP_INFO_STATE						0xAA
+#define DCAC_MBX							0xAB
+#define TOP_MB_INFO_OFFSET						0xAC
+#define TOP_MB_INFO_RD_IDX						0xAD
+#define TOP_MB_INFO_WR_IDX						0xAE
+
+#define VLD_NO_WAIT	 0
+#define VLD_WAIT_BUFFER 1
+#define VLD_WAIT_HOST   2
+#define VLD_WAIT_GAP	3
+
+#define VLD_WAITING							0xAF
+
+#define MB_X_NUM							0xB0
+#define MB_HEIGHT							0xB2
+#define MBX								0xB3
+#define TOTAL_MBY							0xB4
+#define INTR_MSK_SAVE							0xB5
+#define NEED_DISABLE_PPE						0xB6
+#define IS_NEW_PICTURE							0XB7
+#define PREV_NAL_REF_IDC						0XB8
+#define PREV_NAL_UNIT_TYPE						0XB9
+#define FRAME_MB_COUNT							0XBA
+#define SLICE_GROUP_UCODE						0XBB
+#define SLICE_GROUP_CHANGE_RATE						0XBC
+#define SLICE_GROUP_CHANGE_CYCLE_LEN					0XBD
+#define DELAY_LENGTH							0XBE
+#define PICTURE_STRUCT							0XBF
+#define DCAC_PREVIOUS_MB_TYPE						0xC1
+
+#define TIME_STAMP							0XC2
+#define H_TIME_STAMP							0XC3
+#define VPTS_MAP_ADDR							0XC4
+#define H_VPTS_MAP_ADDR							0XC5
+#define PIC_INSERT_FLAG							0XC7
+#define TIME_STAMP_START						0XC8
+#define TIME_STAMP_END							0XDF
+#define OFFSET_FOR_NON_REF_PIC						0XE0
+#define OFFSET_FOR_TOP_TO_BOTTOM_FIELD					0XE2
+#define MAX_REFERENCE_FRAME_NUM						0XE4
+#define FRAME_NUM_GAP_ALLOWED						0XE5
+#define NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE				0XE6
+#define PROFILE_IDC_MMCO						0XE7
+#define LEVEL_IDC_MMCO							0XE8
+#define FRAME_SIZE_IN_MB						0XE9
+#define DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG				0XEA
+#define PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1				0XEB
+#define PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1				0XEC
+#define CURRENT_SPS_ID							0XED
+#define CURRENT_PPS_ID							0XEE
+/* bit 0 - sequence parameter set may change
+ * bit 1 - picture parameter set may change
+ * bit 2 - new dpb just inited
+ * bit 3 - IDR picture not decoded yet
+ * bit 5:4 - 0: mb level code loaded 1: picture
+ * level code loaded 2: slice level code loaded
+ */
+#define DECODE_STATUS							0XEF
+#define FIRST_MB_IN_SLICE						0XF0
+#define PREV_MB_WIDTH							0XF1
+#define PREV_FRAME_SIZE_IN_MB						0XF2
+/* bit 0 - aspect_ratio_info_present_flag
+ * bit 1 - timing_info_present_flag
+ * bit 2 - nal_hrd_parameters_present_flag
+ * bit 3 - vcl_hrd_parameters_present_flag
+ * bit 4 - pic_struct_present_flag
+ * bit 5 - bitstream_restriction_flag
+ */
+#define VUI_STATUS							0XF4
+#define ASPECT_RATIO_IDC						0XF5
+#define ASPECT_RATIO_SAR_WIDTH						0XF6
+#define ASPECT_RATIO_SAR_HEIGHT						0XF7
+#define NUM_UNITS_IN_TICK						0XF8
+#define TIME_SCALE							0XFA
+#define CURRENT_PIC_INFO						0XFC
+#define DPB_BUFFER_INFO							0XFD
+#define REFERENCE_POOL_INFO						0XFE
+#define REFERENCE_LIST_INFO						0XFF
+
+#define REORDER_CMD_MAX             66
+
+/* config parameters to DDR lmem */
+#define GET_SPS_PROFILE_IDC(x)       (((x) & 0xff) << 8)
+#define GET_SPS_LEVEL_IDC(x)         ((x) & 0xff)
+#define GET_SPS_SEQ_PARAM_SET_ID(x)       (((x) & 0x1f) << 8)
+#define GET_SPS_CHROMA_FORMAT_IDC(x)      ((x) << 8)
+#define GET_SPS_NUM_REF_FRAMES(x)         ((x) & 0xff)
+#define GET_SPS_GAPS_ALLOWED_FLAG(x)      ((x) << 8)
+#define GET_SPS_LOG2_MAX_FRAME_NUM(x)     ((x) + 4)
+#define GET_SPS_PIC_ORDER_CNT_LSB(x)      ((x) + 4)
+#define GET_SPS_PIC_ORDER_TYPE(x)         (x)
+#define GET_SPS_OFFSET_FOR_NONREF_PIC_HIGH(x)      (((x) & 0xffff0000) >> 16)
+#define GET_SPS_OFFSET_FOR_NONREF_PIC_LOW(x)         ((x) & 0xffff)
+#define GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_HIGH(x)      (((x) & 0xffff0000) >> 16)
+#define GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_LOW(x)         ((x) & 0xffff)
+#define GET_SPS_PIC_WIDTH_IN_MBS(x)       ((x) + 1)
+#define GET_SPS_PIC_HEIGHT_IN_MBS(x)      ((x) + 1)
+#define GET_SPS_DIRECT_8X8_FLAGS(x)       (((x) & 0x1) << 2)
+#define GET_SPS_MB_ADAPTIVE_FRAME_FIELD_FLAGS(x)       (((x) & 0x1) << 1)
+#define GET_SPS_FRAME_MBS_ONLY_FLAGS(x)   ((x) & 0x1)
+
+#define GET_PPS_PIC_PARAM_SET_ID(x)       ((x) & 0xff)
+#define GET_PPS_SEQ_PARAM_SET_ID(x)       (((x) & 0x1f) << 8)
+#define GET_PPS_ENTROPY_CODING_MODE_FLAG(x)  (((x) & 0x1) << 13)
+#define GET_PPS_PIC_ORDER_PRESENT_FLAG(x)    (((x) & 0x1) << 14)
+#define GET_PPS_NUM_IDX_REF_L0_MINUS1(x)       ((x) & 0x1f)
+#define GET_PPS_NUM_IDX_REF_L1_MINUS1(x)       (((x) & 0x1f) << 5)
+#define GET_PPS_WEIGHTED_PRED_FLAG(x)         (((x) & 0x1) << 10)
+#define GET_PPS_WEIGHTED_BIPRED_IDC(x)        (((x) & 0x3) << 11)
+#define GET_PPS_INIT_QS_MINUS26(x)           (((x) & 0xff) << 8)
+#define GET_PPS_INIT_QP_MINUS26(x)           ((x) & 0xff)
+#define GET_PPS_CHROMA_QP_INDEX_OFFSET(x)   ((x) & 0xff)
+#define GET_PPS_DEBLOCK_FILTER_CTRL_PRESENT_FLAG(x)   (((x) & 0x1) << 8)
+#define GET_PPS_CONSTRAIN_INTRA_PRED_FLAG(x)          (((x) & 0x1) << 9)
+#define GET_PPS_REDUNDANT_PIC_CNT_PRESENT_FLAG(x)     (((x) & 0x1) << 10)
+#define GET_PPS_SCALING_MATRIX_PRESENT_FLAG(x)        (((x) & 0x1) << 1)
+#define GET_PPS_TRANSFORM_8X8_FLAG(x)                 ((x) & 0x1)
+#define GET_PPS_GET_SECOND_CHROMA_QP_OFFSET(x)        (x)
+
+int aml_h264_init(void *priv);
+void aml_h264_exit(void *priv);
+int aml_h264_dec_run(void *priv);
+
+#endif
diff --git a/drivers/media/platform/amlogic/vdec/reg_defines.h b/drivers/media/platform/amlogic/vdec/reg_defines.h
new file mode 100644
index 000000000000..6b1900ecbedb
--- /dev/null
+++ b/drivers/media/platform/amlogic/vdec/reg_defines.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef _REG_DEFINES_H_
+#define _REG_DEFINES_H_
+
+#define VDEC_ASSIST_MMC_CTRL0        0x0001
+#define VDEC_ASSIST_MMC_CTRL1        0x0002
+
+#define VDEC_ASSIST_CANVAS_BLK32     0x0005
+
+#define VDEC_ASSIST_MBOX1_CLR_REG    0x0075
+#define VDEC_ASSIST_MBOX1_MASK       0x0076
+
+#define MPSR                         0x0301
+#define MPC_P                        0x0306
+#define MPC_D                        0x0307
+#define MPC_E                        0x0308
+#define MPC_W                        0x0309
+#define CPSR                         0x0321
+#define IMEM_DMA_CTRL                0x0340
+#define IMEM_DMA_ADR                 0x0341
+#define IMEM_DMA_COUNT               0x0342
+#define WRRSP_IMEM                   0x0343
+#define LMEM_DMA_CTRL                0x0350
+#define WRRSP_LMEM                   0x0353
+
+#define PSCALE_CTRL                  0x0911
+#define GCLK_EN                      0x0983
+#define MDEC_PIC_DC_CTRL             0x098e
+#define MDEC_PIC_DC_MUX_CTRL         0x098d
+#define ANC0_CANVAS_ADDR             0x0990
+#define ANC1_CANVAS_ADDR             0x0991
+#define ANC2_CANVAS_ADDR             0x0992
+#define ANC3_CANVAS_ADDR             0x0993
+#define ANC4_CANVAS_ADDR             0x0994
+#define ANC5_CANVAS_ADDR             0x0995
+#define ANC6_CANVAS_ADDR             0x0996
+#define ANC7_CANVAS_ADDR             0x0997
+#define ANC8_CANVAS_ADDR             0x0998
+#define ANC9_CANVAS_ADDR             0x0999
+#define ANC10_CANVAS_ADDR            0x099a
+#define ANC11_CANVAS_ADDR            0x099b
+#define ANC12_CANVAS_ADDR            0x099c
+#define ANC13_CANVAS_ADDR            0x099d
+#define ANC14_CANVAS_ADDR            0x099e
+#define ANC15_CANVAS_ADDR            0x099f
+#define ANC16_CANVAS_ADDR            0x09a0
+#define ANC17_CANVAS_ADDR            0x09a1
+#define ANC18_CANVAS_ADDR            0x09a2
+#define ANC19_CANVAS_ADDR            0x09a3
+#define ANC20_CANVAS_ADDR            0x09a4
+#define ANC21_CANVAS_ADDR            0x09a5
+#define ANC22_CANVAS_ADDR            0x09a6
+#define ANC23_CANVAS_ADDR            0x09a7
+#define ANC24_CANVAS_ADDR            0x09a8
+#define ANC25_CANVAS_ADDR            0x09a9
+#define ANC26_CANVAS_ADDR            0x09aa
+#define ANC27_CANVAS_ADDR            0x09ab
+#define ANC28_CANVAS_ADDR            0x09ac
+#define ANC29_CANVAS_ADDR            0x09ad
+#define ANC30_CANVAS_ADDR            0x09ae
+#define ANC31_CANVAS_ADDR            0x09af
+#define DBKR_CANVAS_ADDR             0x09b0
+#define DBKW_CANVAS_ADDR             0x09b1
+#define REC_CANVAS_ADDR              0x09b2
+#define CURR_CANVAS_CTRL             0x09b3
+#define MDEC_PIC_DC_THRESH           0x09b8
+#define AV_SCRATCH_0                 0x09c0
+#define AV_SCRATCH_1                 0x09c1
+#define AV_SCRATCH_2                 0x09c2
+#define AV_SCRATCH_3                 0x09c3
+#define AV_SCRATCH_4                 0x09c4
+#define AV_SCRATCH_5                 0x09c5
+#define AV_SCRATCH_6                 0x09c6
+#define AV_SCRATCH_7                 0x09c7
+#define AV_SCRATCH_8                 0x09c8
+#define AV_SCRATCH_9                 0x09c9
+#define AV_SCRATCH_A                 0x09ca
+#define AV_SCRATCH_B                 0x09cb
+#define AV_SCRATCH_C                 0x09cc
+#define AV_SCRATCH_D                 0x09cd
+#define AV_SCRATCH_E                 0x09ce
+#define AV_SCRATCH_F                 0x09cf
+#define AV_SCRATCH_G                 0x09d0
+#define AV_SCRATCH_H                 0x09d1
+#define AV_SCRATCH_I                 0x09d2
+#define AV_SCRATCH_J                 0x09d3
+#define AV_SCRATCH_K                 0x09d4
+#define AV_SCRATCH_L                 0x09d5
+#define AV_SCRATCH_M                 0x09d6
+#define AV_SCRATCH_N                 0x09d7
+#define WRRSP_VLD                    0x09da
+#define MDEC_DOUBLEW_CFG0            0x09db
+#define MDEC_DOUBLEW_CFG1            0x09dc
+#define MDEC_DOUBLEW_CFG2            0x09dd
+#define MDEC_DOUBLEW_CFG3            0x09de
+#define MDEC_DOUBLEW_CFG4            0x09df
+#define MDEC_DOUBLEW_CFG5            0x09e0
+#define MDEC_DOUBLEW_CFG6            0x09e1
+#define MDEC_DOUBLEW_CFG7            0x09e2
+#define MDEC_DOUBLEW_STATUS          0x09e3
+#define MDEC_EXTIF_CFG0              0x09e4
+
+#define MDEC_EXTIF_CFG1              0x09e5
+#define MDEC_EXTIF_CFG2              0x09e6
+
+#define POWER_CTL_VLD                0x0c08
+#define VLD_DECODE_CONTROL           0x0c18
+
+#define PMV1_X                       0x0c20
+#define PMV1_Y                       0x0c21
+#define PMV2_X                       0x0c22
+#define PMV2_Y                       0x0c23
+#define PMV3_X                       0x0c24
+#define PMV3_Y                       0x0c25
+#define PMV4_X                       0x0c26
+#define PMV4_Y                       0x0c27
+#define M4_TABLE_SELECT              0x0c28
+#define M4_CONTROL_REG               0x0c29
+#define BLOCK_NUM                    0x0c2a
+#define PATTERN_CODE                 0x0c2b
+#define MB_INFO                      0x0c2c
+#define VLD_DC_PRED                  0x0c2d
+#define VLD_ERROR_MASK               0x0c2e
+#define VLD_DC_PRED_C                0x0c2f
+#define LAST_SLICE_MV_ADDR           0x0c30
+#define LAST_MVX                     0x0c31
+#define LAST_MVY                     0x0c32
+
+#define MB_MOTION_MODE               0x0c07
+#define VIFF_BIT_CNT                 0x0c1a
+#define M4_CONTROL_REG               0x0c29
+#define VLD_C38                      0x0c38
+#define VLD_C39                      0x0c39
+#define VLD_SHIFT_STATUS             0x0c3b
+#define VLD_C3D                      0x0c3d
+#define VLD_MEM_VIFIFO_START_PTR     0x0c40
+#define VLD_MEM_VIFIFO_CURR_PTR      0x0c41
+#define VLD_MEM_VIFIFO_END_PTR       0x0c42
+#define VLD_MEM_VIFIFO_BYTES_AVAIL   0x0c43
+#define VLD_MEM_VIFIFO_CONTROL       0x0c44
+#define VLD_MEM_VIFIFO_WP            0x0c45
+#define VLD_MEM_VIFIFO_RP            0x0c46
+#define VLD_MEM_VIFIFO_LEVEL         0x0c47
+#define VLD_MEM_VIFIFO_BUF_CNTL      0x0c48
+
+#define VCOP_CTRL_REG                0x0e00
+#define RV_AI_MB_COUNT               0x0e0c
+#define IQIDCT_CONTROL               0x0e0e
+#define DCAC_DDR_BYTE64_CTL          0x0e1d
+
+#define VDEC2_IMEM_DMA_CTRL          0x2340
+#define VDEC2_IMEM_DMA_ADR           0x2341
+#define VDEC2_IMEM_DMA_COUNT         0x2342
+
+#define DOS_SW_RESET0                0x3f00
+#define DOS_GCLK_EN0                 0x3f01
+#define DOS_GCLK_EN1                 0x3f09
+#define DOS_GCLK_EN3                 0x3f35
+
+#define DOS_MEM_PD_VDEC              0x3f30
+#define DOS_MEM_PD_VDEC2             0x3f31
+#define DOS_MEM_PD_HCODEC            0x3f32
+/*add from M8M2*/
+#define DOS_MEM_PD_HEVC              0x3f33
+
+#define DOS_SW_RESET3                0x3f34
+#define DOS_GCLK_EN3                 0x3f35
+#define DOS_HEVC_INT_EN              0x3f36
+
+#endif
+

-- 
2.42.0




From linmq006 at gmail.com  Mon Oct 27 01:42:58 2025
From: linmq006 at gmail.com (Miaoqian Lin)
Date: Mon, 27 Oct 2025 16:42:58 +0800
Subject: [PATCH] drm/meson: Fix reference count leak in meson_encoder_dsi_probe
Message-ID: <20251027084258.79180-1-linmq006@gmail.com>

The of_graph_get_remote_node() function returns a device node with its
reference count incremented. The caller is responsible for calling
of_node_put() to release this reference when done.

Fixes: 42dcf15f901c ("drm/meson: add DSI encoder")
Cc: stable at vger.kernel.org
Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
---
 drivers/gpu/drm/meson/meson_encoder_dsi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c
index 6c6624f9ba24..01edf46e30d0 100644
--- a/drivers/gpu/drm/meson/meson_encoder_dsi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c
@@ -121,6 +121,7 @@ int meson_encoder_dsi_probe(struct meson_drm *priv)
 	}
 
 	meson_encoder_dsi->next_bridge = of_drm_find_bridge(remote);
+	of_node_put(remote);
 	if (!meson_encoder_dsi->next_bridge)
 		return dev_err_probe(priv->dev, -EPROBE_DEFER,
 				     "Failed to find DSI transceiver bridge\n");
-- 
2.39.5 (Apple Git-154)



From naoki at radxa.com  Mon Oct 27 05:51:52 2025
From: naoki at radxa.com (FUKAUMI Naoki)
Date: Mon, 27 Oct 2025 21:51:52 +0900
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <DM4PR05MB102709E0A9C0CF0D62AEC3524C7F1A@DM4PR05MB10270.namprd05.prod.outlook.com>
References: <20251023164205.GA1299816@bhelgaas>
 <DM4PR05MB102709E0A9C0CF0D62AEC3524C7F1A@DM4PR05MB10270.namprd05.prod.outlook.com>
Message-ID: <665677F9F810B6C1+af6c83fd-f262-4721-b544-4336aaa83bfe@radxa.com>

Hi Linnaea,

On 10/24/25 12:27, Linnaea Lavia wrote:
(snip)> With the patch on 6.18-rc2 it fails later with ASPM.
> 
> [??? 5.362080] [???? T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 
> 1 not found
> [??? 5.400163] [???? T50] meson-pcie fc000000.pcie: host bridge /soc/ 
> pcie at fc000000 ranges:
> [??? 5.421350] [???? T50] meson-pcie fc000000.pcie:?????? IO 
> 0x00fc600000..0x00fc6fffff -> 0x0000000000
> [??? 5.428902] [???? T50] meson-pcie fc000000.pcie:????? MEM 
> 0x00fc700000..0x00fdffffff -> 0x00fc700000
> [??? 5.436367] [???? T50] meson-pcie fc000000.pcie: iATU: unroll T, 4 
> ob, 4 ib, align 64K, limit 4G
> [??? 5.485658] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.491449] [???? T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
> [??? 5.512122] [???? T50] meson-pcie fc000000.pcie: PCI host bridge to 
> bus 0000:00
> [??? 5.515375] [???? T50] pci_bus 0000:00: root bus resource [bus 00-ff]
> [??? 5.521523] [???? T50] pci_bus 0000:00: root bus resource [io  
> 0x0000-0xfffff]
> [??? 5.528847] [???? T50] pci_bus 0000:00: root bus resource [mem 
> 0xfc700000-0xfdffffff]
> [??? 5.536237] [???? T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 
> 0x060400 PCIe Root Port
> [??? 5.543415] [???? T50] pci 0000:00:00.0: ROM [mem 
> 0x00000000-0x0000ffff pref]
> [??? 5.543432] [???? T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
> [??? 5.543441] [???? T50] pci 0000:00:00.0:?? bridge window [io  
> 0x0000-0x0fff]
> [??? 5.543448] [???? T50] pci 0000:00:00.0:?? bridge window [mem 
> 0x00000000-0x000fffff]
> [??? 5.569461] [???? T50] pci 0000:00:00.0:?? bridge window [mem 
> 0x00000000-0x000fffff pref]
> [??? 5.587641] [???? T50] pci 0000:00:00.0: supports D1
> [??? 5.591578] [???? T50] pci 0000:00:00.0: PME# supported from D0 D1 
> D3hot D3cold
> [??? 5.603775] [???? T50] pci 0000:01:00.0: [8086:2725] type 00 class 
> 0x028000 PCIe Endpoint
> [??? 5.614373] [???? T50] pci 0000:01:00.0: BAR 0 [mem 
> 0x00000000-0x00003fff 64bit]
> [??? 5.621353] [???? T50] pci 0000:01:00.0: Upstream bridge's Max 
> Payload Size set to 128 (was 256, max 256)
> [??? 5.621374] [???? T50] pci 0000:01:00.0: Max Payload Size set to 128 
> (was 128, max 128)
> [??? 5.623252] [???? T50] pci 0000:01:00.0: PME# supported from D0 D3hot 
> D3cold
> [??? 5.651205] [???? T50] pci 0000:01:00.0: ASPM: DT platform, enabling 
> L0s-up L0s-dw L1 ASPM-L1.1 ASPM-L1.2 PCI-PM-L1.1 PCI-PM-L1.2
> [??? 5.664912] [???? T50] pci 0000:01:00.0: ASPM: DT platform, enabling 
> ClockPM
> [??? 5.706596] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.748181] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.796864] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.798178] [???? T50] pci 0000:00:00.0: bridge window [mem 
> 0xfc700000-0xfc7fffff]: assigned
> [??? 5.806100] [???? T50] pci 0000:00:00.0: ROM [mem 
> 0xfc800000-0xfc80ffff pref]: assigned
> [??? 5.806382] [???? T50] pci 0000:01:00.0: BAR 0 [mem 
> 0xfc700000-0xfc703fff 64bit]: assigned
> [??? 5.863079] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.904553] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.946013] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.987492] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 5.987517] [???? T50] pci 0000:01:00.0: BAR 0: error updating 
> (0xfc700004 != 0xffffffff)
> [??? 6.028979] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 6.080320] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 6.081421] [???? T50] pci 0000:01:00.0: BAR 0: error updating (high 
> 0x00000000 != 0xffffffff)
> [??? 6.131210] [???? T50] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [??? 6.132324] [???? T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
> [??? 6.138215] [???? T50] pci 0000:00:00.0:?? bridge window [mem 
> 0xfc700000-0xfc7fffff]
> [??? 6.145683] [???? T50] pci_bus 0000:00: resource 4 [io? 0x0000-0xfffff]
> [??? 6.151953] [???? T50] pci_bus 0000:00: resource 5 [mem 
> 0xfc700000-0xfdffffff]
> [??? 6.165037] [???? T50] pci_bus 0000:01: resource 1 [mem 
> 0xfc700000-0xfc7fffff]
> [??? 6.165782] [???? T50] pcieport 0000:00:00.0: PME: Signaling with IRQ 25
> [??? 6.181556] [???? T50] pcieport 0000:00:00.0: AER: enabled with IRQ 25
> [?? 11.500464] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.543334] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.544875] [??? T491] iwlwifi 0000:01:00.0: of_irq_parse_pci: failed 
> with rc=134
> [?? 11.593524] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.636355] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.680033] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.721230] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.722728] [??? T491] iwlwifi 0000:01:00.0: Unable to change power 
> state from D3cold to D0, device inaccessible
> [?? 11.773976] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.816771] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.859334] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.901868] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.944393] [??? T491] meson-pcie fc000000.pcie: error: wait linkup 
> timeout
> [?? 11.945931] [??? T491] iwlwifi 0000:01:00.0: HW_REV=0xFFFFFFFF, PCI 
> issues?
> [?? 11.952685] [??? T491] iwlwifi 0000:01:00.0: probe with driver 
> iwlwifi failed with error -5
> 
> Booting with the patch and pcie_aspm=off made the PCIe card work again.(snip)

Regarding the ASPM issue, could you try v6.18-rc3 (in addition to your 
changes)?

https://patchwork.kernel.org/project/linux-pci/patch/20251023180645.1304701-1-helgaas at kernel.org/

Best regards,

--
FUKAUMI Naoki
Radxa Computer (Shenzhen) Co., Ltd.


From christianshewitt at gmail.com  Mon Oct 27 05:57:45 2025
From: christianshewitt at gmail.com (Christian Hewitt)
Date: Mon, 27 Oct 2025 16:57:45 +0400
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
Message-ID: <B9A578FB-BF95-47E1-B202-B59897C2C898@gmail.com>

> On 27 Oct 2025, at 9:42?am, Zhentao Guo via B4 Relay <devnull+zhentao.guo.amlogic.com at kernel.org> wrote:
> 
> Introduce initial driver support for Amlogic's new video acceleration
> hardware architecture, designed for video stream decoding.
> 
> Compared to the current Amlogic video decoder hardware architecture,
> this new implementation eliminates the Esparser hardware component,
> enabling direct vb2 buffer input. The driver is designed to support
> the V4L2 M2M stateless decoder API. The initial phase includes support
> for H.264 decoding on Amlogic S805X2 platform.

It would be nice if you can outline the additional hardware the driver
plans to support so reviewers have perspective on where we are now, and
what more be coming? - the community would also like to understand if
this driver will supersede the stalled driver attempt in staging.

NB: I can only find two S805X2 devices to purchase for testing. The
first is a Mecool KD5 HDMI stick, but this has Widevine L1 certs so
will be unusable due to verified boot. The second is a no-name TV box
on Aliexpress where the advert claims S805X2 inside but also shows a
prominent Rockchip RK3228 logo :) .. please advise on some accessible
hardware that can be used for validating the driver.

> The driver is capable of:
> - Supporting stateless H.264 decoding up to a resolution 1920x1088(on the S805X2 platform).

It would be good to provide guidance to reviewers about other codecs
the driver plans to support and how (architecturally) the driver will
be expanded. I?m aware due to off-list discussions, but others are
not and will want to know.

> - Supporting I/P/B frame handling.
> - Supporting vb2 mmap and dma-buf modes.
> - Supporting frame-based decode mode. (Note that some H.264 bitstreams require
>  DPB reordering to generate reference lists, the stateless decoder driver
>  cannot access reordered reference lists in this mode, requiring the driver
>  to perform reference list reordering itself)
> - Supporting NV12/NV21 output.
> - Supporting Annex B start codes.
> 
> This driver is tested with Gstreamer.
> Example:
> gst-launch-1.0 filesrc location=/tmp/video_640x360_mp4_hevc_450kbps_no_b.mp4 !
> parsebin ! v4l2slh264dec ! filesink location=/tmp/output.yuv

Is this upstream gstreamer? if yes which version? If no, where can
we obtain sources for testing. Has ffmpeg been tested? - the same
questions apply.

> The driver passes v4l2 compliance test, test reports :
> v4l2-compliance 1.30.1, 64 bits, 64-bit time_t
> 
> Compliance test for aml-vdec-drv device /dev/video0:
> 
> Driver Info:
>        Driver name      : aml-vdec-drv
>        Card type        : platform:aml-vdec-drv
>        Bus info         : platform:fe320000.video-codec
>        Driver version   : 6.16.0

It would be preferable to test the next iteration of patches on
the latest kernel release, e.g. 6.18-rc, or recent media tree or
perhaps drm-tip source.

>        Capabilities     : 0x84204000
>                Video Memory-to-Memory Multiplanar
>                Streaming
>                Extended Pix Format
>                Device Capabilities
>        Device Caps      : 0x04204000
>                Video Memory-to-Memory Multiplanar
>                Streaming
>                Extended Pix Format
>        Detected Stateless Decoder
> Media Driver Info:
>        Driver name      : aml-vdec-drv
>        Model            : aml-vdec-drv
>        Serial           :
>        Bus info         : platform:fe320000.video-codec
>        Media version    : 6.16.0
>        Hardware revision: 0x00000000 (0)
>        Driver version   : 6.16.0
> Interface Info:
>        ID               : 0x0300000c
>        Type             : V4L Video
> Entity Info:
>        ID               : 0x00000001 (1)
>        Name             : aml_dev_drv-source
>        Function         : V4L2 I/O
>        Pad 0x01000002   : 0: Source
>          Link 0x02000008: to remote pad 0x1000004 of entity 'aml_dev_drv-proc' (Video Decoder): Data, Enabled, Immutable
> 
> Required ioctls:
>        test MC information (see 'Media Driver Info' above): OK
>        test VIDIOC_QUERYCAP: OK
>        test invalid ioctls: OK
> 
> Allow for multiple opens:
>        test second /dev/video0 open: OK
>        test VIDIOC_QUERYCAP: OK
>        test VIDIOC_G/S_PRIORITY: OK
>        test for unlimited opens: OK
> 
> Debug ioctls:
>        test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>        test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>        test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>        test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>        test VIDIOC_ENUMAUDIO: OK (Not Supported)
>        test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>        test VIDIOC_G/S_AUDIO: OK (Not Supported)
>        Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>        test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>        test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>        test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>        test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>        test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>        Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>        test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>        test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>        test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>        test VIDIOC_G/S_EDID: OK (Not Supported)
> 
> Control ioctls:
>        test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>        test VIDIOC_QUERYCTRL: OK
>        test VIDIOC_G/S_CTRL: OK
>        test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>        test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>        test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>        Standard Controls: 6 Private Controls: 0
>        Standard Compound Controls: 4 Private Compound Controls: 0
> 
> Format ioctls:
>        test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>        test VIDIOC_G/S_PARM: OK (Not Supported)
>        test VIDIOC_G_FBUF: OK (Not Supported)
>        test VIDIOC_G_FMT: OK
>        test VIDIOC_TRY_FMT: OK
>        test VIDIOC_S_FMT: OK
>        test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>        test Cropping: OK (Not Supported)
>        test Composing: OK (Not Supported)
>        test Scaling: OK (Not Supported)
> 
> Codec ioctls:
>        test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>        test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>        test VIDIOC_(TRY_)DECODER_CMD: OK
> 
> Buffer ioctls:
>        test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>        test CREATE_BUFS maximum buffers: OK
>        test VIDIOC_REMOVE_BUFS: OK
>        test VIDIOC_EXPBUF: OK
>        test Requests: OK
>        test blocking wait: OK
> 
> Total for aml-vdec-drv device /dev/video0: 49, Succeeded: 49, Failed: 0, Warnings: 0
> 
> Some Fluster test cases are still failing. We will publish the final results
> once all these Fluster test failures have been resolved.

IMHO good drivers that merge quickly have more merit than perfect
drivers that take forever. No driver passes all fluster tests. If
you share the results, people can advise whether the failures are
normal, something that must be improved, or something that can be
improved with time.

> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
> ---
> Zhentao Guo (3):
>      dt-bindings: vdec: Add binding document of Amlogic decoder accelerator
>      dts: decoder: Support V4L2 stateless decoder dt node for S4
>      decoder: Add V4L2 stateless H.264 decoder driver

None of the patch subject lines are following the naming formats
used for the subsystems. Patch order is also important. Bindings
go first, device-tree changes to expose support normally go last.
Expect maintainer complaints about not reading kernel etiquette
rules before submitting. 

> .../bindings/media/amlogic,vcodec-dec.yaml         |   96 ++
> MAINTAINERS                                        |    7 +
> arch/arm64/boot/dts/amlogic/meson-s4.dtsi          |   24 +
> drivers/media/platform/amlogic/Kconfig             |    2 +
> drivers/media/platform/amlogic/Makefile            |    1 +
> drivers/media/platform/amlogic/vdec/Kconfig        |   15 +
> drivers/media/platform/amlogic/vdec/Makefile       |    4 +
> drivers/media/platform/amlogic/vdec/aml_vdec.c     |  759 +++++++++
> drivers/media/platform/amlogic/vdec/aml_vdec.h     |   31 +
> .../platform/amlogic/vdec/aml_vdec_canvas_utils.c  |  154 ++
> .../platform/amlogic/vdec/aml_vdec_canvas_utils.h  |   22 +
> drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |  263 +++
> drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |  194 +++
> drivers/media/platform/amlogic/vdec/aml_vdec_hw.c  |  652 +++++++
> drivers/media/platform/amlogic/vdec/aml_vdec_hw.h  |  182 ++
> .../platform/amlogic/vdec/aml_vdec_platform.c      |   37 +
> .../platform/amlogic/vdec/aml_vdec_platform.h      |   62 +
> drivers/media/platform/amlogic/vdec/h264.c         | 1790 ++++++++++++++++++++
> drivers/media/platform/amlogic/vdec/h264.h         |  300 ++++
> drivers/media/platform/amlogic/vdec/reg_defines.h  |  175 ++
> 20 files changed, 4770 insertions(+)

The driver requires closed-source firmware blobs (sadly) for each
codec and hardware target. Will that change in future iterations?
If not, the firmware blobs are not provided here so it would be
useful if you could provide a public source for them. There are
known FOSS tools for extracting files from the Android ucode blob
but testing presumably needs a specific blob version?

Most maintainers also prefer a complex driver to be submitted in a
series of patches that break the driver up into logical and easier
to-review pieces. Large uber-patches are harder to digest and are
likely to take much longer to review, and more effort for everyone
to track feedback on over time.

*** 

NB: The fact this driver is being submitted, is still a positive
and welcomed step towards better upstream Amlogic support and it?s
great to see! I would encourage you and colleagues to establish a
public working space to share code and tools so the community can
directly engage and support driver testing and development.

Christian



From krzk at kernel.org  Mon Oct 27 06:05:08 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 27 Oct 2025 14:05:08 +0100
Subject: [PATCH 1/3] dt-bindings: vdec: Add binding document of Amlogic
 decoder accelerator
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-1-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-1-620401813b5d@amlogic.com>
Message-ID: <b989fba3-223d-498a-8efe-7a60e26cf0db@kernel.org>

On 27/10/2025 06:42, Zhentao Guo via B4 Relay wrote:
> From: Zhentao Guo <zhentao.guo at amlogic.com>
> 
> Add dt-binding of the Amlogic hardware decoder accelerator.

Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

A nit, subject: drop second/last, redundant "binding document for". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18

> 
> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
> ---
>  .../bindings/media/amlogic,vcodec-dec.yaml         | 96 ++++++++++++++++++++++
>  1 file changed, 96 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml b/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
> new file mode 100644
> index 000000000000..6cea8af72639
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml

Filename matching compatible.

> @@ -0,0 +1,96 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +# Copyright (C) 2025 Amlogic, Inc. All rights reserved
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/media/amlogic,vcodec-dec.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Amlogic Video Decode Accelerator
> +
> +maintainers:
> +  - Zhentao Guo <zhentao.guo at amlogic.com>
> +
> +description: |


Do not need '|' unless you need to preserve formatting.

> +  The Video Decoder Accelerator present on Amlogic SOCs.
> +  It supports stateless h264 decoding.
> +
> +properties:
> +  compatible:
> +    const: amlogic,s4-vcodec-dec
> +
> +  reg:
> +    maxItems: 2
> +
> +  reg-names:
> +    items:
> +      - const: dosbus
> +      - const: dmcbus

Is "bus" really name of this in datasheet?

> +
> +  interrupts:
> +    maxItems: 3
> +
> +  interrupt-names:
> +    items:
> +      - const: mailbox_0
> +      - const: mailbox_1
> +      - const: mailbox_2

Useless names, so just drop interrupt-names property.

> +
> +  clocks:
> +    maxItems: 3
> +
> +  clock-names:
> +    items:
> +      - const: vdec
> +      - const: clk_vdec_mux
> +      - const: clk_hevcf_mux
> +
> +  power-domains:
> +    maxItems: 2
> +
> +  power-domain-names:
> +    items:
> +      - const: pwrc-vdec

Drop pwrc

> +      - const: pwrc-hevc

Drop pwrc

Missing iommus. I really doubt hardware works without IOMMU.



Best regards,
Krzysztof


From krzk at kernel.org  Mon Oct 27 06:06:08 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 27 Oct 2025 14:06:08 +0100
Subject: [PATCH 2/3] dts: decoder: Support V4L2 stateless decoder dt node
 for S4
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-2-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-2-620401813b5d@amlogic.com>
Message-ID: <43280bcc-5afd-4b46-a83d-d81c80405e71@kernel.org>

On 27/10/2025 06:42, Zhentao Guo via B4 Relay wrote:
> From: Zhentao Guo <zhentao.guo at amlogic.com>
> 
> Add vcodec_dec to the s4 dtsi for the V4L2 stateless decoder driver
> 
> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>


Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching. For bindings, the preferred subjects are
explained here:
https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters

Please order the patchset as expressed in submitting patches DT
document. Or SoC maintainer profile.


Best regards,
Krzysztof


From krzk at kernel.org  Mon Oct 27 06:10:18 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Mon, 27 Oct 2025 14:10:18 +0100
Subject: [PATCH 3/3] decoder: Add V4L2 stateless H.264 decoder driver
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>
Message-ID: <a2ec6794-1131-421e-848b-3fddd39191e2@kernel.org>

On 27/10/2025 06:42, Zhentao Guo via B4 Relay wrote:
> From: Zhentao Guo <zhentao.guo at amlogic.com>
> 
> This patch introduces initial driver support for Amlogic's new

Please do not use "This commit/patch/change", but imperative mood. See
longer explanation here:
https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94

> video acceleration hardware architecture, designed for video
> stream decoding. The driver is designed to support the
> V4L2 M2M stateless decoder API. In phase 1, it supports H.264
> bitstreams decoding.
> 
> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>

...


> +
> +static int aml_vdec_drv_probe(struct platform_device *pdev)
> +{
> +	struct aml_vdec_dev *dev;
> +	struct video_device *vfd_dec;
> +	struct aml_vdec_hw *hw;
> +	int ret = 0;
> +
> +	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->plat_dev = pdev;
> +	mutex_init(&dev->dev_mutex);
> +
> +	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "v4l2_device_register err\n");
> +
> +	vfd_dec = video_device_alloc();
> +	if (!vfd_dec) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
> +		ret = -ENOMEM;
> +		goto err_device_alloc;
> +	}
> +	*vfd_dec = dec_dev;
> +	vfd_dec->v4l2_dev = &dev->v4l2_dev;
> +	vfd_dec->lock = &dev->dev_mutex;
> +	video_set_drvdata(vfd_dec, dev);
> +	dev->vfd = vfd_dec;
> +	platform_set_drvdata(pdev, dev);
> +
> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);

Why aren't you using devm interfaces?

> +	if (!hw) {
> +		ret = -ENOMEM;
> +		goto err_dec_mem_init;
> +	}
> +	dev->dec_hw = hw;
> +
> +	dev->pvdec_data = of_device_get_match_data(&pdev->dev);
> +	ret = dev->pvdec_data->req_hw_resource(dev);
> +	if (ret < 0)
> +		goto err_hw_init;
> +
> +	dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
> +	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {

Huh? Why the cast?

> +		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem dec device\n");
> +		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
> +		goto err_hw_init;
> +	}
> +
> +	ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to register video device");
> +		goto err_vid_dev_register;
> +	}
> +
> +	v4l2_info(&dev->v4l2_dev, "Registered %s as /dev/%s\n",
> +		  vfd_dec->name, video_device_node_name(vfd_dec));

This does not look like useful printk message. Drivers should be silent
on success:
https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/coding-style.rst#L913
https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/debugging/driver_development_debugging_guide.rst#L79

> +
> +	dev->mdev.dev = &pdev->dev;
> +	strscpy(dev->mdev.model, AML_VDEC_DRV_NAME, sizeof(dev->mdev.model));
> +	media_device_init(&dev->mdev);
> +	dev->mdev.ops = &aml_m2m_media_ops;
> +	dev->v4l2_dev.mdev = &dev->mdev;
> +
> +	ret = v4l2_m2m_register_media_controller(dev->m2m_dev_dec, vfd_dec,
> +						 MEDIA_ENT_F_PROC_VIDEO_DECODER);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
> +		goto error_m2m_mc_register;
> +	}
> +
> +	ret = media_device_register(&dev->mdev);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to register media device");
> +		goto err_media_dev_register;
> +	}
> +	vdec_enable(dev->dec_hw);
> +	return 0;
> +
> +err_media_dev_register:
> +	v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
> +error_m2m_mc_register:
> +	media_device_cleanup(&dev->mdev);
> +err_vid_dev_register:
> +	v4l2_m2m_release(dev->m2m_dev_dec);
> +err_hw_init:
> +	kfree(hw);
> +	dev->dec_hw = NULL;
> +err_dec_mem_init:
> +	video_device_release(vfd_dec);
> +err_device_alloc:
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +	return ret;
> +}
> +
> +static void aml_vdec_drv_remove(struct platform_device *pdev)
> +{
> +	struct aml_vdec_dev *dev = platform_get_drvdata(pdev);
> +
> +	vdec_disable(dev->dec_hw);
> +
> +	if (media_devnode_is_registered(dev->mdev.devnode)) {
> +		media_device_unregister(&dev->mdev);
> +		media_device_cleanup(&dev->mdev);
> +	}
> +
> +	if (dev->m2m_dev_dec)
> +		v4l2_m2m_release(dev->m2m_dev_dec);
> +	if (dev->vfd)
> +		video_unregister_device(dev->vfd);
> +	if (dev->dec_hw)
> +		dev->pvdec_data->destroy_hw_resource(dev);
> +
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +
> +	pr_debug("aml v4l2 decoder driver remove\n");


This does not look like useful printk message. Drivers should be silent
on success:
https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/coding-style.rst#L913
https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/debugging/driver_development_debugging_guide.rst#L79

> +}
> +
> +static const struct of_device_id aml_vdec_match[] = {
> +	{.compatible = "amlogic,s4-vcodec-dec", .data = &aml_vdec_s4_pdata},
> +	{},
> +};
> +
> +static struct platform_driver aml_vcodec_dec_driver = {
> +	.probe    = aml_vdec_drv_probe,
> +	.remove    = aml_vdec_drv_remove,
> +	.driver    = {
> +		.name    = AML_VDEC_DRV_NAME,
> +		.of_match_table = aml_vdec_match,
> +	},
> +};
> +
> +static int __init aml_vdec_init(void)
> +{
> +	pr_debug("aml v4l2 decoder module init\n");
> +
> +	if (platform_driver_register(&aml_vcodec_dec_driver)) {
> +		pr_err("failed to register aml v4l2 decoder\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static void __exit aml_vdec_exit(void)
> +{
> +	pr_debug("aml v4l2 decoder module exit\n");
> +	platform_driver_unregister(&aml_vcodec_dec_driver);

No, drop entire init/exit. This is some really odd code, probably
copy-paste from poor downstream. Please look at upstream drivers - do
you see anything like that anywhere?

> +}
> +
> +module_init(aml_vdec_init);
> +module_exit(aml_vdec_exit);
> +

Best regards,
Krzysztof


From linnaea-von-lavia at live.com  Mon Oct 27 11:19:13 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Tue, 28 Oct 2025 02:19:13 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <665677F9F810B6C1+af6c83fd-f262-4721-b544-4336aaa83bfe@radxa.com>
References: <20251023164205.GA1299816@bhelgaas>
 <DM4PR05MB102709E0A9C0CF0D62AEC3524C7F1A@DM4PR05MB10270.namprd05.prod.outlook.com>
 <665677F9F810B6C1+af6c83fd-f262-4721-b544-4336aaa83bfe@radxa.com>
Message-ID: <DM4PR05MB102705BB2124288C68EEFDA04C7FCA@DM4PR05MB10270.namprd05.prod.outlook.com>

On 10/27/2025 8:51 PM, FUKAUMI Naoki wrote:
> Hi Linnaea,
> 
> On 10/24/25 12:27, Linnaea Lavia wrote:
> (snip)> With the patch on 6.18-rc2 it fails later with ASPM.
>>
>> [??? 5.362080] [???? T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
>> [??? 5.400163] [???? T50] meson-pcie fc000000.pcie: host bridge /soc/ pcie at fc000000 ranges:
>> [??? 5.421350] [???? T50] meson-pcie fc000000.pcie:?????? IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
>> [??? 5.428902] [???? T50] meson-pcie fc000000.pcie:????? MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
>> [??? 5.436367] [???? T50] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
>> [??? 5.485658] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.491449] [???? T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
>> [??? 5.512122] [???? T50] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
>> [??? 5.515375] [???? T50] pci_bus 0000:00: root bus resource [bus 00-ff]
>> [??? 5.521523] [???? T50] pci_bus 0000:00: root bus resource [io 0x0000-0xfffff]
>> [??? 5.528847] [???? T50] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
>> [??? 5.536237] [???? T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
>> [??? 5.543415] [???? T50] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
>> [??? 5.543432] [???? T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
>> [??? 5.543441] [???? T50] pci 0000:00:00.0:?? bridge window [io 0x0000-0x0fff]
>> [??? 5.543448] [???? T50] pci 0000:00:00.0:?? bridge window [mem 0x00000000-0x000fffff]
>> [??? 5.569461] [???? T50] pci 0000:00:00.0:?? bridge window [mem 0x00000000-0x000fffff pref]
>> [??? 5.587641] [???? T50] pci 0000:00:00.0: supports D1
>> [??? 5.591578] [???? T50] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
>> [??? 5.603775] [???? T50] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
>> [??? 5.614373] [???? T50] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
>> [??? 5.621353] [???? T50] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
>> [??? 5.621374] [???? T50] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
>> [??? 5.623252] [???? T50] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
>> [??? 5.651205] [???? T50] pci 0000:01:00.0: ASPM: DT platform, enabling L0s-up L0s-dw L1 ASPM-L1.1 ASPM-L1.2 PCI-PM-L1.1 PCI-PM-L1.2
>> [??? 5.664912] [???? T50] pci 0000:01:00.0: ASPM: DT platform, enabling ClockPM
>> [??? 5.706596] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.748181] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.796864] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.798178] [???? T50] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
>> [??? 5.806100] [???? T50] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
>> [??? 5.806382] [???? T50] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
>> [??? 5.863079] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.904553] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.946013] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.987492] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.987517] [???? T50] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
>> [??? 6.028979] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 6.080320] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 6.081421] [???? T50] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)
>> [??? 6.131210] [???? T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 6.132324] [???? T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
>> [??? 6.138215] [???? T50] pci 0000:00:00.0:?? bridge window [mem 0xfc700000-0xfc7fffff]
>> [??? 6.145683] [???? T50] pci_bus 0000:00: resource 4 [io? 0x0000-0xfffff]
>> [??? 6.151953] [???? T50] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
>> [??? 6.165037] [???? T50] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
>> [??? 6.165782] [???? T50] pcieport 0000:00:00.0: PME: Signaling with IRQ 25
>> [??? 6.181556] [???? T50] pcieport 0000:00:00.0: AER: enabled with IRQ 25
>> [?? 11.500464] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.543334] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.544875] [??? T491] iwlwifi 0000:01:00.0: of_irq_parse_pci: failed with rc=134
>> [?? 11.593524] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.636355] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.680033] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.721230] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.722728] [??? T491] iwlwifi 0000:01:00.0: Unable to change power state from D3cold to D0, device inaccessible
>> [?? 11.773976] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.816771] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.859334] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.901868] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.944393] [??? T491] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [?? 11.945931] [??? T491] iwlwifi 0000:01:00.0: HW_REV=0xFFFFFFFF, PCI issues?
>> [?? 11.952685] [??? T491] iwlwifi 0000:01:00.0: probe with driver iwlwifi failed with error -5
>>
>> Booting with the patch and pcie_aspm=off made the PCIe card work again.(snip)
> 
> Regarding the ASPM issue, could you try v6.18-rc3 (in addition to your changes)?
> 
> https://patchwork.kernel.org/project/linux-pci/patch/20251023180645.1304701-1-helgaas at kernel.org/

On 6.18-rc3 with the change the link does not come up without pcie_aspm=off.

[    0.000000] [      T0] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] [      T0] Linux version 6.18.0-rc3 (geeko at buildhost) (gcc (SUSE Linux) 15.1.1 20250714, GNU ld (GNU Binutils; SUSE Linux 16) 2.43.1.20241209-160000.2) #1 SMP PREEMPT_DYNAMIC Mon Oct 27 00:28:53 UTC 2025 (25c11a7)
[    0.000000] [      T0] KASLR enabled
[    0.000000] [      T0] Machine model: Khadas VIM3
[    0.000000] [      T0] efi: EFI v2.10 by Das U-Boot
(...snip...)
[    5.352599] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.396341] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.398529] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.418773] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.425683] [     T50] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.474722] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.480590] [     T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.484394] [     T50] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.490965] [     T50] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.498755] [     T50] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.504874] [     T50] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.511625] [     T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.518768] [     T50] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.525573] [     T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.531506] [     T50] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.538287] [     T50] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.545718] [     T50] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.553588] [     T50] pci 0000:00:00.0: supports D1
[    5.566793] [     T50] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.578507] [     T50] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.587460] [     T50] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.605768] [     T50] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.633594] [     T50] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.637380] [     T50] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.656009] [     T50] pci 0000:01:00.0: ASPM: default states L1
[    5.701063] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.702251] [     T50] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.710285] [     T50] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.724147] [     T50] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.779528] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.822074] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.864902] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.907448] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.908544] [     T50] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
[    5.957865] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    6.000358] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    6.001437] [     T50] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)
[    6.051178] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    6.052267] [     T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    6.058144] [     T50] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    6.069323] [     T50] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    6.069333] [     T50] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    6.069341] [     T50] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    6.081804] [     T50] pcieport 0000:00:00.0: PME: Signaling with IRQ 24
[    6.095413] [     T50] pcieport 0000:00:00.0: AER: enabled with IRQ 24
(...snip...)
[   11.750786] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.793509] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.795130] [    T518] iwlwifi 0000:01:00.0: of_irq_parse_pci: failed with rc=134
[   11.843840] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.885754] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.930959] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.973534] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.975045] [    T518] iwlwifi 0000:01:00.0: Unable to change power state from D3cold to D0, device inaccessible
[   12.026031] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   12.068751] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   12.117585] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   12.158754] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   12.226957] [    T518] meson-pcie fc000000.pcie: error: wait linkup timeout
[   12.228454] [    T518] iwlwifi 0000:01:00.0: HW_REV=0xFFFFFFFF, PCI issues?
[   12.235248] [    T518] iwlwifi 0000:01:00.0: probe with driver iwlwifi failed with error -5

> 
> Best regards,
> 
> -- 
> FUKAUMI Naoki
> Radxa Computer (Shenzhen) Co., Ltd.



From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:27 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:27 +0800
Subject: [PATCH v4 1/8] dt-bindings: clock: Add Amlogic A5 SCMI clock
 controller support
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-1-e62ca0aae243@amlogic.com>

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

Add the SCMI clock controller dt-bindings for the Amlogic A5 SoC
family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 include/dt-bindings/clock/amlogic,a5-scmi-clkc.h | 44 ++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/include/dt-bindings/clock/amlogic,a5-scmi-clkc.h b/include/dt-bindings/clock/amlogic,a5-scmi-clkc.h
new file mode 100644
index 000000000000..1bf027d0110a
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a5-scmi-clkc.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ * Author: Chuan Liu <chuan.liu at amlogic.com>
+ */
+
+#ifndef __AMLOGIC_A5_SCMI_CLKC_H
+#define __AMLOGIC_A5_SCMI_CLKC_H
+
+#define CLKID_OSC				0
+#define CLKID_SYS_CLK				1
+#define CLKID_AXI_CLK				2
+#define CLKID_CPU_CLK				3
+#define CLKID_DSU_CLK				4
+#define CLKID_GP1_PLL				5
+#define CLKID_FIXED_PLL_DCO			6
+#define CLKID_FIXED_PLL				7
+#define CLKID_ACLKM				8
+#define CLKID_SYS_PLL_DIV16			9
+#define CLKID_CPU_CLK_DIV16			10
+#define CLKID_FCLK_50M_PREDIV			11
+#define CLKID_FCLK_50M_DIV			12
+#define CLKID_FCLK_50M				13
+#define CLKID_FCLK_DIV2_DIV			14
+#define CLKID_FCLK_DIV2				15
+#define CLKID_FCLK_DIV2P5_DIV			16
+#define CLKID_FCLK_DIV2P5			17
+#define CLKID_FCLK_DIV3_DIV			18
+#define CLKID_FCLK_DIV3				19
+#define CLKID_FCLK_DIV4_DIV			20
+#define CLKID_FCLK_DIV4				21
+#define CLKID_FCLK_DIV5_DIV			22
+#define CLKID_FCLK_DIV5				23
+#define CLKID_FCLK_DIV7_DIV			24
+#define CLKID_FCLK_DIV7				25
+#define CLKID_SYS_MMC_PCLK			26
+#define CLKID_SYS_CPU_CTRL			27
+#define CLKID_SYS_IRQ_CTRL			28
+#define CLKID_SYS_GIC				29
+#define CLKID_SYS_BIG_NIC			30
+#define CLKID_AXI_SYS_NIC			31
+#define CLKID_AXI_CPU_DMC			32
+
+#endif /* __AMLOGIC_A5_SCMI_CLKC_H */

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:33 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:33 +0800
Subject: [PATCH v4 7/8] arm64: dts: amlogic: A5: Add PLL controller node
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-7-e62ca0aae243@amlogic.com>

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

Add PLL controller node for A5 SoC family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index a6625508893d..70deeab220e0 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -8,6 +8,7 @@
 #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
 #include <dt-bindings/power/amlogic,a5-pwrc.h>
 #include <dt-bindings/clock/amlogic,a5-scmi-clkc.h>
+#include <dt-bindings/clock/amlogic,a5-pll-clkc.h>
 
 / {
 	cpus {
@@ -187,4 +188,16 @@ gpio_intc: interrupt-controller at 4080 {
 		amlogic,channel-interrupts =
 			<10 11 12 13 14 15 16 17 18 19 20 21>;
 	};
+
+	clkc_pll: clock-controller at 8000 {
+		compatible = "amlogic,a5-pll-clkc";
+		reg = <0x0 0x8000 0x0 0x1a4>;
+		#clock-cells = <1>;
+		clocks = <&xtal>,
+			 <&scmi_clk CLKID_FIXED_PLL_DCO>,
+			 <&scmi_clk CLKID_FIXED_PLL>;
+		clock-names = "xtal",
+			      "fix_dco",
+			      "fix";
+	};
 };

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:26 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:26 +0800
Subject: [PATCH v4 0/8] clk: amlogic: Add A5 SoC PLLs and Peripheral clock
Message-ID: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>

The patchset adds support for the peripheral and PLL clock controller
on the Amlogic A5 SoC family, such as A113X2.

Due to work arrangements, I will take over this patchset and be
responsible for submitting and maintaining its subsequent revisions.

I previously resubmitted these patches in another patchset [1],
Jerome pointed out that it made tracking more difficult. Therefore,
I?m continuing the submission here based on Xianwei?s v3 version.
Sorry for this causes any inconvenience to anyone.

[1] https://lore.kernel.org/all/20250930-a4_a5_add_clock_driver-v1-0-a9acf7951589 at amlogic.com/

Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>

---
Changes in v4:
- dt-binding for peripheral clocks (kept Rob?s 'Reviewed-by' here):
  - Added optional clock source rtc pll.
  - Renamed rtc_clk?s clkid to better reflect its function.
- PLL/Clock driver:
  - Adapted to Jerome?s refactored driver interface, naming
conventions, and macros.
  - Updated related CONFIG entries in Kconfig.
- Added dts patch of PLL/Clock.
- Link to v3: https://lore.kernel.org/r/20250103-a5-clk-v3-0-a207ce83b9e9 at amlogic.com

Changes in v3:
- Rename xtal_24m to xtal, and modify some description of Kconfig.
- Drop some comment of PLL source code.
- Move definition of A5_CLK_GATE_FW frome common code into A5 peripheral source code.
- Use hw instead of name to describe parent_data.
- Making SCMI binding the first to submit.
- Link to v2: https://lore.kernel.org/r/20241120-a5-clk-v2-0-1208621e961d at amlogic.com

Changes in v2:
- Move some sys clock and axi clock from peripheral to scmi impletement.
- Remove  ARM_SCMI_PROTOCOL in Kconfig and correct name A5 but not A4.
- Add two optional clock inputs for the peripheral(ddr pll and clk-measure)
- Make some changes and adjustments according to suggestions.
- Link to v1: https://lore.kernel.org/r/20240914-a5-clk-v1-0-5ee2c4f1b08c at amlogic.com

---
Chuan Liu (8):
      dt-bindings: clock: Add Amlogic A5 SCMI clock controller support
      dt-bindings: clock: Add Amlogic A5 PLL clock controller
      dt-bindings: clock: Add Amlogic A5 peripherals clock controller
      clk: amlogic: Add A5 PLL clock controller driver
      clk: amlogic: Add A5 clock peripherals controller driver
      arm64: dts: amlogic: A5: Add scmi-clk node
      arm64: dts: amlogic: A5: Add PLL controller node
      arm64: dts: amlogic: A5: Add peripheral clock controller node

 .../clock/amlogic,a5-peripherals-clkc.yaml         | 134 ++++
 .../bindings/clock/amlogic,a5-pll-clkc.yaml        |  63 ++
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi        |  86 ++
 drivers/clk/meson/Kconfig                          |  27 +
 drivers/clk/meson/Makefile                         |   2 +
 drivers/clk/meson/a5-peripherals.c                 | 883 +++++++++++++++++++++
 drivers/clk/meson/a5-pll.c                         | 476 +++++++++++
 .../clock/amlogic,a5-peripherals-clkc.h            | 132 +++
 include/dt-bindings/clock/amlogic,a5-pll-clkc.h    |  24 +
 include/dt-bindings/clock/amlogic,a5-scmi-clkc.h   |  44 +
 10 files changed, 1871 insertions(+)
---
base-commit: f7d2388eeec24966fc4d5cf32d706f0514f29ac5
change-id: 20240911-a5-clk-35c49acb34e1

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




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:29 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:29 +0800
Subject: [PATCH v4 3/8] dt-bindings: clock: Add Amlogic A5 peripherals
 clock controller
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-3-e62ca0aae243@amlogic.com>

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

Add the peripherals clock controller dt-bindings for the Amlogic A5
SoC family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 .../clock/amlogic,a5-peripherals-clkc.yaml         | 134 +++++++++++++++++++++
 .../clock/amlogic,a5-peripherals-clkc.h            | 132 ++++++++++++++++++++
 2 files changed, 266 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/amlogic,a5-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a5-peripherals-clkc.yaml
new file mode 100644
index 000000000000..88d71d9a72ea
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,a5-peripherals-clkc.yaml
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,a5-peripherals-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic A5 series Peripheral Clock Controller
+
+maintainers:
+  - Xianwei Zhao <xianwei.zhao at amlogic.com>
+  - Chuan Liu <chuan.liu at amlogic.com>
+
+properties:
+  compatible:
+    const: amlogic,a5-peripherals-clkc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 18
+    items:
+      - description: input oscillator
+      - description: input oscillators multiplexer
+      - description: input fix pll
+      - description: input fclk div 2
+      - description: input fclk div 2p5
+      - description: input fclk div 3
+      - description: input fclk div 4
+      - description: input fclk div 5
+      - description: input fclk div 7
+      - description: input mpll2
+      - description: input mpll3
+      - description: input gp0 pll
+      - description: input gp1 pll
+      - description: input hifi pll
+      - description: input sys clk
+      - description: input axi clk
+      - description: input sys pll div 16
+      - description: input cpu clk div 16
+      - description: input pad clock for rtc clk (optional)
+      - description: input ddr pll (optional)
+      - description: input source from clk-measure (optional)
+      - description: input rtc pll (optional)
+
+  clock-names:
+    minItems: 18
+    items:
+      - const: xtal
+      - const: oscin
+      - const: fix
+      - const: fdiv2
+      - const: fdiv2p5
+      - const: fdiv3
+      - const: fdiv4
+      - const: fdiv5
+      - const: fdiv7
+      - const: mpll2
+      - const: mpll3
+      - const: gp0
+      - const: gp1
+      - const: hifi
+      - const: sysclk
+      - const: axiclk
+      - const: sysplldiv16
+      - const: cpudiv16
+      - const: pad_osc
+      - const: ddr
+      - const: clkmsr
+      - const: rtc
+
+  "#clock-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/amlogic,a5-scmi-clkc.h>
+    #include <dt-bindings/clock/amlogic,a5-pll-clkc.h>
+    apb {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        clock-controller at 0 {
+            compatible = "amlogic,a5-peripherals-clkc";
+            reg = <0x0 0x0 0x0 0x224>;
+            #clock-cells = <1>;
+            clocks = <&xtal>,
+                     <&scmi_clk CLKID_OSC>,
+                     <&scmi_clk CLKID_FIXED_PLL>,
+                     <&scmi_clk CLKID_FCLK_DIV2>,
+                     <&scmi_clk CLKID_FCLK_DIV2P5>,
+                     <&scmi_clk CLKID_FCLK_DIV3>,
+                     <&scmi_clk CLKID_FCLK_DIV4>,
+                     <&scmi_clk CLKID_FCLK_DIV5>,
+                     <&scmi_clk CLKID_FCLK_DIV7>,
+                     <&clkc_pll CLKID_MPLL2>,
+                     <&clkc_pll CLKID_MPLL3>,
+                     <&clkc_pll CLKID_GP0_PLL>,
+                     <&scmi_clk CLKID_GP1_PLL>,
+                     <&clkc_pll CLKID_HIFI_PLL>,
+                     <&scmi_clk CLKID_SYS_CLK>,
+                     <&scmi_clk CLKID_AXI_CLK>,
+                     <&scmi_clk CLKID_SYS_PLL_DIV16>,
+                     <&scmi_clk CLKID_CPU_CLK_DIV16>;
+            clock-names = "xtal",
+                          "oscin",
+                          "fix",
+                          "fdiv2",
+                          "fdiv2p5",
+                          "fdiv3",
+                          "fdiv4",
+                          "fdiv5",
+                          "fdiv7",
+                          "mpll2",
+                          "mpll3",
+                          "gp0",
+                          "gp1",
+                          "hifi",
+                          "sysclk",
+                          "axiclk",
+                          "sysplldiv16",
+                          "cpudiv16";
+        };
+    };
diff --git a/include/dt-bindings/clock/amlogic,a5-peripherals-clkc.h b/include/dt-bindings/clock/amlogic,a5-peripherals-clkc.h
new file mode 100644
index 000000000000..b8a68b7f29dc
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a5-peripherals-clkc.h
@@ -0,0 +1,132 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ * Author: Chuan Liu <chuan.liu at amlogic.com>
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_A5_PERIPHERALS_CLKC_H
+#define _DT_BINDINGS_CLOCK_AMLOGIC_A5_PERIPHERALS_CLKC_H
+
+#define CLKID_RTC_DUALDIV_CLKIN			0
+#define CLKID_RTC_DUALDIV			1
+#define CLKID_RTC_DUALDIV_SEL			2
+#define CLKID_RTC_DUALDIV_CLKOUT		3
+#define CLKID_RTC_CLK				4
+#define CLKID_SYS_RESET_CTRL			5
+#define CLKID_SYS_PWR_CTRL			6
+#define CLKID_SYS_PAD_CTRL			7
+#define CLKID_SYS_CTRL				8
+#define CLKID_SYS_TS_PLL			9
+#define CLKID_SYS_DEV_ARB			10
+#define CLKID_SYS_MAILBOX			11
+#define CLKID_SYS_JTAG_CTRL			12
+#define CLKID_SYS_IR_CTRL			13
+#define CLKID_SYS_MSR_CLK			14
+#define CLKID_SYS_ROM				15
+#define CLKID_SYS_CPU_ARB			16
+#define CLKID_SYS_RSA				17
+#define CLKID_SYS_SARADC			18
+#define CLKID_SYS_STARTUP			19
+#define CLKID_SYS_SECURE			20
+#define CLKID_SYS_SPIFC				21
+#define CLKID_SYS_DSPA				22
+#define CLKID_SYS_NNA				23
+#define CLKID_SYS_ETH_MAC			24
+#define CLKID_SYS_RAMA				25
+#define CLKID_SYS_RAMB				26
+#define CLKID_SYS_AUDIO_TOP			27
+#define CLKID_SYS_AUDIO_VAD			28
+#define CLKID_SYS_USB				29
+#define CLKID_SYS_SD_EMMC_A			30
+#define CLKID_SYS_SD_EMMC_C			31
+#define CLKID_SYS_PWM_AB			32
+#define CLKID_SYS_PWM_CD			33
+#define CLKID_SYS_PWM_EF			34
+#define CLKID_SYS_PWM_GH			35
+#define CLKID_SYS_SPICC_1			36
+#define CLKID_SYS_SPICC_0			37
+#define CLKID_SYS_UART_A			38
+#define CLKID_SYS_UART_B			39
+#define CLKID_SYS_UART_C			40
+#define CLKID_SYS_UART_D			41
+#define CLKID_SYS_UART_E			42
+#define CLKID_SYS_I2C_M_A			43
+#define CLKID_SYS_I2C_M_B			44
+#define CLKID_SYS_I2C_M_C			45
+#define CLKID_SYS_I2C_M_D			46
+#define CLKID_SYS_RTC				47
+#define CLKID_AXI_AUDIO_VAD			48
+#define CLKID_AXI_AUDIO_TOP			49
+#define CLKID_AXI_RAMB				50
+#define CLKID_AXI_RAMA				51
+#define CLKID_AXI_NNA				52
+#define CLKID_AXI_DEV1_DMC			53
+#define CLKID_AXI_DEV0_DMC			54
+#define CLKID_AXI_DSP_DMC			55
+#define CLKID_12_24M_IN				56
+#define CLKID_12M_24M				57
+#define CLKID_FCLK_25M_DIV			58
+#define CLKID_FCLK_25M				59
+#define CLKID_GEN_SEL				60
+#define CLKID_GEN_DIV				61
+#define CLKID_GEN				62
+#define CLKID_SARADC_SEL			63
+#define CLKID_SARADC_DIV			64
+#define CLKID_SARADC				65
+#define CLKID_PWM_A_SEL				66
+#define CLKID_PWM_A_DIV				67
+#define CLKID_PWM_A				68
+#define CLKID_PWM_B_SEL				69
+#define CLKID_PWM_B_DIV				70
+#define CLKID_PWM_B				71
+#define CLKID_PWM_C_SEL				72
+#define CLKID_PWM_C_DIV				73
+#define CLKID_PWM_C				74
+#define CLKID_PWM_D_SEL				75
+#define CLKID_PWM_D_DIV				76
+#define CLKID_PWM_D				77
+#define CLKID_PWM_E_SEL				78
+#define CLKID_PWM_E_DIV				79
+#define CLKID_PWM_E				80
+#define CLKID_PWM_F_SEL				81
+#define CLKID_PWM_F_DIV				82
+#define CLKID_PWM_F				83
+#define CLKID_PWM_G_SEL				84
+#define CLKID_PWM_G_DIV				85
+#define CLKID_PWM_G				86
+#define CLKID_PWM_H_SEL				87
+#define CLKID_PWM_H_DIV				88
+#define CLKID_PWM_H				89
+#define CLKID_SPICC_0_SEL			90
+#define CLKID_SPICC_0_DIV			91
+#define CLKID_SPICC_0				92
+#define CLKID_SPICC_1_SEL			93
+#define CLKID_SPICC_1_DIV			94
+#define CLKID_SPICC_1				95
+#define CLKID_SD_EMMC_A_SEL			96
+#define CLKID_SD_EMMC_A_DIV			97
+#define CLKID_SD_EMMC_A				98
+#define CLKID_SD_EMMC_C_SEL			99
+#define CLKID_SD_EMMC_C_DIV			100
+#define CLKID_SD_EMMC_C				101
+#define CLKID_TS_DIV				102
+#define CLKID_TS				103
+#define CLKID_ETH_125M_DIV			104
+#define CLKID_ETH_125M				105
+#define CLKID_ETH_RMII_DIV			106
+#define CLKID_ETH_RMII				107
+#define CLKID_DSPA_0_SEL			108
+#define CLKID_DSPA_0_DIV			109
+#define CLKID_DSPA_0				110
+#define CLKID_DSPA_1_SEL			111
+#define CLKID_DSPA_1_DIV			112
+#define CLKID_DSPA_1				113
+#define CLKID_DSPA				114
+#define CLKID_NNA_CORE_SEL			115
+#define CLKID_NNA_CORE_DIV			116
+#define CLKID_NNA_CORE				117
+#define CLKID_NNA_AXI_SEL			118
+#define CLKID_NNA_AXI_DIV			119
+#define CLKID_NNA_AXI				120
+
+#endif  /* _DT_BINDINGS_CLOCK_AMLOGIC_A5_PERIPHERALS_CLKC_H */

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:32 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:32 +0800
Subject: [PATCH v4 6/8] arm64: dts: amlogic: A5: Add scmi-clk node
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-6-e62ca0aae243@amlogic.com>

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

Add scmi-clk device node information for the Amlogic A5 SoC family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 30 +++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 2b12d8284594..a6625508893d 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -7,6 +7,8 @@
 #include "amlogic-a5-reset.h"
 #include <dt-bindings/pinctrl/amlogic,pinctrl.h>
 #include <dt-bindings/power/amlogic,a5-pwrc.h>
+#include <dt-bindings/clock/amlogic,a5-scmi-clkc.h>
+
 / {
 	cpus {
 		#address-cells = <2>;
@@ -49,6 +51,34 @@ pwrc: power-controller {
 			#power-domain-cells = <1>;
 		};
 	};
+
+	sram0: sram at f702a000 {
+		compatible = "mmio-sram";
+		reg = <0x0 0xf702a000 0x0 0x100>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0x0 0xf702a000 0x100>;
+
+		scmi_buf0: scmi-sram-section at 0 {
+			compatible = "arm,scmi-shmem";
+			reg = <0x0 0x100>;
+		};
+	};
+
+	firmware {
+		scmi {
+			compatible = "arm,scmi-smc";
+			arm,smc-id = <0x820000C1>;
+			shmem = <&scmi_buf0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			scmi_clk: protocol at 14 {
+				reg = <0x14>;
+				#clock-cells = <1>;
+			};
+		};
+	};
 };
 
 &apb {

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:28 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:28 +0800
Subject: [PATCH v4 2/8] dt-bindings: clock: Add Amlogic A5 PLL clock
 controller
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-2-e62ca0aae243@amlogic.com>

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

Add the PLL clock controller dt-bindings for the Amlogic A5 SoC
family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 .../bindings/clock/amlogic,a5-pll-clkc.yaml        | 63 ++++++++++++++++++++++
 include/dt-bindings/clock/amlogic,a5-pll-clkc.h    | 24 +++++++++
 2 files changed, 87 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/amlogic,a5-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a5-pll-clkc.yaml
new file mode 100644
index 000000000000..d74570a90926
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,a5-pll-clkc.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,a5-pll-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic A5 series PLL Clock Controller
+
+maintainers:
+  - Chuan Liu <chuan.liu at amlogic.com>
+  - Xianwei Zhao <xianwei.zhao at amlogic.com>
+
+properties:
+  compatible:
+    const: amlogic,a5-pll-clkc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: input oscillator
+      - description: input fix pll dco
+      - description: input fix pll
+
+  clock-names:
+    items:
+      - const: xtal
+      - const: fix_dco
+      - const: fix
+
+  "#clock-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/amlogic,a5-scmi-clkc.h>
+    apb {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        clock-controller at 8000 {
+            compatible = "amlogic,a5-pll-clkc";
+            reg = <0x0 0x8000 0x0 0x1a4>;
+            clocks = <&xtal>,
+                     <&scmi_clk CLKID_FIXED_PLL_DCO>,
+                     <&scmi_clk CLKID_FIXED_PLL>;
+            clock-names = "xtal",
+                          "fix_dco",
+                          "fix";
+            #clock-cells = <1>;
+        };
+    };
diff --git a/include/dt-bindings/clock/amlogic,a5-pll-clkc.h b/include/dt-bindings/clock/amlogic,a5-pll-clkc.h
new file mode 100644
index 000000000000..a74c448a8d8a
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,a5-pll-clkc.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (c) 2024 Amlogic, Inc. All rights reserved.
+ * Author: Chuan Liu <chuan.liu at amlogic.com>
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_A5_PLL_CLKC_H
+#define _DT_BINDINGS_CLOCK_AMLOGIC_A5_PLL_CLKC_H
+
+#define CLKID_MPLL_PREDIV			0
+#define CLKID_MPLL0_DIV				1
+#define CLKID_MPLL0				2
+#define CLKID_MPLL1_DIV				3
+#define CLKID_MPLL1				4
+#define CLKID_MPLL2_DIV				5
+#define CLKID_MPLL2				6
+#define CLKID_MPLL3_DIV				7
+#define CLKID_MPLL3				8
+#define CLKID_GP0_PLL_DCO			9
+#define CLKID_GP0_PLL				10
+#define CLKID_HIFI_PLL_DCO			11
+#define CLKID_HIFI_PLL				12
+
+#endif  /* _DT_BINDINGS_CLOCK_AMLOGIC_A5_PLL_CLKC_H */

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:34 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:34 +0800
Subject: [PATCH v4 8/8] arm64: dts: amlogic: A5: Add peripheral clock
 controller node
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-8-e62ca0aae243@amlogic.com>

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

Add peripheral clock controller node for A5 SoC family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
 arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi | 43 +++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
index 70deeab220e0..7324e427ed39 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-a5.dtsi
@@ -9,6 +9,7 @@
 #include <dt-bindings/power/amlogic,a5-pwrc.h>
 #include <dt-bindings/clock/amlogic,a5-scmi-clkc.h>
 #include <dt-bindings/clock/amlogic,a5-pll-clkc.h>
+#include <dt-bindings/clock/amlogic,a5-peripherals-clkc.h>
 
 / {
 	cpus {
@@ -83,6 +84,48 @@ scmi_clk: protocol at 14 {
 };
 
 &apb {
+	clkc_periphs: clock-controller at 0 {
+		compatible = "amlogic,a5-peripherals-clkc";
+		reg = <0x0 0x0 0x0 0x224>;
+		#clock-cells = <1>;
+		clocks = <&xtal>,
+			 <&scmi_clk CLKID_OSC>,
+			 <&scmi_clk CLKID_FIXED_PLL>,
+			 <&scmi_clk CLKID_FCLK_DIV2>,
+			 <&scmi_clk CLKID_FCLK_DIV2P5>,
+			 <&scmi_clk CLKID_FCLK_DIV3>,
+			 <&scmi_clk CLKID_FCLK_DIV4>,
+			 <&scmi_clk CLKID_FCLK_DIV5>,
+			 <&scmi_clk CLKID_FCLK_DIV7>,
+			 <&clkc_pll CLKID_MPLL2>,
+			 <&clkc_pll CLKID_MPLL3>,
+			 <&clkc_pll CLKID_GP0_PLL>,
+			 <&scmi_clk CLKID_GP1_PLL>,
+			 <&clkc_pll CLKID_HIFI_PLL>,
+			 <&scmi_clk CLKID_SYS_CLK>,
+			 <&scmi_clk CLKID_AXI_CLK>,
+			 <&scmi_clk CLKID_SYS_PLL_DIV16>,
+			 <&scmi_clk CLKID_CPU_CLK_DIV16>;
+		clock-names = "xtal",
+			      "oscin",
+			      "fix",
+			      "fdiv2",
+			      "fdiv2p5",
+			      "fdiv3",
+			      "fdiv4",
+			      "fdiv5",
+			      "fdiv7",
+			      "mpll2",
+			      "mpll3",
+			      "gp0",
+			      "gp1",
+			      "hifi",
+			      "sysclk",
+			      "axiclk",
+			      "sysplldiv16",
+			      "cpudiv16";
+	};
+
 	reset: reset-controller at 2000 {
 		compatible = "amlogic,a5-reset",
 			     "amlogic,meson-s4-reset";

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:30 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:30 +0800
Subject: [PATCH v4 4/8] clk: amlogic: Add A5 PLL clock controller driver
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-4-e62ca0aae243@amlogic.com>

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

Add the PLL clock controller driver for the Amlogic A5 SoC family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/clk/meson/Kconfig  |  14 ++
 drivers/clk/meson/Makefile |   1 +
 drivers/clk/meson/a5-pll.c | 476 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 491 insertions(+)

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 71481607a6d5..b627821da081 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -132,6 +132,20 @@ config COMMON_CLK_A1_PERIPHERALS
 	  device, A1 SoC Family. Say Y if you want A1 Peripherals clock
 	  controller to work.
 
+config COMMON_CLK_A5_PLL
+	tristate "Amlogic A5 PLL clock controller"
+	depends on ARM64
+	default ARCH_MESON
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_PLL
+	select COMMON_CLK_MESON_MPLL
+	select COMMON_CLK_MESON_CLKC_UTILS
+	imply COMMON_CLK_SCMI
+	help
+	  Support for the PLL clock controller on Amlogic  A113X2 device, AKA A5.
+	  Say Y if you want the board to work, because PLLs are the parent
+	  of most peripherals.
+
 config COMMON_CLK_C3_PLL
 	tristate "Amlogic C3 PLL clock controller"
 	depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index c6998e752c68..a074aa7e187f 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
 obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
 obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
 obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
+obj-$(CONFIG_COMMON_CLK_A5_PLL) += a5-pll.o
 obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
 obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/a5-pll.c b/drivers/clk/meson/a5-pll.c
new file mode 100644
index 000000000000..1789a7e6470d
--- /dev/null
+++ b/drivers/clk/meson/a5-pll.c
@@ -0,0 +1,476 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Amlogic A5 PLL Controller Driver
+ *
+ * Copyright (c) 2024-2025 Amlogic, inc.
+ * Author: Chuan Liu <chuan.liu at amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-mpll.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,a5-pll-clkc.h>
+
+#define GP0PLL_CTRL0			0x80
+#define GP0PLL_CTRL1			0x84
+#define GP0PLL_CTRL2			0x88
+#define GP0PLL_CTRL3			0x8c
+#define GP0PLL_CTRL4			0x90
+#define GP0PLL_CTRL5			0x94
+#define GP0PLL_CTRL6			0x98
+#define HIFIPLL_CTRL0			0x100
+#define HIFIPLL_CTRL1			0x104
+#define HIFIPLL_CTRL2			0x108
+#define HIFIPLL_CTRL3			0x10c
+#define HIFIPLL_CTRL4			0x110
+#define HIFIPLL_CTRL5			0x114
+#define HIFIPLL_CTRL6			0x118
+#define MPLL_CTRL0			0x180
+#define MPLL_CTRL1			0x184
+#define MPLL_CTRL2			0x188
+#define MPLL_CTRL3			0x18c
+#define MPLL_CTRL4			0x190
+#define MPLL_CTRL5			0x194
+#define MPLL_CTRL6			0x198
+#define MPLL_CTRL7			0x19c
+#define MPLL_CTRL8			0x1a0
+
+static struct clk_fixed_factor a5_mpll_prediv = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll_prediv",
+		.ops = &clk_fixed_factor_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "fix_dco"
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct reg_sequence a5_mpll0_init_regs[] = {
+	{ .reg = MPLL_CTRL2,	.def = 0x40000033 },
+};
+
+static struct clk_regmap a5_mpll0_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = a5_mpll0_init_regs,
+		.init_count = ARRAY_SIZE(a5_mpll0_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_mpll0 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL1,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &a5_mpll0_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence a5_mpll1_init_regs[] = {
+	{ .reg = MPLL_CTRL4,	.def = 0x40000033 },
+};
+
+static struct clk_regmap a5_mpll1_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = a5_mpll1_init_regs,
+		.init_count = ARRAY_SIZE(a5_mpll1_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll1_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_mpll1 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL3,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "a5_mpll1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &a5_mpll1_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence a5_mpll2_init_regs[] = {
+	{ .reg = MPLL_CTRL6,	.def = 0x40000033 },
+};
+
+static struct clk_regmap a5_mpll2_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = a5_mpll2_init_regs,
+		.init_count = ARRAY_SIZE(a5_mpll2_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll2_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_mpll2 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL5,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll2",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &a5_mpll2_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence a5_mpll3_init_regs[] = {
+	{ .reg = MPLL_CTRL8,	.def = 0x40000033 },
+};
+
+static struct clk_regmap a5_mpll3_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = a5_mpll3_init_regs,
+		.init_count = ARRAY_SIZE(a5_mpll3_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll3_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_mpll3 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL7,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll3",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &a5_mpll3_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence a5_gp0_init_regs[] = {
+	{ .reg = GP0PLL_CTRL3, .def = 0x6a295c00 },
+	{ .reg = GP0PLL_CTRL4, .def = 0x65771290 },
+	{ .reg = GP0PLL_CTRL5, .def = 0x3927200a },
+	{ .reg = GP0PLL_CTRL6, .def = 0x54540000 }
+};
+
+static const struct pll_mult_range a5_gp0_pll_mult_range = {
+	.min = 125,
+	.max = 250,
+};
+
+static struct clk_regmap a5_gp0_pll_dco = {
+	.data = &(struct meson_clk_pll_data) {
+		.en = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.frac = {
+			.reg_off = GP0PLL_CTRL1,
+			.shift   = 0,
+			.width   = 17,
+		},
+		.n = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.range = &a5_gp0_pll_mult_range,
+		.init_regs = a5_gp0_init_regs,
+		.init_count = ARRAY_SIZE(a5_gp0_init_regs),
+		.frac_max = 100000,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gp0_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+/* The maximum frequency divider supports is 32, not 128(2^7) */
+static const struct clk_div_table a5_gp0_pll_od_table[] = {
+	{ 0,  1 },
+	{ 1,  2 },
+	{ 2,  4 },
+	{ 3,  8 },
+	{ 4, 16 },
+	{ 5, 32 },
+	{ /* sentinel */ }
+};
+
+static struct clk_regmap a5_gp0_pll = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = GP0PLL_CTRL0,
+		.shift = 16,
+		.width = 3,
+		.table = a5_gp0_pll_od_table,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gp0_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_gp0_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence a5_hifi_init_regs[] = {
+	{ .reg = HIFIPLL_CTRL3, .def = 0x6a285c00 },
+	{ .reg = HIFIPLL_CTRL4, .def = 0x65771290 },
+	{ .reg = HIFIPLL_CTRL5, .def = 0x3927200a },
+	{ .reg = HIFIPLL_CTRL6, .def = 0x56540000 }
+};
+
+static const struct pll_mult_range a5_hifi_pll_mult_range = {
+	.min = 125,
+	.max = 250,
+};
+
+static struct clk_regmap a5_hifi_pll_dco = {
+	.data = &(struct meson_clk_pll_data) {
+		.en = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.frac = {
+			.reg_off = HIFIPLL_CTRL1,
+			.shift   = 0,
+			.width   = 17,
+		},
+		.n = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.range = &a5_hifi_pll_mult_range,
+		.init_regs = a5_hifi_init_regs,
+		.init_count = ARRAY_SIZE(a5_hifi_init_regs),
+		.frac_max = 100000,
+		.flags = CLK_MESON_PLL_ROUND_CLOSEST,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "hifi_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_hifi_pll = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = HIFIPLL_CTRL0,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "hifi_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_hifi_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_hw *a5_pll_hw_clks[] = {
+	[CLKID_MPLL_PREDIV]	= &a5_mpll_prediv.hw,
+	[CLKID_MPLL0_DIV]	= &a5_mpll0_div.hw,
+	[CLKID_MPLL0]		= &a5_mpll0.hw,
+	[CLKID_MPLL1_DIV]	= &a5_mpll1_div.hw,
+	[CLKID_MPLL1]		= &a5_mpll1.hw,
+	[CLKID_MPLL2_DIV]	= &a5_mpll2_div.hw,
+	[CLKID_MPLL2]		= &a5_mpll2.hw,
+	[CLKID_MPLL3_DIV]	= &a5_mpll3_div.hw,
+	[CLKID_MPLL3]		= &a5_mpll3.hw,
+	[CLKID_GP0_PLL_DCO]	= &a5_gp0_pll_dco.hw,
+	[CLKID_GP0_PLL]		= &a5_gp0_pll.hw,
+	[CLKID_HIFI_PLL_DCO]	= &a5_hifi_pll_dco.hw,
+	[CLKID_HIFI_PLL]	= &a5_hifi_pll.hw
+};
+
+static const struct meson_clkc_data a5_pll_clkc_data = {
+	.hw_clks = {
+		.hws = a5_pll_hw_clks,
+		.num = ARRAY_SIZE(a5_pll_hw_clks),
+	},
+};
+
+static const struct of_device_id a5_pll_clkc_match_table[] = {
+	{
+		.compatible = "amlogic,a5-pll-clkc",
+		.data = &a5_pll_clkc_data,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, a5_pll_clkc_match_table);
+
+static struct platform_driver a5_pll_clkc_driver = {
+	.probe = meson_clkc_mmio_probe,
+	.driver = {
+		.name = "a5-pll-clkc",
+		.of_match_table = a5_pll_clkc_match_table,
+	},
+};
+module_platform_driver(a5_pll_clkc_driver);
+
+MODULE_DESCRIPTION("Amlogic A5 PLL Clock Controller driver");
+MODULE_AUTHOR("Chuan Liu <chuan.liu at amlogic.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_MESON");

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Tue Oct 28 02:52:31 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Tue, 28 Oct 2025 17:52:31 +0800
Subject: [PATCH v4 5/8] clk: amlogic: Add A5 clock peripherals controller
 driver
In-Reply-To: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
References: <20251028-a5-clk-v4-0-e62ca0aae243@amlogic.com>
Message-ID: <20251028-a5-clk-v4-5-e62ca0aae243@amlogic.com>

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

Add the peripherals clock controller driver for the Amlogic A5 SoC
family.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
Signed-off-by: Xianwei Zhao <xianwei.zhao at amlogic.com>
---
 drivers/clk/meson/Kconfig          |  13 +
 drivers/clk/meson/Makefile         |   1 +
 drivers/clk/meson/a5-peripherals.c | 883 +++++++++++++++++++++++++++++++++++++
 3 files changed, 897 insertions(+)

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index b627821da081..5576f351ef8c 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -146,6 +146,19 @@ config COMMON_CLK_A5_PLL
 	  Say Y if you want the board to work, because PLLs are the parent
 	  of most peripherals.
 
+config COMMON_CLK_A5_PERIPHERALS
+	tristate "Amlogic A5 peripherals clock controller"
+	depends on ARM64
+	default ARCH_MESON
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_DUALDIV
+	select COMMON_CLK_MESON_CLKC_UTILS
+	imply COMMON_CLK_SCMI
+	imply COMMON_CLK_A5_PLL
+	help
+	  Support for the Peripherals clock controller on Amlogic A113X2 device,
+	  AKA A5. Say Y if you want the peripherals clock to work.
+
 config COMMON_CLK_C3_PLL
 	tristate "Amlogic C3 PLL clock controller"
 	depends on ARM64
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index a074aa7e187f..0432027d7e2e 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
 obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o
 obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
 obj-$(CONFIG_COMMON_CLK_A5_PLL) += a5-pll.o
+obj-$(CONFIG_COMMON_CLK_A5_PERIPHERALS) += a5-peripherals.o
 obj-$(CONFIG_COMMON_CLK_C3_PLL) += c3-pll.o
 obj-$(CONFIG_COMMON_CLK_C3_PERIPHERALS) += c3-peripherals.o
 obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/a5-peripherals.c b/drivers/clk/meson/a5-peripherals.c
new file mode 100644
index 000000000000..eca9f3dcc256
--- /dev/null
+++ b/drivers/clk/meson/a5-peripherals.c
@@ -0,0 +1,883 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Amlogic A5 Peripherals Clock Controller Driver
+ *
+ * Copyright (c) 2024-2025 Amlogic, inc.
+ * Author: Chuan Liu <chuan.liu at amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include "clk-regmap.h"
+#include "clk-dualdiv.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,a5-peripherals-clkc.h>
+
+#define RTC_BY_OSCIN_CTRL0		0x8
+#define RTC_BY_OSCIN_CTRL1		0xc
+#define RTC_CTRL			0x10
+#define SYS_CLK_EN0_REG0		0x44
+#define SYS_CLK_EN0_REG1		0x48
+#define DSPA_CLK_CTRL0			0x9c
+#define CLK12_24_CTRL			0xa8
+#define AXI_CLK_EN0			0xac
+#define TS_CLK_CTRL			0x158
+#define ETH_CLK_CTRL			0x164
+#define NAND_CLK_CTRL			0x168
+#define SD_EMMC_CLK_CTRL		0x16c
+#define SPICC_CLK_CTRL			0x174
+#define GEN_CLK_CTRL			0x178
+#define SAR_CLK_CTRL0			0x17c
+#define PWM_CLK_AB_CTRL			0x180
+#define PWM_CLK_CD_CTRL			0x184
+#define PWM_CLK_EF_CTRL			0x188
+#define PWM_CLK_GH_CTRL			0x18c
+#define NNA_CLK_CNTL			0x220
+
+static struct clk_regmap a5_rtc_dualdiv_clkin = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = RTC_BY_OSCIN_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_dualdiv_clkin",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "oscin",
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct meson_clk_dualdiv_param a5_rtc_dualdiv_table[] = {
+	{ 733, 732, 8, 11, 1 },
+	{ /* sentinel */ }
+};
+
+static struct clk_regmap a5_rtc_dualdiv = {
+	.data = &(struct meson_clk_dualdiv_data) {
+		.n1 = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = RTC_BY_OSCIN_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = RTC_BY_OSCIN_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = a5_rtc_dualdiv_table,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_dualdiv",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_rtc_dualdiv_clkin.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct clk_parent_data a5_rtc_dualdiv_parent_data[] = {
+	{ .hw = &a5_rtc_dualdiv.hw },
+	{ .hw = &a5_rtc_dualdiv_clkin.hw }
+};
+
+static struct clk_regmap a5_rtc_dualdiv_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_BY_OSCIN_CTRL1,
+		.mask = 0x1,
+		.shift = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_dualdiv_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = a5_rtc_dualdiv_parent_data,
+		.num_parents = ARRAY_SIZE(a5_rtc_dualdiv_parent_data),
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a5_rtc_dualdiv_clkout = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = RTC_BY_OSCIN_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_dualdiv_clkout",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_rtc_dualdiv_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct clk_parent_data a5_rtc_clk_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .hw = &a5_rtc_dualdiv_clkout.hw },
+	{ .fw_name = "pad_osc" }
+};
+
+static struct clk_regmap a5_rtc_clk = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_CTRL,
+		.mask = 0x3,
+		.shift = 0,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_clk",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = a5_rtc_clk_parent_data,
+		.num_parents = ARRAY_SIZE(a5_rtc_clk_parent_data),
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+#define A5_PCLK(_name, _reg, _bit, _pdata, _flags)			\
+struct clk_regmap a5_##_name = {					\
+	.data = &(struct clk_regmap_gate_data) {			\
+		.offset = (_reg),					\
+		.bit_idx = (_bit),					\
+	},								\
+	.hw.init = &(struct clk_init_data) {				\
+		.name = #_name,						\
+		.ops = &clk_regmap_gate_ops,				\
+		.parent_data = (_pdata),				\
+		.num_parents = 1,					\
+		.flags = (_flags),					\
+	},								\
+}
+
+static const struct clk_parent_data a5_sys_pclk_parents = { .fw_name = "sysclk" };
+
+#define A5_SYS_PCLK(_name, _reg, _bit, _flags) \
+	A5_PCLK(_name, _reg, _bit, &a5_sys_pclk_parents, _flags)
+
+static A5_SYS_PCLK(sys_reset_ctrl,	SYS_CLK_EN0_REG0, 1, 0);
+static A5_SYS_PCLK(sys_pwr_ctrl,	SYS_CLK_EN0_REG0, 3, 0);
+static A5_SYS_PCLK(sys_pad_ctrl,	SYS_CLK_EN0_REG0, 4, 0);
+static A5_SYS_PCLK(sys_ctrl,		SYS_CLK_EN0_REG0, 5, 0);
+static A5_SYS_PCLK(sys_ts_pll,		SYS_CLK_EN0_REG0, 6, 0);
+
+/*
+ * NOTE: sys_dev_arb provides the clock to the ETH and SPICC arbiters that
+ * access the AXI bus.
+ */
+static A5_SYS_PCLK(sys_dev_arb,		SYS_CLK_EN0_REG0, 7, 0);
+static A5_SYS_PCLK(sys_mailbox,		SYS_CLK_EN0_REG0, 10, 0);
+static A5_SYS_PCLK(sys_jtag_ctrl,	SYS_CLK_EN0_REG0, 12, 0);
+static A5_SYS_PCLK(sys_ir_ctrl,		SYS_CLK_EN0_REG0, 13, 0);
+static A5_SYS_PCLK(sys_msr_clk,		SYS_CLK_EN0_REG0, 15, 0);
+static A5_SYS_PCLK(sys_rom,		SYS_CLK_EN0_REG0, 16, 0);
+static A5_SYS_PCLK(sys_cpu_apb,		SYS_CLK_EN0_REG0, 18, 0);
+static A5_SYS_PCLK(sys_rsa,		SYS_CLK_EN0_REG0, 19, 0);
+static A5_SYS_PCLK(sys_saradc,		SYS_CLK_EN0_REG0, 20, 0);
+static A5_SYS_PCLK(sys_startup,		SYS_CLK_EN0_REG0, 21, 0);
+static A5_SYS_PCLK(sys_secure,		SYS_CLK_EN0_REG0, 22, 0);
+static A5_SYS_PCLK(sys_spifc,		SYS_CLK_EN0_REG0, 23, 0);
+static A5_SYS_PCLK(sys_dspa,		SYS_CLK_EN0_REG0, 24, 0);
+static A5_SYS_PCLK(sys_nna,		SYS_CLK_EN0_REG0, 25, 0);
+static A5_SYS_PCLK(sys_eth_mac,		SYS_CLK_EN0_REG0, 26, 0);
+static A5_SYS_PCLK(sys_rama,		SYS_CLK_EN0_REG0, 28, 0);
+static A5_SYS_PCLK(sys_ramb,		SYS_CLK_EN0_REG0, 30, 0);
+static A5_SYS_PCLK(sys_audio_top,	SYS_CLK_EN0_REG1, 0, 0);
+static A5_SYS_PCLK(sys_audio_vad,	SYS_CLK_EN0_REG1, 1, 0);
+static A5_SYS_PCLK(sys_usb,		SYS_CLK_EN0_REG1, 2, 0);
+static A5_SYS_PCLK(sys_sd_emmc_a,	SYS_CLK_EN0_REG1, 3, 0);
+static A5_SYS_PCLK(sys_sd_emmc_c,	SYS_CLK_EN0_REG1, 4, 0);
+static A5_SYS_PCLK(sys_pwm_ab,		SYS_CLK_EN0_REG1, 5, 0);
+static A5_SYS_PCLK(sys_pwm_cd,		SYS_CLK_EN0_REG1, 6, 0);
+static A5_SYS_PCLK(sys_pwm_ef,		SYS_CLK_EN0_REG1, 7, 0);
+static A5_SYS_PCLK(sys_pwm_gh,		SYS_CLK_EN0_REG1, 8, 0);
+static A5_SYS_PCLK(sys_spicc_1,		SYS_CLK_EN0_REG1, 9, 0);
+static A5_SYS_PCLK(sys_spicc_0,		SYS_CLK_EN0_REG1, 10, 0);
+static A5_SYS_PCLK(sys_uart_a,		SYS_CLK_EN0_REG1, 11, 0);
+static A5_SYS_PCLK(sys_uart_b,		SYS_CLK_EN0_REG1, 12, 0);
+static A5_SYS_PCLK(sys_uart_c,		SYS_CLK_EN0_REG1, 13, 0);
+static A5_SYS_PCLK(sys_uart_d,		SYS_CLK_EN0_REG1, 14, 0);
+static A5_SYS_PCLK(sys_uart_e,		SYS_CLK_EN0_REG1, 15, 0);
+static A5_SYS_PCLK(sys_i2c_m_a,		SYS_CLK_EN0_REG1, 16, 0);
+static A5_SYS_PCLK(sys_i2c_m_b,		SYS_CLK_EN0_REG1, 17, 0);
+static A5_SYS_PCLK(sys_i2c_m_c,		SYS_CLK_EN0_REG1, 18, 0);
+static A5_SYS_PCLK(sys_i2c_m_d,		SYS_CLK_EN0_REG1, 19, 0);
+static A5_SYS_PCLK(sys_rtc,		SYS_CLK_EN0_REG1, 21, 0);
+
+static const struct clk_parent_data a5_axi_clk_parents = { .fw_name = "axiclk" };
+
+#define A5_AXI_CLK(_name, _reg, _bit, _flags) \
+	A5_PCLK(_name, _reg, _bit, &a5_axi_clk_parents, _flags)
+
+static A5_AXI_CLK(axi_audio_vad,	AXI_CLK_EN0, 0, 0);
+static A5_AXI_CLK(axi_audio_top,	AXI_CLK_EN0, 1, 0);
+static A5_AXI_CLK(axi_ramb,		AXI_CLK_EN0, 5, 0);
+static A5_AXI_CLK(axi_rama,		AXI_CLK_EN0, 6, 0);
+static A5_AXI_CLK(axi_nna,		AXI_CLK_EN0, 12, 0);
+
+/*
+ * NOTE: axi_dev1_dmc provides the clock for the peripherals(EMMC, SDIO,
+ * sec_top, USB, Audio) to access the AXI bus of the DDR.
+ */
+static A5_AXI_CLK(axi_dev1_dmc,	AXI_CLK_EN0, 13, 0);
+
+/*
+ * NOTE: axi_dev0_dmc provides the clock for the peripherals(ETH and SPICC)
+ * to access the AXI bus of the DDR.
+ */
+static A5_AXI_CLK(axi_dev0_dmc,	AXI_CLK_EN0, 14, 0);
+static A5_AXI_CLK(axi_dsp_dmc,		AXI_CLK_EN0, 15, 0);
+
+static struct clk_regmap a5_clk_12_24m_in = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 11,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "clk_12_24m_in",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_clk_12_24m = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = CLK12_24_CTRL,
+		.shift = 10,
+		.width = 1,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "clk_12_24m",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_clk_12_24m_in.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_fclk_25m_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = CLK12_24_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "fclk_25m_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "fix",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_fclk_25m = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 12,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "fclk_25m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_fclk_25m_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/*
+ * Channel 4 5 8 9 10 11 13 14 15 16 18 are not connected.
+ *
+ * gp1 is designed for DSU (DynamIQ Shared Unit) alone. It cannot be changed
+ * arbitrarily. gp1 is read-only in the kernel and is only open for debug
+ * purposes.
+ */
+static u32 a5_gen_parent_table[] = { 0, 1, 2, 3, 6, 7, 12, 17, 19, 20, 21, 22,
+				    23, 24, 25, 26, 27, 28};
+
+static const struct clk_parent_data a5_gen_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .hw = &a5_rtc_clk.hw },
+	{ .fw_name = "sysplldiv16" },
+	{ .fw_name = "ddr" },
+	{ .fw_name = "gp1" },
+	{ .fw_name = "hifi" },
+	{ .fw_name = "clkmsr" },
+	{ .fw_name = "cpudiv16" },
+	{ .fw_name = "fdiv2" },
+	{ .fw_name = "fdiv2p5" },
+	{ .fw_name = "fdiv3" },
+	{ .fw_name = "fdiv4" },
+	{ .fw_name = "fdiv5" },
+	{ .fw_name = "fdiv7" },
+	{ .fw_name = "mpll0" },
+	{ .fw_name = "mpll1" },
+	{ .fw_name = "mpll2" },
+	{ .fw_name = "mpll3" }
+};
+
+static struct clk_regmap a5_gen_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = GEN_CLK_CTRL,
+		.mask = 0x1f,
+		.shift = 12,
+		.table = a5_gen_parent_table,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gen_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = a5_gen_parent_data,
+		.num_parents = ARRAY_SIZE(a5_gen_parent_data),
+	},
+};
+
+static struct clk_regmap a5_gen_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = GEN_CLK_CTRL,
+		.shift = 0,
+		.width = 11,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gen_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_gen_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a5_gen = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = GEN_CLK_CTRL,
+		.bit_idx = 11,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gen",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_gen_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+#define A5_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
+	MESON_COMP_SEL(a5_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
+
+#define A5_COMP_DIV(_name, _reg, _shift, _width) \
+	MESON_COMP_DIV(a5_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
+
+#define A5_COMP_GATE(_name, _reg, _bit) \
+	MESON_COMP_GATE(a5_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
+
+static const struct clk_parent_data a5_saradc_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .fw_name = "sysclk" }
+};
+
+static A5_COMP_SEL(saradc, SAR_CLK_CTRL0, 9, 0x3, a5_saradc_parent_data);
+static A5_COMP_DIV(saradc, SAR_CLK_CTRL0, 0, 8);
+static A5_COMP_GATE(saradc, SAR_CLK_CTRL0, 8);
+
+static const struct clk_parent_data a5_pwm_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .hw = &a5_rtc_clk.hw },
+	{ .fw_name = "fdiv4" },
+	{ .fw_name = "fdiv3" }
+};
+
+static A5_COMP_SEL(pwm_a, PWM_CLK_AB_CTRL, 9, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_a, PWM_CLK_AB_CTRL, 0, 8);
+static A5_COMP_GATE(pwm_a, PWM_CLK_AB_CTRL, 8);
+
+static A5_COMP_SEL(pwm_b, PWM_CLK_AB_CTRL, 25, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_b, PWM_CLK_AB_CTRL, 16, 8);
+static A5_COMP_GATE(pwm_b, PWM_CLK_AB_CTRL, 24);
+
+static A5_COMP_SEL(pwm_c, PWM_CLK_CD_CTRL, 9, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_c, PWM_CLK_CD_CTRL, 0, 8);
+static A5_COMP_GATE(pwm_c, PWM_CLK_CD_CTRL, 8);
+
+static A5_COMP_SEL(pwm_d, PWM_CLK_CD_CTRL, 25, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_d, PWM_CLK_CD_CTRL, 16, 8);
+static A5_COMP_GATE(pwm_d, PWM_CLK_CD_CTRL, 24);
+
+static A5_COMP_SEL(pwm_e, PWM_CLK_EF_CTRL, 9, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_e, PWM_CLK_EF_CTRL, 0, 8);
+static A5_COMP_GATE(pwm_e, PWM_CLK_EF_CTRL, 8);
+
+static A5_COMP_SEL(pwm_f, PWM_CLK_EF_CTRL, 25, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_f, PWM_CLK_EF_CTRL, 16, 8);
+static A5_COMP_GATE(pwm_f, PWM_CLK_EF_CTRL, 24);
+
+static A5_COMP_SEL(pwm_g, PWM_CLK_GH_CTRL, 9, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_g, PWM_CLK_GH_CTRL, 0, 8);
+static A5_COMP_GATE(pwm_g, PWM_CLK_GH_CTRL, 8);
+
+static A5_COMP_SEL(pwm_h, PWM_CLK_GH_CTRL, 25, 0x3, a5_pwm_parent_data);
+static A5_COMP_DIV(pwm_h, PWM_CLK_GH_CTRL, 16, 8);
+static A5_COMP_GATE(pwm_h, PWM_CLK_GH_CTRL, 24);
+
+/*
+ * NOTE: Channel 7 is gp1, because gp1 is designed for DSU, so spicc does not
+ * support this source in the driver.
+ */
+static const struct clk_parent_data a5_spicc_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .fw_name = "sysclk" },
+	{ .fw_name = "fdiv4" },
+	{ .fw_name = "fdiv3" },
+	{ .fw_name = "fdiv2" },
+	{ .fw_name = "fdiv5" },
+	{ .fw_name = "fdiv7" }
+};
+
+static A5_COMP_SEL(spicc_0, SPICC_CLK_CTRL, 7, 0x7, a5_spicc_parent_data);
+static A5_COMP_DIV(spicc_0, SPICC_CLK_CTRL, 0, 6);
+static A5_COMP_GATE(spicc_0, SPICC_CLK_CTRL, 6);
+
+static A5_COMP_SEL(spicc_1, SPICC_CLK_CTRL, 23, 0x7, a5_spicc_parent_data);
+static A5_COMP_DIV(spicc_1, SPICC_CLK_CTRL, 16, 6);
+static A5_COMP_GATE(spicc_1, SPICC_CLK_CTRL, 22);
+
+static const struct clk_parent_data a5_sd_emmc_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .fw_name = "fdiv2" },
+	{ .fw_name = "fdiv3" },
+	{ .fw_name = "hifi" },
+	{ .fw_name = "fdiv2p5" },
+	{ .fw_name = "mpll2" },
+	{ .fw_name = "mpll3" },
+	{ .fw_name = "gp0" }
+};
+
+static A5_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL, 9, 0x7, a5_sd_emmc_parent_data);
+static A5_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL, 0, 7);
+static A5_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL, 7);
+
+static A5_COMP_SEL(sd_emmc_c, NAND_CLK_CTRL, 9, 0x7, a5_sd_emmc_parent_data);
+static A5_COMP_DIV(sd_emmc_c, NAND_CLK_CTRL, 0, 7);
+static A5_COMP_GATE(sd_emmc_c, NAND_CLK_CTRL, 7);
+
+static struct clk_regmap a5_ts_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = TS_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "ts_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "oscin",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_ts = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = TS_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "ts",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_ts_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_fixed_factor a5_eth_125m_div = {
+	.mult = 1,
+	.div = 8,
+	.hw.init = &(struct clk_init_data) {
+		.name = "eth_125m_div",
+		.ops = &clk_fixed_factor_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "fdiv2",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_eth_125m = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = ETH_CLK_CTRL,
+		.bit_idx = 7,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "eth_125m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_eth_125m_div.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_eth_rmii_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = ETH_CLK_CTRL,
+		.shift = 0,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "eth_rmii_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "fdiv2",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap a5_eth_rmii = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = ETH_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "eth_rmii",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_eth_rmii_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* Channel 6 is gp1. */
+static u32 a5_dspa_parent_table[] = { 0, 1, 2, 3, 4, 5, 7};
+
+static const struct clk_parent_data a5_dspa_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .fw_name = "fdiv2p5" },
+	{ .fw_name = "fdiv3" },
+	{ .fw_name = "rtc" },  /* rtc_pll */
+	{ .fw_name = "hifi" },
+	{ .fw_name = "fdiv4" },
+	{ .hw = &a5_rtc_clk.hw }
+};
+
+static struct clk_regmap a5_dspa_0_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 10,
+		.table = a5_dspa_parent_table,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_0_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = a5_dspa_parent_data,
+		.num_parents = ARRAY_SIZE(a5_dspa_parent_data),
+	},
+};
+
+static struct clk_regmap a5_dspa_0_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = DSPA_CLK_CTRL0,
+		.shift = 0,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_0_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_dspa_0_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a5_dspa_0 = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = DSPA_CLK_CTRL0,
+		.bit_idx = 13,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_dspa_0_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a5_dspa_1_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 26,
+		.table = a5_dspa_parent_table,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_1_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = a5_dspa_parent_data,
+		.num_parents = ARRAY_SIZE(a5_dspa_parent_data),
+	},
+};
+
+static struct clk_regmap a5_dspa_1_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = DSPA_CLK_CTRL0,
+		.shift = 16,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_1_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_dspa_1_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a5_dspa_1 = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = DSPA_CLK_CTRL0,
+		.bit_idx = 29,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_dspa_1_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap a5_dspa = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&a5_dspa_0.hw,
+			&a5_dspa_1.hw
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+#define A5_COMP_SEL_WITH_TAB(_name, _reg, _shift, _mask, _pdata, _table) \
+	MESON_COMP_SEL(a5_, _name, _reg, _shift, _mask, _pdata, _table, 0, 0)
+
+/* Channel 6 is gp1. */
+static u32 a5_nna_parent_table[] = { 0, 1, 2, 3, 4, 5, 7};
+
+static const struct clk_parent_data a5_nna_parent_data[] = {
+	{ .fw_name = "oscin" },
+	{ .fw_name = "fdiv2p5" },
+	{ .fw_name = "fdiv4" },
+	{ .fw_name = "fdiv3" },
+	{ .fw_name = "fdiv5" },
+	{ .fw_name = "fdiv2" },
+	{ .fw_name = "hifi" }
+};
+
+static A5_COMP_SEL_WITH_TAB(nna_core, NNA_CLK_CNTL, 9, 0x7,
+			    a5_nna_parent_data, a5_nna_parent_table);
+static A5_COMP_DIV(nna_core, NNA_CLK_CNTL, 0, 7);
+static A5_COMP_GATE(nna_core, NNA_CLK_CNTL, 8);
+
+static A5_COMP_SEL_WITH_TAB(nna_axi, NNA_CLK_CNTL, 25, 0x7,
+			    a5_nna_parent_data, a5_nna_parent_table);
+static A5_COMP_DIV(nna_axi, NNA_CLK_CNTL, 16, 7);
+static A5_COMP_GATE(nna_axi, NNA_CLK_CNTL, 24);
+
+static struct clk_hw *a5_peripherals_hw_clks[] = {
+	[CLKID_RTC_DUALDIV_CLKIN]	= &a5_rtc_dualdiv_clkin.hw,
+	[CLKID_RTC_DUALDIV]		= &a5_rtc_dualdiv.hw,
+	[CLKID_RTC_DUALDIV_SEL]		= &a5_rtc_dualdiv_sel.hw,
+	[CLKID_RTC_DUALDIV_CLKOUT]	= &a5_rtc_dualdiv_clkout.hw,
+	[CLKID_RTC_CLK]			= &a5_rtc_clk.hw,
+	[CLKID_SYS_RESET_CTRL]		= &a5_sys_reset_ctrl.hw,
+	[CLKID_SYS_PWR_CTRL]		= &a5_sys_pwr_ctrl.hw,
+	[CLKID_SYS_PAD_CTRL]		= &a5_sys_pad_ctrl.hw,
+	[CLKID_SYS_CTRL]		= &a5_sys_ctrl.hw,
+	[CLKID_SYS_TS_PLL]		= &a5_sys_ts_pll.hw,
+	[CLKID_SYS_DEV_ARB]		= &a5_sys_dev_arb.hw,
+	[CLKID_SYS_MAILBOX]		= &a5_sys_mailbox.hw,
+	[CLKID_SYS_JTAG_CTRL]		= &a5_sys_jtag_ctrl.hw,
+	[CLKID_SYS_IR_CTRL]		= &a5_sys_ir_ctrl.hw,
+	[CLKID_SYS_MSR_CLK]		= &a5_sys_msr_clk.hw,
+	[CLKID_SYS_ROM]			= &a5_sys_rom.hw,
+	[CLKID_SYS_CPU_ARB]		= &a5_sys_cpu_apb.hw,
+	[CLKID_SYS_RSA]			= &a5_sys_rsa.hw,
+	[CLKID_SYS_SARADC]		= &a5_sys_saradc.hw,
+	[CLKID_SYS_STARTUP]		= &a5_sys_startup.hw,
+	[CLKID_SYS_SECURE]		= &a5_sys_secure.hw,
+	[CLKID_SYS_SPIFC]		= &a5_sys_spifc.hw,
+	[CLKID_SYS_DSPA]		= &a5_sys_dspa.hw,
+	[CLKID_SYS_NNA]			= &a5_sys_nna.hw,
+	[CLKID_SYS_ETH_MAC]		= &a5_sys_eth_mac.hw,
+	[CLKID_SYS_RAMA]		= &a5_sys_rama.hw,
+	[CLKID_SYS_RAMB]		= &a5_sys_ramb.hw,
+	[CLKID_SYS_AUDIO_TOP]		= &a5_sys_audio_top.hw,
+	[CLKID_SYS_AUDIO_VAD]		= &a5_sys_audio_vad.hw,
+	[CLKID_SYS_USB]			= &a5_sys_usb.hw,
+	[CLKID_SYS_SD_EMMC_A]		= &a5_sys_sd_emmc_a.hw,
+	[CLKID_SYS_SD_EMMC_C]		= &a5_sys_sd_emmc_c.hw,
+	[CLKID_SYS_PWM_AB]		= &a5_sys_pwm_ab.hw,
+	[CLKID_SYS_PWM_CD]		= &a5_sys_pwm_cd.hw,
+	[CLKID_SYS_PWM_EF]		= &a5_sys_pwm_ef.hw,
+	[CLKID_SYS_PWM_GH]		= &a5_sys_pwm_gh.hw,
+	[CLKID_SYS_SPICC_1]		= &a5_sys_spicc_1.hw,
+	[CLKID_SYS_SPICC_0]		= &a5_sys_spicc_0.hw,
+	[CLKID_SYS_UART_A]		= &a5_sys_uart_a.hw,
+	[CLKID_SYS_UART_B]		= &a5_sys_uart_b.hw,
+	[CLKID_SYS_UART_C]		= &a5_sys_uart_c.hw,
+	[CLKID_SYS_UART_D]		= &a5_sys_uart_d.hw,
+	[CLKID_SYS_UART_E]		= &a5_sys_uart_e.hw,
+	[CLKID_SYS_I2C_M_A]		= &a5_sys_i2c_m_a.hw,
+	[CLKID_SYS_I2C_M_B]		= &a5_sys_i2c_m_b.hw,
+	[CLKID_SYS_I2C_M_C]		= &a5_sys_i2c_m_c.hw,
+	[CLKID_SYS_I2C_M_D]		= &a5_sys_i2c_m_d.hw,
+	[CLKID_SYS_RTC]			= &a5_sys_rtc.hw,
+	[CLKID_AXI_AUDIO_VAD]		= &a5_axi_audio_vad.hw,
+	[CLKID_AXI_AUDIO_TOP]		= &a5_axi_audio_top.hw,
+	[CLKID_AXI_RAMB]		= &a5_axi_ramb.hw,
+	[CLKID_AXI_RAMA]		= &a5_axi_rama.hw,
+	[CLKID_AXI_NNA]			= &a5_axi_nna.hw,
+	[CLKID_AXI_DEV1_DMC]		= &a5_axi_dev1_dmc.hw,
+	[CLKID_AXI_DEV0_DMC]		= &a5_axi_dev0_dmc.hw,
+	[CLKID_AXI_DSP_DMC]		= &a5_axi_dsp_dmc.hw,
+	[CLKID_12_24M_IN]		= &a5_clk_12_24m_in.hw,
+	[CLKID_12M_24M]			= &a5_clk_12_24m.hw,
+	[CLKID_FCLK_25M_DIV]		= &a5_fclk_25m_div.hw,
+	[CLKID_FCLK_25M]		= &a5_fclk_25m.hw,
+	[CLKID_GEN_SEL]			= &a5_gen_sel.hw,
+	[CLKID_GEN_DIV]			= &a5_gen_div.hw,
+	[CLKID_GEN]			= &a5_gen.hw,
+	[CLKID_SARADC_SEL]		= &a5_saradc_sel.hw,
+	[CLKID_SARADC_DIV]		= &a5_saradc_div.hw,
+	[CLKID_SARADC]			= &a5_saradc.hw,
+	[CLKID_PWM_A_SEL]		= &a5_pwm_a_sel.hw,
+	[CLKID_PWM_A_DIV]		= &a5_pwm_a_div.hw,
+	[CLKID_PWM_A]			= &a5_pwm_a.hw,
+	[CLKID_PWM_B_SEL]		= &a5_pwm_b_sel.hw,
+	[CLKID_PWM_B_DIV]		= &a5_pwm_b_div.hw,
+	[CLKID_PWM_B]			= &a5_pwm_b.hw,
+	[CLKID_PWM_C_SEL]		= &a5_pwm_c_sel.hw,
+	[CLKID_PWM_C_DIV]		= &a5_pwm_c_div.hw,
+	[CLKID_PWM_C]			= &a5_pwm_c.hw,
+	[CLKID_PWM_D_SEL]		= &a5_pwm_d_sel.hw,
+	[CLKID_PWM_D_DIV]		= &a5_pwm_d_div.hw,
+	[CLKID_PWM_D]			= &a5_pwm_d.hw,
+	[CLKID_PWM_E_SEL]		= &a5_pwm_e_sel.hw,
+	[CLKID_PWM_E_DIV]		= &a5_pwm_e_div.hw,
+	[CLKID_PWM_E]			= &a5_pwm_e.hw,
+	[CLKID_PWM_F_SEL]		= &a5_pwm_f_sel.hw,
+	[CLKID_PWM_F_DIV]		= &a5_pwm_f_div.hw,
+	[CLKID_PWM_F]			= &a5_pwm_f.hw,
+	[CLKID_PWM_G_SEL]		= &a5_pwm_g_sel.hw,
+	[CLKID_PWM_G_DIV]		= &a5_pwm_g_div.hw,
+	[CLKID_PWM_G]			= &a5_pwm_g.hw,
+	[CLKID_PWM_H_SEL]		= &a5_pwm_h_sel.hw,
+	[CLKID_PWM_H_DIV]		= &a5_pwm_h_div.hw,
+	[CLKID_PWM_H]			= &a5_pwm_h.hw,
+	[CLKID_SPICC_0_SEL]		= &a5_spicc_0_sel.hw,
+	[CLKID_SPICC_0_DIV]		= &a5_spicc_0_div.hw,
+	[CLKID_SPICC_0]			= &a5_spicc_0.hw,
+	[CLKID_SPICC_1_SEL]		= &a5_spicc_1_sel.hw,
+	[CLKID_SPICC_1_DIV]		= &a5_spicc_1_div.hw,
+	[CLKID_SPICC_1]			= &a5_spicc_1.hw,
+	[CLKID_SD_EMMC_A_SEL]		= &a5_sd_emmc_a_sel.hw,
+	[CLKID_SD_EMMC_A_DIV]		= &a5_sd_emmc_a_div.hw,
+	[CLKID_SD_EMMC_A]		= &a5_sd_emmc_a.hw,
+	[CLKID_SD_EMMC_C_SEL]		= &a5_sd_emmc_c_sel.hw,
+	[CLKID_SD_EMMC_C_DIV]		= &a5_sd_emmc_c_div.hw,
+	[CLKID_SD_EMMC_C]		= &a5_sd_emmc_c.hw,
+	[CLKID_TS_DIV]			= &a5_ts_div.hw,
+	[CLKID_TS]			= &a5_ts.hw,
+	[CLKID_ETH_125M_DIV]		= &a5_eth_125m_div.hw,
+	[CLKID_ETH_125M]		= &a5_eth_125m.hw,
+	[CLKID_ETH_RMII_DIV]		= &a5_eth_rmii_div.hw,
+	[CLKID_ETH_RMII]		= &a5_eth_rmii.hw,
+	[CLKID_DSPA_0_SEL]		= &a5_dspa_0_sel.hw,
+	[CLKID_DSPA_0_DIV]		= &a5_dspa_0_div.hw,
+	[CLKID_DSPA_0]			= &a5_dspa_0.hw,
+	[CLKID_DSPA_1_SEL]		= &a5_dspa_1_sel.hw,
+	[CLKID_DSPA_1_DIV]		= &a5_dspa_1_div.hw,
+	[CLKID_DSPA_1]			= &a5_dspa_1.hw,
+	[CLKID_DSPA]			= &a5_dspa.hw,
+	[CLKID_NNA_CORE_SEL]		= &a5_nna_core_sel.hw,
+	[CLKID_NNA_CORE_DIV]		= &a5_nna_core_div.hw,
+	[CLKID_NNA_CORE]		= &a5_nna_core.hw,
+	[CLKID_NNA_AXI_SEL]		= &a5_nna_axi_sel.hw,
+	[CLKID_NNA_AXI_DIV]		= &a5_nna_axi_div.hw,
+	[CLKID_NNA_AXI]			= &a5_nna_axi.hw,
+};
+
+static const struct meson_clkc_data a5_peripherals_clkc_data = {
+	.hw_clks = {
+		.hws = a5_peripherals_hw_clks,
+		.num = ARRAY_SIZE(a5_peripherals_hw_clks),
+	},
+};
+
+static const struct of_device_id a5_peripherals_clkc_match_table[] = {
+	{
+		.compatible = "amlogic,a5-peripherals-clkc",
+		.data = &a5_peripherals_clkc_data,
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, a5_peripherals_clkc_match_table);
+
+static struct platform_driver a5_peripherals_clkc_driver = {
+	.probe = meson_clkc_mmio_probe,
+	.driver = {
+		.name = "a5-peripherals-clkc",
+		.of_match_table = a5_peripherals_clkc_match_table,
+	},
+};
+module_platform_driver(a5_peripherals_clkc_driver);
+
+MODULE_DESCRIPTION("Amlogic A5 Peripherals Clock Controller driver");
+MODULE_AUTHOR("Chuan Liu <chuan.liu at amlogic.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_MESON");

-- 
2.42.0




From neil.armstrong at linaro.org  Tue Oct 28 02:53:48 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 28 Oct 2025 10:53:48 +0100
Subject: [PATCH] drm/meson: Fix reference count leak in
 meson_encoder_dsi_probe
In-Reply-To: <20251027084258.79180-1-linmq006@gmail.com>
References: <20251027084258.79180-1-linmq006@gmail.com>
Message-ID: <fbc3237e-0185-4c06-a6ea-f061a2afbd64@linaro.org>

On 10/27/25 09:42, Miaoqian Lin wrote:
> The of_graph_get_remote_node() function returns a device node with its
> reference count incremented. The caller is responsible for calling
> of_node_put() to release this reference when done.
> 
> Fixes: 42dcf15f901c ("drm/meson: add DSI encoder")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miaoqian Lin <linmq006 at gmail.com>
> ---
>   drivers/gpu/drm/meson/meson_encoder_dsi.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c
> index 6c6624f9ba24..01edf46e30d0 100644
> --- a/drivers/gpu/drm/meson/meson_encoder_dsi.c
> +++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c
> @@ -121,6 +121,7 @@ int meson_encoder_dsi_probe(struct meson_drm *priv)
>   	}
>   
>   	meson_encoder_dsi->next_bridge = of_drm_find_bridge(remote);
> +	of_node_put(remote);
>   	if (!meson_encoder_dsi->next_bridge)
>   		return dev_err_probe(priv->dev, -EPROBE_DEFER,
>   				     "Failed to find DSI transceiver bridge\n");

Reviewed-by: Neil Armstrong <neil.armstrong at linaro.org>


From neil.armstrong at linaro.org  Tue Oct 28 03:50:26 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 28 Oct 2025 11:50:26 +0100
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
Message-ID: <b976b442-7d07-4fef-b851-ccd14661a233@linaro.org>

Hi,

On 10/27/25 06:42, Zhentao Guo via B4 Relay wrote:
> Introduce initial driver support for Amlogic's new video acceleration
> hardware architecture, designed for video stream decoding.
> 
> Compared to the current Amlogic video decoder hardware architecture,
> this new implementation eliminates the Esparser hardware component,
> enabling direct vb2 buffer input. The driver is designed to support
> the V4L2 M2M stateless decoder API. The initial phase includes support
> for H.264 decoding on Amlogic S805X2 platform.
> 
> The driver is capable of:
> - Supporting stateless H.264 decoding up to a resolution 1920x1088(on the S805X2 platform).
> - Supporting I/P/B frame handling.
> - Supporting vb2 mmap and dma-buf modes.
> - Supporting frame-based decode mode. (Note that some H.264 bitstreams require
>    DPB reordering to generate reference lists, the stateless decoder driver
>    cannot access reordered reference lists in this mode, requiring the driver
>    to perform reference list reordering itself)
> - Supporting NV12/NV21 output.
> - Supporting Annex B start codes.

Thanks for the initial drop, it's very nice !

First of all, this still requires some work so it would be better if you
used the RFC tag until all issues are sorted out.

You didn't tell anything about the firmware, did you build a specific version
of the firmware to handle the stateless and bypass ESPARSER ?
Will this technique work with the released firmwares of GXL/G12/SM1 ?

Will you support the compressed format and 10bit with this ?

> 
> This driver is tested with Gstreamer.
> Example:
> gst-launch-1.0 filesrc location=/tmp/video_640x360_mp4_hevc_450kbps_no_b.mp4 !
> parsebin ! v4l2slh264dec ! filesink location=/tmp/output.yuv
> 
> The driver passes v4l2 compliance test, test reports :
> v4l2-compliance 1.30.1, 64 bits, 64-bit time_t
> 
> Compliance test for aml-vdec-drv device /dev/video0:
> 
> Driver Info:
>          Driver name      : aml-vdec-drv
>          Card type        : platform:aml-vdec-drv
>          Bus info         : platform:fe320000.video-codec
>          Driver version   : 6.16.0
>          Capabilities     : 0x84204000
>                  Video Memory-to-Memory Multiplanar
>                  Streaming
>                  Extended Pix Format
>                  Device Capabilities
>          Device Caps      : 0x04204000
>                  Video Memory-to-Memory Multiplanar
>                  Streaming
>                  Extended Pix Format
>          Detected Stateless Decoder
> Media Driver Info:
>          Driver name      : aml-vdec-drv
>          Model            : aml-vdec-drv
>          Serial           :
>          Bus info         : platform:fe320000.video-codec
>          Media version    : 6.16.0
>          Hardware revision: 0x00000000 (0)
>          Driver version   : 6.16.0
> Interface Info:
>          ID               : 0x0300000c
>          Type             : V4L Video
> Entity Info:
>          ID               : 0x00000001 (1)
>          Name             : aml_dev_drv-source
>          Function         : V4L2 I/O
>          Pad 0x01000002   : 0: Source
>            Link 0x02000008: to remote pad 0x1000004 of entity 'aml_dev_drv-proc' (Video Decoder): Data, Enabled, Immutable
> 
> Required ioctls:
>          test MC information (see 'Media Driver Info' above): OK
>          test VIDIOC_QUERYCAP: OK
>          test invalid ioctls: OK
> 
> Allow for multiple opens:
>          test second /dev/video0 open: OK
>          test VIDIOC_QUERYCAP: OK
>          test VIDIOC_G/S_PRIORITY: OK
>          test for unlimited opens: OK
> 
> Debug ioctls:
>          test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>          test VIDIOC_LOG_STATUS: OK (Not Supported)
> 
> Input ioctls:
>          test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>          test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>          test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>          test VIDIOC_ENUMAUDIO: OK (Not Supported)
>          test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>          test VIDIOC_G/S_AUDIO: OK (Not Supported)
>          Inputs: 0 Audio Inputs: 0 Tuners: 0
> 
> Output ioctls:
>          test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>          test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>          test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>          test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>          test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>          Outputs: 0 Audio Outputs: 0 Modulators: 0
> 
> Input/Output configuration ioctls:
>          test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>          test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>          test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>          test VIDIOC_G/S_EDID: OK (Not Supported)
> 
> Control ioctls:
>          test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>          test VIDIOC_QUERYCTRL: OK
>          test VIDIOC_G/S_CTRL: OK
>          test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>          test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>          test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>          Standard Controls: 6 Private Controls: 0
>          Standard Compound Controls: 4 Private Compound Controls: 0
> 
> Format ioctls:
>          test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>          test VIDIOC_G/S_PARM: OK (Not Supported)
>          test VIDIOC_G_FBUF: OK (Not Supported)
>          test VIDIOC_G_FMT: OK
>          test VIDIOC_TRY_FMT: OK
>          test VIDIOC_S_FMT: OK
>          test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>          test Cropping: OK (Not Supported)
>          test Composing: OK (Not Supported)
>          test Scaling: OK (Not Supported)
> 
> Codec ioctls:
>          test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>          test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>          test VIDIOC_(TRY_)DECODER_CMD: OK
> 
> Buffer ioctls:
>          test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>          test CREATE_BUFS maximum buffers: OK
>          test VIDIOC_REMOVE_BUFS: OK
>          test VIDIOC_EXPBUF: OK
>          test Requests: OK
>          test blocking wait: OK

Please also enable the streaming tests.

> 
> Total for aml-vdec-drv device /dev/video0: 49, Succeeded: 49, Failed: 0, Warnings: 0
> 
> Some Fluster test cases are still failing. We will publish the final results
> once all these Fluster test failures have been resolved.

As Christian reported, please add the flutter results aswell.

Neil

> 
> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
> ---
> Zhentao Guo (3):
>        dt-bindings: vdec: Add binding document of Amlogic decoder accelerator
>        dts: decoder: Support V4L2 stateless decoder dt node for S4
>        decoder: Add V4L2 stateless H.264 decoder driver
> 
>   .../bindings/media/amlogic,vcodec-dec.yaml         |   96 ++
>   MAINTAINERS                                        |    7 +
>   arch/arm64/boot/dts/amlogic/meson-s4.dtsi          |   24 +
>   drivers/media/platform/amlogic/Kconfig             |    2 +
>   drivers/media/platform/amlogic/Makefile            |    1 +
>   drivers/media/platform/amlogic/vdec/Kconfig        |   15 +
>   drivers/media/platform/amlogic/vdec/Makefile       |    4 +
>   drivers/media/platform/amlogic/vdec/aml_vdec.c     |  759 +++++++++
>   drivers/media/platform/amlogic/vdec/aml_vdec.h     |   31 +
>   .../platform/amlogic/vdec/aml_vdec_canvas_utils.c  |  154 ++
>   .../platform/amlogic/vdec/aml_vdec_canvas_utils.h  |   22 +
>   drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |  263 +++
>   drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |  194 +++
>   drivers/media/platform/amlogic/vdec/aml_vdec_hw.c  |  652 +++++++
>   drivers/media/platform/amlogic/vdec/aml_vdec_hw.h  |  182 ++
>   .../platform/amlogic/vdec/aml_vdec_platform.c      |   37 +
>   .../platform/amlogic/vdec/aml_vdec_platform.h      |   62 +
>   drivers/media/platform/amlogic/vdec/h264.c         | 1790 ++++++++++++++++++++
>   drivers/media/platform/amlogic/vdec/h264.h         |  300 ++++
>   drivers/media/platform/amlogic/vdec/reg_defines.h  |  175 ++
>   20 files changed, 4770 insertions(+)
> ---
> base-commit: 72fb0170ef1f45addf726319c52a0562b6913707
> change-id: 20251027-b4-s4-vdec-upstream-0603c1a4c84a
> 
> Best regards,



From neil.armstrong at linaro.org  Tue Oct 28 04:01:58 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Tue, 28 Oct 2025 12:01:58 +0100
Subject: [PATCH 3/3] decoder: Add V4L2 stateless H.264 decoder driver
In-Reply-To: <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>
Message-ID: <42909f90-e2d3-4911-ae6d-47d180ccb367@linaro.org>

Hi,

On 10/27/25 06:42, Zhentao Guo via B4 Relay wrote:
> From: Zhentao Guo <zhentao.guo at amlogic.com>
> 
> This patch introduces initial driver support for Amlogic's new
> video acceleration hardware architecture, designed for video
> stream decoding. The driver is designed to support the
> V4L2 M2M stateless decoder API. In phase 1, it supports H.264
> bitstreams decoding.
> 
> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
> ---
>   MAINTAINERS                                        |    7 +
>   drivers/media/platform/amlogic/Kconfig             |    2 +
>   drivers/media/platform/amlogic/Makefile            |    1 +
>   drivers/media/platform/amlogic/vdec/Kconfig        |   15 +
>   drivers/media/platform/amlogic/vdec/Makefile       |    4 +
>   drivers/media/platform/amlogic/vdec/aml_vdec.c     |  759 +++++++++
>   drivers/media/platform/amlogic/vdec/aml_vdec.h     |   31 +
>   .../platform/amlogic/vdec/aml_vdec_canvas_utils.c  |  154 ++
>   .../platform/amlogic/vdec/aml_vdec_canvas_utils.h  |   22 +
>   drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |  263 +++
>   drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |  194 +++
>   drivers/media/platform/amlogic/vdec/aml_vdec_hw.c  |  652 +++++++
>   drivers/media/platform/amlogic/vdec/aml_vdec_hw.h  |  182 ++
>   .../platform/amlogic/vdec/aml_vdec_platform.c      |   37 +
>   .../platform/amlogic/vdec/aml_vdec_platform.h      |   62 +
>   drivers/media/platform/amlogic/vdec/h264.c         | 1790 ++++++++++++++++++++
>   drivers/media/platform/amlogic/vdec/h264.h         |  300 ++++
>   drivers/media/platform/amlogic/vdec/reg_defines.h  |  175 ++
>   18 files changed, 4650 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 5ea78444f035..f400b5dabf30 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1352,6 +1352,13 @@ S:	Maintained
>   F:	Documentation/devicetree/bindings/spi/amlogic,a4-spisg.yaml
>   F:	drivers/spi/spi-amlogic-spisg.c
>   
> +AMLOGIC VCODEC DRIVER
> +M:	Zhentao Guo <zhentao.guo at amlogic.com>
> +L:	linux-media at vger.kernel.org
> +S:	Maintained
> +F:	Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
> +F:	drivers/media/platform/amlogic/vdec/
> +
>   AMPHENOL CHIPCAP 2 DRIVER
>   M:	Javier Carrasco <javier.carrasco.cruz at gmail.com>
>   L:	linux-hwmon at vger.kernel.org
> diff --git a/drivers/media/platform/amlogic/Kconfig b/drivers/media/platform/amlogic/Kconfig
> index 458acf3d5fa8..8132f5b9282b 100644
> --- a/drivers/media/platform/amlogic/Kconfig
> +++ b/drivers/media/platform/amlogic/Kconfig
> @@ -4,3 +4,5 @@ comment "Amlogic media platform drivers"
>   
>   source "drivers/media/platform/amlogic/c3/Kconfig"
>   source "drivers/media/platform/amlogic/meson-ge2d/Kconfig"
> +
> +source "drivers/media/platform/amlogic/vdec/Kconfig"

PLease respect original formatting and drop the empty line

> diff --git a/drivers/media/platform/amlogic/Makefile b/drivers/media/platform/amlogic/Makefile
> index c744afcd1b9e..7409de674c0b 100644
> --- a/drivers/media/platform/amlogic/Makefile
> +++ b/drivers/media/platform/amlogic/Makefile
> @@ -2,3 +2,4 @@
>   
>   obj-y += c3/
>   obj-y += meson-ge2d/
> +obj-y += vdec/

Ditto> diff --git a/drivers/media/platform/amlogic/vdec/Kconfig b/drivers/media/platform/amlogic/vdec/Kconfig
> new file mode 100644
> index 000000000000..05c4568e058b
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/Kconfig
> @@ -0,0 +1,15 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +
> +config VIDEO_AMLOGIC_VCODEC
> +    tristate "Amlogic Video Codec Driver"
> +    depends on ARCH_MESON || COMPILE_TEST
> +    depends on VIDEO_DEV
> +    depends on V4L_MEM2MEM_DRIVERS
> +    select VIDEOBUF2_DMA_CONTIG
> +    select V4L2_H264
> +    select V4L2_MEM2MEM_DEV
> +    help
> +      This is a v4l2 driver for Amlogic video codec driver.
> +	  This driver is designed to support V4L2 M2M STATELESS
> +	  interface.
> +      To compile this driver as a module choose m here.
> diff --git a/drivers/media/platform/amlogic/vdec/Makefile b/drivers/media/platform/amlogic/vdec/Makefile
> new file mode 100644
> index 000000000000..f645f7ca5e2d
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/Makefile
> @@ -0,0 +1,4 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +aml-vdec-drv-objs := aml_vdec.o aml_vdec_drv.o aml_vdec_hw.o aml_vdec_platform.o h264.o aml_vdec_canvas_utils.o\
> +
> +obj-$(CONFIG_VIDEO_AMLOGIC_VCODEC) += aml-vdec-drv.o
> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec.c b/drivers/media/platform/amlogic/vdec/aml_vdec.c
> new file mode 100644
> index 000000000000..e8a66bde0397
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec.c
> @@ -0,0 +1,759 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <media/v4l2-mem2mem.h>
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-event.h>
> +#include <media/videobuf2-v4l2.h>
> +#include <media/videobuf2-dma-contig.h>
> +
> +#include "aml_vdec.h"
> +#include "aml_vdec_hw.h"
> +#include "aml_vdec_platform.h"
> +
> +#define VCODEC_DRV_NAME "aml-vdec-drv"
> +
> +static const struct aml_vdec_v4l2_ctrl controls[] = {
> +	{
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_STATELESS_H264_SPS,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_STATELESS_H264_PPS,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_STATELESS_H264_DECODE_MODE,
> +			.min = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
> +			.def = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
> +			.max = V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_STATELESS_H264_START_CODE,
> +			.min = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
> +			.def = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
> +			.max = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
> +		},
> +	}, {
> +		.codec_type = CODEC_TYPE_H264,
> +		.cfg = {
> +			.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
> +			.min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
> +			.max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
> +			.def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN,
> +		},
> +	}
> +};
> +
> +static struct aml_video_fmt aml_video_formats[] = {
> +	{
> +		.name = "H.264",
> +		.fourcc = V4L2_PIX_FMT_H264_SLICE,
> +		.type = AML_FMT_DEC,
> +		.codec_type = CODEC_TYPE_H264,
> +		.num_planes = 1,
> +		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
> +			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
> +	},
> +	{
> +		.name = "NV21M",
> +		.fourcc = V4L2_PIX_FMT_NV21M,
> +		.type = AML_FMT_FRAME,
> +		.codec_type = CODEC_TYPE_FRAME,
> +		.num_planes = 2,
> +		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
> +			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
> +	},
> +	{
> +		.name = "NV21",
> +		.fourcc = V4L2_PIX_FMT_NV21,
> +		.type = AML_FMT_FRAME,
> +		.codec_type = CODEC_TYPE_FRAME,
> +		.num_planes = 1,
> +		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
> +			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
> +	},
> +	{
> +		.name = "NV12M",
> +		.fourcc = V4L2_PIX_FMT_NV12M,
> +		.type = AML_FMT_FRAME,
> +		.codec_type = CODEC_TYPE_FRAME,
> +		.num_planes = 2,
> +		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
> +			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
> +
> +	},
> +	{
> +		.name = "NV12",
> +		.fourcc = V4L2_PIX_FMT_NV12,
> +		.type = AML_FMT_FRAME,
> +		.codec_type = CODEC_TYPE_FRAME,
> +		.num_planes = 1,
> +		.stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
> +			AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
> +	},
> +};
> +
> +void aml_vdec_set_default_params(struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_q_data *q_data = NULL;
> +
> +	ctx->m2m_ctx->q_lock = &ctx->v4l2_intf_lock;
> +
> +	ctx->pic_info.colorspace = V4L2_COLORSPACE_DEFAULT;
> +	ctx->pic_info.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
> +	ctx->pic_info.quantization = V4L2_QUANTIZATION_DEFAULT;
> +	ctx->pic_info.xfer_func = V4L2_XFER_FUNC_DEFAULT;
> +
> +	q_data = &ctx->q_data[AML_Q_DATA_SRC];
> +	memset(q_data, 0, sizeof(struct aml_q_data));
> +	q_data->visible_width = AML_VDEC_MIN_W;
> +	q_data->visible_height = AML_VDEC_MIN_H;
> +	q_data->coded_width = AML_VDEC_MIN_W;
> +	q_data->coded_height = AML_VDEC_MIN_H;
> +	q_data->filed_flag = V4L2_FIELD_NONE;
> +	q_data->bytesperline[0] = 0;
> +	q_data->sizeimage[0] = (1024 * 1024);
> +	q_data->fmt = &aml_video_formats[DEFAULT_OUT_IDX];
> +
> +	q_data = &ctx->q_data[AML_Q_DATA_DST];
> +	memset(q_data, 0, sizeof(struct aml_q_data));
> +	q_data->visible_width = AML_VDEC_MIN_W;
> +	q_data->visible_height = AML_VDEC_MIN_H;
> +	q_data->coded_width = AML_VDEC_MIN_W;
> +	q_data->coded_height = AML_VDEC_MIN_H;
> +	q_data->filed_flag = V4L2_FIELD_NONE;
> +	q_data->bytesperline[0] = q_data->coded_width;
> +	q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
> +	q_data->bytesperline[1] = q_data->coded_width;
> +	q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
> +	q_data->fmt = &aml_video_formats[DEFAULT_CAP_IDX];
> +}
> +
> +int aml_vdec_ctrls_setup(struct aml_vdec_ctx *ctx)
> +{
> +	int i;
> +	int ctrls_size = sizeof(controls) / sizeof(struct aml_vdec_v4l2_ctrl);
> +
> +	v4l2_ctrl_handler_init(&ctx->ctrl_handler, ctrls_size);
> +	for (i = 0; i < ctrls_size; i++) {
> +		v4l2_ctrl_new_custom(&ctx->ctrl_handler, &controls[i].cfg, NULL);
> +		if (ctx->ctrl_handler.error) {
> +			pr_debug("add ctrl for (%d) failed%d\n",
> +				 controls[i].cfg.id, ctx->ctrl_handler.error);
> +			v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> +			return ctx->ctrl_handler.error;
> +		}
> +	}
> +	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
> +	return v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
> +}
> +
> +static void m2mops_vdec_device_run(void *m2m_priv)
> +{
> +	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)m2m_priv;
> +	struct aml_vdec_dev *dev = ctx->dev;
> +	struct vb2_v4l2_buffer *src, *dst;
> +	struct media_request *src_req;
> +	const char *fw_path = dev->pvdec_data->fw_path[ctx->curr_dec_type];
> +
> +	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> +	dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
> +	pr_debug("device run : src buf : %d dst buf %d\n", src->vb2_buf.index, dst->vb2_buf.index);

Switch to dev_dbg everywhere

> +
> +	src_req = src->vb2_buf.req_obj.req;
> +	if (src_req)
> +		v4l2_ctrl_request_setup(src_req, &ctx->ctrl_handler);
> +
> +	dos_enable();
> +	/* incase of bus hang in stop_streaming */
> +	ctx->dos_clk_en = 1;
> +	aml_vdec_reset_core();
> +	load_firmware(dev->dec_hw, fw_path);
> +
> +	if (ctx->codec_ops->run)
> +		ctx->codec_ops->run(ctx);
> +
> +	v4l2_m2m_buf_copy_metadata(src, dst);
> +	if (src_req)
> +		v4l2_ctrl_request_complete(src_req, &ctx->ctrl_handler);
> +
> +	v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx, VB2_BUF_STATE_DONE);
> +}
> +
> +const struct v4l2_m2m_ops aml_vdec_m2m_ops = {
> +	.device_run = m2mops_vdec_device_run,
> +};
> +
> +static int vidioc_vdec_querycap(struct file *file, void *priv,
> +				struct v4l2_capability *cap)
> +{
> +	strscpy(cap->driver, VCODEC_DRV_NAME, sizeof(cap->driver));
> +	strscpy(cap->card, "platform:" VCODEC_DRV_NAME, sizeof(cap->card));
> +
> +	return 0;
> +}
> +
> +static int vidioc_vdec_enum_fmt(struct v4l2_fmtdesc *f, bool is_output)
> +{
> +	struct aml_video_fmt *fmt;
> +	int fmt_size = sizeof(aml_video_formats) / sizeof(struct aml_video_fmt);
> +	int i = 0, j = 0;
> +
> +	for (; i < fmt_size; i++) {
> +		fmt = &aml_video_formats[i];
> +		if (is_output && fmt->type != AML_FMT_DEC)
> +			continue;
> +		if (!is_output && fmt->type != AML_FMT_FRAME)
> +			continue;
> +
> +		if (j == f->index) {
> +			f->pixelformat = fmt->fourcc;
> +			strscpy(f->description, fmt->name,
> +				sizeof(f->description));
> +			if (strlen(fmt->name) >= sizeof(f->description)) {
> +				pr_err("fmt name string is too long!\n");
> +				f->description[sizeof(f->description) - 1] = '\0';
> +			}
> +			return 0;
> +		}
> +		++j;
> +	}
> +	return -EINVAL;
> +}
> +
> +static struct aml_q_data *aml_vdec_get_qdata_by_type(struct aml_vdec_ctx *ctx,
> +						     enum v4l2_buf_type type)
> +{
> +	if (V4L2_TYPE_IS_OUTPUT(type))
> +		return &ctx->q_data[AML_Q_DATA_SRC];
> +
> +	return &ctx->q_data[AML_Q_DATA_DST];
> +}
> +
> +static struct aml_video_fmt *aml_vdec_get_video_fmt(u32 format)
> +{
> +	struct aml_video_fmt *fmt;
> +	unsigned int k;
> +
> +	for (k = 0; k < (sizeof(aml_video_formats) / sizeof(struct aml_video_fmt)); k++) {
> +		fmt = &aml_video_formats[k];
> +		if (fmt->fourcc == format)
> +			return fmt;
> +	}
> +
> +	return NULL;
> +}
> +
> +static int aml_vdec_init_dec_inst(struct aml_vdec_ctx *ctx,
> +				  struct aml_video_fmt *fmt_out)
> +{
> +	struct aml_vdec_dev *dev = ctx->dev;
> +	int ret = -1;
> +
> +	if (!fmt_out)
> +		return ret;
> +
> +	if (fmt_out->codec_type == CODEC_TYPE_FRAME) {
> +		pr_debug("capture type no need to set\n");
> +		return 0;
> +	}
> +
> +	ctx->codec_ops = &dev->pvdec_data->codec_ops[fmt_out->codec_type];
> +	if (ctx->codec_ops->init) {
> +		ret = ctx->codec_ops->init(ctx);
> +		if (ret < 0)
> +			return ret;
> +	}
> +	ctx->curr_dec_type = fmt_out->codec_type;
> +	pr_info("%s set curr_dec_type = %d\n", __func__, ctx->curr_dec_type);

And dev_info/dev_err/dev_warn...

> +
> +	return ret;
> +}
> +

<snip>

> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c
> new file mode 100644
> index 000000000000..066958118b00
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c
> @@ -0,0 +1,154 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#include "aml_vdec_canvas_utils.h"
> +
> +#define CANVAS_REG_OFFSET   (0x12 << 2)
> +
> +/*
> + * DMC_CAV_LUT_DATAL/DMC_CAV_LUT_DATAH
> + * high 32bits of canvas data which need to be configured
> + * to canvas memory.
> + * 64bits CANVAS look up table
> + * bit 61 : 58   Endian control.
> + * bit 61 :  1 : switch 2 64bits data inside 128bits boundary.
> + * 0 : no change.
> + * bit 60 :  1 : switch 2 32bits data inside 64bits data boundary.
> + * 0 : no change.
> + * bit 59 :  1 : switch 2 16bits data inside 32bits data boundary.
> + * 0 : no change.
> + * bit 58 :  1 : switch 2 8bits data  inside 16bits data boundary.
> + * 0 : no change.
> + * bit 57 : 56.   Canvas block mode.  2 : 64x32, 1: 32x32;
> + *  0 : linear mode.
> + * bit 55 :      canvas Y direction wrap control.
> + * 1: wrap back in y.  0: not wrap back.
> + * bit 54 :      canvas X direction wrap control.
> + * 1: wrap back in X.  0: not wrap back.
> + * bit 53 : 41.   canvas Hight.
> + * bit 40 : 29.   canvas Width, unit: 8bytes. must in 32bytes boundary.
> + * that means last 2 bits must be 0.
> + * bit 28 : 0.    canvas start address.   unit. 8 bytes. must be in
> + * 32bytes boundary. that means last 2bits must be 0.
> + */
> +
> +#define CANVAS_WADDR_LBIT       0
> +#define CANVAS_WIDTH_LBIT       29
> +#define CANVAS_HEIGHT_HBIT      (41 - 32)
> +#define CANVAS_WRAPX_HBIT       (54 - 32)
> +#define CANVAS_WRAPY_HBIT       (55 - 32)
> +#define CANVAS_BLKMODE_HBIT     (56 - 32)
> +#define CANVAS_ENDIAN_HBIT      (58 - 32)
> +
> +/* canvas regs */
> +#define DC_CAV_LUT_DATAL        0x12
> +#define DC_CAV_LUT_DATAH        0x13
> +#define DC_CAV_LUT_ADDR         0x14
> +#define DC_CAV_LUT_RDATAL       0x15
> +#define DC_CAV_LUT_RDATAH       0x16
> +
> +#define CANVAS_ADDR_LMASK       0x1fffffff
> +#define CANVAS_WIDTH_LMASK      0x7
> +#define CANVAS_WIDTH_LWID       3
> +#define CANVAS_WIDTH_HMASK      0x1ff
> +#define CANVAS_WIDTH_HBIT       0
> +#define CANVAS_HEIGHT_MASK      0x1fff
> +#define CANVAS_HEIGHT_BIT       9
> +#define CANVAS_ADDR_NOWRAP      0x00
> +#define CANVAS_ADDR_WRAPX       0x01
> +#define CANVAS_ADDR_WRAPY       0x02
> +#define CANVAS_BLKMODE_MASK     0x03
> +
> +#define CANVAS_BLKMODE_LINEAR   0x00
> +#define CANVAS_BLKMODE_32X32    0x01
> +#define CANVAS_BLKMODE_64X32    0x02
> +
> +#define CANVAS_LUT_WR_EN   (0x2 << 8)
> +#define CANVAS_LUT_RD_EN   (0x1 << 8)
> +
> +#define CANVAS_ADDR_BITS_MASK		GENMASK(28, 0)
> +#define CANVAS_WIDTH_L_MASK		GENMASK(31, 29)
> +#define CANVAS_WIDTH_H_MASK		GENMASK(8, 0)
> +#define CANVAS_HEIGHT_H_MASK		GENMASK(21, 9)
> +#define CANVAS_WRAP_H_MASK		GENMASK(23, 23)
> +#define CANVAS_BLOCK_H_MASK		GENMASK(25, 24)
> +#define CANVAS_BITS_CTRL_MASK		GENMASK(29, 26)
> +
> +static struct vdec_canvas_s canvas;

There's already a canvas driver for that, please use it and extend it if necessary:
drivers/soc/amlogic/meson-canvas.c
<snip>

> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
> new file mode 100644
> index 000000000000..ef2c779839d8
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
> @@ -0,0 +1,263 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +
> +#include "aml_vdec.h"
> +#include "aml_vdec_hw.h"
> +#include "aml_vdec_platform.h"
> +
> +#define AML_VDEC_DRV_NAME "aml-vdec-drv"
> +
> +static int fops_vcodec_open(struct file *file)
> +{
> +	struct aml_vdec_dev *dec_dev = video_drvdata(file);
> +	struct aml_vdec_ctx *ctx = NULL;
> +	int ret = 0;
> +
> +	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> +	if (!ctx)
> +		return -ENOMEM;
> +
> +	mutex_lock(&dec_dev->dev_mutex);
> +	dec_dev->dec_ctx = ctx;
> +	ctx->dev = dec_dev;
> +	v4l2_fh_init(&ctx->fh, video_devdata(file));
> +	file->private_data = &ctx->fh;
> +	v4l2_fh_add(&ctx->fh, file);
> +	dec_dev->filp = file;
> +	mutex_init(&ctx->v4l2_intf_lock);
> +	init_waitqueue_head(&ctx->queue);
> +	ctx->int_cond = 0;
> +
> +	ctx->m2m_ctx = v4l2_m2m_ctx_init(dec_dev->m2m_dev_dec, ctx,
> +					 &aml_vdec_queue_init);
> +	if (IS_ERR((__force void *)ctx->m2m_ctx)) {
> +		ret = PTR_ERR((__force void *)ctx->m2m_ctx);
> +		v4l2_err(&dec_dev->v4l2_dev, "Failed to v4l2_m2m_ctx_init() (%d)", ret);
> +		goto err_m2m_ctx_init;
> +	}
> +
> +	ctx->fh.m2m_ctx = ctx->m2m_ctx;
> +	ret = aml_vdec_ctrls_setup(ctx);
> +	if (ret) {
> +		v4l2_err(&dec_dev->v4l2_dev, "Failed to init all ctrls (%d)", ret);
> +		goto err_ctrls_setup;
> +	}
> +
> +	aml_vdec_set_default_params(ctx);
> +	mutex_unlock(&dec_dev->dev_mutex);
> +
> +	return ret;
> +
> +err_ctrls_setup:
> +	v4l2_m2m_ctx_release(ctx->m2m_ctx);
> +err_m2m_ctx_init:
> +	v4l2_fh_del(&ctx->fh, file);
> +	v4l2_fh_exit(&ctx->fh);
> +	kfree(ctx);
> +	mutex_unlock(&dec_dev->dev_mutex);
> +
> +	return ret;
> +}
> +
> +static int fops_vcodec_release(struct file *file)
> +{
> +	struct aml_vdec_dev *dec_dev = video_drvdata(file);
> +	struct aml_vdec_ctx *ctx = fh_to_dec_ctx(file->private_data);
> +
> +	mutex_lock(&dec_dev->dev_mutex);
> +	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
> +	v4l2_m2m_ctx_release(ctx->m2m_ctx);
> +	v4l2_fh_del(&ctx->fh, file);
> +	v4l2_fh_exit(&ctx->fh);
> +	kfree(ctx);
> +	mutex_unlock(&dec_dev->dev_mutex);
> +
> +	return 0;
> +}
> +
> +static const struct v4l2_file_operations aml_vdec_fops = {
> +	.owner        = THIS_MODULE,
> +	.open        = fops_vcodec_open,
> +	.release    = fops_vcodec_release,
> +	.poll        = v4l2_m2m_fop_poll,
> +	.unlocked_ioctl    = video_ioctl2,
> +	.mmap        = v4l2_m2m_fop_mmap,
> +};
> +
> +static const struct video_device dec_dev = {
> +	.name = "aml_dev_drv",
> +	.fops = &aml_vdec_fops,
> +	.ioctl_ops = &aml_vdec_ioctl_ops,
> +	.release = video_device_release,
> +	.vfl_dir = VFL_DIR_M2M,
> +	.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
> +};
> +
> +static const struct media_device_ops aml_m2m_media_ops = {
> +	.req_validate = vb2_request_validate,
> +	.req_queue = v4l2_m2m_request_queue,
> +};
> +
> +static int aml_vdec_drv_probe(struct platform_device *pdev)
> +{
> +	struct aml_vdec_dev *dev;
> +	struct video_device *vfd_dec;
> +	struct aml_vdec_hw *hw;
> +	int ret = 0;
> +
> +	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
> +	if (!dev)
> +		return -ENOMEM;
> +
> +	dev->plat_dev = pdev;
> +	mutex_init(&dev->dev_mutex);
> +
> +	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
> +	if (ret)
> +		return dev_err_probe(&pdev->dev, ret, "v4l2_device_register err\n");
> +
> +	vfd_dec = video_device_alloc();
> +	if (!vfd_dec) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
> +		ret = -ENOMEM;
> +		goto err_device_alloc;
> +	}
> +	*vfd_dec = dec_dev;
> +	vfd_dec->v4l2_dev = &dev->v4l2_dev;
> +	vfd_dec->lock = &dev->dev_mutex;
> +	video_set_drvdata(vfd_dec, dev);
> +	dev->vfd = vfd_dec;
> +	platform_set_drvdata(pdev, dev);
> +
> +	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> +	if (!hw) {
> +		ret = -ENOMEM;
> +		goto err_dec_mem_init;
> +	}
> +	dev->dec_hw = hw;
> +
> +	dev->pvdec_data = of_device_get_match_data(&pdev->dev);
> +	ret = dev->pvdec_data->req_hw_resource(dev);
> +	if (ret < 0)
> +		goto err_hw_init;
> +
> +	dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
> +	if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem dec device\n");
> +		ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
> +		goto err_hw_init;
> +	}
> +
> +	ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to register video device");
> +		goto err_vid_dev_register;
> +	}
> +
> +	v4l2_info(&dev->v4l2_dev, "Registered %s as /dev/%s\n",
> +		  vfd_dec->name, video_device_node_name(vfd_dec));
> +
> +	dev->mdev.dev = &pdev->dev;
> +	strscpy(dev->mdev.model, AML_VDEC_DRV_NAME, sizeof(dev->mdev.model));
> +	media_device_init(&dev->mdev);
> +	dev->mdev.ops = &aml_m2m_media_ops;
> +	dev->v4l2_dev.mdev = &dev->mdev;
> +
> +	ret = v4l2_m2m_register_media_controller(dev->m2m_dev_dec, vfd_dec,
> +						 MEDIA_ENT_F_PROC_VIDEO_DECODER);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
> +		goto error_m2m_mc_register;
> +	}
> +
> +	ret = media_device_register(&dev->mdev);
> +	if (ret) {
> +		v4l2_err(&dev->v4l2_dev, "Failed to register media device");
> +		goto err_media_dev_register;
> +	}
> +	vdec_enable(dev->dec_hw);
> +	return 0;
> +
> +err_media_dev_register:
> +	v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
> +error_m2m_mc_register:
> +	media_device_cleanup(&dev->mdev);
> +err_vid_dev_register:
> +	v4l2_m2m_release(dev->m2m_dev_dec);
> +err_hw_init:
> +	kfree(hw);
> +	dev->dec_hw = NULL;
> +err_dec_mem_init:
> +	video_device_release(vfd_dec);
> +err_device_alloc:
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +	return ret;
> +}
> +
> +static void aml_vdec_drv_remove(struct platform_device *pdev)
> +{
> +	struct aml_vdec_dev *dev = platform_get_drvdata(pdev);
> +
> +	vdec_disable(dev->dec_hw);
> +
> +	if (media_devnode_is_registered(dev->mdev.devnode)) {
> +		media_device_unregister(&dev->mdev);
> +		media_device_cleanup(&dev->mdev);
> +	}
> +
> +	if (dev->m2m_dev_dec)
> +		v4l2_m2m_release(dev->m2m_dev_dec);
> +	if (dev->vfd)
> +		video_unregister_device(dev->vfd);
> +	if (dev->dec_hw)
> +		dev->pvdec_data->destroy_hw_resource(dev);
> +
> +	v4l2_device_unregister(&dev->v4l2_dev);
> +
> +	pr_debug("aml v4l2 decoder driver remove\n");
> +}
> +
> +static const struct of_device_id aml_vdec_match[] = {
> +	{.compatible = "amlogic,s4-vcodec-dec", .data = &aml_vdec_s4_pdata},
> +	{},
> +};
> +
> +static struct platform_driver aml_vcodec_dec_driver = {
> +	.probe    = aml_vdec_drv_probe,
> +	.remove    = aml_vdec_drv_remove,
> +	.driver    = {
> +		.name    = AML_VDEC_DRV_NAME,

Use proper formatting here

> +		.of_match_table = aml_vdec_match,
> +	},
> +};
> +
> +static int __init aml_vdec_init(void)
> +{
> +	pr_debug("aml v4l2 decoder module init\n");
> +
> +	if (platform_driver_register(&aml_vcodec_dec_driver)) {
> +		pr_err("failed to register aml v4l2 decoder\n");
> +		return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static void __exit aml_vdec_exit(void)
> +{
> +	pr_debug("aml v4l2 decoder module exit\n");
> +	platform_driver_unregister(&aml_vcodec_dec_driver);
> +}
> +
> +module_init(aml_vdec_init);
> +module_exit(aml_vdec_exit);
> +
> +MODULE_DESCRIPTION("Amlogic V4L2 decoder driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h
> new file mode 100644
> index 000000000000..f3318cceff3f
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h
> @@ -0,0 +1,194 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#ifndef _AML_VDEC_DRV_H_
> +#define _AML_VDEC_DRV_H_
> +
> +#include <linux/platform_device.h>
> +#include <linux/videodev2.h>
> +#include <linux/clk.h>
> +
> +#include <media/v4l2-ctrls.h>
> +#include <media/v4l2-device.h>
> +#include <media/v4l2-ioctl.h>
> +#include <media/v4l2-mem2mem.h>
> +#include <media/videobuf2-core.h>
> +#include <media/videobuf2-dma-contig.h>
> +
> +#define AML_VCODEC_MAX_PLANES 3
> +#define AML_VDEC_MIN_W    64U
> +#define AML_VDEC_MIN_H    64U
> +#define AML_VDEC_1080P_MAX_H  1088U
> +#define AML_VDEC_1080P_MAX_W  1920U
> +
> +struct aml_vdec_ctx;
> +/**
> + * enum aml_fmt_type - Type of format type
> + */
> +enum aml_fmt_type {
> +	AML_FMT_DEC = 0,
> +	AML_FMT_FRAME = 1,
> +};
> +
> +/**
> + * enum aml_codec_type - Type of codec format
> + */
> +enum aml_codec_type {
> +	CODEC_TYPE_H264 = 0,
> +	CODEC_TYPE_FRAME,
> +};
> +
> +/**
> + * enum aml_q_type - Type of queue : cap or output
> + */
> +enum aml_q_type {
> +	AML_Q_DATA_SRC = 0,
> +	AML_Q_DATA_DST = 1,
> +};
> +
> +/**
> + * struct aml_video_fmt - aml video decoder fmt information
> + * @fourcc: FourCC code of the format. See V4L2_PIX_FMT_*.
> + * @type: Curr queue type: capture or output.
> + * @codec_type: Codec mode related. See aml_codec_type.
> + * @num_planes: Num planes of the format.
> + * @name: Name of the format.
> + * @stepwise: Supported range of frame sizes (only for bitstream formats).
> + */
> +struct aml_video_fmt {
> +	u32 fourcc;
> +	enum aml_fmt_type type;
> +	enum aml_codec_type codec_type;
> +	u32 num_planes;
> +	const u8 *name;
> +	struct v4l2_frmsize_stepwise stepwise;
> +};
> +
> +/**
> + * struct aml_q_data - aml video queue information
> + * @visible_width: Width for display.
> + * @visible_height: Height for display.
> + * @coded_width: Width for decode, which is 64/32 aligned.
> + * @coded_height: Height for decode, which is 64/32 aligned.
> + * @filed_flag: Field pic flag.
> + * @bytesperline: Byte num of each pixel line.
> + * @sizeimage: Size of frame in bytes.
> + * @fmt: Format for curr queue. See struct aml_video_fmt.
> + */
> +struct aml_q_data {
> +	u32 visible_width;
> +	u32 visible_height;
> +	u32 coded_width;
> +	u32 coded_height;
> +	u32 filed_flag;
> +	u32 bytesperline[AML_VCODEC_MAX_PLANES];
> +	u32 sizeimage[AML_VCODEC_MAX_PLANES];
> +	struct aml_video_fmt *fmt;
> +};
> +
> +/**
> + * struct aml_vdec_dev - driver data
> + * @plat_dev: Platform device for the current driver.
> + * @v4l2_dev: V4L2 device to register video devices for.
> + * @m2m_dev_dec: Mem2mem device associated to this device.
> + * @vfd: Video_device associated to this device.
> + * @mdev: Media_device associated to this device.
> + * @dec_ctx: Decoder context. See struct aml_vdec_ctx.
> + * @dec_hw: Decoder hardware resources. See struct aml_vdec_hw.
> + * @pvdec_data: Decoder platform data. See struct aml_dev_platform_data.
> + * @dev_mutex: video_device lock.
> + * @filp: v4l2 file handle pointer.
> + */
> +struct aml_vdec_dev {
> +	struct platform_device *plat_dev;
> +	struct v4l2_device v4l2_dev;
> +	struct v4l2_m2m_dev *m2m_dev_dec;
> +	struct video_device *vfd;
> +	struct media_device mdev;
> +
> +	struct aml_vdec_ctx *dec_ctx;
> +	struct aml_vdec_hw *dec_hw;
> +	const struct aml_dev_platform_data *pvdec_data;
> +
> +	struct mutex dev_mutex;
> +	struct file *filp;
> +};
> +
> +/**
> + * struct dec_pic_info - pic information description
> + * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
> + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
> + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
> + * @quantization: enum v4l2_quantization, colorspace quantization
> + * @cap_pix_fmt: Pixel format for capture queue.
> + * @output_pix_fmt: Pixel format for output queue.
> + * @coded_width: Width for decode.
> + * @coded_height: Height for decode.
> + * @fb_size: Frame buffer size for Y or UV.
> + * @plane_num: Num for planes for curr format.
> + */
> +struct dec_pic_info {
> +	enum v4l2_colorspace colorspace;
> +	enum v4l2_ycbcr_encoding ycbcr_enc;
> +	enum v4l2_xfer_func xfer_func;
> +	enum v4l2_quantization quantization;
> +	u32 cap_pix_fmt;
> +	u32 output_pix_fmt;
> +	u32 coded_width;
> +	u32 coded_height;
> +	u32 fb_size[2];
> +	u32 plane_num;
> +};
> +
> +/**
> + * struct aml_vdec_ctx - driver instance context
> + * @dev: pointer to the aml_vdec_dev of the device.
> + * @fh: struct v4l2 fh.
> + * @m2m_ctx: pointer to v4l2_m2m_ctx context.
> + * @ctrl_handler: V4L2 ctrl handler.
> + * @v4l2_intf_lock: Mutex lock for v4l2 interface.
> + * @codec_ops: Codec operation functions. See struct aml_codec_ops.
> + * @int_cond: Variable used by the waitqueue.
> + * @queue: Waitqueue to wait for the current decode context finish.
> + * @q_data: feature supported by the current decoder instance.
> + * @is_cap_streamon: indicates if the current capture stream is on.
> + * @is_output_streamon: indicates if the current output stream is on.
> + * @dos_clk_en: indicates if dos clk is enabled.
> + * @pic_info: Pic information for curr decoder context. See struct dec_pic_info.
> + * @curr_dec_type: Current decoder type. (CODEC_TYPE_H264, etc.)
> + * @codec_priv: Pointer to current decoder instance.
> + */
> +struct aml_vdec_ctx {
> +	struct aml_vdec_dev *dev;
> +	struct v4l2_fh fh;
> +	struct v4l2_m2m_ctx *m2m_ctx;
> +	struct v4l2_ctrl_handler ctrl_handler;
> +	struct mutex v4l2_intf_lock;
> +
> +	const struct aml_codec_ops *codec_ops;
> +	int int_cond;
> +	wait_queue_head_t queue;
> +	struct aml_q_data q_data[2];
> +
> +	bool is_cap_streamon;
> +	bool is_output_streamon;
> +	bool dos_clk_en;
> +
> +	struct dec_pic_info pic_info;
> +	u32 curr_dec_type;
> +	void *codec_priv;
> +};
> +
> +static inline struct aml_vdec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
> +{
> +	return container_of(fh, struct aml_vdec_ctx, fh);
> +}
> +
> +static inline struct aml_vdec_ctx *ctrl_to_dec_ctx(struct v4l2_ctrl_handler *ctrl)
> +{
> +	return container_of(ctrl, struct aml_vdec_ctx, ctrl_handler);
> +}
> +
> +#endif
> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
> new file mode 100644
> index 000000000000..4db0e3076761
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
> @@ -0,0 +1,652 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/slab.h>
> +#include <linux/firmware.h>
> +
> +#include "aml_vdec_drv.h"
> +#include "aml_vdec_hw.h"
> +#include "aml_vdec_platform.h"
> +#include "aml_vdec_canvas_utils.h"
> +
> +#define MHz     (1000000)
> +#define MC_SIZE (4096 * 16)
> +
> +static void __iomem *reg_base[MAX_REG_BUS];
> +
> +static struct pm_pd_s vdec_domain_data[] = {
> +	[VDEC_1] = {.name = "pwrc-vdec", },
> +	[VDEC_HEVC] = {.name = "pwrc-hevc", },
> +};
> +
> +u32 read_dos_reg(u32 addr)
> +{
> +	return readl(reg_base[DOS_BUS] + (addr << 2));
> +}
> +
> +void write_dos_reg(u32 addr, int val)
> +{
> +	writel(val, reg_base[DOS_BUS] + (addr << 2));
> +}
> +
> +u32 read_dmc_reg(u32 addr)
> +{
> +	return readl(reg_base[DMC_BUS] + (addr << 2));
> +}
> +
> +void write_dmc_reg(u32 addr, int val)
> +{
> +	writel(val, reg_base[DMC_BUS] + (addr << 2));
> +}
> +
> +void dos_reg_set_mask(u32 addr, u32 mask)
> +{
> +	u32 r;
> +
> +	r = read_dos_reg(addr);
> +	write_dos_reg(addr, (r | mask));
> +}
> +
> +void dos_reg_clear_mask(u32 addr, u32 mask)
> +{
> +	u32 r;
> +
> +	r = read_dos_reg(addr);
> +	write_dos_reg(addr, (r & (~mask)));
> +}
> +
> +void dos_reg_write_bits(u32 reg, u32 val, int start, int len)
> +{
> +	u32 to_val = read_dos_reg(reg);
> +	u32 mask = (((1L << (len)) - 1) << (start));
> +
> +	to_val &= ~mask;
> +	to_val |= (val << start) & mask;
> +	write_dos_reg(reg, to_val);
> +}

Do not reinvent register writting, use regmap for all that.

> +
> +void dos_enable(void)
> +{
> +	WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10);
> +
> +	WRITE_VREG(GCLK_EN, 0x3ff);
> +
> +	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 31));
> +}
> +
> +void aml_vdec_reset_core(void)
> +{
> +	unsigned int mask = 0;
> +
> +	mask = (1 << 21);
> +
> +	write_dmc_reg(0x0, (read_dmc_reg(0x0) & ~mask));
> +	usleep_range(60, 70);
> +	WRITE_VREG(DOS_SW_RESET0, (1 << 3) | (1 << 4) |
> +		   (1 << 5) | (1 << 7) | (1 << 8) | (1 << 9));
> +	WRITE_VREG(DOS_SW_RESET0, 0);
> +	CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
> +	CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
> +	WRITE_VREG(MDEC_EXTIF_CFG1, 0);
> +
> +	write_dmc_reg(0x0, (read_dmc_reg(0x0) | mask));
> +}
> +
> +void aml_start_vdec_hw(void)
> +{
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +
> +	WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
> +	WRITE_VREG(DOS_SW_RESET0, 0);
> +
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +
> +	WRITE_VREG(MPSR, 0x0001);

This is basilly copuy of downstream code, use proper register writing
functions and stop using downstream macros.

> +}
> +
> +void aml_stop_vdec_hw(void)
> +{
> +	ulong timeout = jiffies + HZ / 10;
> +
> +	WRITE_VREG(MPSR, 0);
> +	WRITE_VREG(CPSR, 0);
> +
> +	while (RD_VREG(IMEM_DMA_CTRL) & 0x8000) {
> +		if (time_after(jiffies, timeout))
> +			break;
> +	}

Use read_poll_timeout() or any variant instead of re-inventig polling.

> +
> +	timeout = jiffies + HZ / 10;
> +	while (RD_VREG(LMEM_DMA_CTRL) & 0x8000) {
> +		if (time_after(jiffies, timeout))
> +			break;
> +	}
> +
> +	timeout = jiffies + HZ / 80;
> +	while (RD_VREG(WRRSP_LMEM) & 0xfff) {
> +		if (time_after(jiffies, timeout)) {
> +			pr_err("%s, ctrl %x, rsp %x, pc %x status %x,%x\n",
> +			       __func__, RD_VREG(LMEM_DMA_CTRL),
> +			       RD_VREG(WRRSP_LMEM), RD_VREG(MPC_E),
> +			       RD_VREG(AV_SCRATCH_J), RD_VREG(AV_SCRATCH_9));
> +			break;
> +		}
> +	}
> +
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +
> +	WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
> +	WRITE_VREG(DOS_SW_RESET0, 0);
> +
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +	RD_VREG(DOS_SW_RESET0);
> +}
> +
> +int load_firmware(struct aml_vdec_hw *hw, const char *path)
> +{
> +	const struct firmware *fw;
> +	struct device *dev = hw->dev;
> +	static u8 *mc_addr;
> +	static dma_addr_t mc_addr_map;
> +	int fw_head_len;
> +	ulong timeout;
> +	int ret;
> +
> +	ret = request_firmware(&fw, path, dev);
> +	if (ret < 0) {
> +		pr_info("request_firmware %s failed ret %d\n", path, ret);
> +		return -EINVAL;
> +	}
> +
> +	if (fw->size > MC_SIZE) {
> +		pr_info("fw %s oversize\n", path);
> +		ret = -EINVAL;
> +		goto release_firmware;
> +	}
> +
> +	fw_head_len = 512;
> +	mc_addr = dma_alloc_coherent(dev, MC_SIZE, &mc_addr_map, GFP_KERNEL);
> +	if (!mc_addr) {
> +		pr_info("no mem for fw %s\n", path);
> +		ret = -ENOMEM;
> +		goto release_firmware;
> +	}
> +	memset(mc_addr, 0, MC_SIZE);
> +	memcpy(mc_addr, ((u8 *)fw->data + fw_head_len),
> +	       (fw->size - fw_head_len));
> +
> +	WRITE_VREG(MPSR, 0);
> +	WRITE_VREG(CPSR, 0);
> +
> +	timeout = RD_VREG(MPSR);
> +	timeout = RD_VREG(MPSR);
> +	timeout = jiffies + HZ;
> +
> +	WRITE_VREG(IMEM_DMA_ADR, mc_addr_map);
> +	WRITE_VREG(IMEM_DMA_COUNT, 0x1000);
> +	WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
> +
> +	while (RD_VREG(IMEM_DMA_CTRL) & 0x8000) {
> +		if (time_before(jiffies, timeout)) {
> +			schedule();
> +		} else {
> +			pr_info("vdec load mc error\n");
> +			ret = -EBUSY;
> +			break;
> +		}
> +	}
> +
> +	/* Only h264 needs this step */
> +	if (hw->hw_ops.load_firmware_ex) {
> +		ret = hw->hw_ops.load_firmware_ex(hw->curr_ctx,
> +						  mc_addr,
> +						  (fw->size - fw_head_len));
> +		if (ret < 0) {
> +			ret = -EINVAL;
> +			goto free_dma_mem;
> +		}
> +	}
> +
> +free_dma_mem:
> +	dma_free_coherent(dev, MC_SIZE, mc_addr, mc_addr_map);
> +release_firmware:
> +	release_firmware(fw);
> +	return ret;
> +}
> +
> +static int vdec_clock_gate_init(struct aml_vdec_hw *hw)
> +{
> +	int i;
> +
> +	hw->gates[VDEC].name = "vdec";
> +	hw->gates[VDEC_MUX].name = "clk_vdec_mux";
> +	hw->gates[HEVCF_MUX].name = "clk_hevcf_mux";
> +
> +	for (i = 0; i < DOS_CLK_MAX; i++) {
> +		hw->gates[i].clk = devm_clk_get(hw->dev, hw->gates[i].name);
> +		hw->gates[i].ref_count = 0;
> +		mutex_init(&hw->gates[i].mutex);
> +	}
> +
> +	return 0;
> +}
> +
> +static int vdec_gate_clk(struct gate_switch_node *gate_node, bool enable)
> +{
> +	int ret = 0;
> +
> +	mutex_lock(&gate_node->mutex);
> +	if (enable) {
> +		gate_node->ref_count++;
> +		if (gate_node->ref_count == 1) {
> +			ret = clk_prepare_enable(gate_node->clk);
> +			pr_debug("the %-15s clock on, ref cnt: %d ret = %d\n",
> +				 gate_node->name, gate_node->ref_count, ret);
> +		}
> +	} else {
> +		gate_node->ref_count--;
> +		if (!gate_node->ref_count) {
> +			clk_disable_unprepare(gate_node->clk);
> +			pr_debug("the %-15s clock off, ref cnt: %d ret = %d\n",
> +				 gate_node->name, gate_node->ref_count, ret);
> +		}
> +	}
> +	mutex_unlock(&gate_node->mutex);
> +
> +	return 0;
> +}
> +
> +static int vdec_switch_gate(struct aml_vdec_hw *hw,
> +			    const char *name, bool enable)
> +{
> +	int i;
> +
> +	for (i = 0; i < DOS_CLK_MAX; i++) {
> +		if (!strcmp(name, hw->gates[i].name)) {
> +			if (hw->gates[i].clk)
> +				vdec_gate_clk(&hw->gates[i], enable);
> +			else
> +				return -ENODEV;
> +		}
> +	}
> +	return 0;
> +}
> +
> +static int vdec_set_rate(struct aml_vdec_hw *hw,
> +			 const char *name, unsigned long hz)
> +{
> +	int i;
> +
> +	for (i = 0; i < DOS_CLK_MAX; i++) {
> +		if (!strcmp(name, hw->gates[i].name)) {
> +			if (hw->gates[i].clk && hw->gates[i].ref_count) {
> +				clk_set_rate(hw->gates[i].clk, hz);
> +				pr_debug("after set, vdec mux clock is %lu Hz\n",
> +					 clk_get_rate(hw->gates[i].clk));
> +			} else {
> +				return -ENODEV;
> +			}
> +		}
> +	}
> +	return 0;
> +}
> +
> +static void pm_vdec_clock_switch(struct aml_vdec_hw *hw, int id, bool on)
> +{
> +	int ret = 0;
> +
> +	if (id == VDEC_1) {
> +		ret = vdec_switch_gate(hw, "clk_vdec_mux", on);
> +		vdec_set_rate(hw, "clk_vdec_mux", 499999992);
> +	} else if (id == VDEC_HEVC) {
> +		/* enable hevc clock */
> +		ret = vdec_switch_gate(hw, "clk_hevcf_mux", on);
> +		if (ret == -ENODEV)
> +			ret = vdec_switch_gate(hw, "clk_hevc_mux", on);
> +	}
> +
> +	if (ret < 0)
> +		pr_debug("clk %d, unreachable ret %d\n", id, ret);
> +}
> +
> +static void pm_vdec_power_switch(struct pm_pd_s *pd, int id, bool on)
> +{
> +	struct device *dev = pd[id].dev;
> +	int ret;
> +
> +	if (!dev) {
> +		pr_debug("no dev %d, maybe always on\n", id);
> +		return;
> +	}
> +
> +	if (on)
> +		ret = pm_runtime_get_sync(dev);
> +	else
> +		ret = pm_runtime_put_sync(dev);
> +
> +	pr_debug("dev: %p link %p the %-15s power %s ret %d\n",
> +		 dev, pd[id].link, pd[id].name, on ? "on" : "off", ret);
> +}

Thoses helpers functions are quite overengineered and only used in 2 functions,
just call pm_runtime_XXX, clk_XXX functions directly...

> +
> +static int pm_vdec_power_domain_init(struct aml_vdec_hw *hw)
> +{
> +	int i, err;
> +	const struct power_manager_s *pm = hw->pm;
> +	struct pm_pd_s *pd = pm->pd_data;
> +
> +	mutex_init(&hw->pm_mutex);
> +
> +	for (i = 0; i < VDEC_MAX; i++) {
> +		pd[i].dev = dev_pm_domain_attach_by_name(hw->dev, pd[i].name);
> +		if (IS_ERR_OR_NULL(pd[i].dev)) {
> +			err = PTR_ERR(pd[i].dev);
> +			pr_debug("Get %s failed, pm-domain: %d\n",
> +				 pd[i].name, err);
> +			continue;
> +		}
> +
> +		pd[i].link = device_link_add(hw->dev, pd[i].dev,
> +					     DL_FLAG_PM_RUNTIME |
> +					     DL_FLAG_STATELESS);
> +		if (IS_ERR_OR_NULL(pd[i].link)) {
> +			pr_err("Adding %s device link failed!\n", pd[i].name);
> +			return -ENODEV;
> +		}
> +
> +		pr_debug("power domain: name: %s, dev: %p, link: %p\n",
> +			 pd[i].name, pd[i].dev, pd[i].link);
> +	}
> +
> +	return 0;
> +}
> +
> +static void pm_vdec_power_domain_release(struct aml_vdec_hw *hw)
> +{
> +	int i;
> +	const struct power_manager_s *pm = hw->pm;
> +	struct pm_pd_s *pd = pm->pd_data;
> +
> +	for (i = 0; i < VDEC_MAX; i++) {
> +		if (!IS_ERR_OR_NULL(pd[i].link))
> +			device_link_del(pd[i].link);
> +
> +		if (!IS_ERR_OR_NULL(pd[i].dev))
> +			dev_pm_domain_detach(pd[i].dev, true);
> +	}
> +}
> +
> +static void dos_local_config(bool is_on, int id)
> +{
> +	if (is_on) {
> +		usleep_range(20, 100);
> +
> +		switch (id) {
> +		case VDEC_1:
> +			WRITE_VREG(DOS_MEM_PD_VDEC, 0);
> +			WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_SW_RESET0, 0);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_MEM_PD_VDEC, 0);
> +			break;
> +		case VDEC_HEVC:
> +			WRITE_VREG(DOS_MEM_PD_HEVC, 0);
> +			WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_SW_RESET3, 0);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_MEM_PD_HEVC, 0);
> +			break;
> +		default:
> +			pr_debug("%s on, not found id %d\n", __func__, id);
> +			break;
> +		}
> +	} else {
> +		switch (id) {
> +		case VDEC_1:
> +			WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_SW_RESET0, 0);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
> +			break;
> +		case VDEC_HEVC:
> +			WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_SW_RESET3, 0);
> +			usleep_range(20, 100);
> +			WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
> +			break;
> +		default:
> +			pr_debug("%s off, not found id %d\n", __func__, id);
> +			break;
> +		}
> +	}
> +
> +	pr_debug("%s end, id %d, is_on %d\n", __func__, id, is_on);
> +}
> +
> +static void pm_vdec_power_domain_power_on(struct aml_vdec_hw *hw, int id)
> +{
> +	const struct power_manager_s *pm = hw->pm;
> +
> +	pm_vdec_clock_switch(hw, id, true);
> +	pm_vdec_power_switch(pm->pd_data, id, true);
> +
> +	dos_local_config(1, id);
> +}
> +
> +static void pm_vdec_power_domain_power_off(struct aml_vdec_hw *hw, int id)
> +{
> +	const struct power_manager_s *pm = hw->pm;
> +
> +	dos_local_config(0, id);
> +
> +	pm_vdec_clock_switch(hw, id, false);
> +	pm_vdec_power_switch(pm->pd_data, id, false);
> +}
> +
> +static bool pm_vdec_power_domain_power_state(struct aml_vdec_hw *hw, int id)
> +{
> +	if (hw->pm->pd_data[id].dev)
> +		return pm_runtime_active(hw->pm->pd_data[id].dev);
> +	else
> +		return false;
> +}
> +
> +static void vdec_poweron(struct aml_vdec_hw *hw, enum vdec_type_e core)
> +{
> +	if (core >= VDEC_MAX)
> +		return;
> +
> +	mutex_lock(&hw->pm_mutex);
> +	if (!hw->pm->pd_data[core].dev)
> +		goto out;
> +
> +	hw->pm->pd_data[core].ref_count++;
> +	if (hw->pm->pd_data[core].ref_count > 1)
> +		goto out;
> +
> +	if (hw->pm->power_state(hw, core))
> +		goto out;
> +
> +	hw->pm->power_on(hw, core);
> +
> +out:
> +	mutex_unlock(&hw->pm_mutex);
> +}
> +
> +static void vdec_poweroff(struct aml_vdec_hw *hw, enum vdec_type_e core)
> +{
> +	if (core >= VDEC_MAX)
> +		return;
> +
> +	mutex_lock(&hw->pm_mutex);
> +	if (hw->pm->pd_data[core].ref_count == 0)
> +		goto out;
> +
> +	hw->pm->pd_data[core].ref_count--;
> +	if (hw->pm->pd_data[core].ref_count > 0)
> +		goto out;
> +
> +	hw->pm->power_off(hw, core);
> +
> +out:
> +	mutex_unlock(&hw->pm_mutex);
> +}
> +
> +int vdec_enable(struct aml_vdec_hw *hw)
> +{
> +	vdec_switch_gate(hw, "vdec", 1);
> +	vdec_poweron(hw, VDEC_1);
> +
> +	return 0;
> +}
> +
> +int vdec_disable(struct aml_vdec_hw *hw)
> +{
> +	vdec_poweroff(hw, VDEC_1);
> +	vdec_switch_gate(hw, "vdec", 0);
> +
> +	return 0;
> +}
> +
> +static const struct power_manager_s pm[] = {
> +	[AML_PM_PD] = {
> +		.pd_data    = vdec_domain_data,
> +		.init        = pm_vdec_power_domain_init,
> +		.release    = pm_vdec_power_domain_release,
> +		.power_on    = pm_vdec_power_domain_power_on,
> +		.power_off    = pm_vdec_power_domain_power_off,
> +		.power_state = pm_vdec_power_domain_power_state,
> +	},
> +};
> +
> +static irqreturn_t vdec_irq_handler(int irq, void *priv)
> +{
> +	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
> +	struct aml_vdec_hw *hw = dev->dec_hw;
> +	irqreturn_t ret;
> +
> +	if (hw->hw_ops.irq_handler)
> +		ret = hw->hw_ops.irq_handler(irq, priv);
> +
> +	return ret;
> +}
> +
> +static irqreturn_t vdec_threaded_isr_handler(int irq, void *priv)
> +{
> +	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
> +	struct aml_vdec_hw *hw = dev->dec_hw;
> +	irqreturn_t ret = IRQ_HANDLED;
> +
> +	if (hw->hw_ops.irq_threaded_func)
> +		ret = hw->hw_ops.irq_threaded_func(irq, priv);
> +
> +	return ret;
> +}
> +
> +struct aml_vdec_hw *vdec_get_hw(void *priv)
> +{
> +	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
> +
> +	return dev->dec_hw;
> +}
> +
> +int dev_request_hw_resources(void *priv)
> +{
> +	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
> +	struct aml_vdec_hw *hw;
> +	struct platform_device *pdev;
> +	struct resource res;
> +	u32 res_size;
> +	int i;
> +	int ret = -1;
> +
> +	if (!dev || !dev->dec_hw) {
> +		pr_err("%s param invalid\n", __func__);
> +		return -1;
> +	}
> +	pdev = dev->plat_dev;
> +	hw = dev->dec_hw;
> +	hw->dev = &pdev->dev;
> +
> +	hw->dec_irq = platform_get_irq(pdev, VDEC_IRQ_1);
> +	if (hw->dec_irq < 0) {
> +		dev_err(&pdev->dev, "get irq failed\n");
> +		return hw->dec_irq;
> +	}
> +	ret = devm_request_threaded_irq(&pdev->dev, hw->dec_irq, vdec_irq_handler,
> +					vdec_threaded_isr_handler, IRQF_ONESHOT,
> +					"vdec-1", dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to install irq %d (%d)",
> +			hw->dec_irq, ret);
> +		return -1;
> +	}
> +
> +	for (i = 0; i < MAX_REG_BUS; i++) {
> +		if (of_address_to_resource(pdev->dev.of_node, i, &res)) {
> +			pr_err("of_address_to_resource %d failed\n", i);
> +			return -EINVAL;
> +		}
> +
> +		res_size = resource_size(&res);
> +		hw->regs[i] = ioremap(res.start, res_size);
> +		reg_base[i] = hw->regs[i];
> +
> +		pr_debug("%s, res start %llx, end %llx, iomap: %p\n",
> +			 __func__, (unsigned long long)res.start,
> +			 (unsigned long long)res.end, reg_base[i]);
> +	}
> +
> +	hw->pm = &pm[dev->pvdec_data->power_type];
> +	if (hw->pm->init) {
> +		ret = hw->pm->init(hw);
> +		if (ret < 0) {
> +			pr_err("power mgr init failed!\n");
> +			return ret;
> +		}
> +	}
> +	vdec_clock_gate_init(hw);
> +
> +	aml_vdec_canvas_register(hw);
> +
> +	pr_debug("##Amlogic hw resource init OK##\n");
> +
> +	return 0;
> +}
> +
> +void dev_destroy_hw_resources(void *priv)
> +{
> +	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
> +	struct aml_vdec_hw *hw;
> +
> +	if (!dev || !dev->dec_hw) {
> +		pr_err("%s param invalid\n", __func__);
> +		return;
> +	}
> +	hw = dev->dec_hw;
> +
> +	if (hw->pm->release)
> +		hw->pm->release(hw);
> +
> +	kfree(hw);
> +	dev->dec_hw = NULL;
> +	pr_debug("##Amlogic hw resource release OK##\n");
> +}
> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h
> new file mode 100644
> index 000000000000..ad1e613a2cf8
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h
> @@ -0,0 +1,182 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#ifndef _AML_VDEC_HW_H_
> +#define _AML_VDEC_HW_H_
> +
> +#include <linux/module.h>
> +#include <linux/clk.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/pm_domain.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/delay.h>
> +#include <linux/regmap.h>
> +#include <linux/interrupt.h>
> +#include "reg_defines.h"
> +
> +#define VDEC_FIFO_ALIGN     8
> +#define VLD_PADDING_SIZE    1024
> +
> +#define RD_VREG(addr) read_dos_reg(addr)
> +#define WRITE_VREG(addr, val) write_dos_reg(addr, val)
> +#define WRITE_VREG_BITS(r, val, start, len) dos_reg_write_bits(r, val, start, len)
> +#define CLEAR_VREG_MASK(r, mask) dos_reg_clear_mask(r, mask)
> +#define SET_VREG_MASK(r, mask) dos_reg_set_mask(r, mask)


Please drop this macros and use the functions directly.

> +
> +/**
> + * struct aml_vdec_hw_ops - codec mode specific operations for hw
> + * @load_firmware_ex: Load firmware for current dec specific.
> + * @irq_handler: mandatory call when the ISR triggers
> + * @irq_threaded_func: mandatory call for the threaded ISR
> + * @canvas_alloc: Alloc canvas for curr frame
> + * @canvas_free: Release canvas.
> + * @config_canvas: Config for curr frame, such as w/h, Y/UV start addr etc.
> + */
> +struct aml_vdec_hw_ops {
> +	int (*load_firmware_ex)(void *priv, const u8 *data, u32 len);
> +	irqreturn_t (*irq_handler)(int irq, void *priv);
> +	irqreturn_t (*irq_threaded_func)(int irq, void *priv);
> +	int (*canvas_alloc)(u8 *canvas_index);
> +	void (*canvas_free)(u8 canvas_index);
> +	void (*config_canvas)(u8 canvas_index,
> +			      ulong addr, u32 width, u32 height,
> +			      u32 wrap, u32 blkmode, u32 endian);
> +};
> +
> +/**
> + * enum vdec_type_e - Type of decoder hardware.
> + */
> +enum vdec_type_e {
> +	VDEC_1 = 0,
> +	VDEC_HEVC,
> +	VDEC_MAX,
> +};
> +
> +/**
> + * enum vdec_irq_num - Definition of the irq.
> + */
> +enum vdec_irq_num {
> +	VDEC_IRQ_0 = 0,
> +	VDEC_IRQ_1,
> +	VDEC_IRQ_2,
> +	VDEC_IRQ_MAX,
> +};
> +
> +/**
> + * enum vdec_type_e - Type of decoder clock.
> + */
> +enum clk_type_e {
> +	VDEC = 0,
> +	VDEC_MUX,
> +	HEVCF_MUX,
> +	DOS_CLK_MAX,
> +};
> +
> +/**
> + * enum aml_power_type_e - Type of decoder power.
> + */
> +enum aml_power_type_e {
> +	AML_PM_PD = 0,
> +};
> +
> +/**
> + * enum mm_bus_e - Type of decoder hardware bus.
> + */
> +enum mm_bus_e {
> +	DOS_BUS = 0,
> +	DMC_BUS,
> +	MAX_REG_BUS
> +};
> +
> +/**
> + * struct gate_switch_node - clock node definition
> + * @clk: Pointer to clk instance.
> + * @name: Clock name used.
> + * @mutex: Mutex lock for multi decoder instance.
> + * @ref_count: Curr clk instance ref count.
> + */
> +struct gate_switch_node {
> +	struct clk *clk;
> +	const char *name;
> +	struct mutex mutex;
> +	int ref_count;
> +};
> +
> +/**
> + * struct pm_pd_s - power domain definition
> + * @name: Power domain name.
> + * @dev: Pointer to device structure.
> + * @mutex: Pointer to device_link structure.
> + * @ref_count: Curr power domain instance ref count.
> + */
> +struct pm_pd_s {
> +	u8 *name;
> +	struct device *dev;
> +	struct device_link *link;
> +	int ref_count;
> +};
> +
> +/**
> + * struct aml_vdec_hw - decoder hardware resources definition
> + * @pdev: Pointer to struct platform_device.
> + * @dev: Pointer to struct device.
> + * @regs: Reg base for dos/dmc hardware.
> + * @pm_mutex: Mutex for pm->pd_data.
> + * @pm: Pointer to struct power_manager_s.
> + * @hw_ops: Hardware resource operation functions. See struct aml_vdec_hw_ops.
> + * @gates: Clk instance used by curr decoder context.
> + * @dec_irq: Irq registered.
> + * @curr_ctx: Pointer to curr decoder context.
> + */
> +struct aml_vdec_hw {
> +	struct platform_device *pdev;
> +	struct device *dev;
> +	void __iomem *regs[MAX_REG_BUS];
> +	struct mutex pm_mutex;
> +	const struct power_manager_s *pm;
> +	struct aml_vdec_hw_ops hw_ops;
> +	struct gate_switch_node gates[DOS_CLK_MAX];
> +	int dec_irq;
> +	void *curr_ctx;
> +};
> +
> +/**
> + * struct power_manager_s - Power manager & opertion function
> + * @pd_data: Pointer to struct pm_pd_s
> + * @init: Power manager init.
> + * @release: Power manager release.
> + * @power_on: Power on for decoder hw.
> + * @power_off: Power off for decoder hw.
> + * @power_state: Query the power state.
> + */
> +struct power_manager_s {
> +	struct pm_pd_s *pd_data;
> +	int (*init)(struct aml_vdec_hw *hw);
> +	void (*release)(struct aml_vdec_hw *hw);
> +	void (*power_on)(struct aml_vdec_hw *hw, int id);
> +	void (*power_off)(struct aml_vdec_hw *hw, int id);
> +	bool (*power_state)(struct aml_vdec_hw *hw, int id);
> +};
> +
> +int dev_request_hw_resources(void *priv);
> +void dev_destroy_hw_resources(void *priv);
> +struct aml_vdec_hw *vdec_get_hw(void *priv);
> +u32 read_dos_reg(u32 reg_addr);
> +void write_dos_reg(u32 addr, int val);
> +void dos_reg_write_bits(u32 reg, u32 val, int start, int len);
> +void dos_reg_clear_mask(u32 addr, u32 mask);
> +void dos_reg_set_mask(u32 addr, u32 mask);
> +u32 read_dmc_reg(u32 addr);
> +void write_dmc_reg(u32 addr, int val);
> +int vdec_enable(struct aml_vdec_hw *hw);
> +int vdec_disable(struct aml_vdec_hw *hw);
> +void dos_enable(void);
> +void aml_start_vdec_hw(void);
> +void aml_stop_vdec_hw(void);
> +int load_firmware(struct aml_vdec_hw *hw, const char *path);
> +void aml_vdec_reset_core(void);
> +
> +#endif
> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c
> new file mode 100644
> index 000000000000..f1f8ba1f4ff6
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c
> @@ -0,0 +1,37 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#include "aml_vdec_platform.h"
> +#include "aml_vdec_drv.h"
> +#include "aml_vdec_hw.h"
> +#include "h264.h"
> +
> +#define VIDEO_DEC_H264  "s4_h264_multi.bin"
> +
> +const struct aml_codec_ops aml_S4_dec_ops[] = {
> +	[CODEC_TYPE_H264] = {
> +		.init = aml_h264_init,
> +		.exit = aml_h264_exit,
> +		.run = aml_h264_dec_run,
> +	},
> +};
> +
> +static const struct aml_video_dec_fmt aml_S4_dec_fmts = {
> +	.max_height = AML_VDEC_1080P_MAX_H,
> +	.max_width = AML_VDEC_1080P_MAX_W,
> +	.align = 32,
> +	.is_10_bit_support = 0,
> +};
> +
> +const struct aml_dev_platform_data aml_vdec_s4_pdata = {
> +	.dec_fmt = &aml_S4_dec_fmts,
> +	.codec_ops = aml_S4_dec_ops,
> +	.power_type = AML_PM_PD,
> +	.req_hw_resource = dev_request_hw_resources,
> +	.destroy_hw_resource = dev_destroy_hw_resources,
> +	.fw_path = {
> +		VIDEO_DEC_H264,
> +	},
> +};
> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h
> new file mode 100644
> index 000000000000..ff0933f6f074
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h
> @@ -0,0 +1,62 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#ifndef AML_VDEC_PLATFORM_H_
> +#define AML_VDEC_PLATFORM_H_
> +
> +#include <linux/videodev2.h>
> +
> +#define MAX_DEC_FORMAT 3
> +
> +/**
> + * struct aml_codec_ops - codec mode specific operations
> + * @init: Used for decoder initialization.
> + * @exit: If needed, can be used to undo the .init phase.
> + * @run: Start a single decoding job. Called from atomic context.
> + * Caller should ensure that a pair of buffers is ready and the
> + * hardware is powered on and clk is enabled. Returns zero if OK,
> + * a negative value in error cases.
> + */
> +struct aml_codec_ops {
> +	int (*init)(void *priv);
> +	void (*exit)(void *priv);
> +	int (*run)(void *priv);
> +};
> +
> +/**
> + * struct aml_video_dec_fmt - codec format required by platform
> + * @max_height: Max decode frame height of current platform.
> + * @max_width: Max decode frame width of current platform.
> + * @align: Align requirement of the current platform.
> + * @is_10_bit_support: Whether the platform supports 10 bit.
> + */
> +struct aml_video_dec_fmt {
> +	u32 max_height;
> +	u32 max_width;
> +	int align;
> +	int is_10_bit_support;
> +};
> +
> +/**
> + * struct aml_dev_platform_data - compatible data for each chip.
> + * @dec_fmt: Support dec format.
> + * @codec_ops: Codec operation function.
> + * @req_hw_resource: Operation function to request the hardware resource.
> + * @destroy_hw_resource: Operation function to release the hardware resource.
> + * @power_type: Type of power that the current chip need. See aml_power_type_e.
> + * @fw_path: Path of the firmware.bin.
> + */
> +struct aml_dev_platform_data {
> +	const struct aml_video_dec_fmt *dec_fmt;
> +	const struct aml_codec_ops *codec_ops;
> +	int (*req_hw_resource)(void *priv);
> +	void (*destroy_hw_resource)(void *priv);
> +	int power_type;
> +	const char *fw_path[MAX_DEC_FORMAT];
> +};
> +
> +extern const struct aml_dev_platform_data aml_vdec_s4_pdata;
> +
> +#endif
> diff --git a/drivers/media/platform/amlogic/vdec/h264.c b/drivers/media/platform/amlogic/vdec/h264.c
> new file mode 100644
> index 000000000000..ebfd10885eaa
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/h264.c
> @@ -0,0 +1,1790 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#include <media/v4l2-h264.h>
> +#include <linux/vmalloc.h>
> +#include "aml_vdec.h"
> +#include "aml_vdec_hw.h"
> +#include "h264.h"
> +
> +#define INVALID_POC 0xffffffff
> +
> +#define H264_SLICE_HEADER_DONE		0x1
> +#define H264_SLICE_DATA_DONE		0x2
> +
> +#define DECODER_TIMEOUT_MS			500
> +
> +#define COL_BUFFER_MARGIN			2
> +
> +struct vdec_h264_stateless_ctrl_ref {
> +	const struct v4l2_ctrl_h264_decode_params *decode;
> +	const struct v4l2_ctrl_h264_scaling_matrix *scaling;
> +	const struct v4l2_ctrl_h264_sps *sps;
> +	const struct v4l2_ctrl_h264_pps *pps;
> +};
> +
> +enum SliceType {
> +	P_SLICE = 0,
> +	B_SLICE = 1,
> +	I_SLICE = 2,
> +	SP_SLICE = 3,
> +	SI_SLICE = 4,
> +	MAX_SLICE_TYPES = 5
> +};
> +
> +/* Used by firmware */
> +union param {
> +	struct {
> +		unsigned short data[RPM_END - RPM_BEGIN];
> +	} l;
> +	struct {
> +		unsigned short dump[DPB_OFFSET];
> +		unsigned short dpb_base[FRAME_IN_DPB << 3];
> +
> +		unsigned short dpb_max_buffer_frame;
> +		unsigned short actual_dpb_size;
> +
> +		unsigned short colocated_buf_status;
> +
> +		unsigned short num_forward_short_term_reference_pic;
> +		unsigned short num_short_term_reference_pic;
> +		unsigned short num_reference_pic;
> +
> +		unsigned short current_dpb_index;
> +		unsigned short current_decoded_frame_num;
> +		unsigned short current_reference_frame_num;
> +
> +		unsigned short l0_size;
> +		unsigned short l1_size;
> +		/**
> +		 * [6:5] : nal_ref_idc
> +		 * [4:0] : nal_unit_type
> +		 */
> +		unsigned short NAL_info_mmco;
> +		/**
> +		 * [1:0] : 00 - top field, 01 - bottom field,
> +		 *         10 - frame, 11 - mbaff frame
> +		 */
> +		unsigned short picture_structure_mmco;
> +		unsigned short frame_num;
> +		unsigned short pic_order_cnt_lsb;
> +
> +		unsigned short num_ref_idx_l0_active_minus1;
> +		unsigned short num_ref_idx_l1_active_minus1;
> +
> +		unsigned short PrevPicOrderCntLsb;
> +		unsigned short PreviousFrameNum;
> +
> +		/* 32 bits variables */
> +		unsigned short delta_pic_order_cnt_bottom[2];
> +		unsigned short delta_pic_order_cnt_0[2];
> +		unsigned short delta_pic_order_cnt_1[2];
> +
> +		unsigned short PrevPicOrderCntMsb[2];
> +		unsigned short PrevFrameNumOffset[2];
> +
> +		unsigned short frame_pic_order_cnt[2];
> +		unsigned short top_field_pic_order_cnt[2];
> +		unsigned short bottom_field_pic_order_cnt[2];
> +
> +		unsigned short colocated_mv_addr_start[2];
> +		unsigned short colocated_mv_addr_end[2];
> +		unsigned short colocated_mv_wr_addr[2];
> +	} dpb;
> +	struct {
> +		unsigned short dump[MMCO_OFFSET];
> +
> +		/* array base address for offset_for_ref_frame */
> +		unsigned short offset_for_ref_frame_base[128];
> +
> +		/**
> +		 * 0 - Index in DPB
> +		 * 1 - Picture Flag
> +		 *  [2] : 0 - short term reference,
> +		 *			1 - long term reference
> +		 *  [1] : bottom field
> +		 *  [0] : top field
> +		 * 2 - Picture Number (short term or long term) low 16 bits
> +		 * 3 - Picture Number (short term or long term) high 16 bits
> +		 */
> +		unsigned short reference_base[128];
> +
> +		/* command and parameter, until command is 3 */
> +		unsigned short l0_reorder_cmd[REORDER_CMD_MAX];
> +		unsigned short l1_reorder_cmd[REORDER_CMD_MAX];
> +
> +		/* command and parameter, until command is 0 */
> +		unsigned short mmco_cmd[44];
> +
> +		unsigned short l0_base[40];
> +		unsigned short l1_base[40];
> +	} mmco;
> +	struct {
> +		/* from ucode lmem, do not change this struct */
> +	} p;
> +};
> +
> +struct h264_decode_buf_spec {
> +	struct v4l2_h264_dpb_entry *dpb;
> +	u32 canvas_pos;
> +	u32 dpb_index;
> +	u32 poc;
> +	int col_buf_index;
> +	u8 y_canvas_index;
> +	u8 u_canvas_index;
> +	u8 v_canvas_index;
> +	u8 used;
> +	u8 long_term_flag;
> +	dma_addr_t y_dma_addr;
> +	dma_addr_t c_dma_addr;
> +};
> +
> +#define REORDERING_COMMAND_MAX_SIZE	33
> +struct slice {
> +	int frame_num;
> +	/*modification */
> +	int slice_type;
> +	int num_ref_idx_l0;
> +	int num_ref_idx_l1;
> +	int ref_pic_list_reordering_flag[2];
> +	int modification_of_pic_nums_idc[2][REORDERING_COMMAND_MAX_SIZE];
> +	int abs_diff_pic_num_minus1[2][REORDERING_COMMAND_MAX_SIZE];
> +	int long_term_pic_idx[2][REORDERING_COMMAND_MAX_SIZE];
> +	unsigned char dec_ref_pic_marking_buffer_valid;
> +};
> +
> +struct aml_h264_ctx {
> +	struct aml_vdec_ctx *v4l2_ctx;
> +	u8 init_flag;
> +	u8 new_pic_flag;
> +	u8 mc_cpu_loaded;
> +	u8 param_set;
> +	u8 colocated_buf_num;
> +	u8 reg_iqidct_control_init_flag;
> +	u32 reg_iqidct_control;
> +	u32 reg_vcop_ctrl_reg;
> +	u32 reg_rv_ai_mb_count;
> +	u32 vld_dec_control;
> +	u32 save_avscratch_f;
> +	u32 seq_info;
> +	u32 decode_pic_count;
> +	union param dpb_param;
> +	u32 dec_status;
> +	struct slice mslice;
> +	struct h264_decode_buf_spec curr_spec;
> +	struct h264_decode_buf_spec ref_list0[V4L2_H264_NUM_DPB_ENTRIES + 1];
> +	struct h264_decode_buf_spec ref_list1[V4L2_H264_NUM_DPB_ENTRIES + 1];
> +	struct h264_decode_buf_spec ref_list0_unreordered[V4L2_H264_NUM_DPB_ENTRIES + 1];
> +	struct h264_decode_buf_spec ref_list1_unreordered[V4L2_H264_NUM_DPB_ENTRIES + 1];
> +	u8 list_size[2];
> +	dma_addr_t lmem_phy_addr;
> +	void *lmem_addr;
> +	dma_addr_t mc_cpu_paddr;
> +	void *mc_cpu_vaddr;
> +	dma_addr_t cma_alloc_addr;
> +	void *cma_alloc_vaddr;
> +	dma_addr_t collated_cma_addr;
> +	dma_addr_t collated_cma_addr_end;
> +	void *collated_cma_vaddr;
> +	dma_addr_t workspace_offset;
> +	void *workspace_vaddr;
> +	u32 col_buf_alloc_size;
> +	u32 one_col_buf_size;
> +	u32 colocated_buf_map;
> +	int colocated_buf_poc[32];
> +
> +	u32 frame_width;
> +	u32 frame_height;
> +	u32 mb_width;
> +	u32 mb_height;
> +	u32 mb_total;
> +	u32 max_num_ref_frames;
> +
> +	struct vdec_h264_stateless_ctrl_ref ctrl_ref;
> +};
> +
> +static inline int get_flag(u32 flag, u32 mask)
> +{
> +	return (flag & mask) ? 1 : 0;
> +}
> +
> +static inline void write_lmem(unsigned short *base, u32 offset, u32 value)
> +{
> +	base[offset] = value;
> +}
> +
> +static inline uint32_t spec2canvas(struct h264_decode_buf_spec *buf_spec)
> +{
> +	return (buf_spec->v_canvas_index << 16) |
> +		(buf_spec->u_canvas_index << 8) |
> +		(buf_spec->y_canvas_index << 0);
> +}
> +
> +static struct h264_decode_buf_spec *find_spec_by_dpb_index(struct aml_h264_ctx *h264_ctx, int index)
> +{
> +	int i;
> +
> +	for (i = 0; i < h264_ctx->list_size[0]; i++) {
> +		if (index == h264_ctx->ref_list0[i].dpb_index)
> +			return &h264_ctx->ref_list0[i];
> +	}
> +
> +	for (i = 0; i < h264_ctx->list_size[1]; i++) {
> +		if (index == h264_ctx->ref_list1[i].dpb_index)
> +			return &h264_ctx->ref_list1[i];
> +	}
> +	return NULL;
> +}
> +
> +static int h264_prepare_input(struct aml_vdec_ctx *ctx)
> +{
> +	struct vb2_v4l2_buffer *src;
> +	struct vb2_buffer *vb;
> +	dma_addr_t src_dma;
> +	u32 payload_size;
> +	int dummy;
> +
> +	src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
> +	if (!src) {
> +		pr_info("no input buffer available!\n");
> +		return -1;
> +	}
> +	vb = &src->vb2_buf;
> +	payload_size = vb2_get_plane_payload(vb, 0);
> +	src_dma = vb2_dma_contig_plane_dma_addr(vb, 0);
> +
> +	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
> +	/* reset VLD fifo for all vdec */
> +	WRITE_VREG(DOS_SW_RESET0, (1 << 5) | (1 << 4) | (1 << 3));
> +	WRITE_VREG(DOS_SW_RESET0, 0);
> +	WRITE_VREG(POWER_CTL_VLD, 1 << 4);
> +
> +	WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, src_dma);
> +	WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, (src_dma + payload_size));
> +	WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
> +		   round_down(src_dma, VDEC_FIFO_ALIGN));
> +
> +	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
> +	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
> +	WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
> +
> +	WRITE_VREG(VLD_MEM_VIFIFO_RP,
> +		   round_down(src_dma, VDEC_FIFO_ALIGN));
> +	dummy = payload_size + VLD_PADDING_SIZE;
> +	WRITE_VREG(VLD_MEM_VIFIFO_WP,
> +		   round_down((src_dma + dummy), VDEC_FIFO_ALIGN));
> +
> +	WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3);
> +	WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
> +
> +	WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
> +		   (0x11 << 16) | (1 << 10) | (7 << 3));
> +
> +	WRITE_VREG(AV_SCRATCH_1, 0x0);
> +	WRITE_VREG(H264_DECODE_INFO, (1 << 13));
> +	WRITE_VREG(H264_DECODE_SIZE, payload_size);
> +	WRITE_VREG(VIFF_BIT_CNT, payload_size * 8);
> +
> +	return 0;
> +}
> +
> +static void config_sps_params(struct aml_h264_ctx *h264_ctx,
> +			      unsigned short *sps_base,
> +			      const struct v4l2_ctrl_h264_sps *sps)
> +{
> +	u32 cfg_tmp = 0;
> +	u32 frame_size;
> +	u32 offset = 0;
> +	unsigned short data_tmp[0x100];
> +	int i, ii;
> +
> +	memset(sps_base, 0, 0x100);
> +
> +	h264_ctx->frame_width = (sps->pic_width_in_mbs_minus1 + 1) << 4;
> +	h264_ctx->frame_height = (sps->pic_height_in_map_units_minus1 + 1) << 4;
> +
> +	data_tmp[offset] = PARAM_BASE_VAL;
> +	offset += 2;
> +
> +	data_tmp[offset++] = GET_SPS_PROFILE_IDC(sps->profile_idc);
> +
> +	data_tmp[offset++] = GET_SPS_SEQ_PARAM_SET_ID(sps->seq_parameter_set_id) |
> +	    GET_SPS_LEVEL_IDC(sps->level_idc);
> +
> +	if (sps->profile_idc >= 100) {
> +		data_tmp[offset++] = GET_SPS_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
> +
> +		data_tmp[offset++] = ((sps->chroma_format_idc ^ 1) << 1);
> +	}
> +
> +	data_tmp[offset++] = GET_SPS_LOG2_MAX_FRAME_NUM(sps->log2_max_frame_num_minus4);
> +	data_tmp[offset++] = GET_SPS_PIC_ORDER_TYPE(sps->pic_order_cnt_type);
> +
> +	if (sps->pic_order_cnt_type == 0) {
> +		data_tmp[offset++] =
> +			GET_SPS_PIC_ORDER_CNT_LSB(sps->log2_max_pic_order_cnt_lsb_minus4);
> +	} else if (sps->pic_order_cnt_type == 1) {
> +		data_tmp[offset++] =
> +			get_flag(sps->flags,
> +				 V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO);
> +		data_tmp[offset++] =
> +			GET_SPS_OFFSET_FOR_NONREF_PIC_LOW(sps->offset_for_non_ref_pic);
> +		data_tmp[offset++] =
> +			GET_SPS_OFFSET_FOR_NONREF_PIC_HIGH(sps->offset_for_non_ref_pic);
> +		data_tmp[offset++] =
> +			GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_LOW(sps->offset_for_top_to_bottom_field);
> +		data_tmp[offset++] =
> +			GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_HIGH(sps->offset_for_top_to_bottom_field);
> +		data_tmp[offset++] = sps->num_ref_frames_in_pic_order_cnt_cycle;
> +	}
> +
> +	data_tmp[offset++] = GET_SPS_NUM_REF_FRAMES(sps->max_num_ref_frames) |
> +	    GET_SPS_GAPS_ALLOWED_FLAG(get_flag(sps->flags,
> +					       V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED));
> +
> +	data_tmp[offset++] = GET_SPS_PIC_WIDTH_IN_MBS(sps->pic_width_in_mbs_minus1);
> +
> +	data_tmp[offset++] = GET_SPS_PIC_HEIGHT_IN_MBS(sps->pic_height_in_map_units_minus1);
> +	data_tmp[offset++] =
> +		GET_SPS_DIRECT_8X8_FLAGS
> +				(get_flag(sps->flags,
> +					  V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) |
> +		GET_SPS_MB_ADAPTIVE_FRAME_FIELD_FLAGS
> +				(get_flag(sps->flags,
> +					  V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) |
> +		GET_SPS_FRAME_MBS_ONLY_FLAGS
> +				(get_flag(sps->flags,
> +					  V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY));
> +
> +	for (i = 0; i < 0x100; i += 4) {
> +		for (ii = 0; ii < 4; ii++)
> +			sps_base[i + 3 - ii] = data_tmp[i + ii];
> +	}
> +
> +	frame_size = (sps->pic_width_in_mbs_minus1 + 1) * (sps->pic_height_in_map_units_minus1 + 1);
> +	cfg_tmp = (get_flag(sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) << 31) |
> +				(sps->max_num_ref_frames << 24) | (frame_size << 8) |
> +				(sps->pic_width_in_mbs_minus1 + 1);
> +	WRITE_VREG(AV_SCRATCH_1, cfg_tmp);
> +	h264_ctx->seq_info = cfg_tmp;
> +
> +	cfg_tmp = 0;
> +	cfg_tmp = (get_flag(sps->flags, V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) << 15) |
> +				(sps->chroma_format_idc);
> +	WRITE_VREG(AV_SCRATCH_2, cfg_tmp);
> +
> +	cfg_tmp = 0;
> +	cfg_tmp = (sps->max_num_ref_frames << 8) | (sps->level_idc);
> +	WRITE_VREG(AV_SCRATCH_B, cfg_tmp);
> +
> +	cfg_tmp = ((sps->level_idc & 0xff) << 7) |
> +	    (get_flag(sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) << 2);
> +	WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) | cfg_tmp);
> +
> +	h264_ctx->mb_width = (sps->pic_width_in_mbs_minus1 + 4) & 0xfffffffc;
> +	h264_ctx->mb_height = (sps->pic_height_in_map_units_minus1 + 4) & 0xfffffffc;
> +	h264_ctx->mb_total = h264_ctx->mb_width * h264_ctx->mb_height;
> +	h264_ctx->max_num_ref_frames = sps->max_num_ref_frames;
> +}
> +
> +static void config_pps_params(struct aml_h264_ctx *h264_ctx,
> +			      unsigned short *pps_base,
> +			      const struct v4l2_ctrl_h264_pps *pps)
> +{
> +	u32 offset = 0;
> +	unsigned short data_tmp[0x100];
> +	u32 max_reference_size = V4L2_H264_NUM_DPB_ENTRIES;
> +	u32 max_list_size;
> +	int i, ii;
> +
> +	memset(pps_base, 0, 0x100);
> +
> +	data_tmp[offset++] = PARAM_BASE_VAL;
> +
> +	data_tmp[offset++] =
> +		GET_PPS_PIC_PARAM_SET_ID(pps->pic_parameter_set_id) |
> +	    GET_PPS_SEQ_PARAM_SET_ID(pps->seq_parameter_set_id) |
> +	    GET_PPS_ENTROPY_CODING_MODE_FLAG
> +			(get_flag(pps->flags,
> +				  V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)) |
> +	    GET_PPS_PIC_ORDER_PRESENT_FLAG
> +			(get_flag(pps->flags,
> +				  V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT));
> +
> +	data_tmp[offset++] =
> +		GET_PPS_WEIGHTED_BIPRED_IDC(pps->weighted_bipred_idc) |
> +		GET_PPS_WEIGHTED_PRED_FLAG(get_flag(pps->flags,
> +						    V4L2_H264_PPS_FLAG_WEIGHTED_PRED)) |
> +		GET_PPS_NUM_IDX_REF_L1_MINUS1(pps->num_ref_idx_l1_default_active_minus1) |
> +		GET_PPS_NUM_IDX_REF_L0_MINUS1(pps->num_ref_idx_l0_default_active_minus1);
> +
> +	data_tmp[offset++] = GET_PPS_INIT_QS_MINUS26(pps->pic_init_qs_minus26) |
> +	    GET_PPS_INIT_QP_MINUS26(pps->pic_init_qp_minus26);
> +
> +	data_tmp[offset] =
> +	    GET_PPS_CHROMA_QP_INDEX_OFFSET(pps->chroma_qp_index_offset) |
> +	    GET_PPS_DEBLOCK_FILTER_CTRL_PRESENT_FLAG
> +				(get_flag(pps->flags,
> +					  V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)) |
> +	    GET_PPS_CONSTRAIN_INTRA_PRED_FLAG
> +				(get_flag(pps->flags,
> +					  V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)) |
> +	    GET_PPS_REDUNDANT_PIC_CNT_PRESENT_FLAG
> +				(get_flag(pps->flags,
> +					  V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT));
> +	if (get_flag
> +	    (pps->flags,
> +	     V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE |
> +	     V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
> +		data_tmp[offset] |= (1 << 11);
> +	offset++;
> +
> +	data_tmp[offset++] =
> +	    GET_PPS_SCALING_MATRIX_PRESENT_FLAG(get_flag
> +						(pps->flags,
> +						 V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) |
> +	    GET_PPS_TRANSFORM_8X8_FLAG(get_flag
> +				       (pps->flags,
> +					V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE));
> +
> +	data_tmp[offset++] =
> +		GET_PPS_GET_SECOND_CHROMA_QP_OFFSET(pps->second_chroma_qp_index_offset);
> +
> +	max_list_size = (pps->num_ref_idx_l1_default_active_minus1 + 1) +
> +	    (pps->num_ref_idx_l0_default_active_minus1 + 1);
> +
> +	h264_ctx->max_num_ref_frames = max_list_size > h264_ctx->max_num_ref_frames ?
> +						max_list_size : h264_ctx->max_num_ref_frames;
> +
> +	WRITE_VREG(AV_SCRATCH_0, ((h264_ctx->max_num_ref_frames + 1) << 24) |
> +		   (max_reference_size << 16) | (max_reference_size << 8));
> +
> +	for (i = 0; i < 0x100; i += 4) {
> +		for (ii = 0; ii < 4; ii++)
> +			pps_base[i + 3 - ii] = data_tmp[i + ii];
> +	}
> +}
> +
> +static void h264_config_params(struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
> +	unsigned short *p_sps_base, *p_pps_base;
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +	const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
> +	const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
> +
> +	p_sps_base = (unsigned short *)(h264_ctx->workspace_vaddr +
> +		MEM_SPS_BASE + sps->seq_parameter_set_id * 0x400);
> +	p_pps_base = (unsigned short *)(h264_ctx->workspace_vaddr +
> +		MEM_PPS_BASE + pps->pic_parameter_set_id * 0x200);
> +
> +	config_sps_params(h264_ctx, p_sps_base, sps);
> +	config_pps_params(h264_ctx, p_pps_base, pps);
> +}
> +
> +static void config_decode_canvas(struct aml_vdec_hw *hw,
> +				 struct h264_decode_buf_spec *buf_spec,
> +				 u32 mb_width, u32 mb_height)
> +{
> +	int canvas_alloc_result = 0;
> +	int blkmode = 0x0;
> +
> +	canvas_alloc_result = hw->hw_ops.canvas_alloc(&buf_spec->y_canvas_index);
> +	canvas_alloc_result = hw->hw_ops.canvas_alloc(&buf_spec->u_canvas_index);
> +	buf_spec->v_canvas_index = buf_spec->u_canvas_index;
> +
> +	if (!canvas_alloc_result) {
> +		/* config y canvas */
> +		hw->hw_ops.config_canvas(buf_spec->y_canvas_index,
> +					 buf_spec->y_dma_addr, mb_width << 4,
> +					 mb_height << 4, 0, blkmode, 7);
> +		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, (1 << 11) |	/* canvas_blk32_wr */
> +			   (blkmode << 10) |	/* canvas_blk32 */
> +			   (1 << 8) |	/* canvas_index_wr */
> +			   (buf_spec->y_canvas_index << 0)	/* canvas index */
> +		    );
> +
> +		/* config uv canvas */
> +		hw->hw_ops.config_canvas(buf_spec->u_canvas_index,
> +					 buf_spec->c_dma_addr, mb_width << 4,
> +					 mb_height << 3, 0, blkmode, 7);
> +		WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, (1 << 11) |	/* canvas_blk32_wr */
> +			   (blkmode << 10) |	/* canvas_blk32 */
> +			   (1 << 8) |	/* canvas_index_wr */
> +			   (buf_spec->u_canvas_index << 0)	/* canvas index */
> +		    );
> +
> +		WRITE_VREG(ANC0_CANVAS_ADDR + buf_spec->canvas_pos,
> +			   spec2canvas(buf_spec));
> +	}
> +}
> +
> +static int allocate_colocate_buf(struct aml_h264_ctx *h264_ctx, int poc)
> +{
> +	int i;
> +
> +	for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
> +		if (((h264_ctx->colocated_buf_map >> i) & 0x1) == 0) {
> +			h264_ctx->colocated_buf_map |= (1 << i);
> +			break;
> +		}
> +	}
> +
> +	if (i == h264_ctx->colocated_buf_num)
> +		return -1;
> +
> +	h264_ctx->colocated_buf_poc[i] = poc;
> +	pr_debug("%s colocated_buf_index %d poc %d\n", __func__, i,
> +		 h264_ctx->colocated_buf_poc[i]);
> +
> +	return i;
> +}
> +
> +static void release_colocate_buf(struct aml_h264_ctx *h264_ctx, int index)
> +{
> +	if (index >= 0) {
> +		if (index >= h264_ctx->colocated_buf_num) {
> +			pr_debug
> +			    ("%s error, index %d is bigger than buf count %d\n",
> +			     __func__, index, h264_ctx->max_num_ref_frames);
> +		} else {
> +			if (((h264_ctx->colocated_buf_map >> index) & 0x1) == 0x1) {
> +				h264_ctx->colocated_buf_map &= (~(1 << index));
> +				pr_debug
> +				    ("%s colocated_buf_index %d released poc %d\n",
> +				     __func__, index,
> +				     h264_ctx->colocated_buf_poc[index]);
> +			}
> +			h264_ctx->colocated_buf_poc[index] = INVALID_POC;
> +		}
> +	}
> +}
> +
> +static int get_col_buf_index_by_poc(struct aml_h264_ctx *h264_ctx, int poc)
> +{
> +	int idx;
> +
> +	for (idx = 0; idx < h264_ctx->colocated_buf_num; idx++) {
> +		if (h264_ctx->colocated_buf_poc[idx] == poc)
> +			break;
> +	}
> +
> +	if (idx == h264_ctx->colocated_buf_num)
> +		idx = -1;
> +
> +	return idx;
> +}
> +
> +static int alloc_colocate_cma(struct aml_h264_ctx *h264_ctx,
> +			      struct aml_vdec_ctx *ctx)
> +{
> +	int alloc_size = 0;
> +	int i;
> +	struct aml_vdec_hw *hw;
> +
> +	if (h264_ctx->collated_cma_vaddr)
> +		return 0;
> +
> +	hw = vdec_get_hw(ctx->dev);
> +	if (!hw)
> +		return -1;
> +
> +	/* 96 :col buf size for each mb */
> +	h264_ctx->one_col_buf_size = h264_ctx->mb_total * 96;
> +	alloc_size = PAGE_ALIGN(h264_ctx->one_col_buf_size *
> +			(h264_ctx->max_num_ref_frames + COL_BUFFER_MARGIN));
> +	h264_ctx->collated_cma_vaddr = dma_alloc_coherent(hw->dev, alloc_size,
> +							  &h264_ctx->collated_cma_addr, GFP_KERNEL);
> +	if (!h264_ctx->collated_cma_vaddr)
> +		return -ENOMEM;
> +
> +	pr_debug
> +	    ("collated_cma_addr = 0x%llx, one_col_buf_size = %x alloc_size = %x\n",
> +	     h264_ctx->collated_cma_addr, h264_ctx->one_col_buf_size,
> +	     alloc_size);
> +	h264_ctx->collated_cma_addr_end =
> +	    h264_ctx->collated_cma_addr + alloc_size;
> +	memset(h264_ctx->collated_cma_vaddr, 0, alloc_size);
> +	h264_ctx->col_buf_alloc_size = alloc_size;
> +	h264_ctx->colocated_buf_map = 0;
> +	h264_ctx->colocated_buf_num = h264_ctx->max_num_ref_frames + COL_BUFFER_MARGIN;
> +
> +	/* 32 : max index of co-locate buffer */
> +	for (i = 0; i < 32; i++)
> +		h264_ctx->colocated_buf_poc[i] = INVALID_POC;
> +
> +	return 0;
> +}
> +
> +static void config_p_reflist(struct aml_h264_ctx *h264_ctx,
> +			     struct v4l2_h264_reference *v4l2_p0_reflist,
> +			     u32 list_size)
> +{
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +	struct v4l2_ctrl_h264_decode_params *decode =
> +	    (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
> +	struct v4l2_h264_dpb_entry *dpb = decode->dpb;
> +	u8 index;
> +	int i;
> +
> +	for (i = 0; i < list_size; i++) {
> +		index = v4l2_p0_reflist[i].index;
> +		h264_ctx->ref_list0[i].used = 1;
> +		h264_ctx->ref_list0[i].dpb = &dpb[index];
> +		h264_ctx->ref_list0[i].poc = dpb[index].top_field_order_cnt;
> +		h264_ctx->ref_list0[i].long_term_flag =
> +		    dpb[index].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
> +		h264_ctx->ref_list0[i].dpb_index = index;
> +	}
> +	h264_ctx->list_size[0] = i;
> +}
> +
> +static void config_b_reflist(struct aml_h264_ctx *h264_ctx,
> +			     struct v4l2_h264_reference *v4l2_b0_reflist,
> +			     struct v4l2_h264_reference *v4l2_b1_reflist,
> +			     u32 list_size)
> +{
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +	struct v4l2_ctrl_h264_decode_params *decode =
> +	    (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
> +	struct v4l2_h264_dpb_entry *dpb = decode->dpb;
> +	u8 index;
> +	int i, j;
> +
> +	for (i = 0; i < list_size; i++) {
> +		index = v4l2_b0_reflist[i].index;
> +		if (dpb[index].top_field_order_cnt > decode->top_field_order_cnt) {
> +			h264_ctx->list_size[0] = i;
> +			break;
> +		}
> +		h264_ctx->ref_list0[i].used = 1;
> +		h264_ctx->ref_list0[i].dpb = &dpb[index];
> +		h264_ctx->ref_list0[i].poc = dpb[index].top_field_order_cnt;
> +		h264_ctx->ref_list0[i].long_term_flag =
> +		    dpb[index].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
> +		h264_ctx->ref_list0[i].col_buf_index =
> +			get_col_buf_index_by_poc(h264_ctx, dpb[index].top_field_order_cnt);
> +		h264_ctx->ref_list0[i].dpb_index = index;
> +	}
> +
> +	for (j = 0; j < list_size; j++) {
> +		index = v4l2_b1_reflist[j].index;
> +		if (dpb[index].top_field_order_cnt < decode->top_field_order_cnt) {
> +			h264_ctx->list_size[1] = j;
> +			break;
> +		}
> +		h264_ctx->ref_list1[j].used = 1;
> +		h264_ctx->ref_list1[j].dpb = &dpb[index];
> +		h264_ctx->ref_list1[j].poc = dpb[index].top_field_order_cnt;
> +		h264_ctx->ref_list1[j].long_term_flag =
> +		    dpb[index].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
> +		h264_ctx->ref_list1[j].col_buf_index =
> +			get_col_buf_index_by_poc(h264_ctx, dpb[index].top_field_order_cnt);
> +		h264_ctx->ref_list1[j].dpb_index = index;
> +	}
> +
> +	if ((h264_ctx->list_size[1] + h264_ctx->list_size[0]) < list_size)
> +		pr_info("ref list incorrect list0 %d list0 %d list_size%d\n",
> +			h264_ctx->list_size[0], h264_ctx->list_size[1], list_size);
> +}
> +
> +static int poc_is_in_dpb(int poc, const struct v4l2_h264_dpb_entry *dpb)
> +{
> +	int i;
> +	int ret = 0;
> +
> +	for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
> +		if (poc == dpb[i].top_field_order_cnt) {
> +			ret = 1;
> +			pr_debug("%s find poc %d col index %x inDPB\n", __func__, poc, i);
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static int get_ref_list_size(struct aml_h264_ctx *h264_ctx, int cur_list)
> +{
> +	unsigned short override_flag = h264_ctx->dpb_param.l.data[REF_IDC_OVERRIDE_FLAG];
> +	int num_ref_idx_lx_active_minus1;
> +
> +	if (cur_list == 0) {
> +		num_ref_idx_lx_active_minus1 =
> +			h264_ctx->ctrl_ref.pps->num_ref_idx_l0_default_active_minus1;
> +		if (override_flag)
> +			num_ref_idx_lx_active_minus1 =
> +				h264_ctx->dpb_param.dpb.num_ref_idx_l0_active_minus1;
> +	} else {
> +		num_ref_idx_lx_active_minus1 =
> +			h264_ctx->ctrl_ref.pps->num_ref_idx_l1_default_active_minus1;
> +	}
> +	pr_debug("%s get list %d size %d\n", __func__, cur_list, num_ref_idx_lx_active_minus1 + 1);
> +
> +	return num_ref_idx_lx_active_minus1 + 1;
> +}
> +
> +static int get_refidx_by_picnum(struct aml_h264_ctx *h264_ctx, int pic_num,
> +				int curr_list)
> +{
> +	int i;
> +	struct h264_decode_buf_spec *ref_list;
> +
> +	if (curr_list == 0)
> +		ref_list = &h264_ctx->ref_list0[0];
> +	else
> +		ref_list = &h264_ctx->ref_list1[0];
> +
> +	for (i = 0; ref_list[i].dpb; i++) {
> +		if (pic_num == ref_list[i].dpb->pic_num)
> +			return i;
> +	}
> +
> +	return -1;
> +}
> +
> +static struct h264_decode_buf_spec *get_st_refpic_by_num(struct aml_h264_ctx *h264_ctx,
> +							 int pic_num, int curr_list)
> +{
> +	int i;
> +	struct h264_decode_buf_spec *ref_list;
> +
> +	if (curr_list == 0)
> +		ref_list = &h264_ctx->ref_list0_unreordered[0];
> +	else
> +		ref_list = &h264_ctx->ref_list1_unreordered[0];
> +
> +	for (i = 0; ref_list[i].dpb; i++) {
> +		if (pic_num == ref_list[i].dpb->pic_num && ref_list[i].long_term_flag == 0)
> +			return &ref_list[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static struct h264_decode_buf_spec *get_lt_refpic_by_num(struct aml_h264_ctx *h264_ctx,
> +							 int pic_num, int curr_list)
> +{
> +	int i;
> +	struct h264_decode_buf_spec *ref_list;
> +
> +	if (curr_list == 0)
> +		ref_list = &h264_ctx->ref_list0_unreordered[0];
> +	else
> +		ref_list = &h264_ctx->ref_list1_unreordered[0];
> +
> +	for (i = 0; ref_list[i].dpb; i++) {
> +		if (pic_num == ref_list[i].dpb->pic_num && ref_list[i].long_term_flag == 1)
> +			return &ref_list[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static void reorder_short_term(struct slice *curr_slice, int cur_list,
> +			       int pic_num_lx, int *ref_idx_lx)
> +{
> +	struct aml_h264_ctx *h264_ctx = container_of(curr_slice, struct aml_h264_ctx, mslice);
> +	int c_idx, n_idx;
> +	int num_ref_idx_lx_active;
> +	struct h264_decode_buf_spec *pic_lx = NULL;
> +	struct h264_decode_buf_spec *ref_list_reordered;
> +
> +	if (cur_list == 0)
> +		ref_list_reordered = &h264_ctx->ref_list0[0];
> +	else
> +		ref_list_reordered = &h264_ctx->ref_list1[0];
> +
> +	num_ref_idx_lx_active = get_ref_list_size(h264_ctx, cur_list);
> +
> +	/* find short-term ref frame with pic_num is pic_num_lx */
> +	pic_lx = get_st_refpic_by_num(h264_ctx, pic_num_lx, cur_list);
> +	if (!pic_lx) {
> +		pr_debug("cannot find st pic_lx for %d\n", pic_num_lx);
> +		return;
> +	}
> +
> +	if (*ref_idx_lx == get_refidx_by_picnum(h264_ctx, pic_num_lx, cur_list)) {
> +		pr_debug("no need to move pic lx %d\n", *ref_idx_lx);
> +		*ref_idx_lx = *ref_idx_lx + 1;
> +		return;
> +	}
> +
> +	for (c_idx = num_ref_idx_lx_active; c_idx > *ref_idx_lx; c_idx--)
> +		memcpy(&ref_list_reordered[c_idx], &ref_list_reordered[c_idx - 1],
> +		       sizeof(struct h264_decode_buf_spec));
> +
> +	memcpy(&ref_list_reordered[*ref_idx_lx], pic_lx, sizeof(struct h264_decode_buf_spec));
> +	pr_debug("%s 1 : RefPicListX[%d ] = pic %p pic_num(%d)\n", __func__,
> +		 *ref_idx_lx, pic_lx, ref_list_reordered[*ref_idx_lx].dpb->pic_num);
> +	*ref_idx_lx = *ref_idx_lx + 1;
> +
> +	n_idx = *ref_idx_lx;
> +	for (c_idx = *ref_idx_lx; c_idx <= num_ref_idx_lx_active; c_idx++) {
> +		if (ref_list_reordered[c_idx].long_term_flag || !ref_list_reordered[c_idx].dpb ||
> +		    ref_list_reordered[c_idx].dpb->pic_num != pic_num_lx)
> +			memcpy(&ref_list_reordered[n_idx++], &ref_list_reordered[c_idx],
> +			       sizeof(struct h264_decode_buf_spec));
> +	}
> +
> +	h264_ctx->list_size[cur_list] = num_ref_idx_lx_active;
> +}
> +
> +static void reorder_long_term(struct slice *curr_slice, int cur_list,
> +			      int lt_pic_num, int *ref_idx_lx)
> +{
> +	struct aml_h264_ctx *h264_ctx = container_of(curr_slice, struct aml_h264_ctx, mslice);
> +	int num_ref_idx_lx_active;
> +	int c_idx, n_idx;
> +	struct h264_decode_buf_spec *ref_list;
> +	struct h264_decode_buf_spec *pic_lt = NULL;
> +
> +	if (cur_list == 0)
> +		ref_list = &h264_ctx->ref_list0[0];
> +	else
> +		ref_list = &h264_ctx->ref_list1[0];
> +
> +	num_ref_idx_lx_active = get_ref_list_size(h264_ctx, cur_list);
> +
> +	/* find long-term ref frame with pic_num is lt_pic_num */
> +	pic_lt = get_lt_refpic_by_num(h264_ctx, lt_pic_num, cur_list);
> +	if (!pic_lt) {
> +		pr_debug("cannot find lt pic_lx for %d\n", lt_pic_num);
> +		return;
> +	}
> +
> +	if (*ref_idx_lx == get_refidx_by_picnum(h264_ctx, lt_pic_num, cur_list)) {
> +		pr_debug("no need to move pic lx %d\n", *ref_idx_lx);
> +		*ref_idx_lx = *ref_idx_lx + 1;
> +		return;
> +	}
> +
> +	for (c_idx = num_ref_idx_lx_active; c_idx > *ref_idx_lx; c_idx--)
> +		memcpy(&ref_list[c_idx], &ref_list[c_idx - 1], sizeof(struct h264_decode_buf_spec));
> +
> +	memcpy(&ref_list[*ref_idx_lx], pic_lt, sizeof(struct h264_decode_buf_spec));
> +	pr_debug("%s 1 : RefPicListX[%d ] = pic %p pic_num(%d)\n", __func__,
> +		 *ref_idx_lx, pic_lt, ref_list[*ref_idx_lx].dpb->pic_num);
> +	*ref_idx_lx = *ref_idx_lx + 1;
> +
> +	n_idx = *ref_idx_lx;
> +	/* Pointer dpb is NULL means this is a dummy frame store */
> +	for (c_idx = *ref_idx_lx; c_idx <= num_ref_idx_lx_active; c_idx++) {
> +		if (!ref_list[c_idx].long_term_flag || !ref_list[c_idx].dpb ||
> +		    ref_list[c_idx].dpb->pic_num != lt_pic_num)
> +			memcpy(&ref_list[n_idx++], &ref_list[c_idx],
> +			       sizeof(struct h264_decode_buf_spec));
> +	}
> +
> +	h264_ctx->list_size[cur_list] = num_ref_idx_lx_active;
> +}
> +
> +static void get_modification_cmd(unsigned short *reorder_cmd, struct slice *curr_slice, int list)
> +{
> +	int i, j, val;
> +
> +	val = curr_slice->ref_pic_list_reordering_flag[list];
> +	if (val) {
> +		i = 0;
> +		j = 0;
> +		do {
> +			curr_slice->modification_of_pic_nums_idc[list][i] =
> +				reorder_cmd[j++];
> +			if (j >= REORDER_CMD_MAX) {
> +				curr_slice->modification_of_pic_nums_idc[list][i] = 0;
> +				break;
> +			}
> +
> +			val = curr_slice->modification_of_pic_nums_idc[list][i];
> +			if (val == 0 || val == 1)
> +				curr_slice->abs_diff_pic_num_minus1[list][i] = reorder_cmd[j++];
> +			else if (val == 2)
> +				curr_slice->long_term_pic_idx[list][i] = reorder_cmd[j++];
> +
> +			i++;
> +
> +			if (i >= REORDERING_COMMAND_MAX_SIZE) {
> +				curr_slice->ref_pic_list_reordering_flag[list] = 0;
> +				break;
> +			};
> +			if (j > REORDER_CMD_MAX) {
> +				curr_slice->ref_pic_list_reordering_flag[list] = 0;
> +				break;
> +			};
> +		} while (val != 3);
> +	}
> +}
> +
> +static void reorder_pics(struct aml_h264_ctx *h264_ctx, struct slice *curr_slice, int cur_list)
> +{
> +	int *modification_of_pic_nums_idc =
> +		curr_slice->modification_of_pic_nums_idc[cur_list];
> +	int *abs_diff_pic_num_minus1 =
> +		curr_slice->abs_diff_pic_num_minus1[cur_list];
> +	int *long_term_pic_idx = curr_slice->long_term_pic_idx[cur_list];
> +	int pic_num_lx_nowarp, pic_num_lx_pred, pic_num_lx;
> +	int curr_pic_num = curr_slice->frame_num;
> +	int max_pic_num = 1 << (4 + h264_ctx->ctrl_ref.sps->log2_max_frame_num_minus4);
> +	int ref_idx_lx = 0;
> +	int nowarp_tmp = 0;
> +	int i;
> +
> +	pic_num_lx_pred = curr_pic_num;
> +	for (i = 0; i < REORDERING_COMMAND_MAX_SIZE && modification_of_pic_nums_idc[i] != 3; i++) {
> +		if (modification_of_pic_nums_idc[i] > 3) {
> +			pr_info("error, Invalid modification_of_pic_nums_idc command\n");
> +			break;
> +		}
> +
> +		if (modification_of_pic_nums_idc[i] < 2) {
> +			if (modification_of_pic_nums_idc[i] == 0) {
> +				nowarp_tmp = pic_num_lx_pred - (abs_diff_pic_num_minus1[i] + 1);
> +				pic_num_lx_nowarp = nowarp_tmp + (nowarp_tmp < 0 ? max_pic_num : 0);
> +			} else if (modification_of_pic_nums_idc[i] == 1) {
> +				nowarp_tmp = pic_num_lx_pred + (abs_diff_pic_num_minus1[i] + 1);
> +				pic_num_lx_nowarp = nowarp_tmp -
> +					(nowarp_tmp > max_pic_num ? max_pic_num : 0);
> +			}
> +			pic_num_lx_pred = pic_num_lx_nowarp;
> +			if (pic_num_lx_nowarp > curr_pic_num)
> +				pic_num_lx = pic_num_lx_nowarp - max_pic_num;
> +			else
> +				pic_num_lx = pic_num_lx_nowarp;
> +
> +			reorder_short_term(curr_slice, cur_list, pic_num_lx, &ref_idx_lx);
> +		} else {
> +			reorder_long_term(curr_slice, cur_list, long_term_pic_idx[i], &ref_idx_lx);
> +		}
> +	}
> +}
> +
> +static void copy_ref_list(struct aml_h264_ctx *h264_ctx, int curr_list)
> +{
> +	if (curr_list == 0)
> +		memcpy(h264_ctx->ref_list0_unreordered, h264_ctx->ref_list0,
> +		       sizeof(h264_ctx->ref_list0));
> +	else
> +		memcpy(h264_ctx->ref_list1_unreordered, h264_ctx->ref_list0,
> +		       sizeof(h264_ctx->ref_list1));
> +}
> +
> +static void h264_reorder_reflists(struct aml_h264_ctx *h264_ctx)
> +{
> +	unsigned short *reorder_cmd;
> +	struct slice *curr_slice = &h264_ctx->mslice;
> +
> +	memset(curr_slice, 0, sizeof(struct slice));
> +	/* parsed by ucode */
> +	curr_slice->slice_type = h264_ctx->dpb_param.l.data[SLICE_TYPE];
> +	curr_slice->num_ref_idx_l0 = h264_ctx->dpb_param.dpb.num_ref_idx_l0_active_minus1 + 1;
> +	curr_slice->num_ref_idx_l1 = h264_ctx->dpb_param.dpb.num_ref_idx_l1_active_minus1 + 1;
> +	curr_slice->frame_num = h264_ctx->ctrl_ref.decode->frame_num;
> +
> +	if (curr_slice->slice_type != I_SLICE && curr_slice->slice_type != SI_SLICE) {
> +		reorder_cmd = &h264_ctx->dpb_param.mmco.l0_reorder_cmd[0];
> +		/* 3:parsed by ucode, means no reorder needed */
> +		if (reorder_cmd[0] != 3)
> +			curr_slice->ref_pic_list_reordering_flag[0] = 1;
> +		else
> +			curr_slice->ref_pic_list_reordering_flag[0] = 0;
> +
> +		get_modification_cmd(reorder_cmd, curr_slice, 0);
> +	}
> +
> +	if (curr_slice->slice_type == B_SLICE) {
> +		reorder_cmd = &h264_ctx->dpb_param.mmco.l1_reorder_cmd[0];
> +		/* 3:parsed by ucode, means no reorder needed */
> +		if (reorder_cmd[0] != 3)
> +			curr_slice->ref_pic_list_reordering_flag[1] = 1;
> +		else
> +			curr_slice->ref_pic_list_reordering_flag[1] = 0;
> +
> +		get_modification_cmd(reorder_cmd, curr_slice, 1);
> +	}
> +
> +	if (curr_slice->slice_type != I_SLICE &&
> +	    curr_slice->slice_type != SI_SLICE &&
> +	    curr_slice->ref_pic_list_reordering_flag[0] != 0) {
> +		copy_ref_list(h264_ctx, 0);
> +		reorder_pics(h264_ctx, curr_slice, 0);
> +	}
> +
> +	if (curr_slice->slice_type == B_SLICE && curr_slice->ref_pic_list_reordering_flag[1] != 0) {
> +		copy_ref_list(h264_ctx, 1);
> +		reorder_pics(h264_ctx, curr_slice, 1);
> +	}
> +}
> +
> +static void h264_config_ref_lists(struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +	struct v4l2_ctrl_h264_decode_params *decode =
> +		(struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
> +	struct v4l2_ctrl_h264_sps *sps = (struct v4l2_ctrl_h264_sps *)ctrls->sps;
> +	const struct v4l2_h264_dpb_entry *dpb = decode->dpb;
> +	struct v4l2_h264_reflist_builder builder;
> +	struct v4l2_h264_reference v4l2_p0_reflist[V4L2_H264_REF_LIST_LEN];
> +	struct v4l2_h264_reference v4l2_b0_reflist[V4L2_H264_REF_LIST_LEN];
> +	struct v4l2_h264_reference v4l2_b1_reflist[V4L2_H264_REF_LIST_LEN];
> +
> +	if (decode->flags == V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC)
> +		return;
> +
> +	v4l2_h264_init_reflist_builder(&builder, decode, sps, dpb);
> +	pr_debug("%s num_valid = %d", __func__, builder.num_valid);
> +
> +	if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_PFRAME) {
> +		v4l2_h264_build_p_ref_list(&builder, v4l2_p0_reflist);
> +		config_p_reflist(h264_ctx, v4l2_p0_reflist, builder.num_valid);
> +	} else if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BFRAME) {
> +		v4l2_h264_build_b_ref_lists(&builder, v4l2_b0_reflist, v4l2_b1_reflist);
> +		config_b_reflist(h264_ctx, v4l2_b0_reflist, v4l2_b1_reflist, builder.num_valid);
> +	}
> +}
> +
> +static void clear_unused_col_buf(struct aml_h264_ctx *h264_ctx,
> +				 struct v4l2_ctrl_h264_decode_params *decode)
> +{
> +	int i, col_poc;
> +
> +	/* flush all col buffers when IDR */
> +	if (decode->flags == V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) {
> +		/* 32 : max index of co-locate buffer */
> +		for (i = 0; i < 32; i++)
> +			release_colocate_buf(h264_ctx, i);
> +		return;
> +	}
> +
> +	for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
> +		col_poc = h264_ctx->colocated_buf_poc[i];
> +		if (col_poc != INVALID_POC && (poc_is_in_dpb(col_poc, decode->dpb) != 1))
> +			release_colocate_buf(h264_ctx, i);
> +	}
> +}
> +
> +static void h264_config_decode_spec(struct aml_vdec_hw *hw, struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)hw->curr_ctx;
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +	struct v4l2_ctrl_h264_decode_params *decode =
> +		(struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
> +	struct h264_decode_buf_spec *buf_spec;
> +	struct vb2_buffer *vb;
> +	struct vb2_v4l2_buffer *vb2_v4l2;
> +	struct vb2_queue *vq;
> +	int i;
> +
> +	clear_unused_col_buf(h264_ctx, decode);
> +
> +	vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
> +	vb = &vb2_v4l2->vb2_buf;
> +
> +	h264_ctx->curr_spec.y_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
> +	if (ctx->pic_info.plane_num > 1)
> +		h264_ctx->curr_spec.c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
> +	else
> +		h264_ctx->curr_spec.c_dma_addr =
> +				h264_ctx->curr_spec.y_dma_addr + ctx->pic_info.fb_size[0];
> +	h264_ctx->curr_spec.canvas_pos = 0;
> +	h264_ctx->curr_spec.col_buf_index =
> +		allocate_colocate_buf(h264_ctx, decode->top_field_order_cnt);
> +	h264_ctx->curr_spec.poc = decode->top_field_order_cnt;
> +	config_decode_canvas(hw, &h264_ctx->curr_spec, h264_ctx->mb_width, h264_ctx->mb_height);
> +
> +	h264_config_ref_lists(ctx);
> +
> +	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
> +
> +	for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
> +		struct v4l2_h264_dpb_entry *dpb = &decode->dpb[i];
> +
> +		if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
> +			continue;
> +
> +		buf_spec = find_spec_by_dpb_index(h264_ctx, i);
> +		if (buf_spec) {
> +			buf_spec->canvas_pos = i + 1;
> +			vb = vb2_find_buffer(vq, dpb->reference_ts);
> +			if (!vb) {
> +				pr_err("ref pic for ts %llu lost\n", dpb->reference_ts);
> +				continue;
> +			}
> +
> +			buf_spec->y_dma_addr =
> +				vb2_dma_contig_plane_dma_addr(vb, 0);
> +			if (ctx->pic_info.plane_num > 1)
> +				buf_spec->c_dma_addr = vb2_dma_contig_plane_dma_addr(vb, 1);
> +			else
> +				buf_spec->c_dma_addr =
> +					buf_spec->y_dma_addr + ctx->pic_info.fb_size[0];
> +			config_decode_canvas(hw, buf_spec, h264_ctx->mb_width, h264_ctx->mb_height);
> +			pr_debug
> +			    ("config canvas for poc %d canvas %d y_dma_addr 0x%llx\n",
> +			     buf_spec->dpb->top_field_order_cnt,
> +			     buf_spec->canvas_pos, buf_spec->y_dma_addr);
> +		}
> +	}
> +
> +	h264_reorder_reflists(h264_ctx);
> +}
> +
> +static int h264_config_decode_buf(struct aml_vdec_hw *hw, struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)hw->curr_ctx;
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +	struct v4l2_ctrl_h264_decode_params *decode =
> +		(struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
> +	unsigned long canvas_adr;
> +	unsigned int ref_cfg;
> +	unsigned int ref_cfg_once = 0;
> +	unsigned int type_cfg = 0x3; /* 0x3: frame type */
> +	unsigned int colocate_adr_offset, colocate_wr_adr;
> +	unsigned int info0;
> +	unsigned int info1;
> +	unsigned int info2;
> +	int i, j;
> +	int h264_buffer_info_data_write_count;
> +	u8 canvas_pos;
> +	u8 use_mode_8x8_flag;
> +
> +	WRITE_VREG(H264_CURRENT_POC_IDX_RESET, 0);
> +	WRITE_VREG(H264_CURRENT_POC, decode->top_field_order_cnt);
> +	WRITE_VREG(H264_CURRENT_POC, decode->top_field_order_cnt);
> +	WRITE_VREG(H264_CURRENT_POC, decode->bottom_field_order_cnt);
> +	WRITE_VREG(CURR_CANVAS_CTRL, h264_ctx->curr_spec.canvas_pos << 24);
> +	canvas_adr = RD_VREG(CURR_CANVAS_CTRL) & 0xffffff;
> +	pr_debug("canvas_pos = %d canvas_adr 0x%lx\n", h264_ctx->curr_spec.canvas_pos, canvas_adr);
> +
> +	WRITE_VREG(REC_CANVAS_ADDR, canvas_adr);
> +	WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr);
> +	WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr);
> +
> +	WRITE_VREG(H264_BUFFER_INFO_INDEX, 16);
> +	info0 = 0xf480;
> +	info1 = decode->top_field_order_cnt;
> +	info2 = decode->bottom_field_order_cnt;
> +	if (decode->bottom_field_order_cnt < decode->top_field_order_cnt)
> +		info0 |= 0x100;
> +
> +	WRITE_VREG(H264_BUFFER_INFO_DATA, info0 | 0xf);
> +	WRITE_VREG(H264_BUFFER_INFO_DATA, info1);
> +	WRITE_VREG(H264_BUFFER_INFO_DATA, info2);
> +
> +	for (j = 0; j < V4L2_H264_NUM_DPB_ENTRIES; j++) {
> +		struct v4l2_h264_dpb_entry *dpb = &decode->dpb[j];
> +
> +		info0 = 0;
> +		info1 = 0;
> +		info2 = 0;
> +		if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
> +			info0 = 0xf480;
> +			if (decode->bottom_field_order_cnt < decode->top_field_order_cnt)
> +				info0 |= 0x100;
> +			info1 = dpb->top_field_order_cnt;
> +			info2 = dpb->bottom_field_order_cnt;
> +			if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
> +				info0 |= ((1 << 5) | (1 << 4));
> +		}
> +		WRITE_VREG(H264_BUFFER_INFO_DATA, info0);
> +		WRITE_VREG(H264_BUFFER_INFO_DATA, info1);
> +		WRITE_VREG(H264_BUFFER_INFO_DATA, info2);
> +	}
> +
> +	WRITE_VREG(H264_BUFFER_INFO_INDEX, 0);
> +	/* when frame width <= 256, Disable DDR_BYTE64_CACHE */
> +	if (ctx->pic_info.coded_width <= 256) {
> +		SET_VREG_MASK(IQIDCT_CONTROL, (1 << 16));
> +		WRITE_VREG(DCAC_DDR_BYTE64_CTL,
> +			   (RD_VREG(DCAC_DDR_BYTE64_CTL) & (~0xf)) | 0xa);
> +	} else {
> +		CLEAR_VREG_MASK(IQIDCT_CONTROL, (1 << 16));
> +	}
> +
> +	ref_cfg = 0;
> +	j = 0;
> +
> +	if (h264_ctx->list_size[0] > 0) {
> +		for (i = 0; i < h264_ctx->list_size[0]; i++) {
> +			canvas_pos = h264_ctx->ref_list0[i].canvas_pos;
> +			/* bit 0:3 canvas_pos bit 5:6 frame struct cfg */
> +			ref_cfg_once = (canvas_pos & 0x1f) | (type_cfg << 5);
> +			ref_cfg <<= 8;
> +			ref_cfg |= ref_cfg_once;
> +			j++;
> +
> +			if (j == 4) {
> +				WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
> +				pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
> +				h264_buffer_info_data_write_count++;
> +				j = 0;
> +			}
> +		}
> +
> +		if (j != 0) {
> +			while (j != 4) {
> +				ref_cfg <<= 8;
> +				ref_cfg |= ref_cfg_once;
> +				j++;
> +			}
> +			WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
> +			pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
> +			h264_buffer_info_data_write_count++;
> +		}
> +		ref_cfg = (ref_cfg_once << 24) | (ref_cfg_once << 16) |
> +			(ref_cfg_once << 8) | ref_cfg_once;
> +		for (j = h264_buffer_info_data_write_count; j < 8; j++)
> +			WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
> +	}
> +
> +	WRITE_VREG(H264_BUFFER_INFO_INDEX, 8);
> +	j = 0;
> +	ref_cfg = 0;
> +
> +	if (h264_ctx->list_size[1] > 0) {
> +		for (i = 0; i < h264_ctx->list_size[1]; i++) {
> +			canvas_pos = h264_ctx->ref_list1[i].canvas_pos;
> +			ref_cfg_once = (canvas_pos & 0x1f) | (type_cfg << 5);
> +			ref_cfg <<= 8;
> +			ref_cfg |= ref_cfg_once;
> +			j++;
> +
> +			if (j == 4) {
> +				WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
> +				pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
> +				j = 0;
> +			}
> +		}
> +	}
> +
> +	if (j != 0) {
> +		while (j != 4) {
> +			ref_cfg <<= 8;
> +			ref_cfg |= ref_cfg_once;
> +			j++;
> +		}
> +		pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
> +		WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
> +	}
> +
> +	if (get_flag(ctrls->sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
> +	    get_flag(ctrls->sps->flags, V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
> +		use_mode_8x8_flag = 1;
> +	else
> +		use_mode_8x8_flag = 0;
> +
> +	while ((RD_VREG(H264_CO_MB_RW_CTL) >> 11) & 0x1)
> +		continue;
> +
> +	/* col buf for curr frame */
> +	colocate_adr_offset = 0;
> +	if (h264_ctx->curr_spec.col_buf_index >= 0 &&
> +	    h264_ctx->curr_spec.col_buf_index < h264_ctx->colocated_buf_num) {
> +		colocate_wr_adr = h264_ctx->collated_cma_addr +
> +			((h264_ctx->one_col_buf_size * h264_ctx->curr_spec.col_buf_index) >>
> +			(use_mode_8x8_flag ? 2 : 0));
> +		if (colocate_wr_adr + h264_ctx->one_col_buf_size >
> +		    h264_ctx->collated_cma_addr_end) {
> +			pr_err
> +			    ("Error, colocate buf is not enough, index is %d\n",
> +			     h264_ctx->curr_spec.col_buf_index);
> +			return -1;
> +		}
> +		WRITE_VREG(H264_CO_MB_WR_ADDR,
> +			   (colocate_wr_adr + colocate_adr_offset));
> +		pr_debug("col buffer addr = 0x%x col_buf_index %d\n",
> +			 (colocate_wr_adr + colocate_adr_offset),
> +			 h264_ctx->curr_spec.col_buf_index);
> +	} else {
> +		WRITE_VREG(H264_CO_MB_WR_ADDR, 0xffffffff);
> +		pr_debug("col buffer addr = 0xffffffff\n");
> +	}
> +
> +	if (h264_ctx->list_size[1] > 0) {
> +		struct h264_decode_buf_spec *colocate_pic = &h264_ctx->ref_list1[0];
> +		struct h264_decode_buf_spec *curr_pic = &h264_ctx->curr_spec;
> +		int l10_structure = 2; /* for pic struct == FRAME, default to 2 */
> +		int cur_colocate_ref_type;
> +		unsigned int colocate_rd_adr;
> +		unsigned int colocate_rd_adr_offset = 0;
> +		unsigned int val;
> +
> +		cur_colocate_ref_type =
> +			(abs(curr_pic->poc - colocate_pic->dpb->top_field_order_cnt) <
> +			abs(curr_pic->poc - colocate_pic->dpb->bottom_field_order_cnt)) ?
> +			0 : 1;
> +
> +		if (colocate_pic->col_buf_index >= 0 &&
> +		    colocate_pic->col_buf_index < h264_ctx->colocated_buf_num) {
> +			colocate_rd_adr = h264_ctx->collated_cma_addr +
> +				((h264_ctx->one_col_buf_size * colocate_pic->col_buf_index) >>
> +				(use_mode_8x8_flag ? 2 : 0));
> +			if (colocate_rd_adr + h264_ctx->one_col_buf_size >
> +			    h264_ctx->collated_cma_addr_end) {
> +				pr_err
> +				    ("Error, colocate rd buf is not enough, index is %d\n",
> +				     colocate_pic->col_buf_index);
> +				return -1;
> +			}
> +			val  = ((colocate_rd_adr_offset + colocate_rd_adr) >> 3) |
> +				(cur_colocate_ref_type << 29) |
> +				(l10_structure << 30);
> +			WRITE_VREG(H264_CO_MB_RD_ADDR, val);
> +		} else {
> +			pr_err
> +			    ("Error, reference pic has no colocated buf poc %d\n",
> +			     curr_pic->poc);
> +			return -1;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static void h264_release_decode_spec(struct aml_vdec_hw *hw, struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)hw->curr_ctx;
> +	int i;
> +	struct h264_decode_buf_spec *buf;
> +
> +	hw->hw_ops.canvas_free(h264_ctx->curr_spec.y_canvas_index);
> +	hw->hw_ops.canvas_free(h264_ctx->curr_spec.v_canvas_index);
> +
> +	if (h264_ctx->list_size[0] > 0) {
> +		for (i = 0; i < h264_ctx->list_size[0]; i++) {
> +			buf = &h264_ctx->ref_list0[i];
> +			if (buf->used) {
> +				buf->canvas_pos = 0;
> +				buf->dpb = NULL;
> +				hw->hw_ops.canvas_free(buf->y_canvas_index);
> +				hw->hw_ops.canvas_free(buf->u_canvas_index);
> +				buf->used = 0;
> +			}
> +		}
> +		h264_ctx->list_size[0] = 0;
> +	}
> +
> +	if (h264_ctx->list_size[1] > 0) {
> +		for (i = 0; i < h264_ctx->list_size[1]; i++) {
> +			buf = &h264_ctx->ref_list1[i];
> +			if (buf->used) {
> +				buf->canvas_pos = 0;
> +				buf->dpb = NULL;
> +				hw->hw_ops.canvas_free(buf->y_canvas_index);
> +				hw->hw_ops.canvas_free(buf->u_canvas_index);
> +				buf->used = 0;
> +			}
> +		}
> +		h264_ctx->list_size[1] = 0;
> +	}
> +}
> +
> +static void save_reg_status(struct aml_h264_ctx *h264_ctx)
> +{
> +	h264_ctx->reg_iqidct_control = RD_VREG(IQIDCT_CONTROL);
> +	h264_ctx->reg_iqidct_control_init_flag = 1;
> +	h264_ctx->reg_vcop_ctrl_reg = RD_VREG(VCOP_CTRL_REG);
> +	h264_ctx->reg_rv_ai_mb_count = RD_VREG(RV_AI_MB_COUNT);
> +	h264_ctx->vld_dec_control = RD_VREG(VLD_DECODE_CONTROL);
> +}
> +
> +static irqreturn_t h264_isr(int irq, void *priv)
> +{
> +	WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
> +
> +	return IRQ_WAKE_THREAD;
> +}
> +
> +static irqreturn_t h264_threaded_isr_func(int irq, void *priv)
> +{
> +	int dec_status = RD_VREG(DPB_STATUS_REG);
> +	struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)dev->dec_hw->curr_ctx;
> +	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)dev->dec_ctx;
> +	struct aml_vdec_hw *hw = (struct aml_vdec_hw *)dev->dec_hw;
> +	unsigned short *p = (unsigned short *)h264_ctx->lmem_addr;
> +	int i, ii;
> +
> +	h264_ctx->dec_status = dec_status;
> +	pr_debug
> +	    ("%s, dec_status 0x%x VIFF_BIT_CNT 0x%x MBY_MBX 0x%x VLD_SHIFT_STATUS 0x%x\n",
> +	     __func__, dec_status, RD_VREG(VIFF_BIT_CNT), RD_VREG(MBY_MBX),
> +	     RD_VREG(VLD_SHIFT_STATUS));
> +
> +	h264_ctx->save_avscratch_f = RD_VREG(AV_SCRATCH_F);
> +
> +	switch (dec_status) {
> +	case H264_SLICE_HEADER_DONE:
> +		for (i = 0; i < 0x400; i += 4)
> +			for (ii = 0; ii < 4; ii++)
> +				h264_ctx->dpb_param.l.data[i + ii] = p[i + 3 - ii];
> +		save_reg_status(h264_ctx);
> +		if (h264_ctx->new_pic_flag == 1)
> +			h264_config_decode_spec(hw, ctx);
> +
> +		if (h264_config_decode_buf(hw, ctx) < 0) {
> +			h264_release_decode_spec(hw, ctx);
> +			ctx->int_cond = 1;
> +			wake_up_interruptible(&ctx->queue);
> +			goto irq_handled;
> +		}
> +		if (h264_ctx->new_pic_flag == 1) {
> +			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_NEWPIC);
> +			pr_debug("action decode new pic\n");
> +			h264_ctx->new_pic_flag = 0;
> +		} else {
> +			WRITE_VREG(DPB_STATUS_REG, H264_ACTION_DECODE_SLICE);
> +			pr_debug("action decode new slice\n");
> +		}
> +		break;
> +	case H264_SLICE_DATA_DONE:
> +		h264_release_decode_spec(hw, ctx);
> +		h264_ctx->decode_pic_count++;
> +		ctx->int_cond = 1;
> +		wake_up_interruptible(&ctx->queue);
> +		break;
> +	default:
> +		h264_release_decode_spec(hw, ctx);
> +		ctx->int_cond = 1;
> +		wake_up_interruptible(&ctx->queue);
> +		break;
> +	}
> +irq_handled:
> +	return IRQ_HANDLED;
> +}
> +
> +static int h264_restore_hw_ctx(struct aml_vdec_ctx *ctx)
> +{
> +	struct aml_h264_ctx *h264_ctx =
> +		(struct aml_h264_ctx *)ctx->codec_priv;
> +
> +	WRITE_VREG(POWER_CTL_VLD,
> +		   (RD_VREG(POWER_CTL_VLD) | (0 << 10) | (1 << 9) | (1 << 6)));
> +
> +	WRITE_VREG(PSCALE_CTRL, 0);
> +
> +	/* clear mailbox interrupt */
> +	WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
> +
> +	/* enable mailbox interrupt */
> +	WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 1);
> +
> +	SET_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 17));
> +	if (ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21 ||
> +	    ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)
> +		SET_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 16));
> +	else
> +		CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 16));
> +
> +	SET_VREG_MASK(MDEC_PIC_DC_CTRL, (0xbf << 24));
> +	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (0xbf << 24));
> +	CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 31));
> +
> +	CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
> +	WRITE_VREG(MDEC_EXTIF_CFG1, 0);
> +	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
> +
> +	WRITE_VREG(DPB_STATUS_REG, 0);
> +
> +	WRITE_VREG(LMEM_DUMP_ADR, h264_ctx->lmem_phy_addr);
> +	WRITE_VREG(FRAME_COUNTER_REG, h264_ctx->decode_pic_count);
> +	WRITE_VREG(AV_SCRATCH_8, h264_ctx->workspace_offset);
> +	WRITE_VREG(AV_SCRATCH_G, h264_ctx->mc_cpu_paddr);
> +
> +	WRITE_VREG(AV_SCRATCH_F, ((h264_ctx->save_avscratch_f & 0xffffffc3) | (1 << 4)));
> +	CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6);
> +
> +	WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
> +
> +	if (h264_ctx->reg_iqidct_control_init_flag == 0)
> +		WRITE_VREG(IQIDCT_CONTROL, 0x200);
> +
> +	if (h264_ctx->reg_iqidct_control)
> +		WRITE_VREG(IQIDCT_CONTROL, h264_ctx->reg_iqidct_control);
> +
> +	if (h264_ctx->reg_vcop_ctrl_reg)
> +		WRITE_VREG(VCOP_CTRL_REG, h264_ctx->reg_vcop_ctrl_reg);
> +
> +	if (h264_ctx->vld_dec_control)
> +		WRITE_VREG(VLD_DECODE_CONTROL, h264_ctx->vld_dec_control);
> +
> +	pr_debug
> +	    ("IQIDCT_CONTROL = 0x%x, VCOP_CTRL_REG 0x%x VLD_DECODE_CONTROL 0x%x\n",
> +	     RD_VREG(IQIDCT_CONTROL), RD_VREG(VCOP_CTRL_REG),
> +	     RD_VREG(VLD_DECODE_CONTROL));
> +
> +	return 0;
> +}
> +
> +static void *aml_h264_get_ctrl(struct v4l2_ctrl_handler *hdl, u32 id)
> +{
> +	struct v4l2_ctrl *ctrl;
> +
> +	ctrl = v4l2_ctrl_find(hdl, id);
> +	return ctrl ? ctrl->p_cur.p : NULL;
> +}
> +
> +static int aml_h264_get_stateless_ctrl_ref(struct aml_h264_ctx *h264_ctx)
> +{
> +	struct aml_vdec_ctx *ctx = h264_ctx->v4l2_ctx;
> +	struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
> +
> +	ctrls->sps =
> +		(struct v4l2_ctrl_h264_sps *)aml_h264_get_ctrl(&ctx->ctrl_handler,
> +			V4L2_CID_STATELESS_H264_SPS);
> +	if (WARN_ON(!ctrls->sps))
> +		return -EINVAL;
> +
> +	ctrls->pps =
> +		(struct v4l2_ctrl_h264_pps *)aml_h264_get_ctrl(&ctx->ctrl_handler,
> +			V4L2_CID_STATELESS_H264_PPS);
> +	if (WARN_ON(!ctrls->pps))
> +		return -EINVAL;
> +
> +	ctrls->decode =
> +		(struct v4l2_ctrl_h264_decode_params *)aml_h264_get_ctrl(&ctx->ctrl_handler,
> +			V4L2_CID_STATELESS_H264_DECODE_PARAMS);
> +	if (WARN_ON(!ctrls->decode))
> +		return -EINVAL;
> +
> +	ctrls->scaling =
> +		(struct v4l2_ctrl_h264_scaling_matrix *)aml_h264_get_ctrl(&ctx->ctrl_handler,
> +			V4L2_CID_STATELESS_H264_SCALING_MATRIX);
> +	if (WARN_ON(!ctrls->scaling))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static void copy_mc_cpu_fw(void *mc_cpu_addr, const u8 *data)
> +{
> +	/*header */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_HEADER,
> +	       data + 0x4000, MC_SWAP_SIZE);
> +	/*data */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_DATA,
> +	       data + 0x2000, MC_SWAP_SIZE);
> +	/*mmco */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MMCO,
> +	       data + 0x6000, MC_SWAP_SIZE);
> +	/*list */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_LIST,
> +	       data + 0x3000, MC_SWAP_SIZE);
> +	/*slice */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_SLICE,
> +	       data + 0x5000, MC_SWAP_SIZE);
> +	/*main */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN, data, 0x2000);
> +	/*data */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN + 0x2000,
> +	       data + 0x2000, 0x1000);
> +	/*slice */
> +	memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN + 0x3000,
> +	       data + 0x5000, 0x1000);
> +}
> +
> +static int aml_h264_load_fw_ext(void *priv, const u8 *data, u32 len)
> +{
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)priv;
> +	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)h264_ctx->v4l2_ctx;
> +	struct aml_vdec_hw *dec_hw;
> +
> +	if (h264_ctx->mc_cpu_loaded)
> +		return 0;
> +
> +	dec_hw = vdec_get_hw(ctx->dev);
> +	if (!dec_hw)
> +		return -1;
> +
> +	if (len > MC_TOTAL_SIZE) {
> +		pr_info("size of mc_cpu_fw id invalid\n");
> +		return -1;
> +	}
> +
> +	h264_ctx->mc_cpu_vaddr = dma_alloc_coherent(dec_hw->dev, MC_TOTAL_SIZE,
> +						    &h264_ctx->mc_cpu_paddr,
> +						    GFP_KERNEL);
> +	if (!h264_ctx->mc_cpu_vaddr)
> +		return -ENOMEM;
> +
> +	copy_mc_cpu_fw(h264_ctx->mc_cpu_vaddr, data);
> +
> +	h264_ctx->mc_cpu_loaded = true;
> +
> +	pr_debug("h264 mccpu fw loaded\n");
> +
> +	return 0;
> +}
> +
> +int aml_h264_init(void *priv)
> +{
> +	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
> +	struct aml_vdec_hw *dec_hw;
> +	struct aml_h264_ctx *h264_ctx;
> +	int ret = 0;
> +
> +	h264_ctx = kzalloc(sizeof(*h264_ctx), GFP_KERNEL);
> +	if (!h264_ctx)
> +		return -ENOMEM;
> +
> +	h264_ctx->v4l2_ctx = ctx;
> +	dec_hw = vdec_get_hw(ctx->dev);
> +	if (!dec_hw)
> +		return -1;
> +
> +	h264_ctx->mc_cpu_loaded = false;
> +	dec_hw->hw_ops.irq_handler = h264_isr;
> +	dec_hw->hw_ops.irq_threaded_func = h264_threaded_isr_func;
> +	dec_hw->hw_ops.load_firmware_ex = aml_h264_load_fw_ext;
> +
> +	h264_ctx->lmem_addr = dma_alloc_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
> +						 &h264_ctx->lmem_phy_addr,
> +						 GFP_KERNEL);
> +	if (!h264_ctx->lmem_addr) {
> +		ret = -ENOMEM;
> +		goto err_alloc_lmem;
> +	}
> +
> +	h264_ctx->cma_alloc_vaddr =
> +	    dma_alloc_coherent(dec_hw->dev, V_BUF_ADDR_OFFSET,
> +			       &h264_ctx->cma_alloc_addr, GFP_KERNEL);
> +	if (!h264_ctx->cma_alloc_vaddr) {
> +		ret = -ENOMEM;
> +		goto err_alloc_workspace;
> +	}
> +
> +	h264_ctx->workspace_offset = h264_ctx->cma_alloc_addr + DCAC_READ_MARGIN;
> +	h264_ctx->workspace_vaddr = h264_ctx->cma_alloc_vaddr + DCAC_READ_MARGIN;
> +
> +	ctx->codec_priv = h264_ctx;
> +	dec_hw->curr_ctx = h264_ctx;
> +	h264_ctx->col_buf_alloc_size = 0;
> +	h264_ctx->init_flag = 0;
> +	h264_ctx->new_pic_flag = 0;
> +	h264_ctx->param_set = 0;
> +	h264_ctx->reg_iqidct_control_init_flag = 0;
> +	h264_ctx->decode_pic_count = 0;
> +
> +	return 0;
> +
> +err_alloc_workspace:
> +	dma_free_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
> +			  h264_ctx->lmem_addr, h264_ctx->lmem_phy_addr);
> +err_alloc_lmem:
> +	kfree(h264_ctx);
> +
> +	return ret;
> +}
> +
> +void aml_h264_exit(void *priv)
> +{
> +	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
> +	struct aml_vdec_hw *dec_hw;
> +
> +	if (!h264_ctx) {
> +		pr_info("h264 decoder is already destroyed or not created!\n");
> +		return;
> +	}
> +	dec_hw = vdec_get_hw(ctx->dev);
> +	h264_ctx->param_set = 0;
> +
> +	if (ctx->dos_clk_en)
> +		aml_stop_vdec_hw();
> +
> +	if (h264_ctx->collated_cma_vaddr) {
> +		dma_free_coherent(dec_hw->dev, h264_ctx->col_buf_alloc_size,
> +				  h264_ctx->collated_cma_vaddr,
> +				  h264_ctx->collated_cma_addr);
> +		h264_ctx->col_buf_alloc_size = 0;
> +	}
> +
> +	if (h264_ctx->mc_cpu_vaddr) {
> +		dma_free_coherent(dec_hw->dev, MC_TOTAL_SIZE,
> +				  h264_ctx->mc_cpu_vaddr,
> +				  h264_ctx->mc_cpu_paddr);
> +		h264_ctx->mc_cpu_loaded = false;
> +	}
> +
> +	if (h264_ctx->lmem_addr)
> +		dma_free_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
> +				  h264_ctx->lmem_addr, h264_ctx->lmem_phy_addr);
> +
> +	if (h264_ctx->cma_alloc_vaddr)
> +		dma_free_coherent(dec_hw->dev, V_BUF_ADDR_OFFSET,
> +				  h264_ctx->cma_alloc_vaddr,
> +				  h264_ctx->cma_alloc_addr);
> +
> +	kfree(ctx->codec_priv);
> +	dec_hw->curr_ctx = NULL;
> +	ctx->codec_priv = NULL;
> +}
> +
> +static void config_decode_mode(struct aml_h264_ctx *h264_ctx)
> +{
> +	WRITE_VREG(H264_DECODE_MODE, 0x1);  /*decode mode framebase*/
> +	WRITE_VREG(HEAD_PADDING_REG, 0);
> +	WRITE_VREG(H264_DECODE_SEQINFO, h264_ctx->seq_info);
> +	WRITE_VREG(INIT_FLAG_REG, 1);
> +}
> +
> +int aml_h264_dec_run(void *priv)
> +{
> +	struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
> +	struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)ctx->codec_priv;
> +	int ret = -1;
> +	int i;
> +
> +	ret = aml_h264_get_stateless_ctrl_ref(h264_ctx);
> +	if (ret < 0) {
> +		pr_err("not ctrl ref for h264 decoder\n");
> +		return ret;
> +	}
> +
> +	h264_config_params(ctx);
> +
> +	if (h264_prepare_input(ctx) < 0)
> +		return ret;
> +
> +	if (alloc_colocate_cma(h264_ctx, ctx) < 0)
> +		return ret;
> +
> +	h264_restore_hw_ctx(ctx);
> +
> +	config_decode_mode(h264_ctx);
> +	/* enable stream input hardware */
> +	SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1 << 2) | (1 << 1));
> +	/* enable hardware timer */
> +	WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) | (1 << 16));
> +	WRITE_VREG(MDEC_EXTIF_CFG2, RD_VREG(MDEC_EXTIF_CFG2) | 0x20);
> +	WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) & (~0x2));
> +	CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
> +
> +	aml_start_vdec_hw();
> +	h264_ctx->init_flag = 1;
> +	h264_ctx->new_pic_flag = 1;
> +
> +	WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD);
> +
> +	ret = wait_event_interruptible_timeout(ctx->queue, ctx->int_cond,
> +					       msecs_to_jiffies(DECODER_TIMEOUT_MS));
> +	ctx->int_cond = 0;
> +	if (!ret) {
> +		ret = -1;
> +		pr_err("dec timeout=%u\n", DECODER_TIMEOUT_MS);
> +		for (i = 0; i < 16; i++) {	/* 16 : show ucode PC 16 times when timeout */
> +			pr_info("decoder timeout, pc 0x%x\n", RD_VREG(MPC_E));
> +			usleep_range(10, 20);
> +		}
> +	} else if (-ERESTARTSYS == ret) {
> +		ret = -1;
> +		pr_err("dec inter fail\n");
> +	}
> +
> +	aml_stop_vdec_hw();
> +	h264_ctx->init_flag = 0;
> +
> +	return ret;
> +}
> diff --git a/drivers/media/platform/amlogic/vdec/h264.h b/drivers/media/platform/amlogic/vdec/h264.h
> new file mode 100644
> index 000000000000..3d3a35a641c9
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/h264.h
> @@ -0,0 +1,300 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +#ifndef _H264_H_
> +#define _H264_H_
> +
> +#define RPM_BEGIN           0x0
> +#define FRAME_IN_DPB        24
> +#define RPM_END             0x400
> +#define DPB_OFFSET          0x100
> +#define MMCO_OFFSET         0x200
> +#define SPS_OFFSET          0x100
> +#define PPS_OFFSET          0x300
> +#define PARAM_BASE_VAL      0x414d
> +#define MEM_MMCO_BASE       0x01c3000
> +#define MEM_SPS_BASE        0x01c3c00
> +#define MEM_PPS_BASE        0x01cbc00
> +#define MC_TOTAL_SIZE       ((20 + 16) * SZ_1K)
> +#define MC_SWAP_SIZE        (4 * SZ_1K)
> +#define LMEM_DUMP_SIZE      4096
> +#define V_BUF_ADDR_OFFSET   (0x200000 + 0x8000 + 0x20000 + 0x1000)
> +#define DCAC_READ_MARGIN    (64 * 1024)
> +#define MC_OFFSET_HEADER    0x0000
> +#define MC_OFFSET_DATA      0x1000
> +#define MC_OFFSET_MMCO      0x2000
> +#define MC_OFFSET_LIST      0x3000
> +#define MC_OFFSET_SLICE     0x4000
> +#define MC_OFFSET_MAIN      0x5000
> +
> +/* Rename the dos regs */
> +#define H264_DECODE_INFO    M4_CONTROL_REG
> +#define INIT_FLAG_REG       AV_SCRATCH_2
> +#define HEAD_PADDING_REG     AV_SCRATCH_3
> +#define UCODE_WATCHDOG_REG   AV_SCRATCH_7
> +#define LMEM_DUMP_ADR       AV_SCRATCH_L
> +#define DEBUG_REG1          AV_SCRATCH_M
> +#define DEBUG_REG2          AV_SCRATCH_N
> +#define FRAME_COUNTER_REG       AV_SCRATCH_I
> +#define RPM_CMD_REG          AV_SCRATCH_A
> +#define H264_DECODE_SIZE    AV_SCRATCH_E
> +#define H264_DECODE_MODE    AV_SCRATCH_4
> +#define H264_DECODE_SEQINFO    AV_SCRATCH_5
> +/**
> + * NAL_SEARCH_CTL: bit 0, enable itu_t35
> + * NAL_SEARCH_CTL: bit 1, enable mmu
> + * NAL_SEARCH_CTL: bit 2, detect frame_mbs_only_flag whether switch resolution
> + * NAL_SEARCH_CTL: bit 3, recover the correct sps pps
> + * NAL_SEARCH_CTL: bit 7-14,level_idc
> + * NAL_SEARCH_CTL: bit 15,bitstream_restriction_flag
> + */
> +#define NAL_SEARCH_CTL      AV_SCRATCH_9
> +#define DPB_STATUS_REG      AV_SCRATCH_J
> +#define ERROR_STATUS_REG    AV_SCRATCH_9
> +
> +#define H264_BUFFER_INFO_INDEX      PMV3_X	/* 0xc24 */
> +#define H264_BUFFER_INFO_DATA       PMV2_X	/* 0xc22 */
> +#define H264_CURRENT_POC_IDX_RESET  LAST_SLICE_MV_ADDR	/* 0xc30 */
> +#define H264_CURRENT_POC            LAST_MVY	/* 0xc32 shared with conceal MV */
> +#define H264_CO_MB_WR_ADDR          VLD_C38
> +#define H264_CO_MB_RD_ADDR          VLD_C39
> +#define H264_CO_MB_RW_CTL           VLD_C3D
> +#define MBY_MBX                     MB_MOTION_MODE
> +
> +#define H264_ACTION_SEARCH_HEAD     0xf0
> +#define H264_ACTION_DECODE_SLICE    0xf1
> +#define H264_ACTION_CONFIG_DONE     0xf2
> +#define H264_ACTION_DECODE_NEWPIC   0xf3
> +#define H264_ACTION_DECODE_START    0xff
> +
> +/* RPM memory definition */
> +#define FIXED_FRAME_RATE_FLAG						0X21
> +#define OFFSET_DELIMITER_LO						0x2f
> +#define OFFSET_DELIMITER_HI						0x30
> +#define REF_IDC_OVERRIDE_FLAG						0x35
> +#define SLICE_IPONLY_BREAK						0X5C
> +#define PREV_MAX_REFERENCE_FRAME_NUM					0X5D
> +#define EOS								0X5E
> +#define FRAME_PACKING_TYPE						0X5F
> +#define OLD_POC_PAR_1							0X60
> +#define OLD_POC_PAR_2							0X61
> +#define PREV_MBX							0X62
> +#define PREV_MBY							0X63
> +#define ERROR_SKIP_MB_NUM						0X64
> +#define ERROR_MB_STATUS							0X65
> +#define L0_PIC0_STATUS							0X66
> +#define TIMEOUT_COUNTER							0X67
> +#define BUFFER_SIZE							0X68
> +#define BUFFER_SIZE_HI							0X69
> +#define CROPPING_LEFT_RIGHT						0X6A
> +#define CROPPING_TOP_BOTTOM						0X6B
> +/**
> + * sps_flags2:
> + * bit 3, bitstream_restriction_flag
> + * bit 2, pic_struct_present_flag
> + * bit 1, vcl_hrd_parameters_present_flag
> + * bit 0, nal_hrd_parameters_present_flag
> + */
> +#define SPS_FLAGS2							0x6C
> +#define NUM_REORDER_FRAMES						0x6D
> +#define MAX_BUFFER_FRAME						0X6E
> +
> +#define NON_CONFORMING_STREAM						0X70
> +#define RECOVERY_POINT							0X71
> +#define POST_CANVAS							0X72
> +#define POST_CANVAS_H							0X73
> +#define SKIP_PIC_COUNT							0X74
> +#define TARGET_NUM_SCALING_LIST						0X75
> +#define FF_POST_ONE_FRAME						0X76
> +#define PREVIOUS_BIT_CNT						0X77
> +#define MB_NOT_SHIFT_COUNT						0X78
> +#define PIC_STATUS							0X79
> +#define FRAME_COUNTER							0X7A
> +#define NEW_SLICE_TYPE							0X7B
> +#define NEW_PICTURE_STRUCTURE						0X7C
> +#define NEW_FRAME_NUM							0X7D
> +#define NEW_IDR_PIC_ID							0X7E
> +#define IDR_PIC_ID							0X7F
> +
> +/* h264 LOCAL */
> +#define NAL_UNIT_TYPE							0X80
> +#define NAL_REF_IDC							0X81
> +#define SLICE_TYPE							0X82
> +#define LOG2_MAX_FRAME_NUM						0X83
> +#define FRAME_MBS_ONLY_FLAG						0X84
> +#define PIC_ORDER_CNT_TYPE						0X85
> +#define LOG2_MAX_PIC_ORDER_CNT_LSB					0X86
> +#define PIC_ORDER_PRESENT_FLAG						0X87
> +#define REDUNDANT_PIC_CNT_PRESENT_FLAG					0X88
> +#define PIC_INIT_QP_MINUS26						0X89
> +#define DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG				0X8A
> +#define NUM_SLICE_GROUPS_MINUS1						0X8B
> +#define MODE_8X8_FLAGS							0X8C
> +#define ENTROPY_CODING_MODE_FLAG					0X8D
> +#define SLICE_QUANT							0X8E
> +#define TOTAL_MB_HEIGHT							0X8F
> +#define PICTURE_STRUCTURE						0X90
> +#define TOP_INTRA_TYPE							0X91
> +#define RV_AI_STATUS							0X92
> +#define AI_READ_START							0X93
> +#define AI_WRITE_START							0X94
> +#define AI_CUR_BUFFER							0X95
> +#define AI_DMA_BUFFER							0X96
> +#define AI_READ_OFFSET							0X97
> +#define AI_WRITE_OFFSET							0X98
> +#define AI_WRITE_OFFSET_SAVE						0X99
> +#define RV_AI_BUFF_START						0X9A
> +#define I_PIC_MB_COUNT							0X9B
> +#define AI_WR_DCAC_DMA_CTRL						0X9C
> +#define SLICE_MB_COUNT							0X9D
> +#define PICTYPE								0X9E
> +#define SLICE_GROUP_MAP_TYPE						0X9F
> +#define MB_TYPE								0XA0
> +#define MB_AFF_ADDED_DMA						0XA1
> +#define PREVIOUS_MB_TYPE						0XA2
> +#define WEIGHTED_PRED_FLAG						0XA3
> +#define WEIGHTED_BIPRED_IDC						0XA4
> +/* bit 3:2 - PICTURE_STRUCTURE
> + * bit 1 - MB_ADAPTIVE_FRAME_FIELD_FLAG
> + * bit 0 - FRAME_MBS_ONLY_FLAG
> + */
> +#define MBFF_INFO							0XA5
> +#define TOP_INTRA_TYPE_TOP						0XA6
> +#define RV_AI_BUFF_INC							0xA7
> +#define DEFAULT_MB_INFO_LO						0xA8
> +/* 0 -- no need to read
> + * 1 -- need to wait Left
> + * 2 -- need to read Intra
> + * 3 -- need to read back MV
> + */
> +#define NEED_READ_TOP_INFO						0xA9
> +/* 0 -- idle
> + * 1 -- wait Left
> + * 2 -- reading top Intra
> + * 3 -- reading back MV
> + */
> +#define READ_TOP_INFO_STATE						0xAA
> +#define DCAC_MBX							0xAB
> +#define TOP_MB_INFO_OFFSET						0xAC
> +#define TOP_MB_INFO_RD_IDX						0xAD
> +#define TOP_MB_INFO_WR_IDX						0xAE
> +
> +#define VLD_NO_WAIT	 0
> +#define VLD_WAIT_BUFFER 1
> +#define VLD_WAIT_HOST   2
> +#define VLD_WAIT_GAP	3
> +
> +#define VLD_WAITING							0xAF
> +
> +#define MB_X_NUM							0xB0
> +#define MB_HEIGHT							0xB2
> +#define MBX								0xB3
> +#define TOTAL_MBY							0xB4
> +#define INTR_MSK_SAVE							0xB5
> +#define NEED_DISABLE_PPE						0xB6
> +#define IS_NEW_PICTURE							0XB7
> +#define PREV_NAL_REF_IDC						0XB8
> +#define PREV_NAL_UNIT_TYPE						0XB9
> +#define FRAME_MB_COUNT							0XBA
> +#define SLICE_GROUP_UCODE						0XBB
> +#define SLICE_GROUP_CHANGE_RATE						0XBC
> +#define SLICE_GROUP_CHANGE_CYCLE_LEN					0XBD
> +#define DELAY_LENGTH							0XBE
> +#define PICTURE_STRUCT							0XBF
> +#define DCAC_PREVIOUS_MB_TYPE						0xC1
> +
> +#define TIME_STAMP							0XC2
> +#define H_TIME_STAMP							0XC3
> +#define VPTS_MAP_ADDR							0XC4
> +#define H_VPTS_MAP_ADDR							0XC5
> +#define PIC_INSERT_FLAG							0XC7
> +#define TIME_STAMP_START						0XC8
> +#define TIME_STAMP_END							0XDF
> +#define OFFSET_FOR_NON_REF_PIC						0XE0
> +#define OFFSET_FOR_TOP_TO_BOTTOM_FIELD					0XE2
> +#define MAX_REFERENCE_FRAME_NUM						0XE4
> +#define FRAME_NUM_GAP_ALLOWED						0XE5
> +#define NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE				0XE6
> +#define PROFILE_IDC_MMCO						0XE7
> +#define LEVEL_IDC_MMCO							0XE8
> +#define FRAME_SIZE_IN_MB						0XE9
> +#define DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG				0XEA
> +#define PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1				0XEB
> +#define PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1				0XEC
> +#define CURRENT_SPS_ID							0XED
> +#define CURRENT_PPS_ID							0XEE
> +/* bit 0 - sequence parameter set may change
> + * bit 1 - picture parameter set may change
> + * bit 2 - new dpb just inited
> + * bit 3 - IDR picture not decoded yet
> + * bit 5:4 - 0: mb level code loaded 1: picture
> + * level code loaded 2: slice level code loaded
> + */
> +#define DECODE_STATUS							0XEF
> +#define FIRST_MB_IN_SLICE						0XF0
> +#define PREV_MB_WIDTH							0XF1
> +#define PREV_FRAME_SIZE_IN_MB						0XF2
> +/* bit 0 - aspect_ratio_info_present_flag
> + * bit 1 - timing_info_present_flag
> + * bit 2 - nal_hrd_parameters_present_flag
> + * bit 3 - vcl_hrd_parameters_present_flag
> + * bit 4 - pic_struct_present_flag
> + * bit 5 - bitstream_restriction_flag
> + */
> +#define VUI_STATUS							0XF4
> +#define ASPECT_RATIO_IDC						0XF5
> +#define ASPECT_RATIO_SAR_WIDTH						0XF6
> +#define ASPECT_RATIO_SAR_HEIGHT						0XF7
> +#define NUM_UNITS_IN_TICK						0XF8
> +#define TIME_SCALE							0XFA
> +#define CURRENT_PIC_INFO						0XFC
> +#define DPB_BUFFER_INFO							0XFD
> +#define REFERENCE_POOL_INFO						0XFE
> +#define REFERENCE_LIST_INFO						0XFF
> +
> +#define REORDER_CMD_MAX             66
> +
> +/* config parameters to DDR lmem */
> +#define GET_SPS_PROFILE_IDC(x)       (((x) & 0xff) << 8)
> +#define GET_SPS_LEVEL_IDC(x)         ((x) & 0xff)
> +#define GET_SPS_SEQ_PARAM_SET_ID(x)       (((x) & 0x1f) << 8)
> +#define GET_SPS_CHROMA_FORMAT_IDC(x)      ((x) << 8)
> +#define GET_SPS_NUM_REF_FRAMES(x)         ((x) & 0xff)
> +#define GET_SPS_GAPS_ALLOWED_FLAG(x)      ((x) << 8)
> +#define GET_SPS_LOG2_MAX_FRAME_NUM(x)     ((x) + 4)
> +#define GET_SPS_PIC_ORDER_CNT_LSB(x)      ((x) + 4)
> +#define GET_SPS_PIC_ORDER_TYPE(x)         (x)
> +#define GET_SPS_OFFSET_FOR_NONREF_PIC_HIGH(x)      (((x) & 0xffff0000) >> 16)
> +#define GET_SPS_OFFSET_FOR_NONREF_PIC_LOW(x)         ((x) & 0xffff)
> +#define GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_HIGH(x)      (((x) & 0xffff0000) >> 16)
> +#define GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_LOW(x)         ((x) & 0xffff)
> +#define GET_SPS_PIC_WIDTH_IN_MBS(x)       ((x) + 1)
> +#define GET_SPS_PIC_HEIGHT_IN_MBS(x)      ((x) + 1)
> +#define GET_SPS_DIRECT_8X8_FLAGS(x)       (((x) & 0x1) << 2)
> +#define GET_SPS_MB_ADAPTIVE_FRAME_FIELD_FLAGS(x)       (((x) & 0x1) << 1)
> +#define GET_SPS_FRAME_MBS_ONLY_FLAGS(x)   ((x) & 0x1)
> +
> +#define GET_PPS_PIC_PARAM_SET_ID(x)       ((x) & 0xff)
> +#define GET_PPS_SEQ_PARAM_SET_ID(x)       (((x) & 0x1f) << 8)
> +#define GET_PPS_ENTROPY_CODING_MODE_FLAG(x)  (((x) & 0x1) << 13)
> +#define GET_PPS_PIC_ORDER_PRESENT_FLAG(x)    (((x) & 0x1) << 14)
> +#define GET_PPS_NUM_IDX_REF_L0_MINUS1(x)       ((x) & 0x1f)
> +#define GET_PPS_NUM_IDX_REF_L1_MINUS1(x)       (((x) & 0x1f) << 5)
> +#define GET_PPS_WEIGHTED_PRED_FLAG(x)         (((x) & 0x1) << 10)
> +#define GET_PPS_WEIGHTED_BIPRED_IDC(x)        (((x) & 0x3) << 11)
> +#define GET_PPS_INIT_QS_MINUS26(x)           (((x) & 0xff) << 8)
> +#define GET_PPS_INIT_QP_MINUS26(x)           ((x) & 0xff)
> +#define GET_PPS_CHROMA_QP_INDEX_OFFSET(x)   ((x) & 0xff)
> +#define GET_PPS_DEBLOCK_FILTER_CTRL_PRESENT_FLAG(x)   (((x) & 0x1) << 8)
> +#define GET_PPS_CONSTRAIN_INTRA_PRED_FLAG(x)          (((x) & 0x1) << 9)
> +#define GET_PPS_REDUNDANT_PIC_CNT_PRESENT_FLAG(x)     (((x) & 0x1) << 10)
> +#define GET_PPS_SCALING_MATRIX_PRESENT_FLAG(x)        (((x) & 0x1) << 1)
> +#define GET_PPS_TRANSFORM_8X8_FLAG(x)                 ((x) & 0x1)
> +#define GET_PPS_GET_SECOND_CHROMA_QP_OFFSET(x)        (x)
> +
> +int aml_h264_init(void *priv);
> +void aml_h264_exit(void *priv);
> +int aml_h264_dec_run(void *priv);
> +
> +#endif
> diff --git a/drivers/media/platform/amlogic/vdec/reg_defines.h b/drivers/media/platform/amlogic/vdec/reg_defines.h
> new file mode 100644
> index 000000000000..6b1900ecbedb
> --- /dev/null
> +++ b/drivers/media/platform/amlogic/vdec/reg_defines.h
> @@ -0,0 +1,175 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
> +/*
> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
> + */
> +
> +#ifndef _REG_DEFINES_H_
> +#define _REG_DEFINES_H_
> +
> +#define VDEC_ASSIST_MMC_CTRL0        0x0001
> +#define VDEC_ASSIST_MMC_CTRL1        0x0002
> +
> +#define VDEC_ASSIST_CANVAS_BLK32     0x0005
> +
> +#define VDEC_ASSIST_MBOX1_CLR_REG    0x0075
> +#define VDEC_ASSIST_MBOX1_MASK       0x0076
> +
> +#define MPSR                         0x0301
> +#define MPC_P                        0x0306
> +#define MPC_D                        0x0307
> +#define MPC_E                        0x0308
> +#define MPC_W                        0x0309
> +#define CPSR                         0x0321
> +#define IMEM_DMA_CTRL                0x0340
> +#define IMEM_DMA_ADR                 0x0341
> +#define IMEM_DMA_COUNT               0x0342
> +#define WRRSP_IMEM                   0x0343
> +#define LMEM_DMA_CTRL                0x0350
> +#define WRRSP_LMEM                   0x0353
> +
> +#define PSCALE_CTRL                  0x0911
> +#define GCLK_EN                      0x0983
> +#define MDEC_PIC_DC_CTRL             0x098e
> +#define MDEC_PIC_DC_MUX_CTRL         0x098d
> +#define ANC0_CANVAS_ADDR             0x0990
> +#define ANC1_CANVAS_ADDR             0x0991
> +#define ANC2_CANVAS_ADDR             0x0992
> +#define ANC3_CANVAS_ADDR             0x0993
> +#define ANC4_CANVAS_ADDR             0x0994
> +#define ANC5_CANVAS_ADDR             0x0995
> +#define ANC6_CANVAS_ADDR             0x0996
> +#define ANC7_CANVAS_ADDR             0x0997
> +#define ANC8_CANVAS_ADDR             0x0998
> +#define ANC9_CANVAS_ADDR             0x0999
> +#define ANC10_CANVAS_ADDR            0x099a
> +#define ANC11_CANVAS_ADDR            0x099b
> +#define ANC12_CANVAS_ADDR            0x099c
> +#define ANC13_CANVAS_ADDR            0x099d
> +#define ANC14_CANVAS_ADDR            0x099e
> +#define ANC15_CANVAS_ADDR            0x099f
> +#define ANC16_CANVAS_ADDR            0x09a0
> +#define ANC17_CANVAS_ADDR            0x09a1
> +#define ANC18_CANVAS_ADDR            0x09a2
> +#define ANC19_CANVAS_ADDR            0x09a3
> +#define ANC20_CANVAS_ADDR            0x09a4
> +#define ANC21_CANVAS_ADDR            0x09a5
> +#define ANC22_CANVAS_ADDR            0x09a6
> +#define ANC23_CANVAS_ADDR            0x09a7
> +#define ANC24_CANVAS_ADDR            0x09a8
> +#define ANC25_CANVAS_ADDR            0x09a9
> +#define ANC26_CANVAS_ADDR            0x09aa
> +#define ANC27_CANVAS_ADDR            0x09ab
> +#define ANC28_CANVAS_ADDR            0x09ac
> +#define ANC29_CANVAS_ADDR            0x09ad
> +#define ANC30_CANVAS_ADDR            0x09ae
> +#define ANC31_CANVAS_ADDR            0x09af
> +#define DBKR_CANVAS_ADDR             0x09b0
> +#define DBKW_CANVAS_ADDR             0x09b1
> +#define REC_CANVAS_ADDR              0x09b2
> +#define CURR_CANVAS_CTRL             0x09b3
> +#define MDEC_PIC_DC_THRESH           0x09b8
> +#define AV_SCRATCH_0                 0x09c0
> +#define AV_SCRATCH_1                 0x09c1
> +#define AV_SCRATCH_2                 0x09c2
> +#define AV_SCRATCH_3                 0x09c3
> +#define AV_SCRATCH_4                 0x09c4
> +#define AV_SCRATCH_5                 0x09c5
> +#define AV_SCRATCH_6                 0x09c6
> +#define AV_SCRATCH_7                 0x09c7
> +#define AV_SCRATCH_8                 0x09c8
> +#define AV_SCRATCH_9                 0x09c9
> +#define AV_SCRATCH_A                 0x09ca
> +#define AV_SCRATCH_B                 0x09cb
> +#define AV_SCRATCH_C                 0x09cc
> +#define AV_SCRATCH_D                 0x09cd
> +#define AV_SCRATCH_E                 0x09ce
> +#define AV_SCRATCH_F                 0x09cf
> +#define AV_SCRATCH_G                 0x09d0
> +#define AV_SCRATCH_H                 0x09d1
> +#define AV_SCRATCH_I                 0x09d2
> +#define AV_SCRATCH_J                 0x09d3
> +#define AV_SCRATCH_K                 0x09d4
> +#define AV_SCRATCH_L                 0x09d5
> +#define AV_SCRATCH_M                 0x09d6
> +#define AV_SCRATCH_N                 0x09d7
> +#define WRRSP_VLD                    0x09da
> +#define MDEC_DOUBLEW_CFG0            0x09db
> +#define MDEC_DOUBLEW_CFG1            0x09dc
> +#define MDEC_DOUBLEW_CFG2            0x09dd
> +#define MDEC_DOUBLEW_CFG3            0x09de
> +#define MDEC_DOUBLEW_CFG4            0x09df
> +#define MDEC_DOUBLEW_CFG5            0x09e0
> +#define MDEC_DOUBLEW_CFG6            0x09e1
> +#define MDEC_DOUBLEW_CFG7            0x09e2
> +#define MDEC_DOUBLEW_STATUS          0x09e3
> +#define MDEC_EXTIF_CFG0              0x09e4
> +
> +#define MDEC_EXTIF_CFG1              0x09e5
> +#define MDEC_EXTIF_CFG2              0x09e6
> +
> +#define POWER_CTL_VLD                0x0c08
> +#define VLD_DECODE_CONTROL           0x0c18
> +
> +#define PMV1_X                       0x0c20
> +#define PMV1_Y                       0x0c21
> +#define PMV2_X                       0x0c22
> +#define PMV2_Y                       0x0c23
> +#define PMV3_X                       0x0c24
> +#define PMV3_Y                       0x0c25
> +#define PMV4_X                       0x0c26
> +#define PMV4_Y                       0x0c27
> +#define M4_TABLE_SELECT              0x0c28
> +#define M4_CONTROL_REG               0x0c29
> +#define BLOCK_NUM                    0x0c2a
> +#define PATTERN_CODE                 0x0c2b
> +#define MB_INFO                      0x0c2c
> +#define VLD_DC_PRED                  0x0c2d
> +#define VLD_ERROR_MASK               0x0c2e
> +#define VLD_DC_PRED_C                0x0c2f
> +#define LAST_SLICE_MV_ADDR           0x0c30
> +#define LAST_MVX                     0x0c31
> +#define LAST_MVY                     0x0c32
> +
> +#define MB_MOTION_MODE               0x0c07
> +#define VIFF_BIT_CNT                 0x0c1a
> +#define M4_CONTROL_REG               0x0c29
> +#define VLD_C38                      0x0c38
> +#define VLD_C39                      0x0c39
> +#define VLD_SHIFT_STATUS             0x0c3b
> +#define VLD_C3D                      0x0c3d
> +#define VLD_MEM_VIFIFO_START_PTR     0x0c40
> +#define VLD_MEM_VIFIFO_CURR_PTR      0x0c41
> +#define VLD_MEM_VIFIFO_END_PTR       0x0c42
> +#define VLD_MEM_VIFIFO_BYTES_AVAIL   0x0c43
> +#define VLD_MEM_VIFIFO_CONTROL       0x0c44
> +#define VLD_MEM_VIFIFO_WP            0x0c45
> +#define VLD_MEM_VIFIFO_RP            0x0c46
> +#define VLD_MEM_VIFIFO_LEVEL         0x0c47
> +#define VLD_MEM_VIFIFO_BUF_CNTL      0x0c48
> +
> +#define VCOP_CTRL_REG                0x0e00
> +#define RV_AI_MB_COUNT               0x0e0c
> +#define IQIDCT_CONTROL               0x0e0e
> +#define DCAC_DDR_BYTE64_CTL          0x0e1d
> +
> +#define VDEC2_IMEM_DMA_CTRL          0x2340
> +#define VDEC2_IMEM_DMA_ADR           0x2341
> +#define VDEC2_IMEM_DMA_COUNT         0x2342
> +
> +#define DOS_SW_RESET0                0x3f00
> +#define DOS_GCLK_EN0                 0x3f01
> +#define DOS_GCLK_EN1                 0x3f09
> +#define DOS_GCLK_EN3                 0x3f35
> +
> +#define DOS_MEM_PD_VDEC              0x3f30
> +#define DOS_MEM_PD_VDEC2             0x3f31
> +#define DOS_MEM_PD_HCODEC            0x3f32
> +/*add from M8M2*/
> +#define DOS_MEM_PD_HEVC              0x3f33
> +
> +#define DOS_SW_RESET3                0x3f34
> +#define DOS_GCLK_EN3                 0x3f35
> +#define DOS_HEVC_INT_EN              0x3f36
> +
> +#endif
> +
> 
Thanks,
Neil


From zhentao.guo at amlogic.com  Tue Oct 28 04:08:50 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 19:08:50 +0800
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
In-Reply-To: <B9A578FB-BF95-47E1-B202-B59897C2C898@gmail.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <B9A578FB-BF95-47E1-B202-B59897C2C898@gmail.com>
Message-ID: <9a8e0391-c73f-4913-88e1-0a278d99f90d@amlogic.com>


? 2025/10/27 20:57, Christian Hewitt ??:
> [christianshewitt at gmail.com appears similar to someone who previously sent you email, but may not be that person. Learn why this could be a risk at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
>> On 27 Oct 2025, at 9:42?am, Zhentao Guo via B4 Relay <devnull+zhentao.guo.amlogic.com at kernel.org> wrote:
>>
>> Introduce initial driver support for Amlogic's new video acceleration
>> hardware architecture, designed for video stream decoding.
>>
>> Compared to the current Amlogic video decoder hardware architecture,
>> this new implementation eliminates the Esparser hardware component,
>> enabling direct vb2 buffer input. The driver is designed to support
>> the V4L2 M2M stateless decoder API. The initial phase includes support
>> for H.264 decoding on Amlogic S805X2 platform.
> It would be nice if you can outline the additional hardware the driver
> plans to support so reviewers have perspective on where we are now, and
> what more be coming? - the community would also like to understand if
> this driver will supersede the stalled driver attempt in staging.
Yes, we will follow Amlogic's overall upstream progress to support more 
hardware
platforms in the future. The next step will be adding support for 
A311D2(T7) platform.
We also plan to replace the stalled driver with the new stateless 
decoder driver.
The new stateless driver is fully compatible with the old G12/SM1 
platforms, making
this transition feasible.
> NB: I can only find two S805X2 devices to purchase for testing. The
> first is a Mecool KD5 HDMI stick, but this has Widevine L1 certs so
> will be unusable due to verified boot. The second is a no-name TV box
> on Aliexpress where the advert claims S805X2 inside but also shows a
> prominent Rockchip RK3228 logo :) .. please advise on some accessible
> hardware that can be used for validating the driver.
I'm not familiar with the two S805X2 devices you mentioned. Maybe we can
post you a S805X2 reference board for testing. I will talk to my colleagues
about it and follow up.
>> The driver is capable of:
>> - Supporting stateless H.264 decoding up to a resolution 1920x1088(on the S805X2 platform).
> It would be good to provide guidance to reviewers about other codecs
> the driver plans to support and how (architecturally) the driver will
> be expanded. I?m aware due to off-list discussions, but others are
> not and will want to know.
Thanks for the suggestion. Our roadmap is to implement support for five
codecs?H.264, H.265, VP9, AV1, and MPEG-2?in phases. This patch is the
initial phase of development, including the V4L2 interface layer and
the H.264 driver code. The H.265 decoder is also in development.
I'll add our plan in the cover-letter of the next version (v2) patch
series to make it clear for the kernel reviewers.
>> - Supporting I/P/B frame handling.
>> - Supporting vb2 mmap and dma-buf modes.
>> - Supporting frame-based decode mode. (Note that some H.264 bitstreams require
>>   DPB reordering to generate reference lists, the stateless decoder driver
>>   cannot access reordered reference lists in this mode, requiring the driver
>>   to perform reference list reordering itself)
>> - Supporting NV12/NV21 output.
>> - Supporting Annex B start codes.
>>
>> This driver is tested with Gstreamer.
>> Example:
>> gst-launch-1.0 filesrc location=/tmp/video_640x360_mp4_hevc_450kbps_no_b.mp4 !
>> parsebin ! v4l2slh264dec ! filesink location=/tmp/output.yuv
> Is this upstream gstreamer? if yes which version? If no, where can
> we obtain sources for testing. Has ffmpeg been tested? - the same
> questions apply.
The version is Gstreamer 1.24, I downloaded the source code from the 
official
website: https://gstreamer.freedesktop.org/.
FFmpeg hasn't been tested yet. We will also try to test the driver with 
ffmpeg.
>> The driver passes v4l2 compliance test, test reports :
>> v4l2-compliance 1.30.1, 64 bits, 64-bit time_t
>>
>> Compliance test for aml-vdec-drv device /dev/video0:
>>
>> Driver Info:
>>         Driver name      : aml-vdec-drv
>>         Card type        : platform:aml-vdec-drv
>>         Bus info         : platform:fe320000.video-codec
>>         Driver version   : 6.16.0
> It would be preferable to test the next iteration of patches on
> the latest kernel release, e.g. 6.18-rc, or recent media tree or
> perhaps drm-tip source.
Thanks for the suggestion, we will do the compliance test on kernel
6.18 and post the result of the next version(v2) patch series.
>>         Capabilities     : 0x84204000
>>                 Video Memory-to-Memory Multiplanar
>>                 Streaming
>>                 Extended Pix Format
>>                 Device Capabilities
>>         Device Caps      : 0x04204000
>>                 Video Memory-to-Memory Multiplanar
>>                 Streaming
>>                 Extended Pix Format
>>         Detected Stateless Decoder
>> Media Driver Info:
>>         Driver name      : aml-vdec-drv
>>         Model            : aml-vdec-drv
>>         Serial           :
>>         Bus info         : platform:fe320000.video-codec
>>         Media version    : 6.16.0
>>         Hardware revision: 0x00000000 (0)
>>         Driver version   : 6.16.0
>> Interface Info:
>>         ID               : 0x0300000c
>>         Type             : V4L Video
>> Entity Info:
>>         ID               : 0x00000001 (1)
>>         Name             : aml_dev_drv-source
>>         Function         : V4L2 I/O
>>         Pad 0x01000002   : 0: Source
>>           Link 0x02000008: to remote pad 0x1000004 of entity 'aml_dev_drv-proc' (Video Decoder): Data, Enabled, Immutable
>>
>> Required ioctls:
>>         test MC information (see 'Media Driver Info' above): OK
>>         test VIDIOC_QUERYCAP: OK
>>         test invalid ioctls: OK
>>
>> Allow for multiple opens:
>>         test second /dev/video0 open: OK
>>         test VIDIOC_QUERYCAP: OK
>>         test VIDIOC_G/S_PRIORITY: OK
>>         test for unlimited opens: OK
>>
>> Debug ioctls:
>>         test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>>         test VIDIOC_LOG_STATUS: OK (Not Supported)
>>
>> Input ioctls:
>>         test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>>         test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>>         test VIDIOC_ENUMAUDIO: OK (Not Supported)
>>         test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>>         test VIDIOC_G/S_AUDIO: OK (Not Supported)
>>         Inputs: 0 Audio Inputs: 0 Tuners: 0
>>
>> Output ioctls:
>>         test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>>         test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>>         test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>>         test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>>         test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>>         Outputs: 0 Audio Outputs: 0 Modulators: 0
>>
>> Input/Output configuration ioctls:
>>         test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>>         test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>>         test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>>         test VIDIOC_G/S_EDID: OK (Not Supported)
>>
>> Control ioctls:
>>         test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>>         test VIDIOC_QUERYCTRL: OK
>>         test VIDIOC_G/S_CTRL: OK
>>         test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>>         test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>>         test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>>         Standard Controls: 6 Private Controls: 0
>>         Standard Compound Controls: 4 Private Compound Controls: 0
>>
>> Format ioctls:
>>         test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>>         test VIDIOC_G/S_PARM: OK (Not Supported)
>>         test VIDIOC_G_FBUF: OK (Not Supported)
>>         test VIDIOC_G_FMT: OK
>>         test VIDIOC_TRY_FMT: OK
>>         test VIDIOC_S_FMT: OK
>>         test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>>         test Cropping: OK (Not Supported)
>>         test Composing: OK (Not Supported)
>>         test Scaling: OK (Not Supported)
>>
>> Codec ioctls:
>>         test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>>         test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>>         test VIDIOC_(TRY_)DECODER_CMD: OK
>>
>> Buffer ioctls:
>>         test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>>         test CREATE_BUFS maximum buffers: OK
>>         test VIDIOC_REMOVE_BUFS: OK
>>         test VIDIOC_EXPBUF: OK
>>         test Requests: OK
>>         test blocking wait: OK
>>
>> Total for aml-vdec-drv device /dev/video0: 49, Succeeded: 49, Failed: 0, Warnings: 0
>>
>> Some Fluster test cases are still failing. We will publish the final results
>> once all these Fluster test failures have been resolved.
> IMHO good drivers that merge quickly have more merit than perfect
> drivers that take forever. No driver passes all fluster tests. If
> you share the results, people can advise whether the failures are
> normal, something that must be improved, or something that can be
> improved with time.
Thanks. We have now tested the JVT-AVC_V1.
Result:
Ran 54/135 tests successfully

- 52 test vectors failed due to interlaced or mbaff clips: The Amlogic 
stateless
 ? decoder driver only support bitstreams with frame_mbs_only_flags == 1.
 ? Test Vectors:
 ? ? ? ? cabac_mot_fld0_full
 ? ? ? ? cabac_mot_mbaff0_full
 ? ? ? ? cabac_mot_picaff0_full
 ? ? ? ? CABREF3_Sand_D
 ? ? ? ? CAFI1_SVA_C
 ? ? ? ? CAMA1_Sony_C
 ? ? ? ? CAMA1_TOSHIBA_B
 ? ? ? ? cama1_vtc_c
 ? ? ? ? cama2_vtc_b
 ? ? ? ? CAMA3_Sand_E
 ? ? ? ? cama3_vtc_b
 ? ? ? ? CAMACI3_Sony_C
 ? ? ? ? CAMANL1_TOSHIBA_B
 ? ? ? ? CAMANL2_TOSHIBA_B
 ? ? ? ? CAMANL3_Sand_E
 ? ? ? ? CAMASL3_Sony_B
 ? ? ? ? CAMP_MOT_MBAFF_L30
 ? ? ? ? CAMP_MOT_MBAFF_L31
 ? ? ? ? CANLMA2_Sony_C
 ? ? ? ? CANLMA3_Sony_C
 ? ? ? ? CAPA1_TOSHIBA_B
 ? ? ? ? CAPAMA3_Sand_F
 ? ? ? ? cavlc_mot_fld0_full_B
 ? ? ? ? cavlc_mot_mbaff0_full_B
 ? ? ? ? cavlc_mot_picaff0_full_B
 ? ? ? ? CVCANLMA2_Sony_C
 ? ? ? ? CVFI1_Sony_D
 ? ? ? ? CVFI1_SVA_C
 ? ? ? ? CVFI2_Sony_H
 ? ? ? ? CVFI2_SVA_C
 ? ? ? ? CVMA1_Sony_D
 ? ? ? ? CVMA1_TOSHIBA_B
 ? ? ? ? CVMANL1_TOSHIBA_B
 ? ? ? ? CVMANL2_TOSHIBA_B
 ? ? ? ? CVMAPAQP3_Sony_E
 ? ? ? ? CVMAQP2_Sony_G
 ? ? ? ? CVMAQP3_Sony_D
 ? ? ? ? CVMP_MOT_FLD_L30_B
 ? ? ? ? CVNLFI1_Sony_C
 ? ? ? ? CVNLFI2_Sony_H
 ? ? ? ? CVPA1_TOSHIBA_B
 ? ? ? ? FI1_Sony_E
 ? ? ? ? MR6_BT_B
 ? ? ? ? MR7_BT_B
 ? ? ? ? MR8_BT_B
 ? ? ? ? MR9_BT_B
 ? ? ? ? Sharp_MP_Field_1_B
 ? ? ? ? Sharp_MP_Field_2_B
 ? ? ? ? Sharp_MP_Field_3_B
 ? ? ? ? Sharp_MP_PAFF_1r2
 ? ? ? ? Sharp_MP_PAFF_2r
 ? ? ? ? CVMP_MOT_FRM_L31_B
- 3 test vectors failed due to unsupported bitstream.
 ? num_slice_group_minus1 greater than zero is not supported by the
 ? hardware.
 ? Test Vectors:
 ? ? ? ? FM1_BT_B
 ? ? ? ? FM1_FT_E
 ? ? ? ? FM2_SVA_C
- 2 test vectors failed because SP_SLICE type is not supported by the
 ? hardware.
 ? Test Vectors:
 ? ? ? ? SP1_BT_A
 ? ? ? ? sp2_bt_b
We are working with the remain failures, we think that these fail cases
must be resolved.
>> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
>> ---
>> Zhentao Guo (3):
>>       dt-bindings: vdec: Add binding document of Amlogic decoder accelerator
>>       dts: decoder: Support V4L2 stateless decoder dt node for S4
>>       decoder: Add V4L2 stateless H.264 decoder driver
> None of the patch subject lines are following the naming formats
> used for the subsystems. Patch order is also important. Bindings
> go first, device-tree changes to expose support normally go last.
> Expect maintainer complaints about not reading kernel etiquette
> rules before submitting.
Thanks for the reminder. I will rebase the patches in correct order
and revise the subject according to the specifications.
>> .../bindings/media/amlogic,vcodec-dec.yaml         |   96 ++
>> MAINTAINERS                                        |    7 +
>> arch/arm64/boot/dts/amlogic/meson-s4.dtsi          |   24 +
>> drivers/media/platform/amlogic/Kconfig             |    2 +
>> drivers/media/platform/amlogic/Makefile            |    1 +
>> drivers/media/platform/amlogic/vdec/Kconfig        |   15 +
>> drivers/media/platform/amlogic/vdec/Makefile       |    4 +
>> drivers/media/platform/amlogic/vdec/aml_vdec.c     |  759 +++++++++
>> drivers/media/platform/amlogic/vdec/aml_vdec.h     |   31 +
>> .../platform/amlogic/vdec/aml_vdec_canvas_utils.c  |  154 ++
>> .../platform/amlogic/vdec/aml_vdec_canvas_utils.h  |   22 +
>> drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |  263 +++
>> drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |  194 +++
>> drivers/media/platform/amlogic/vdec/aml_vdec_hw.c  |  652 +++++++
>> drivers/media/platform/amlogic/vdec/aml_vdec_hw.h  |  182 ++
>> .../platform/amlogic/vdec/aml_vdec_platform.c      |   37 +
>> .../platform/amlogic/vdec/aml_vdec_platform.h      |   62 +
>> drivers/media/platform/amlogic/vdec/h264.c         | 1790 ++++++++++++++++++++
>> drivers/media/platform/amlogic/vdec/h264.h         |  300 ++++
>> drivers/media/platform/amlogic/vdec/reg_defines.h  |  175 ++
>> 20 files changed, 4770 insertions(+)
> The driver requires closed-source firmware blobs (sadly) for each
> codec and hardware target. Will that change in future iterations?
> If not, the firmware blobs are not provided here so it would be
> useful if you could provide a public source for them. There are
> known FOSS tools for extracting files from the Android ucode blob
> but testing presumably needs a specific blob version?
Yes, we plan to address this in future iterations. We intend? to pack
the firmware blobs for all codecs together but they will still remain
categorized by different hardware platforms sine we want to avoid making
the firmware package excessively large. The closed-source firmware will be
uploaded to the firmware repo:
https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git.
I will share the commit link once the upload is completed.
> Most maintainers also prefer a complex driver to be submitted in a
> series of patches that break the driver up into logical and easier
> to-review pieces. Large uber-patches are harder to digest and are
> likely to take much longer to review, and more effort for everyone
> to track feedback on over time.
Thanks for reminder. I admittedly overlooked these considerations.
The next version of the patch series will be improved accordingly.
> ***
>
> NB: The fact this driver is being submitted, is still a positive
> and welcomed step towards better upstream Amlogic support and it?s
> great to see! I would encourage you and colleagues to establish a
> public working space to share code and tools so the community can
> directly engage and support driver testing and development.
Yes, we will take this into consideration. Thanks again for all your
suggestions above, we look forward to cooperate with community.
>
> Christian
Best Regrads
Zhentao



From zhentao.guo at amlogic.com  Tue Oct 28 04:14:51 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 19:14:51 +0800
Subject: [PATCH 1/3] dt-bindings: vdec: Add binding document of Amlogic
 decoder accelerator
In-Reply-To: <b989fba3-223d-498a-8efe-7a60e26cf0db@kernel.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-1-620401813b5d@amlogic.com>
 <b989fba3-223d-498a-8efe-7a60e26cf0db@kernel.org>
Message-ID: <40830266-692a-4731-8957-4462d4993746@amlogic.com>


? 2025/10/27 21:05, Krzysztof Kozlowski ??:
> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On 27/10/2025 06:42, Zhentao Guo via B4 Relay wrote:
>> From: Zhentao Guo <zhentao.guo at amlogic.com>
>>
>> Add dt-binding of the Amlogic hardware decoder accelerator.
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
> your patch is touching. For bindings, the preferred subjects are
> explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
>
> A nit, subject: drop second/last, redundant "binding document for". The
> "dt-bindings" prefix is already stating that these are bindings.
> See also:
> https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
Thank you for pointing this out and providing the guidance. We'll revise 
the subjects according to the specifications.
>> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
>> ---
>>   .../bindings/media/amlogic,vcodec-dec.yaml         | 96 ++++++++++++++++++++++
>>   1 file changed, 96 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml b/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
>> new file mode 100644
>> index 000000000000..6cea8af72639
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
> Filename matching compatible.
Yes, we will correct this.
>> @@ -0,0 +1,96 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +# Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/media/amlogic,vcodec-dec.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Amlogic Video Decode Accelerator
>> +
>> +maintainers:
>> +  - Zhentao Guo <zhentao.guo at amlogic.com>
>> +
>> +description: |
>
> Do not need '|' unless you need to preserve formatting.
OK, I'll get rid of this.
>> +  The Video Decoder Accelerator present on Amlogic SOCs.
>> +  It supports stateless h264 decoding.
>> +
>> +properties:
>> +  compatible:
>> +    const: amlogic,s4-vcodec-dec
>> +
>> +  reg:
>> +    maxItems: 2
>> +
>> +  reg-names:
>> +    items:
>> +      - const: dosbus
>> +      - const: dmcbus
> Is "bus" really name of this in datasheet?
No, it is not from the datasheet, in fact it was inherited from the
older SOCs. Do you have any suggestions about this?
>> +
>> +  interrupts:
>> +    maxItems: 3
>> +
>> +  interrupt-names:
>> +    items:
>> +      - const: mailbox_0
>> +      - const: mailbox_1
>> +      - const: mailbox_2
> Useless names, so just drop interrupt-names property.
Yes, we don't need the interrupt names. I'll drop them.
>
>> +
>> +  clocks:
>> +    maxItems: 3
>> +
>> +  clock-names:
>> +    items:
>> +      - const: vdec
>> +      - const: clk_vdec_mux
>> +      - const: clk_hevcf_mux
>> +
>> +  power-domains:
>> +    maxItems: 2
>> +
>> +  power-domain-names:
>> +    items:
>> +      - const: pwrc-vdec
> Drop pwrc
>
>> +      - const: pwrc-hevc
> Drop pwrc
Ok, I'll drop the two pwrc(s) above.
>
> Missing iommus. I really doubt hardware works without IOMMU.

IOMMU is not supported by Amlogic SOCs, the decoder hardware needs to 
use contiguous memory.

>
>
> Best regards,
> Krzysztof


From zhentao.guo at amlogic.com  Tue Oct 28 04:18:40 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 19:18:40 +0800
Subject: [PATCH 2/3] dts: decoder: Support V4L2 stateless decoder dt node
 for S4
In-Reply-To: <43280bcc-5afd-4b46-a83d-d81c80405e71@kernel.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-2-620401813b5d@amlogic.com>
 <43280bcc-5afd-4b46-a83d-d81c80405e71@kernel.org>
Message-ID: <e4744e78-25c1-4ecc-b5fc-9ce7dcebd36d@amlogic.com>


? 2025/10/27 21:06, Krzysztof Kozlowski ??:
> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On 27/10/2025 06:42, Zhentao Guo via B4 Relay wrote:
>> From: Zhentao Guo <zhentao.guo at amlogic.com>
>>
>> Add vcodec_dec to the s4 dtsi for the V4L2 stateless decoder driver
>>
>> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
>
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
> your patch is touching. For bindings, the preferred subjects are
> explained here:
> https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html#i-for-patch-submitters
Got it. I will revise the subject according to the doc.
> Please order the patchset as expressed in submitting patches DT
> document. Or SoC maintainer profile.
OK, I will ensure the patchset is ordered properly in the next patch 
version.
>
> Best regards,
> Krzysztof

Thank you

Zhentao



From zhentao.guo at amlogic.com  Tue Oct 28 04:22:32 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 19:22:32 +0800
Subject: [PATCH 3/3] decoder: Add V4L2 stateless H.264 decoder driver
In-Reply-To: <a2ec6794-1131-421e-848b-3fddd39191e2@kernel.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>
 <a2ec6794-1131-421e-848b-3fddd39191e2@kernel.org>
Message-ID: <c1de12a1-a9ee-4d8f-957c-811b4eb33890@amlogic.com>


? 2025/10/27 21:10, Krzysztof Kozlowski ??:
> [You don't often get email from krzk at kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On 27/10/2025 06:42, Zhentao Guo via B4 Relay wrote:
>> From: Zhentao Guo <zhentao.guo at amlogic.com>
>>
>> This patch introduces initial driver support for Amlogic's new
> Please do not use "This commit/patch/change", but imperative mood. See
> longer explanation here:
> https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94
Got it, I'll refer to the document and revise the commit message.
>
>> video acceleration hardware architecture, designed for video
>> stream decoding. The driver is designed to support the
>> V4L2 M2M stateless decoder API. In phase 1, it supports H.264
>> bitstreams decoding.
>>
>> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
> ...
>
>
>> +
>> +static int aml_vdec_drv_probe(struct platform_device *pdev)
>> +{
>> +     struct aml_vdec_dev *dev;
>> +     struct video_device *vfd_dec;
>> +     struct aml_vdec_hw *hw;
>> +     int ret = 0;
>> +
>> +     dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
>> +     if (!dev)
>> +             return -ENOMEM;
>> +
>> +     dev->plat_dev = pdev;
>> +     mutex_init(&dev->dev_mutex);
>> +
>> +     ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
>> +     if (ret)
>> +             return dev_err_probe(&pdev->dev, ret, "v4l2_device_register err\n");
>> +
>> +     vfd_dec = video_device_alloc();
>> +     if (!vfd_dec) {
>> +             v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n");
>> +             ret = -ENOMEM;
>> +             goto err_device_alloc;
>> +     }
>> +     *vfd_dec = dec_dev;
>> +     vfd_dec->v4l2_dev = &dev->v4l2_dev;
>> +     vfd_dec->lock = &dev->dev_mutex;
>> +     video_set_drvdata(vfd_dec, dev);
>> +     dev->vfd = vfd_dec;
>> +     platform_set_drvdata(pdev, dev);
>> +
>> +     hw = kzalloc(sizeof(*hw), GFP_KERNEL);
> Why aren't you using devm interfaces?
Thanks for the reminder, It would be better to use the devm interfaces here,
I'll fix this.
>> +     if (!hw) {
>> +             ret = -ENOMEM;
>> +             goto err_dec_mem_init;
>> +     }
>> +     dev->dec_hw = hw;
>> +
>> +     dev->pvdec_data = of_device_get_match_data(&pdev->dev);
>> +     ret = dev->pvdec_data->req_hw_resource(dev);
>> +     if (ret < 0)
>> +             goto err_hw_init;
>> +
>> +     dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
>> +     if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
> Huh? Why the cast?
The cast seems superfluous here, I'll remove it.
>> +             v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem dec device\n");
>> +             ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
>> +             goto err_hw_init;
>> +     }
>> +
>> +     ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
>> +     if (ret) {
>> +             v4l2_err(&dev->v4l2_dev, "Failed to register video device");
>> +             goto err_vid_dev_register;
>> +     }
>> +
>> +     v4l2_info(&dev->v4l2_dev, "Registered %s as /dev/%s\n",
>> +               vfd_dec->name, video_device_node_name(vfd_dec));
> This does not look like useful printk message. Drivers should be silent
> on success:
> https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/coding-style.rst#L913
> https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/debugging/driver_development_debugging_guide.rst#L79
Got it, I'll get rid of it.
>
>> +
>> +     dev->mdev.dev = &pdev->dev;
>> +     strscpy(dev->mdev.model, AML_VDEC_DRV_NAME, sizeof(dev->mdev.model));
>> +     media_device_init(&dev->mdev);
>> +     dev->mdev.ops = &aml_m2m_media_ops;
>> +     dev->v4l2_dev.mdev = &dev->mdev;
>> +
>> +     ret = v4l2_m2m_register_media_controller(dev->m2m_dev_dec, vfd_dec,
>> +                                              MEDIA_ENT_F_PROC_VIDEO_DECODER);
>> +     if (ret) {
>> +             v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
>> +             goto error_m2m_mc_register;
>> +     }
>> +
>> +     ret = media_device_register(&dev->mdev);
>> +     if (ret) {
>> +             v4l2_err(&dev->v4l2_dev, "Failed to register media device");
>> +             goto err_media_dev_register;
>> +     }
>> +     vdec_enable(dev->dec_hw);
>> +     return 0;
>> +
>> +err_media_dev_register:
>> +     v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
>> +error_m2m_mc_register:
>> +     media_device_cleanup(&dev->mdev);
>> +err_vid_dev_register:
>> +     v4l2_m2m_release(dev->m2m_dev_dec);
>> +err_hw_init:
>> +     kfree(hw);
>> +     dev->dec_hw = NULL;
>> +err_dec_mem_init:
>> +     video_device_release(vfd_dec);
>> +err_device_alloc:
>> +     v4l2_device_unregister(&dev->v4l2_dev);
>> +     return ret;
>> +}
>> +
>> +static void aml_vdec_drv_remove(struct platform_device *pdev)
>> +{
>> +     struct aml_vdec_dev *dev = platform_get_drvdata(pdev);
>> +
>> +     vdec_disable(dev->dec_hw);
>> +
>> +     if (media_devnode_is_registered(dev->mdev.devnode)) {
>> +             media_device_unregister(&dev->mdev);
>> +             media_device_cleanup(&dev->mdev);
>> +     }
>> +
>> +     if (dev->m2m_dev_dec)
>> +             v4l2_m2m_release(dev->m2m_dev_dec);
>> +     if (dev->vfd)
>> +             video_unregister_device(dev->vfd);
>> +     if (dev->dec_hw)
>> +             dev->pvdec_data->destroy_hw_resource(dev);
>> +
>> +     v4l2_device_unregister(&dev->v4l2_dev);
>> +
>> +     pr_debug("aml v4l2 decoder driver remove\n");
>
> This does not look like useful printk message. Drivers should be silent
> on success:
> https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/coding-style.rst#L913
> https://elixir.bootlin.com/linux/v6.15-rc7/source/Documentation/process/debugging/driver_development_debugging_guide.rst#L79
I'll remove this message.
>
>> +}
>> +
>> +static const struct of_device_id aml_vdec_match[] = {
>> +     {.compatible = "amlogic,s4-vcodec-dec", .data = &aml_vdec_s4_pdata},
>> +     {},
>> +};
>> +
>> +static struct platform_driver aml_vcodec_dec_driver = {
>> +     .probe    = aml_vdec_drv_probe,
>> +     .remove    = aml_vdec_drv_remove,
>> +     .driver    = {
>> +             .name    = AML_VDEC_DRV_NAME,
>> +             .of_match_table = aml_vdec_match,
>> +     },
>> +};
>> +
>> +static int __init aml_vdec_init(void)
>> +{
>> +     pr_debug("aml v4l2 decoder module init\n");
>> +
>> +     if (platform_driver_register(&aml_vcodec_dec_driver)) {
>> +             pr_err("failed to register aml v4l2 decoder\n");
>> +             return -ENODEV;
>> +     }
>> +
>> +     return 0;
>> +}
>> +
>> +static void __exit aml_vdec_exit(void)
>> +{
>> +     pr_debug("aml v4l2 decoder module exit\n");
>> +     platform_driver_unregister(&aml_vcodec_dec_driver);
> No, drop entire init/exit. This is some really odd code, probably
> copy-paste from poor downstream. Please look at upstream drivers - do
> you see anything like that anywhere?
Yes, it should be dropped. I reviewed some other upstream drivers, nobody
add this.
>> +}
>> +
>> +module_init(aml_vdec_init);
>> +module_exit(aml_vdec_exit);
>> +
> Best regards,
> Krzysztof

Thank you

Zhentao



From krzk at kernel.org  Tue Oct 28 04:33:19 2025
From: krzk at kernel.org (Krzysztof Kozlowski)
Date: Tue, 28 Oct 2025 12:33:19 +0100
Subject: [PATCH 1/3] dt-bindings: vdec: Add binding document of Amlogic
 decoder accelerator
In-Reply-To: <40830266-692a-4731-8957-4462d4993746@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-1-620401813b5d@amlogic.com>
 <b989fba3-223d-498a-8efe-7a60e26cf0db@kernel.org>
 <40830266-692a-4731-8957-4462d4993746@amlogic.com>
Message-ID: <606da3b1-f042-4cc1-89d0-4feb257f032f@kernel.org>

On 28/10/2025 12:14, Zhentao Guo wrote:
>>> +properties:
>>> +  compatible:
>>> +    const: amlogic,s4-vcodec-dec
>>> +
>>> +  reg:
>>> +    maxItems: 2
>>> +
>>> +  reg-names:
>>> +    items:
>>> +      - const: dosbus
>>> +      - const: dmcbus
>> Is "bus" really name of this in datasheet?
> No, it is not from the datasheet, in fact it was inherited from the
> older SOCs. Do you have any suggestions about this?

dos, dmc

>>> +
>>> +  interrupts:
>>> +    maxItems: 3
>>> +
>>> +  interrupt-names:
>>> +    items:
>>> +      - const: mailbox_0
>>> +      - const: mailbox_1
>>> +      - const: mailbox_2
>> Useless names, so just drop interrupt-names property.
> Yes, we don't need the interrupt names. I'll drop them.
>>
>>> +
>>> +  clocks:
>>> +    maxItems: 3
>>> +
>>> +  clock-names:
>>> +    items:
>>> +      - const: vdec
>>> +      - const: clk_vdec_mux
>>> +      - const: clk_hevcf_mux
>>> +
>>> +  power-domains:
>>> +    maxItems: 2
>>> +
>>> +  power-domain-names:
>>> +    items:
>>> +      - const: pwrc-vdec
>> Drop pwrc
>>
>>> +      - const: pwrc-hevc
>> Drop pwrc
> Ok, I'll drop the two pwrc(s) above.
>>
>> Missing iommus. I really doubt hardware works without IOMMU.
> 
> IOMMU is not supported by Amlogic SOCs, the decoder hardware needs to 
> use contiguous memory.

I assume you speak about hardware, not drivers, so it is fine.

Best regards,
Krzysztof


From zhentao.guo at amlogic.com  Tue Oct 28 04:47:40 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 19:47:40 +0800
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
In-Reply-To: <b976b442-7d07-4fef-b851-ccd14661a233@linaro.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <b976b442-7d07-4fef-b851-ccd14661a233@linaro.org>
Message-ID: <540d98ea-114c-43bc-94c0-e944b5613d74@amlogic.com>


? 2025/10/28 18:50, Neil Armstrong ??:
> [ EXTERNAL EMAIL ]
>
> Hi,
>
> On 10/27/25 06:42, Zhentao Guo via B4 Relay wrote:
>> Introduce initial driver support for Amlogic's new video acceleration
>> hardware architecture, designed for video stream decoding.
>>
>> Compared to the current Amlogic video decoder hardware architecture,
>> this new implementation eliminates the Esparser hardware component,
>> enabling direct vb2 buffer input. The driver is designed to support
>> the V4L2 M2M stateless decoder API. The initial phase includes support
>> for H.264 decoding on Amlogic S805X2 platform.
>>
>> The driver is capable of:
>> - Supporting stateless H.264 decoding up to a resolution 1920x1088(on 
>> the S805X2 platform).
>> - Supporting I/P/B frame handling.
>> - Supporting vb2 mmap and dma-buf modes.
>> - Supporting frame-based decode mode. (Note that some H.264 
>> bitstreams require
>> ?? DPB reordering to generate reference lists, the stateless decoder 
>> driver
>> ?? cannot access reordered reference lists in this mode, requiring 
>> the driver
>> ?? to perform reference list reordering itself)
>> - Supporting NV12/NV21 output.
>> - Supporting Annex B start codes.
>
> Thanks for the initial drop, it's very nice !
>
> First of all, this still requires some work so it would be better if you
> used the RFC tag until all issues are sorted out.
>
Thanks for the reminder, I will add the RFC tag from the next patch 
version.
> You didn't tell anything about the firmware, did you build a specific 
> version
> of the firmware to handle the stateless and bypass ESPARSER ?
> Will this technique work with the released firmwares of GXL/G12/SM1 ?
For the firmware, we need to build a specific version for stateless decoder
driver. The ESPARSER is fully dropped. As I mentioned, this technique needs
specific firmware so it would not work with the released firmware of the 
older
SOCs. We plan to submit the new firmware to the linux-firmware repo. I will
share the commit once the upload is completed.
>
> Will you support the compressed format and 10bit with this ?
No, the compressed format and 10bit are not supported.
>
>>
>> This driver is tested with Gstreamer.
>> Example:
>> gst-launch-1.0 filesrc 
>> location=/tmp/video_640x360_mp4_hevc_450kbps_no_b.mp4 !
>> parsebin ! v4l2slh264dec ! filesink location=/tmp/output.yuv
>>
>> The driver passes v4l2 compliance test, test reports :
>> v4l2-compliance 1.30.1, 64 bits, 64-bit time_t
>>
>> Compliance test for aml-vdec-drv device /dev/video0:
>>
>> Driver Info:
>> ???????? Driver name????? : aml-vdec-drv
>> ???????? Card type??????? : platform:aml-vdec-drv
>> ???????? Bus info???????? : platform:fe320000.video-codec
>> ???????? Driver version?? : 6.16.0
>> ???????? Capabilities???? : 0x84204000
>> ???????????????? Video Memory-to-Memory Multiplanar
>> ???????????????? Streaming
>> ???????????????? Extended Pix Format
>> ???????????????? Device Capabilities
>> ???????? Device Caps????? : 0x04204000
>> ???????????????? Video Memory-to-Memory Multiplanar
>> ???????????????? Streaming
>> ???????????????? Extended Pix Format
>> ???????? Detected Stateless Decoder
>> Media Driver Info:
>> ???????? Driver name????? : aml-vdec-drv
>> ???????? Model??????????? : aml-vdec-drv
>> ???????? Serial?????????? :
>> ???????? Bus info???????? : platform:fe320000.video-codec
>> ???????? Media version??? : 6.16.0
>> ???????? Hardware revision: 0x00000000 (0)
>> ???????? Driver version?? : 6.16.0
>> Interface Info:
>> ???????? ID?????????????? : 0x0300000c
>> ???????? Type???????????? : V4L Video
>> Entity Info:
>> ???????? ID?????????????? : 0x00000001 (1)
>> ???????? Name???????????? : aml_dev_drv-source
>> ???????? Function???????? : V4L2 I/O
>> ???????? Pad 0x01000002?? : 0: Source
>> ?????????? Link 0x02000008: to remote pad 0x1000004 of entity 
>> 'aml_dev_drv-proc' (Video Decoder): Data, Enabled, Immutable
>>
>> Required ioctls:
>> ???????? test MC information (see 'Media Driver Info' above): OK
>> ???????? test VIDIOC_QUERYCAP: OK
>> ???????? test invalid ioctls: OK
>>
>> Allow for multiple opens:
>> ???????? test second /dev/video0 open: OK
>> ???????? test VIDIOC_QUERYCAP: OK
>> ???????? test VIDIOC_G/S_PRIORITY: OK
>> ???????? test for unlimited opens: OK
>>
>> Debug ioctls:
>> ???????? test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported)
>> ???????? test VIDIOC_LOG_STATUS: OK (Not Supported)
>>
>> Input ioctls:
>> ???????? test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported)
>> ???????? test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>> ???????? test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported)
>> ???????? test VIDIOC_ENUMAUDIO: OK (Not Supported)
>> ???????? test VIDIOC_G/S/ENUMINPUT: OK (Not Supported)
>> ???????? test VIDIOC_G/S_AUDIO: OK (Not Supported)
>> ???????? Inputs: 0 Audio Inputs: 0 Tuners: 0
>>
>> Output ioctls:
>> ???????? test VIDIOC_G/S_MODULATOR: OK (Not Supported)
>> ???????? test VIDIOC_G/S_FREQUENCY: OK (Not Supported)
>> ???????? test VIDIOC_ENUMAUDOUT: OK (Not Supported)
>> ???????? test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported)
>> ???????? test VIDIOC_G/S_AUDOUT: OK (Not Supported)
>> ???????? Outputs: 0 Audio Outputs: 0 Modulators: 0
>>
>> Input/Output configuration ioctls:
>> ???????? test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported)
>> ???????? test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported)
>> ???????? test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
>> ???????? test VIDIOC_G/S_EDID: OK (Not Supported)
>>
>> Control ioctls:
>> ???????? test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK
>> ???????? test VIDIOC_QUERYCTRL: OK
>> ???????? test VIDIOC_G/S_CTRL: OK
>> ???????? test VIDIOC_G/S/TRY_EXT_CTRLS: OK
>> ???????? test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
>> ???????? test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
>> ???????? Standard Controls: 6 Private Controls: 0
>> ???????? Standard Compound Controls: 4 Private Compound Controls: 0
>>
>> Format ioctls:
>> ???????? test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK
>> ???????? test VIDIOC_G/S_PARM: OK (Not Supported)
>> ???????? test VIDIOC_G_FBUF: OK (Not Supported)
>> ???????? test VIDIOC_G_FMT: OK
>> ???????? test VIDIOC_TRY_FMT: OK
>> ???????? test VIDIOC_S_FMT: OK
>> ???????? test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
>> ???????? test Cropping: OK (Not Supported)
>> ???????? test Composing: OK (Not Supported)
>> ???????? test Scaling: OK (Not Supported)
>>
>> Codec ioctls:
>> ???????? test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported)
>> ???????? test VIDIOC_G_ENC_INDEX: OK (Not Supported)
>> ???????? test VIDIOC_(TRY_)DECODER_CMD: OK
>>
>> Buffer ioctls:
>> ???????? test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
>> ???????? test CREATE_BUFS maximum buffers: OK
>> ???????? test VIDIOC_REMOVE_BUFS: OK
>> ???????? test VIDIOC_EXPBUF: OK
>> ???????? test Requests: OK
>> ???????? test blocking wait: OK
>
> Please also enable the streaming tests.
Yes, we did some streaming tests with Gstreamer, fluster test and bug 
fix is also in progress.
>>
>> Total for aml-vdec-drv device /dev/video0: 49, Succeeded: 49, Failed: 
>> 0, Warnings: 0
>>
>> Some Fluster test cases are still failing. We will publish the final 
>> results
>> once all these Fluster test failures have been resolved.
>
> As Christian reported, please add the flutter results aswell.
Thanks. We have now tested the JVT-AVC_V1.
Result:
Ran 54/135 tests successfully

- 52 test vectors failed due to interlaced or mbaff clips: The Amlogic 
stateless
 ? decoder driver only support bitstreams with frame_mbs_only_flags == 1.
 ? Test Vectors:
 ? ? ? ? cabac_mot_fld0_full
 ? ? ? ? cabac_mot_mbaff0_full
 ? ? ? ? cabac_mot_picaff0_full
 ? ? ? ? CABREF3_Sand_D
 ? ? ? ? CAFI1_SVA_C
 ? ? ? ? CAMA1_Sony_C
 ? ? ? ? CAMA1_TOSHIBA_B
 ? ? ? ? cama1_vtc_c
 ? ? ? ? cama2_vtc_b
 ? ? ? ? CAMA3_Sand_E
 ? ? ? ? cama3_vtc_b
 ? ? ? ? CAMACI3_Sony_C
 ? ? ? ? CAMANL1_TOSHIBA_B
 ? ? ? ? CAMANL2_TOSHIBA_B
 ? ? ? ? CAMANL3_Sand_E
 ? ? ? ? CAMASL3_Sony_B
 ? ? ? ? CAMP_MOT_MBAFF_L30
 ? ? ? ? CAMP_MOT_MBAFF_L31
 ? ? ? ? CANLMA2_Sony_C
 ? ? ? ? CANLMA3_Sony_C
 ? ? ? ? CAPA1_TOSHIBA_B
 ? ? ? ? CAPAMA3_Sand_F
 ? ? ? ? cavlc_mot_fld0_full_B
 ? ? ? ? cavlc_mot_mbaff0_full_B
 ? ? ? ? cavlc_mot_picaff0_full_B
 ? ? ? ? CVCANLMA2_Sony_C
 ? ? ? ? CVFI1_Sony_D
 ? ? ? ? CVFI1_SVA_C
 ? ? ? ? CVFI2_Sony_H
 ? ? ? ? CVFI2_SVA_C
 ? ? ? ? CVMA1_Sony_D
 ? ? ? ? CVMA1_TOSHIBA_B
 ? ? ? ? CVMANL1_TOSHIBA_B
 ? ? ? ? CVMANL2_TOSHIBA_B
 ? ? ? ? CVMAPAQP3_Sony_E
 ? ? ? ? CVMAQP2_Sony_G
 ? ? ? ? CVMAQP3_Sony_D
 ? ? ? ? CVMP_MOT_FLD_L30_B
 ? ? ? ? CVNLFI1_Sony_C
 ? ? ? ? CVNLFI2_Sony_H
 ? ? ? ? CVPA1_TOSHIBA_B
 ? ? ? ? FI1_Sony_E
 ? ? ? ? MR6_BT_B
 ? ? ? ? MR7_BT_B
 ? ? ? ? MR8_BT_B
 ? ? ? ? MR9_BT_B
 ? ? ? ? Sharp_MP_Field_1_B
 ? ? ? ? Sharp_MP_Field_2_B
 ? ? ? ? Sharp_MP_Field_3_B
 ? ? ? ? Sharp_MP_PAFF_1r2
 ? ? ? ? Sharp_MP_PAFF_2r
 ? ? ? ? CVMP_MOT_FRM_L31_B
- 3 test vectors failed due to unsupported bitstream.
 ? num_slice_group_minus1 greater than zero is not supported by the
 ? hardware.
 ? Test Vectors:
 ? ? ? ? FM1_BT_B
 ? ? ? ? FM1_FT_E
 ? ? ? ? FM2_SVA_C
- 2 test vectors failed because SP_SLICE type is not supported by the
 ? hardware.
 ? Test Vectors:
 ? ? ? ? SP1_BT_A
 ? ? ? ? sp2_bt_b

We are working with the remain failures, we think that these fail cases

must be resolved.

I'll add the fluster result to the cover-letter from the next patch version.

>
> Neil
>
>>
>> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
>> ---
>> Zhentao Guo (3):
>> ?????? dt-bindings: vdec: Add binding document of Amlogic decoder 
>> accelerator
>> ?????? dts: decoder: Support V4L2 stateless decoder dt node for S4
>> ?????? decoder: Add V4L2 stateless H.264 decoder driver
>>
>> ? .../bindings/media/amlogic,vcodec-dec.yaml???????? |?? 96 ++
>> ? MAINTAINERS??????????????????????????????????????? |??? 7 +
>> ? arch/arm64/boot/dts/amlogic/meson-s4.dtsi????????? |?? 24 +
>> ? drivers/media/platform/amlogic/Kconfig???????????? |??? 2 +
>> ? drivers/media/platform/amlogic/Makefile??????????? |??? 1 +
>> ? drivers/media/platform/amlogic/vdec/Kconfig??????? |?? 15 +
>> ? drivers/media/platform/amlogic/vdec/Makefile?????? |??? 4 +
>> ? drivers/media/platform/amlogic/vdec/aml_vdec.c???? |? 759 +++++++++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec.h???? |?? 31 +
>> ? .../platform/amlogic/vdec/aml_vdec_canvas_utils.c? |? 154 ++
>> ? .../platform/amlogic/vdec/aml_vdec_canvas_utils.h? |?? 22 +
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |? 263 +++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |? 194 +++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_hw.c? |? 652 +++++++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_hw.h? |? 182 ++
>> ? .../platform/amlogic/vdec/aml_vdec_platform.c????? |?? 37 +
>> ? .../platform/amlogic/vdec/aml_vdec_platform.h????? |?? 62 +
>> ? drivers/media/platform/amlogic/vdec/h264.c???????? | 1790 
>> ++++++++++++++++++++
>> ? drivers/media/platform/amlogic/vdec/h264.h???????? |? 300 ++++
>> ? drivers/media/platform/amlogic/vdec/reg_defines.h? |? 175 ++
>> ? 20 files changed, 4770 insertions(+)
>> ---
>> base-commit: 72fb0170ef1f45addf726319c52a0562b6913707
>> change-id: 20251027-b4-s4-vdec-upstream-0603c1a4c84a
>>
>> Best regards,
>
Thank you

Zhentao



From zhentao.guo at amlogic.com  Tue Oct 28 05:16:44 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 20:16:44 +0800
Subject: [PATCH 3/3] decoder: Add V4L2 stateless H.264 decoder driver
In-Reply-To: <42909f90-e2d3-4911-ae6d-47d180ccb367@linaro.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-3-620401813b5d@amlogic.com>
 <42909f90-e2d3-4911-ae6d-47d180ccb367@linaro.org>
Message-ID: <107081de-8ef5-4ad8-9482-424e218d49e2@amlogic.com>


? 2025/10/28 19:01, Neil Armstrong ??:
> [ EXTERNAL EMAIL ]
>
> Hi,
>
> On 10/27/25 06:42, Zhentao Guo via B4 Relay wrote:
>> From: Zhentao Guo <zhentao.guo at amlogic.com>
>>
>> This patch introduces initial driver support for Amlogic's new
>> video acceleration hardware architecture, designed for video
>> stream decoding. The driver is designed to support the
>> V4L2 M2M stateless decoder API. In phase 1, it supports H.264
>> bitstreams decoding.
>>
>> Signed-off-by: Zhentao Guo <zhentao.guo at amlogic.com>
>> ---
>> ? MAINTAINERS??????????????????????????????????????? |??? 7 +
>> ? drivers/media/platform/amlogic/Kconfig???????????? |??? 2 +
>> ? drivers/media/platform/amlogic/Makefile??????????? |??? 1 +
>> ? drivers/media/platform/amlogic/vdec/Kconfig??????? |?? 15 +
>> ? drivers/media/platform/amlogic/vdec/Makefile?????? |??? 4 +
>> ? drivers/media/platform/amlogic/vdec/aml_vdec.c???? |? 759 +++++++++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec.h???? |?? 31 +
>> ? .../platform/amlogic/vdec/aml_vdec_canvas_utils.c? |? 154 ++
>> ? .../platform/amlogic/vdec/aml_vdec_canvas_utils.h? |?? 22 +
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_drv.c |? 263 +++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_drv.h |? 194 +++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_hw.c? |? 652 +++++++
>> ? drivers/media/platform/amlogic/vdec/aml_vdec_hw.h? |? 182 ++
>> ? .../platform/amlogic/vdec/aml_vdec_platform.c????? |?? 37 +
>> ? .../platform/amlogic/vdec/aml_vdec_platform.h????? |?? 62 +
>> ? drivers/media/platform/amlogic/vdec/h264.c???????? | 1790 
>> ++++++++++++++++++++
>> ? drivers/media/platform/amlogic/vdec/h264.h???????? |? 300 ++++
>> ? drivers/media/platform/amlogic/vdec/reg_defines.h? |? 175 ++
>> ? 18 files changed, 4650 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 5ea78444f035..f400b5dabf30 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -1352,6 +1352,13 @@ S:???? Maintained
>> ? F: Documentation/devicetree/bindings/spi/amlogic,a4-spisg.yaml
>> ? F:? drivers/spi/spi-amlogic-spisg.c
>>
>> +AMLOGIC VCODEC DRIVER
>> +M:?? Zhentao Guo <zhentao.guo at amlogic.com>
>> +L:?? linux-media at vger.kernel.org
>> +S:?? Maintained
>> +F: Documentation/devicetree/bindings/media/amlogic,vcodec-dec.yaml
>> +F:?? drivers/media/platform/amlogic/vdec/
>> +
>> ? AMPHENOL CHIPCAP 2 DRIVER
>> ? M:? Javier Carrasco <javier.carrasco.cruz at gmail.com>
>> ? L:? linux-hwmon at vger.kernel.org
>> diff --git a/drivers/media/platform/amlogic/Kconfig 
>> b/drivers/media/platform/amlogic/Kconfig
>> index 458acf3d5fa8..8132f5b9282b 100644
>> --- a/drivers/media/platform/amlogic/Kconfig
>> +++ b/drivers/media/platform/amlogic/Kconfig
>> @@ -4,3 +4,5 @@ comment "Amlogic media platform drivers"
>>
>> ? source "drivers/media/platform/amlogic/c3/Kconfig"
>> ? source "drivers/media/platform/amlogic/meson-ge2d/Kconfig"
>> +
>> +source "drivers/media/platform/amlogic/vdec/Kconfig"
>
> PLease respect original formatting and drop the empty line
Got it, I'll correct this.
>
>> diff --git a/drivers/media/platform/amlogic/Makefile 
>> b/drivers/media/platform/amlogic/Makefile
>> index c744afcd1b9e..7409de674c0b 100644
>> --- a/drivers/media/platform/amlogic/Makefile
>> +++ b/drivers/media/platform/amlogic/Makefile
>> @@ -2,3 +2,4 @@
>>
>> ? obj-y += c3/
>> ? obj-y += meson-ge2d/
>> +obj-y += vdec/
>
> Ditto> diff --git a/drivers/media/platform/amlogic/vdec/Kconfig 
> b/drivers/media/platform/amlogic/vdec/Kconfig
I'm sorry, I did not get what you mean here. It is a mistake?
>> new file mode 100644
>> index 000000000000..05c4568e058b
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/Kconfig
>> @@ -0,0 +1,15 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +
>> +config VIDEO_AMLOGIC_VCODEC
>> +??? tristate "Amlogic Video Codec Driver"
>> +??? depends on ARCH_MESON || COMPILE_TEST
>> +??? depends on VIDEO_DEV
>> +??? depends on V4L_MEM2MEM_DRIVERS
>> +??? select VIDEOBUF2_DMA_CONTIG
>> +??? select V4L2_H264
>> +??? select V4L2_MEM2MEM_DEV
>> +??? help
>> +????? This is a v4l2 driver for Amlogic video codec driver.
>> +?????? This driver is designed to support V4L2 M2M STATELESS
>> +?????? interface.
>> +????? To compile this driver as a module choose m here.
>> diff --git a/drivers/media/platform/amlogic/vdec/Makefile 
>> b/drivers/media/platform/amlogic/vdec/Makefile
>> new file mode 100644
>> index 000000000000..f645f7ca5e2d
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/Makefile
>> @@ -0,0 +1,4 @@
>> +# SPDX-License-Identifier: GPL-2.0-only
>> +aml-vdec-drv-objs := aml_vdec.o aml_vdec_drv.o aml_vdec_hw.o 
>> aml_vdec_platform.o h264.o aml_vdec_canvas_utils.o\
>> +
>> +obj-$(CONFIG_VIDEO_AMLOGIC_VCODEC) += aml-vdec-drv.o
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec.c 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec.c
>> new file mode 100644
>> index 000000000000..e8a66bde0397
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec.c
>> @@ -0,0 +1,759 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#include <media/v4l2-mem2mem.h>
>> +#include <media/v4l2-ctrls.h>
>> +#include <media/v4l2-event.h>
>> +#include <media/videobuf2-v4l2.h>
>> +#include <media/videobuf2-dma-contig.h>
>> +
>> +#include "aml_vdec.h"
>> +#include "aml_vdec_hw.h"
>> +#include "aml_vdec_platform.h"
>> +
>> +#define VCODEC_DRV_NAME "aml-vdec-drv"
>> +
>> +static const struct aml_vdec_v4l2_ctrl controls[] = {
>> +???? {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_STATELESS_H264_DECODE_PARAMS,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_STATELESS_H264_SPS,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_STATELESS_H264_PPS,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_STATELESS_H264_SCALING_MATRIX,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_STATELESS_H264_DECODE_MODE,
>> +???????????????????? .min = 
>> V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
>> +???????????????????? .def = 
>> V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
>> +???????????????????? .max = 
>> V4L2_STATELESS_H264_DECODE_MODE_FRAME_BASED,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_STATELESS_H264_START_CODE,
>> +???????????????????? .min = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
>> +???????????????????? .def = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
>> +???????????????????? .max = V4L2_STATELESS_H264_START_CODE_ANNEX_B,
>> +???????????? },
>> +???? }, {
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .cfg = {
>> +???????????????????? .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE,
>> +???????????????????? .min = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE,
>> +???????????????????? .max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
>> +???????????????????? .def = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN,
>> +???????????? },
>> +???? }
>> +};
>> +
>> +static struct aml_video_fmt aml_video_formats[] = {
>> +???? {
>> +???????????? .name = "H.264",
>> +???????????? .fourcc = V4L2_PIX_FMT_H264_SLICE,
>> +???????????? .type = AML_FMT_DEC,
>> +???????????? .codec_type = CODEC_TYPE_H264,
>> +???????????? .num_planes = 1,
>> +???????????? .stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
>> +???????????????????? AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
>> +???? },
>> +???? {
>> +???????????? .name = "NV21M",
>> +???????????? .fourcc = V4L2_PIX_FMT_NV21M,
>> +???????????? .type = AML_FMT_FRAME,
>> +???????????? .codec_type = CODEC_TYPE_FRAME,
>> +???????????? .num_planes = 2,
>> +???????????? .stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
>> +???????????????????? AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
>> +???? },
>> +???? {
>> +???????????? .name = "NV21",
>> +???????????? .fourcc = V4L2_PIX_FMT_NV21,
>> +???????????? .type = AML_FMT_FRAME,
>> +???????????? .codec_type = CODEC_TYPE_FRAME,
>> +???????????? .num_planes = 1,
>> +???????????? .stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
>> +???????????????????? AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
>> +???? },
>> +???? {
>> +???????????? .name = "NV12M",
>> +???????????? .fourcc = V4L2_PIX_FMT_NV12M,
>> +???????????? .type = AML_FMT_FRAME,
>> +???????????? .codec_type = CODEC_TYPE_FRAME,
>> +???????????? .num_planes = 2,
>> +???????????? .stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
>> +???????????????????? AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
>> +
>> +???? },
>> +???? {
>> +???????????? .name = "NV12",
>> +???????????? .fourcc = V4L2_PIX_FMT_NV12,
>> +???????????? .type = AML_FMT_FRAME,
>> +???????????? .codec_type = CODEC_TYPE_FRAME,
>> +???????????? .num_planes = 1,
>> +???????????? .stepwise = {AML_VDEC_MIN_W, AML_VDEC_1080P_MAX_W, 2,
>> +???????????????????? AML_VDEC_MIN_H, AML_VDEC_1080P_MAX_H, 2},
>> +???? },
>> +};
>> +
>> +void aml_vdec_set_default_params(struct aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_q_data *q_data = NULL;
>> +
>> +???? ctx->m2m_ctx->q_lock = &ctx->v4l2_intf_lock;
>> +
>> +???? ctx->pic_info.colorspace = V4L2_COLORSPACE_DEFAULT;
>> +???? ctx->pic_info.ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
>> +???? ctx->pic_info.quantization = V4L2_QUANTIZATION_DEFAULT;
>> +???? ctx->pic_info.xfer_func = V4L2_XFER_FUNC_DEFAULT;
>> +
>> +???? q_data = &ctx->q_data[AML_Q_DATA_SRC];
>> +???? memset(q_data, 0, sizeof(struct aml_q_data));
>> +???? q_data->visible_width = AML_VDEC_MIN_W;
>> +???? q_data->visible_height = AML_VDEC_MIN_H;
>> +???? q_data->coded_width = AML_VDEC_MIN_W;
>> +???? q_data->coded_height = AML_VDEC_MIN_H;
>> +???? q_data->filed_flag = V4L2_FIELD_NONE;
>> +???? q_data->bytesperline[0] = 0;
>> +???? q_data->sizeimage[0] = (1024 * 1024);
>> +???? q_data->fmt = &aml_video_formats[DEFAULT_OUT_IDX];
>> +
>> +???? q_data = &ctx->q_data[AML_Q_DATA_DST];
>> +???? memset(q_data, 0, sizeof(struct aml_q_data));
>> +???? q_data->visible_width = AML_VDEC_MIN_W;
>> +???? q_data->visible_height = AML_VDEC_MIN_H;
>> +???? q_data->coded_width = AML_VDEC_MIN_W;
>> +???? q_data->coded_height = AML_VDEC_MIN_H;
>> +???? q_data->filed_flag = V4L2_FIELD_NONE;
>> +???? q_data->bytesperline[0] = q_data->coded_width;
>> +???? q_data->sizeimage[0] = q_data->coded_width * q_data->coded_height;
>> +???? q_data->bytesperline[1] = q_data->coded_width;
>> +???? q_data->sizeimage[1] = q_data->sizeimage[0] / 2;
>> +???? q_data->fmt = &aml_video_formats[DEFAULT_CAP_IDX];
>> +}
>> +
>> +int aml_vdec_ctrls_setup(struct aml_vdec_ctx *ctx)
>> +{
>> +???? int i;
>> +???? int ctrls_size = sizeof(controls) / sizeof(struct 
>> aml_vdec_v4l2_ctrl);
>> +
>> +???? v4l2_ctrl_handler_init(&ctx->ctrl_handler, ctrls_size);
>> +???? for (i = 0; i < ctrls_size; i++) {
>> +???????????? v4l2_ctrl_new_custom(&ctx->ctrl_handler, 
>> &controls[i].cfg, NULL);
>> +???????????? if (ctx->ctrl_handler.error) {
>> +???????????????????? pr_debug("add ctrl for (%d) failed%d\n",
>> +????????????????????????????? controls[i].cfg.id, 
>> ctx->ctrl_handler.error);
>> + v4l2_ctrl_handler_free(&ctx->ctrl_handler);
>> +???????????????????? return ctx->ctrl_handler.error;
>> +???????????? }
>> +???? }
>> +???? ctx->fh.ctrl_handler = &ctx->ctrl_handler;
>> +???? return v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
>> +}
>> +
>> +static void m2mops_vdec_device_run(void *m2m_priv)
>> +{
>> +???? struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)m2m_priv;
>> +???? struct aml_vdec_dev *dev = ctx->dev;
>> +???? struct vb2_v4l2_buffer *src, *dst;
>> +???? struct media_request *src_req;
>> +???? const char *fw_path = 
>> dev->pvdec_data->fw_path[ctx->curr_dec_type];
>> +
>> +???? src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
>> +???? dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
>> +???? pr_debug("device run : src buf : %d dst buf %d\n", 
>> src->vb2_buf.index, dst->vb2_buf.index);
>
> Switch to dev_dbg everywhere
OK, I'll replace all these pr_xxx with dev_debug.
>
>> +
>> +???? src_req = src->vb2_buf.req_obj.req;
>> +???? if (src_req)
>> +???????????? v4l2_ctrl_request_setup(src_req, &ctx->ctrl_handler);
>> +
>> +???? dos_enable();
>> +???? /* incase of bus hang in stop_streaming */
>> +???? ctx->dos_clk_en = 1;
>> +???? aml_vdec_reset_core();
>> +???? load_firmware(dev->dec_hw, fw_path);
>> +
>> +???? if (ctx->codec_ops->run)
>> +???????????? ctx->codec_ops->run(ctx);
>> +
>> +???? v4l2_m2m_buf_copy_metadata(src, dst);
>> +???? if (src_req)
>> +???????????? v4l2_ctrl_request_complete(src_req, &ctx->ctrl_handler);
>> +
>> +???? v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, 
>> ctx->m2m_ctx, VB2_BUF_STATE_DONE);
>> +}
>> +
>> +const struct v4l2_m2m_ops aml_vdec_m2m_ops = {
>> +???? .device_run = m2mops_vdec_device_run,
>> +};
>> +
>> +static int vidioc_vdec_querycap(struct file *file, void *priv,
>> +???????????????????????????? struct v4l2_capability *cap)
>> +{
>> +???? strscpy(cap->driver, VCODEC_DRV_NAME, sizeof(cap->driver));
>> +???? strscpy(cap->card, "platform:" VCODEC_DRV_NAME, 
>> sizeof(cap->card));
>> +
>> +???? return 0;
>> +}
>> +
>> +static int vidioc_vdec_enum_fmt(struct v4l2_fmtdesc *f, bool is_output)
>> +{
>> +???? struct aml_video_fmt *fmt;
>> +???? int fmt_size = sizeof(aml_video_formats) / sizeof(struct 
>> aml_video_fmt);
>> +???? int i = 0, j = 0;
>> +
>> +???? for (; i < fmt_size; i++) {
>> +???????????? fmt = &aml_video_formats[i];
>> +???????????? if (is_output && fmt->type != AML_FMT_DEC)
>> +???????????????????? continue;
>> +???????????? if (!is_output && fmt->type != AML_FMT_FRAME)
>> +???????????????????? continue;
>> +
>> +???????????? if (j == f->index) {
>> +???????????????????? f->pixelformat = fmt->fourcc;
>> +???????????????????? strscpy(f->description, fmt->name,
>> +???????????????????????????? sizeof(f->description));
>> +???????????????????? if (strlen(fmt->name) >= sizeof(f->description)) {
>> +???????????????????????????? pr_err("fmt name string is too long!\n");
>> + f->description[sizeof(f->description) - 1] = '\0';
>> +???????????????????? }
>> +???????????????????? return 0;
>> +???????????? }
>> +???????????? ++j;
>> +???? }
>> +???? return -EINVAL;
>> +}
>> +
>> +static struct aml_q_data *aml_vdec_get_qdata_by_type(struct 
>> aml_vdec_ctx *ctx,
>> +????????????????????????????????????????????????? enum v4l2_buf_type 
>> type)
>> +{
>> +???? if (V4L2_TYPE_IS_OUTPUT(type))
>> +???????????? return &ctx->q_data[AML_Q_DATA_SRC];
>> +
>> +???? return &ctx->q_data[AML_Q_DATA_DST];
>> +}
>> +
>> +static struct aml_video_fmt *aml_vdec_get_video_fmt(u32 format)
>> +{
>> +???? struct aml_video_fmt *fmt;
>> +???? unsigned int k;
>> +
>> +???? for (k = 0; k < (sizeof(aml_video_formats) / sizeof(struct 
>> aml_video_fmt)); k++) {
>> +???????????? fmt = &aml_video_formats[k];
>> +???????????? if (fmt->fourcc == format)
>> +???????????????????? return fmt;
>> +???? }
>> +
>> +???? return NULL;
>> +}
>> +
>> +static int aml_vdec_init_dec_inst(struct aml_vdec_ctx *ctx,
>> +?????????????????????????????? struct aml_video_fmt *fmt_out)
>> +{
>> +???? struct aml_vdec_dev *dev = ctx->dev;
>> +???? int ret = -1;
>> +
>> +???? if (!fmt_out)
>> +???????????? return ret;
>> +
>> +???? if (fmt_out->codec_type == CODEC_TYPE_FRAME) {
>> +???????????? pr_debug("capture type no need to set\n");
>> +???????????? return 0;
>> +???? }
>> +
>> +???? ctx->codec_ops = &dev->pvdec_data->codec_ops[fmt_out->codec_type];
>> +???? if (ctx->codec_ops->init) {
>> +???????????? ret = ctx->codec_ops->init(ctx);
>> +???????????? if (ret < 0)
>> +???????????????????? return ret;
>> +???? }
>> +???? ctx->curr_dec_type = fmt_out->codec_type;
>> +???? pr_info("%s set curr_dec_type = %d\n", __func__, 
>> ctx->curr_dec_type);
>
> And dev_info/dev_err/dev_warn...
Got it. I'll get rid of them and replace with dev logs.
>
>> +
>> +???? return ret;
>> +}
>> +
>
> <snip>
>
>> diff --git 
>> a/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c
>> new file mode 100644
>> index 000000000000..066958118b00
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_canvas_utils.c
>> @@ -0,0 +1,154 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#include "aml_vdec_canvas_utils.h"
>> +
>> +#define CANVAS_REG_OFFSET?? (0x12 << 2)
>> +
>> +/*
>> + * DMC_CAV_LUT_DATAL/DMC_CAV_LUT_DATAH
>> + * high 32bits of canvas data which need to be configured
>> + * to canvas memory.
>> + * 64bits CANVAS look up table
>> + * bit 61 : 58?? Endian control.
>> + * bit 61 :? 1 : switch 2 64bits data inside 128bits boundary.
>> + * 0 : no change.
>> + * bit 60 :? 1 : switch 2 32bits data inside 64bits data boundary.
>> + * 0 : no change.
>> + * bit 59 :? 1 : switch 2 16bits data inside 32bits data boundary.
>> + * 0 : no change.
>> + * bit 58 :? 1 : switch 2 8bits data? inside 16bits data boundary.
>> + * 0 : no change.
>> + * bit 57 : 56.?? Canvas block mode.? 2 : 64x32, 1: 32x32;
>> + *? 0 : linear mode.
>> + * bit 55 :????? canvas Y direction wrap control.
>> + * 1: wrap back in y.? 0: not wrap back.
>> + * bit 54 :????? canvas X direction wrap control.
>> + * 1: wrap back in X.? 0: not wrap back.
>> + * bit 53 : 41.?? canvas Hight.
>> + * bit 40 : 29.?? canvas Width, unit: 8bytes. must in 32bytes boundary.
>> + * that means last 2 bits must be 0.
>> + * bit 28 : 0.??? canvas start address.?? unit. 8 bytes. must be in
>> + * 32bytes boundary. that means last 2bits must be 0.
>> + */
>> +
>> +#define CANVAS_WADDR_LBIT?????? 0
>> +#define CANVAS_WIDTH_LBIT?????? 29
>> +#define CANVAS_HEIGHT_HBIT????? (41 - 32)
>> +#define CANVAS_WRAPX_HBIT?????? (54 - 32)
>> +#define CANVAS_WRAPY_HBIT?????? (55 - 32)
>> +#define CANVAS_BLKMODE_HBIT???? (56 - 32)
>> +#define CANVAS_ENDIAN_HBIT????? (58 - 32)
>> +
>> +/* canvas regs */
>> +#define DC_CAV_LUT_DATAL??????? 0x12
>> +#define DC_CAV_LUT_DATAH??????? 0x13
>> +#define DC_CAV_LUT_ADDR???????? 0x14
>> +#define DC_CAV_LUT_RDATAL?????? 0x15
>> +#define DC_CAV_LUT_RDATAH?????? 0x16
>> +
>> +#define CANVAS_ADDR_LMASK?????? 0x1fffffff
>> +#define CANVAS_WIDTH_LMASK????? 0x7
>> +#define CANVAS_WIDTH_LWID?????? 3
>> +#define CANVAS_WIDTH_HMASK????? 0x1ff
>> +#define CANVAS_WIDTH_HBIT?????? 0
>> +#define CANVAS_HEIGHT_MASK????? 0x1fff
>> +#define CANVAS_HEIGHT_BIT?????? 9
>> +#define CANVAS_ADDR_NOWRAP????? 0x00
>> +#define CANVAS_ADDR_WRAPX?????? 0x01
>> +#define CANVAS_ADDR_WRAPY?????? 0x02
>> +#define CANVAS_BLKMODE_MASK???? 0x03
>> +
>> +#define CANVAS_BLKMODE_LINEAR?? 0x00
>> +#define CANVAS_BLKMODE_32X32??? 0x01
>> +#define CANVAS_BLKMODE_64X32??? 0x02
>> +
>> +#define CANVAS_LUT_WR_EN?? (0x2 << 8)
>> +#define CANVAS_LUT_RD_EN?? (0x1 << 8)
>> +
>> +#define CANVAS_ADDR_BITS_MASK??????????????? GENMASK(28, 0)
>> +#define CANVAS_WIDTH_L_MASK????????? GENMASK(31, 29)
>> +#define CANVAS_WIDTH_H_MASK????????? GENMASK(8, 0)
>> +#define CANVAS_HEIGHT_H_MASK???????? GENMASK(21, 9)
>> +#define CANVAS_WRAP_H_MASK?????????? GENMASK(23, 23)
>> +#define CANVAS_BLOCK_H_MASK????????? GENMASK(25, 24)
>> +#define CANVAS_BITS_CTRL_MASK??????????????? GENMASK(29, 26)
>> +
>> +static struct vdec_canvas_s canvas;
>
> There's already a canvas driver for that, please use it and extend it 
> if necessary:
> drivers/soc/amlogic/meson-canvas.c
Ok, I'll check if we can use the existing canvas interfaces.
> <snip>
>
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
>> new file mode 100644
>> index 000000000000..ef2c779839d8
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.c
>> @@ -0,0 +1,263 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <media/v4l2-device.h>
>> +#include <media/v4l2-ioctl.h>
>> +
>> +#include "aml_vdec.h"
>> +#include "aml_vdec_hw.h"
>> +#include "aml_vdec_platform.h"
>> +
>> +#define AML_VDEC_DRV_NAME "aml-vdec-drv"
>> +
>> +static int fops_vcodec_open(struct file *file)
>> +{
>> +???? struct aml_vdec_dev *dec_dev = video_drvdata(file);
>> +???? struct aml_vdec_ctx *ctx = NULL;
>> +???? int ret = 0;
>> +
>> +???? ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
>> +???? if (!ctx)
>> +???????????? return -ENOMEM;
>> +
>> +???? mutex_lock(&dec_dev->dev_mutex);
>> +???? dec_dev->dec_ctx = ctx;
>> +???? ctx->dev = dec_dev;
>> +???? v4l2_fh_init(&ctx->fh, video_devdata(file));
>> +???? file->private_data = &ctx->fh;
>> +???? v4l2_fh_add(&ctx->fh, file);
>> +???? dec_dev->filp = file;
>> +???? mutex_init(&ctx->v4l2_intf_lock);
>> +???? init_waitqueue_head(&ctx->queue);
>> +???? ctx->int_cond = 0;
>> +
>> +???? ctx->m2m_ctx = v4l2_m2m_ctx_init(dec_dev->m2m_dev_dec, ctx,
>> + &aml_vdec_queue_init);
>> +???? if (IS_ERR((__force void *)ctx->m2m_ctx)) {
>> +???????????? ret = PTR_ERR((__force void *)ctx->m2m_ctx);
>> +???????????? v4l2_err(&dec_dev->v4l2_dev, "Failed to 
>> v4l2_m2m_ctx_init() (%d)", ret);
>> +???????????? goto err_m2m_ctx_init;
>> +???? }
>> +
>> +???? ctx->fh.m2m_ctx = ctx->m2m_ctx;
>> +???? ret = aml_vdec_ctrls_setup(ctx);
>> +???? if (ret) {
>> +???????????? v4l2_err(&dec_dev->v4l2_dev, "Failed to init all ctrls 
>> (%d)", ret);
>> +???????????? goto err_ctrls_setup;
>> +???? }
>> +
>> +???? aml_vdec_set_default_params(ctx);
>> +???? mutex_unlock(&dec_dev->dev_mutex);
>> +
>> +???? return ret;
>> +
>> +err_ctrls_setup:
>> +???? v4l2_m2m_ctx_release(ctx->m2m_ctx);
>> +err_m2m_ctx_init:
>> +???? v4l2_fh_del(&ctx->fh, file);
>> +???? v4l2_fh_exit(&ctx->fh);
>> +???? kfree(ctx);
>> +???? mutex_unlock(&dec_dev->dev_mutex);
>> +
>> +???? return ret;
>> +}
>> +
>> +static int fops_vcodec_release(struct file *file)
>> +{
>> +???? struct aml_vdec_dev *dec_dev = video_drvdata(file);
>> +???? struct aml_vdec_ctx *ctx = fh_to_dec_ctx(file->private_data);
>> +
>> +???? mutex_lock(&dec_dev->dev_mutex);
>> +???? v4l2_ctrl_handler_free(&ctx->ctrl_handler);
>> +???? v4l2_m2m_ctx_release(ctx->m2m_ctx);
>> +???? v4l2_fh_del(&ctx->fh, file);
>> +???? v4l2_fh_exit(&ctx->fh);
>> +???? kfree(ctx);
>> +???? mutex_unlock(&dec_dev->dev_mutex);
>> +
>> +???? return 0;
>> +}
>> +
>> +static const struct v4l2_file_operations aml_vdec_fops = {
>> +???? .owner??????? = THIS_MODULE,
>> +???? .open??????? = fops_vcodec_open,
>> +???? .release??? = fops_vcodec_release,
>> +???? .poll??????? = v4l2_m2m_fop_poll,
>> +???? .unlocked_ioctl??? = video_ioctl2,
>> +???? .mmap??????? = v4l2_m2m_fop_mmap,
>> +};
>> +
>> +static const struct video_device dec_dev = {
>> +???? .name = "aml_dev_drv",
>> +???? .fops = &aml_vdec_fops,
>> +???? .ioctl_ops = &aml_vdec_ioctl_ops,
>> +???? .release = video_device_release,
>> +???? .vfl_dir = VFL_DIR_M2M,
>> +???? .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
>> +};
>> +
>> +static const struct media_device_ops aml_m2m_media_ops = {
>> +???? .req_validate = vb2_request_validate,
>> +???? .req_queue = v4l2_m2m_request_queue,
>> +};
>> +
>> +static int aml_vdec_drv_probe(struct platform_device *pdev)
>> +{
>> +???? struct aml_vdec_dev *dev;
>> +???? struct video_device *vfd_dec;
>> +???? struct aml_vdec_hw *hw;
>> +???? int ret = 0;
>> +
>> +???? dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
>> +???? if (!dev)
>> +???????????? return -ENOMEM;
>> +
>> +???? dev->plat_dev = pdev;
>> +???? mutex_init(&dev->dev_mutex);
>> +
>> +???? ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
>> +???? if (ret)
>> +???????????? return dev_err_probe(&pdev->dev, ret, 
>> "v4l2_device_register err\n");
>> +
>> +???? vfd_dec = video_device_alloc();
>> +???? if (!vfd_dec) {
>> +???????????? v4l2_err(&dev->v4l2_dev, "Failed to allocate video 
>> device\n");
>> +???????????? ret = -ENOMEM;
>> +???????????? goto err_device_alloc;
>> +???? }
>> +???? *vfd_dec = dec_dev;
>> +???? vfd_dec->v4l2_dev = &dev->v4l2_dev;
>> +???? vfd_dec->lock = &dev->dev_mutex;
>> +???? video_set_drvdata(vfd_dec, dev);
>> +???? dev->vfd = vfd_dec;
>> +???? platform_set_drvdata(pdev, dev);
>> +
>> +???? hw = kzalloc(sizeof(*hw), GFP_KERNEL);
>> +???? if (!hw) {
>> +???????????? ret = -ENOMEM;
>> +???????????? goto err_dec_mem_init;
>> +???? }
>> +???? dev->dec_hw = hw;
>> +
>> +???? dev->pvdec_data = of_device_get_match_data(&pdev->dev);
>> +???? ret = dev->pvdec_data->req_hw_resource(dev);
>> +???? if (ret < 0)
>> +???????????? goto err_hw_init;
>> +
>> +???? dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
>> +???? if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
>> +???????????? v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem dec 
>> device\n");
>> +???????????? ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
>> +???????????? goto err_hw_init;
>> +???? }
>> +
>> +???? ret = video_register_device(vfd_dec, VFL_TYPE_VIDEO, -1);
>> +???? if (ret) {
>> +???????????? v4l2_err(&dev->v4l2_dev, "Failed to register video 
>> device");
>> +???????????? goto err_vid_dev_register;
>> +???? }
>> +
>> +???? v4l2_info(&dev->v4l2_dev, "Registered %s as /dev/%s\n",
>> +?????????????? vfd_dec->name, video_device_node_name(vfd_dec));
>> +
>> +???? dev->mdev.dev = &pdev->dev;
>> +???? strscpy(dev->mdev.model, AML_VDEC_DRV_NAME, 
>> sizeof(dev->mdev.model));
>> +???? media_device_init(&dev->mdev);
>> +???? dev->mdev.ops = &aml_m2m_media_ops;
>> +???? dev->v4l2_dev.mdev = &dev->mdev;
>> +
>> +???? ret = v4l2_m2m_register_media_controller(dev->m2m_dev_dec, 
>> vfd_dec,
>> + MEDIA_ENT_F_PROC_VIDEO_DECODER);
>> +???? if (ret) {
>> +???????????? v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media 
>> controller\n");
>> +???????????? goto error_m2m_mc_register;
>> +???? }
>> +
>> +???? ret = media_device_register(&dev->mdev);
>> +???? if (ret) {
>> +???????????? v4l2_err(&dev->v4l2_dev, "Failed to register media 
>> device");
>> +???????????? goto err_media_dev_register;
>> +???? }
>> +???? vdec_enable(dev->dec_hw);
>> +???? return 0;
>> +
>> +err_media_dev_register:
>> +???? v4l2_m2m_unregister_media_controller(dev->m2m_dev_dec);
>> +error_m2m_mc_register:
>> +???? media_device_cleanup(&dev->mdev);
>> +err_vid_dev_register:
>> +???? v4l2_m2m_release(dev->m2m_dev_dec);
>> +err_hw_init:
>> +???? kfree(hw);
>> +???? dev->dec_hw = NULL;
>> +err_dec_mem_init:
>> +???? video_device_release(vfd_dec);
>> +err_device_alloc:
>> +???? v4l2_device_unregister(&dev->v4l2_dev);
>> +???? return ret;
>> +}
>> +
>> +static void aml_vdec_drv_remove(struct platform_device *pdev)
>> +{
>> +???? struct aml_vdec_dev *dev = platform_get_drvdata(pdev);
>> +
>> +???? vdec_disable(dev->dec_hw);
>> +
>> +???? if (media_devnode_is_registered(dev->mdev.devnode)) {
>> +???????????? media_device_unregister(&dev->mdev);
>> +???????????? media_device_cleanup(&dev->mdev);
>> +???? }
>> +
>> +???? if (dev->m2m_dev_dec)
>> +???????????? v4l2_m2m_release(dev->m2m_dev_dec);
>> +???? if (dev->vfd)
>> +???????????? video_unregister_device(dev->vfd);
>> +???? if (dev->dec_hw)
>> +???????????? dev->pvdec_data->destroy_hw_resource(dev);
>> +
>> +???? v4l2_device_unregister(&dev->v4l2_dev);
>> +
>> +???? pr_debug("aml v4l2 decoder driver remove\n");
>> +}
>> +
>> +static const struct of_device_id aml_vdec_match[] = {
>> +???? {.compatible = "amlogic,s4-vcodec-dec", .data = 
>> &aml_vdec_s4_pdata},
>> +???? {},
>> +};
>> +
>> +static struct platform_driver aml_vcodec_dec_driver = {
>> +???? .probe??? = aml_vdec_drv_probe,
>> +???? .remove??? = aml_vdec_drv_remove,
>> +???? .driver??? = {
>> +???????????? .name??? = AML_VDEC_DRV_NAME,
>
> Use proper formatting here
Could you please give me some examples? Thanks a lot!
>
>> +???????????? .of_match_table = aml_vdec_match,
>> +???? },
>> +};
>> +
>> +static int __init aml_vdec_init(void)
>> +{
>> +???? pr_debug("aml v4l2 decoder module init\n");
>> +
>> +???? if (platform_driver_register(&aml_vcodec_dec_driver)) {
>> +???????????? pr_err("failed to register aml v4l2 decoder\n");
>> +???????????? return -ENODEV;
>> +???? }
>> +
>> +???? return 0;
>> +}
>> +
>> +static void __exit aml_vdec_exit(void)
>> +{
>> +???? pr_debug("aml v4l2 decoder module exit\n");
>> +???? platform_driver_unregister(&aml_vcodec_dec_driver);
>> +}
>> +
>> +module_init(aml_vdec_init);
>> +module_exit(aml_vdec_exit);
>> +
>> +MODULE_DESCRIPTION("Amlogic V4L2 decoder driver");
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h
>> new file mode 100644
>> index 000000000000..f3318cceff3f
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_drv.h
>> @@ -0,0 +1,194 @@
>> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#ifndef _AML_VDEC_DRV_H_
>> +#define _AML_VDEC_DRV_H_
>> +
>> +#include <linux/platform_device.h>
>> +#include <linux/videodev2.h>
>> +#include <linux/clk.h>
>> +
>> +#include <media/v4l2-ctrls.h>
>> +#include <media/v4l2-device.h>
>> +#include <media/v4l2-ioctl.h>
>> +#include <media/v4l2-mem2mem.h>
>> +#include <media/videobuf2-core.h>
>> +#include <media/videobuf2-dma-contig.h>
>> +
>> +#define AML_VCODEC_MAX_PLANES 3
>> +#define AML_VDEC_MIN_W??? 64U
>> +#define AML_VDEC_MIN_H??? 64U
>> +#define AML_VDEC_1080P_MAX_H? 1088U
>> +#define AML_VDEC_1080P_MAX_W? 1920U
>> +
>> +struct aml_vdec_ctx;
>> +/**
>> + * enum aml_fmt_type - Type of format type
>> + */
>> +enum aml_fmt_type {
>> +???? AML_FMT_DEC = 0,
>> +???? AML_FMT_FRAME = 1,
>> +};
>> +
>> +/**
>> + * enum aml_codec_type - Type of codec format
>> + */
>> +enum aml_codec_type {
>> +???? CODEC_TYPE_H264 = 0,
>> +???? CODEC_TYPE_FRAME,
>> +};
>> +
>> +/**
>> + * enum aml_q_type - Type of queue : cap or output
>> + */
>> +enum aml_q_type {
>> +???? AML_Q_DATA_SRC = 0,
>> +???? AML_Q_DATA_DST = 1,
>> +};
>> +
>> +/**
>> + * struct aml_video_fmt - aml video decoder fmt information
>> + * @fourcc: FourCC code of the format. See V4L2_PIX_FMT_*.
>> + * @type: Curr queue type: capture or output.
>> + * @codec_type: Codec mode related. See aml_codec_type.
>> + * @num_planes: Num planes of the format.
>> + * @name: Name of the format.
>> + * @stepwise: Supported range of frame sizes (only for bitstream 
>> formats).
>> + */
>> +struct aml_video_fmt {
>> +???? u32 fourcc;
>> +???? enum aml_fmt_type type;
>> +???? enum aml_codec_type codec_type;
>> +???? u32 num_planes;
>> +???? const u8 *name;
>> +???? struct v4l2_frmsize_stepwise stepwise;
>> +};
>> +
>> +/**
>> + * struct aml_q_data - aml video queue information
>> + * @visible_width: Width for display.
>> + * @visible_height: Height for display.
>> + * @coded_width: Width for decode, which is 64/32 aligned.
>> + * @coded_height: Height for decode, which is 64/32 aligned.
>> + * @filed_flag: Field pic flag.
>> + * @bytesperline: Byte num of each pixel line.
>> + * @sizeimage: Size of frame in bytes.
>> + * @fmt: Format for curr queue. See struct aml_video_fmt.
>> + */
>> +struct aml_q_data {
>> +???? u32 visible_width;
>> +???? u32 visible_height;
>> +???? u32 coded_width;
>> +???? u32 coded_height;
>> +???? u32 filed_flag;
>> +???? u32 bytesperline[AML_VCODEC_MAX_PLANES];
>> +???? u32 sizeimage[AML_VCODEC_MAX_PLANES];
>> +???? struct aml_video_fmt *fmt;
>> +};
>> +
>> +/**
>> + * struct aml_vdec_dev - driver data
>> + * @plat_dev: Platform device for the current driver.
>> + * @v4l2_dev: V4L2 device to register video devices for.
>> + * @m2m_dev_dec: Mem2mem device associated to this device.
>> + * @vfd: Video_device associated to this device.
>> + * @mdev: Media_device associated to this device.
>> + * @dec_ctx: Decoder context. See struct aml_vdec_ctx.
>> + * @dec_hw: Decoder hardware resources. See struct aml_vdec_hw.
>> + * @pvdec_data: Decoder platform data. See struct 
>> aml_dev_platform_data.
>> + * @dev_mutex: video_device lock.
>> + * @filp: v4l2 file handle pointer.
>> + */
>> +struct aml_vdec_dev {
>> +???? struct platform_device *plat_dev;
>> +???? struct v4l2_device v4l2_dev;
>> +???? struct v4l2_m2m_dev *m2m_dev_dec;
>> +???? struct video_device *vfd;
>> +???? struct media_device mdev;
>> +
>> +???? struct aml_vdec_ctx *dec_ctx;
>> +???? struct aml_vdec_hw *dec_hw;
>> +???? const struct aml_dev_platform_data *pvdec_data;
>> +
>> +???? struct mutex dev_mutex;
>> +???? struct file *filp;
>> +};
>> +
>> +/**
>> + * struct dec_pic_info - pic information description
>> + * @colorspace: enum v4l2_colorspace; supplemental to pixelformat
>> + * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
>> + * @xfer_func: enum v4l2_xfer_func, colorspace transfer function
>> + * @quantization: enum v4l2_quantization, colorspace quantization
>> + * @cap_pix_fmt: Pixel format for capture queue.
>> + * @output_pix_fmt: Pixel format for output queue.
>> + * @coded_width: Width for decode.
>> + * @coded_height: Height for decode.
>> + * @fb_size: Frame buffer size for Y or UV.
>> + * @plane_num: Num for planes for curr format.
>> + */
>> +struct dec_pic_info {
>> +???? enum v4l2_colorspace colorspace;
>> +???? enum v4l2_ycbcr_encoding ycbcr_enc;
>> +???? enum v4l2_xfer_func xfer_func;
>> +???? enum v4l2_quantization quantization;
>> +???? u32 cap_pix_fmt;
>> +???? u32 output_pix_fmt;
>> +???? u32 coded_width;
>> +???? u32 coded_height;
>> +???? u32 fb_size[2];
>> +???? u32 plane_num;
>> +};
>> +
>> +/**
>> + * struct aml_vdec_ctx - driver instance context
>> + * @dev: pointer to the aml_vdec_dev of the device.
>> + * @fh: struct v4l2 fh.
>> + * @m2m_ctx: pointer to v4l2_m2m_ctx context.
>> + * @ctrl_handler: V4L2 ctrl handler.
>> + * @v4l2_intf_lock: Mutex lock for v4l2 interface.
>> + * @codec_ops: Codec operation functions. See struct aml_codec_ops.
>> + * @int_cond: Variable used by the waitqueue.
>> + * @queue: Waitqueue to wait for the current decode context finish.
>> + * @q_data: feature supported by the current decoder instance.
>> + * @is_cap_streamon: indicates if the current capture stream is on.
>> + * @is_output_streamon: indicates if the current output stream is on.
>> + * @dos_clk_en: indicates if dos clk is enabled.
>> + * @pic_info: Pic information for curr decoder context. See struct 
>> dec_pic_info.
>> + * @curr_dec_type: Current decoder type. (CODEC_TYPE_H264, etc.)
>> + * @codec_priv: Pointer to current decoder instance.
>> + */
>> +struct aml_vdec_ctx {
>> +???? struct aml_vdec_dev *dev;
>> +???? struct v4l2_fh fh;
>> +???? struct v4l2_m2m_ctx *m2m_ctx;
>> +???? struct v4l2_ctrl_handler ctrl_handler;
>> +???? struct mutex v4l2_intf_lock;
>> +
>> +???? const struct aml_codec_ops *codec_ops;
>> +???? int int_cond;
>> +???? wait_queue_head_t queue;
>> +???? struct aml_q_data q_data[2];
>> +
>> +???? bool is_cap_streamon;
>> +???? bool is_output_streamon;
>> +???? bool dos_clk_en;
>> +
>> +???? struct dec_pic_info pic_info;
>> +???? u32 curr_dec_type;
>> +???? void *codec_priv;
>> +};
>> +
>> +static inline struct aml_vdec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
>> +{
>> +???? return container_of(fh, struct aml_vdec_ctx, fh);
>> +}
>> +
>> +static inline struct aml_vdec_ctx *ctrl_to_dec_ctx(struct 
>> v4l2_ctrl_handler *ctrl)
>> +{
>> +???? return container_of(ctrl, struct aml_vdec_ctx, ctrl_handler);
>> +}
>> +
>> +#endif
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
>> new file mode 100644
>> index 000000000000..4db0e3076761
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.c
>> @@ -0,0 +1,652 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#include <linux/interrupt.h>
>> +#include <linux/irq.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/of_address.h>
>> +#include <linux/slab.h>
>> +#include <linux/firmware.h>
>> +
>> +#include "aml_vdec_drv.h"
>> +#include "aml_vdec_hw.h"
>> +#include "aml_vdec_platform.h"
>> +#include "aml_vdec_canvas_utils.h"
>> +
>> +#define MHz???? (1000000)
>> +#define MC_SIZE (4096 * 16)
>> +
>> +static void __iomem *reg_base[MAX_REG_BUS];
>> +
>> +static struct pm_pd_s vdec_domain_data[] = {
>> +???? [VDEC_1] = {.name = "pwrc-vdec", },
>> +???? [VDEC_HEVC] = {.name = "pwrc-hevc", },
>> +};
>> +
>> +u32 read_dos_reg(u32 addr)
>> +{
>> +???? return readl(reg_base[DOS_BUS] + (addr << 2));
>> +}
>> +
>> +void write_dos_reg(u32 addr, int val)
>> +{
>> +???? writel(val, reg_base[DOS_BUS] + (addr << 2));
>> +}
>> +
>> +u32 read_dmc_reg(u32 addr)
>> +{
>> +???? return readl(reg_base[DMC_BUS] + (addr << 2));
>> +}
>> +
>> +void write_dmc_reg(u32 addr, int val)
>> +{
>> +???? writel(val, reg_base[DMC_BUS] + (addr << 2));
>> +}
>> +
>> +void dos_reg_set_mask(u32 addr, u32 mask)
>> +{
>> +???? u32 r;
>> +
>> +???? r = read_dos_reg(addr);
>> +???? write_dos_reg(addr, (r | mask));
>> +}
>> +
>> +void dos_reg_clear_mask(u32 addr, u32 mask)
>> +{
>> +???? u32 r;
>> +
>> +???? r = read_dos_reg(addr);
>> +???? write_dos_reg(addr, (r & (~mask)));
>> +}
>> +
>> +void dos_reg_write_bits(u32 reg, u32 val, int start, int len)
>> +{
>> +???? u32 to_val = read_dos_reg(reg);
>> +???? u32 mask = (((1L << (len)) - 1) << (start));
>> +
>> +???? to_val &= ~mask;
>> +???? to_val |= (val << start) & mask;
>> +???? write_dos_reg(reg, to_val);
>> +}
>
> Do not reinvent register writting, use regmap for all that.
Ok, I'll use regmap instead of custom register I/O function.
>
>> +
>> +void dos_enable(void)
>> +{
>> +???? WRITE_VREG_BITS(DOS_GCLK_EN0, 0x3ff, 0, 10);
>> +
>> +???? WRITE_VREG(GCLK_EN, 0x3ff);
>> +
>> +???? CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 31));
>> +}
>> +
>> +void aml_vdec_reset_core(void)
>> +{
>> +???? unsigned int mask = 0;
>> +
>> +???? mask = (1 << 21);
>> +
>> +???? write_dmc_reg(0x0, (read_dmc_reg(0x0) & ~mask));
>> +???? usleep_range(60, 70);
>> +???? WRITE_VREG(DOS_SW_RESET0, (1 << 3) | (1 << 4) |
>> +??????????????? (1 << 5) | (1 << 7) | (1 << 8) | (1 << 9));
>> +???? WRITE_VREG(DOS_SW_RESET0, 0);
>> +???? CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
>> +???? CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
>> +???? WRITE_VREG(MDEC_EXTIF_CFG1, 0);
>> +
>> +???? write_dmc_reg(0x0, (read_dmc_reg(0x0) | mask));
>> +}
>> +
>> +void aml_start_vdec_hw(void)
>> +{
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +
>> +???? WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
>> +???? WRITE_VREG(DOS_SW_RESET0, 0);
>> +
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +
>> +???? WRITE_VREG(MPSR, 0x0001);
>
> This is basilly copuy of downstream code, use proper register writing
> functions and stop using downstream macros.
Got it. I'll replace all these function with proper functions.
>
>> +}
>> +
>> +void aml_stop_vdec_hw(void)
>> +{
>> +???? ulong timeout = jiffies + HZ / 10;
>> +
>> +???? WRITE_VREG(MPSR, 0);
>> +???? WRITE_VREG(CPSR, 0);
>> +
>> +???? while (RD_VREG(IMEM_DMA_CTRL) & 0x8000) {
>> +???????????? if (time_after(jiffies, timeout))
>> +???????????????????? break;
>> +???? }
>
> Use read_poll_timeout() or any variant instead of re-inventig polling. 
Ok, I'll fix this.
>> +
>> +???? timeout = jiffies + HZ / 10;
>> +???? while (RD_VREG(LMEM_DMA_CTRL) & 0x8000) {
>> +???????????? if (time_after(jiffies, timeout))
>> +???????????????????? break;
>> +???? }
>> +
>> +???? timeout = jiffies + HZ / 80;
>> +???? while (RD_VREG(WRRSP_LMEM) & 0xfff) {
>> +???????????? if (time_after(jiffies, timeout)) {
>> +???????????????????? pr_err("%s, ctrl %x, rsp %x, pc %x status 
>> %x,%x\n",
>> +??????????????????????????? __func__, RD_VREG(LMEM_DMA_CTRL),
>> +??????????????????????????? RD_VREG(WRRSP_LMEM), RD_VREG(MPC_E),
>> +??????????????????????????? RD_VREG(AV_SCRATCH_J), 
>> RD_VREG(AV_SCRATCH_9));
>> +???????????????????? break;
>> +???????????? }
>> +???? }
>> +
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +
>> +???? WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
>> +???? WRITE_VREG(DOS_SW_RESET0, 0);
>> +
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +???? RD_VREG(DOS_SW_RESET0);
>> +}
>> +
>> +int load_firmware(struct aml_vdec_hw *hw, const char *path)
>> +{
>> +???? const struct firmware *fw;
>> +???? struct device *dev = hw->dev;
>> +???? static u8 *mc_addr;
>> +???? static dma_addr_t mc_addr_map;
>> +???? int fw_head_len;
>> +???? ulong timeout;
>> +???? int ret;
>> +
>> +???? ret = request_firmware(&fw, path, dev);
>> +???? if (ret < 0) {
>> +???????????? pr_info("request_firmware %s failed ret %d\n", path, ret);
>> +???????????? return -EINVAL;
>> +???? }
>> +
>> +???? if (fw->size > MC_SIZE) {
>> +???????????? pr_info("fw %s oversize\n", path);
>> +???????????? ret = -EINVAL;
>> +???????????? goto release_firmware;
>> +???? }
>> +
>> +???? fw_head_len = 512;
>> +???? mc_addr = dma_alloc_coherent(dev, MC_SIZE, &mc_addr_map, 
>> GFP_KERNEL);
>> +???? if (!mc_addr) {
>> +???????????? pr_info("no mem for fw %s\n", path);
>> +???????????? ret = -ENOMEM;
>> +???????????? goto release_firmware;
>> +???? }
>> +???? memset(mc_addr, 0, MC_SIZE);
>> +???? memcpy(mc_addr, ((u8 *)fw->data + fw_head_len),
>> +??????????? (fw->size - fw_head_len));
>> +
>> +???? WRITE_VREG(MPSR, 0);
>> +???? WRITE_VREG(CPSR, 0);
>> +
>> +???? timeout = RD_VREG(MPSR);
>> +???? timeout = RD_VREG(MPSR);
>> +???? timeout = jiffies + HZ;
>> +
>> +???? WRITE_VREG(IMEM_DMA_ADR, mc_addr_map);
>> +???? WRITE_VREG(IMEM_DMA_COUNT, 0x1000);
>> +???? WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
>> +
>> +???? while (RD_VREG(IMEM_DMA_CTRL) & 0x8000) {
>> +???????????? if (time_before(jiffies, timeout)) {
>> +???????????????????? schedule();
>> +???????????? } else {
>> +???????????????????? pr_info("vdec load mc error\n");
>> +???????????????????? ret = -EBUSY;
>> +???????????????????? break;
>> +???????????? }
>> +???? }
>> +
>> +???? /* Only h264 needs this step */
>> +???? if (hw->hw_ops.load_firmware_ex) {
>> +???????????? ret = hw->hw_ops.load_firmware_ex(hw->curr_ctx,
>> +?????????????????????????????????????????????? mc_addr,
>> +?????????????????????????????????????????????? (fw->size - 
>> fw_head_len));
>> +???????????? if (ret < 0) {
>> +???????????????????? ret = -EINVAL;
>> +???????????????????? goto free_dma_mem;
>> +???????????? }
>> +???? }
>> +
>> +free_dma_mem:
>> +???? dma_free_coherent(dev, MC_SIZE, mc_addr, mc_addr_map);
>> +release_firmware:
>> +???? release_firmware(fw);
>> +???? return ret;
>> +}
>> +
>> +static int vdec_clock_gate_init(struct aml_vdec_hw *hw)
>> +{
>> +???? int i;
>> +
>> +???? hw->gates[VDEC].name = "vdec";
>> +???? hw->gates[VDEC_MUX].name = "clk_vdec_mux";
>> +???? hw->gates[HEVCF_MUX].name = "clk_hevcf_mux";
>> +
>> +???? for (i = 0; i < DOS_CLK_MAX; i++) {
>> +???????????? hw->gates[i].clk = devm_clk_get(hw->dev, 
>> hw->gates[i].name);
>> +???????????? hw->gates[i].ref_count = 0;
>> +???????????? mutex_init(&hw->gates[i].mutex);
>> +???? }
>> +
>> +???? return 0;
>> +}
>> +
>> +static int vdec_gate_clk(struct gate_switch_node *gate_node, bool 
>> enable)
>> +{
>> +???? int ret = 0;
>> +
>> +???? mutex_lock(&gate_node->mutex);
>> +???? if (enable) {
>> +???????????? gate_node->ref_count++;
>> +???????????? if (gate_node->ref_count == 1) {
>> +???????????????????? ret = clk_prepare_enable(gate_node->clk);
>> +???????????????????? pr_debug("the %-15s clock on, ref cnt: %d ret = 
>> %d\n",
>> +????????????????????????????? gate_node->name, gate_node->ref_count, 
>> ret);
>> +???????????? }
>> +???? } else {
>> +???????????? gate_node->ref_count--;
>> +???????????? if (!gate_node->ref_count) {
>> +???????????????????? clk_disable_unprepare(gate_node->clk);
>> +???????????????????? pr_debug("the %-15s clock off, ref cnt: %d ret 
>> = %d\n",
>> +????????????????????????????? gate_node->name, gate_node->ref_count, 
>> ret);
>> +???????????? }
>> +???? }
>> +???? mutex_unlock(&gate_node->mutex);
>> +
>> +???? return 0;
>> +}
>> +
>> +static int vdec_switch_gate(struct aml_vdec_hw *hw,
>> +???????????????????????? const char *name, bool enable)
>> +{
>> +???? int i;
>> +
>> +???? for (i = 0; i < DOS_CLK_MAX; i++) {
>> +???????????? if (!strcmp(name, hw->gates[i].name)) {
>> +???????????????????? if (hw->gates[i].clk)
>> + vdec_gate_clk(&hw->gates[i], enable);
>> +???????????????????? else
>> +???????????????????????????? return -ENODEV;
>> +???????????? }
>> +???? }
>> +???? return 0;
>> +}
>> +
>> +static int vdec_set_rate(struct aml_vdec_hw *hw,
>> +????????????????????? const char *name, unsigned long hz)
>> +{
>> +???? int i;
>> +
>> +???? for (i = 0; i < DOS_CLK_MAX; i++) {
>> +???????????? if (!strcmp(name, hw->gates[i].name)) {
>> +???????????????????? if (hw->gates[i].clk && hw->gates[i].ref_count) {
>> +???????????????????????????? clk_set_rate(hw->gates[i].clk, hz);
>> +???????????????????????????? pr_debug("after set, vdec mux clock is 
>> %lu Hz\n",
>> + clk_get_rate(hw->gates[i].clk));
>> +???????????????????? } else {
>> +???????????????????????????? return -ENODEV;
>> +???????????????????? }
>> +???????????? }
>> +???? }
>> +???? return 0;
>> +}
>> +
>> +static void pm_vdec_clock_switch(struct aml_vdec_hw *hw, int id, 
>> bool on)
>> +{
>> +???? int ret = 0;
>> +
>> +???? if (id == VDEC_1) {
>> +???????????? ret = vdec_switch_gate(hw, "clk_vdec_mux", on);
>> +???????????? vdec_set_rate(hw, "clk_vdec_mux", 499999992);
>> +???? } else if (id == VDEC_HEVC) {
>> +???????????? /* enable hevc clock */
>> +???????????? ret = vdec_switch_gate(hw, "clk_hevcf_mux", on);
>> +???????????? if (ret == -ENODEV)
>> +???????????????????? ret = vdec_switch_gate(hw, "clk_hevc_mux", on);
>> +???? }
>> +
>> +???? if (ret < 0)
>> +???????????? pr_debug("clk %d, unreachable ret %d\n", id, ret);
>> +}
>> +
>> +static void pm_vdec_power_switch(struct pm_pd_s *pd, int id, bool on)
>> +{
>> +???? struct device *dev = pd[id].dev;
>> +???? int ret;
>> +
>> +???? if (!dev) {
>> +???????????? pr_debug("no dev %d, maybe always on\n", id);
>> +???????????? return;
>> +???? }
>> +
>> +???? if (on)
>> +???????????? ret = pm_runtime_get_sync(dev);
>> +???? else
>> +???????????? ret = pm_runtime_put_sync(dev);
>> +
>> +???? pr_debug("dev: %p link %p the %-15s power %s ret %d\n",
>> +????????????? dev, pd[id].link, pd[id].name, on ? "on" : "off", ret);
>> +}
>
> Thoses helpers functions are quite overengineered and only used in 2 
> functions,
> just call pm_runtime_XXX, clk_XXX functions directly...
OK, this can be simplified. I'll get rid of it and use pm_runtime_XXX, 
clk_XXX
functions instead.
>
>> +
>> +static int pm_vdec_power_domain_init(struct aml_vdec_hw *hw)
>> +{
>> +???? int i, err;
>> +???? const struct power_manager_s *pm = hw->pm;
>> +???? struct pm_pd_s *pd = pm->pd_data;
>> +
>> +???? mutex_init(&hw->pm_mutex);
>> +
>> +???? for (i = 0; i < VDEC_MAX; i++) {
>> +???????????? pd[i].dev = dev_pm_domain_attach_by_name(hw->dev, 
>> pd[i].name);
>> +???????????? if (IS_ERR_OR_NULL(pd[i].dev)) {
>> +???????????????????? err = PTR_ERR(pd[i].dev);
>> +???????????????????? pr_debug("Get %s failed, pm-domain: %d\n",
>> +????????????????????????????? pd[i].name, err);
>> +???????????????????? continue;
>> +???????????? }
>> +
>> +???????????? pd[i].link = device_link_add(hw->dev, pd[i].dev,
>> +????????????????????????????????????????? DL_FLAG_PM_RUNTIME |
>> +????????????????????????????????????????? DL_FLAG_STATELESS);
>> +???????????? if (IS_ERR_OR_NULL(pd[i].link)) {
>> +???????????????????? pr_err("Adding %s device link failed!\n", 
>> pd[i].name);
>> +???????????????????? return -ENODEV;
>> +???????????? }
>> +
>> +???????????? pr_debug("power domain: name: %s, dev: %p, link: %p\n",
>> +????????????????????? pd[i].name, pd[i].dev, pd[i].link);
>> +???? }
>> +
>> +???? return 0;
>> +}
>> +
>> +static void pm_vdec_power_domain_release(struct aml_vdec_hw *hw)
>> +{
>> +???? int i;
>> +???? const struct power_manager_s *pm = hw->pm;
>> +???? struct pm_pd_s *pd = pm->pd_data;
>> +
>> +???? for (i = 0; i < VDEC_MAX; i++) {
>> +???????????? if (!IS_ERR_OR_NULL(pd[i].link))
>> +???????????????????? device_link_del(pd[i].link);
>> +
>> +???????????? if (!IS_ERR_OR_NULL(pd[i].dev))
>> +???????????????????? dev_pm_domain_detach(pd[i].dev, true);
>> +???? }
>> +}
>> +
>> +static void dos_local_config(bool is_on, int id)
>> +{
>> +???? if (is_on) {
>> +???????????? usleep_range(20, 100);
>> +
>> +???????????? switch (id) {
>> +???????????? case VDEC_1:
>> +???????????????????? WRITE_VREG(DOS_MEM_PD_VDEC, 0);
>> +???????????????????? WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_SW_RESET0, 0);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_MEM_PD_VDEC, 0);
>> +???????????????????? break;
>> +???????????? case VDEC_HEVC:
>> +???????????????????? WRITE_VREG(DOS_MEM_PD_HEVC, 0);
>> +???????????????????? WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_SW_RESET3, 0);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_MEM_PD_HEVC, 0);
>> +???????????????????? break;
>> +???????????? default:
>> +???????????????????? pr_debug("%s on, not found id %d\n", __func__, 
>> id);
>> +???????????????????? break;
>> +???????????? }
>> +???? } else {
>> +???????????? switch (id) {
>> +???????????? case VDEC_1:
>> +???????????????????? WRITE_VREG(DOS_SW_RESET0, 0xfffffffc);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_SW_RESET0, 0);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_MEM_PD_VDEC, 0xffffffffUL);
>> +???????????????????? break;
>> +???????????? case VDEC_HEVC:
>> +???????????????????? WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_SW_RESET3, 0);
>> +???????????????????? usleep_range(20, 100);
>> +???????????????????? WRITE_VREG(DOS_MEM_PD_HEVC, 0xffffffffUL);
>> +???????????????????? break;
>> +???????????? default:
>> +???????????????????? pr_debug("%s off, not found id %d\n", __func__, 
>> id);
>> +???????????????????? break;
>> +???????????? }
>> +???? }
>> +
>> +???? pr_debug("%s end, id %d, is_on %d\n", __func__, id, is_on);
>> +}
>> +
>> +static void pm_vdec_power_domain_power_on(struct aml_vdec_hw *hw, 
>> int id)
>> +{
>> +???? const struct power_manager_s *pm = hw->pm;
>> +
>> +???? pm_vdec_clock_switch(hw, id, true);
>> +???? pm_vdec_power_switch(pm->pd_data, id, true);
>> +
>> +???? dos_local_config(1, id);
>> +}
>> +
>> +static void pm_vdec_power_domain_power_off(struct aml_vdec_hw *hw, 
>> int id)
>> +{
>> +???? const struct power_manager_s *pm = hw->pm;
>> +
>> +???? dos_local_config(0, id);
>> +
>> +???? pm_vdec_clock_switch(hw, id, false);
>> +???? pm_vdec_power_switch(pm->pd_data, id, false);
>> +}
>> +
>> +static bool pm_vdec_power_domain_power_state(struct aml_vdec_hw *hw, 
>> int id)
>> +{
>> +???? if (hw->pm->pd_data[id].dev)
>> +???????????? return pm_runtime_active(hw->pm->pd_data[id].dev);
>> +???? else
>> +???????????? return false;
>> +}
>> +
>> +static void vdec_poweron(struct aml_vdec_hw *hw, enum vdec_type_e core)
>> +{
>> +???? if (core >= VDEC_MAX)
>> +???????????? return;
>> +
>> +???? mutex_lock(&hw->pm_mutex);
>> +???? if (!hw->pm->pd_data[core].dev)
>> +???????????? goto out;
>> +
>> +???? hw->pm->pd_data[core].ref_count++;
>> +???? if (hw->pm->pd_data[core].ref_count > 1)
>> +???????????? goto out;
>> +
>> +???? if (hw->pm->power_state(hw, core))
>> +???????????? goto out;
>> +
>> +???? hw->pm->power_on(hw, core);
>> +
>> +out:
>> +???? mutex_unlock(&hw->pm_mutex);
>> +}
>> +
>> +static void vdec_poweroff(struct aml_vdec_hw *hw, enum vdec_type_e 
>> core)
>> +{
>> +???? if (core >= VDEC_MAX)
>> +???????????? return;
>> +
>> +???? mutex_lock(&hw->pm_mutex);
>> +???? if (hw->pm->pd_data[core].ref_count == 0)
>> +???????????? goto out;
>> +
>> +???? hw->pm->pd_data[core].ref_count--;
>> +???? if (hw->pm->pd_data[core].ref_count > 0)
>> +???????????? goto out;
>> +
>> +???? hw->pm->power_off(hw, core);
>> +
>> +out:
>> +???? mutex_unlock(&hw->pm_mutex);
>> +}
>> +
>> +int vdec_enable(struct aml_vdec_hw *hw)
>> +{
>> +???? vdec_switch_gate(hw, "vdec", 1);
>> +???? vdec_poweron(hw, VDEC_1);
>> +
>> +???? return 0;
>> +}
>> +
>> +int vdec_disable(struct aml_vdec_hw *hw)
>> +{
>> +???? vdec_poweroff(hw, VDEC_1);
>> +???? vdec_switch_gate(hw, "vdec", 0);
>> +
>> +???? return 0;
>> +}
>> +
>> +static const struct power_manager_s pm[] = {
>> +???? [AML_PM_PD] = {
>> +???????????? .pd_data??? = vdec_domain_data,
>> +???????????? .init??????? = pm_vdec_power_domain_init,
>> +???????????? .release??? = pm_vdec_power_domain_release,
>> +???????????? .power_on??? = pm_vdec_power_domain_power_on,
>> +???????????? .power_off??? = pm_vdec_power_domain_power_off,
>> +???????????? .power_state = pm_vdec_power_domain_power_state,
>> +???? },
>> +};
>> +
>> +static irqreturn_t vdec_irq_handler(int irq, void *priv)
>> +{
>> +???? struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
>> +???? struct aml_vdec_hw *hw = dev->dec_hw;
>> +???? irqreturn_t ret;
>> +
>> +???? if (hw->hw_ops.irq_handler)
>> +???????????? ret = hw->hw_ops.irq_handler(irq, priv);
>> +
>> +???? return ret;
>> +}
>> +
>> +static irqreturn_t vdec_threaded_isr_handler(int irq, void *priv)
>> +{
>> +???? struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
>> +???? struct aml_vdec_hw *hw = dev->dec_hw;
>> +???? irqreturn_t ret = IRQ_HANDLED;
>> +
>> +???? if (hw->hw_ops.irq_threaded_func)
>> +???????????? ret = hw->hw_ops.irq_threaded_func(irq, priv);
>> +
>> +???? return ret;
>> +}
>> +
>> +struct aml_vdec_hw *vdec_get_hw(void *priv)
>> +{
>> +???? struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
>> +
>> +???? return dev->dec_hw;
>> +}
>> +
>> +int dev_request_hw_resources(void *priv)
>> +{
>> +???? struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
>> +???? struct aml_vdec_hw *hw;
>> +???? struct platform_device *pdev;
>> +???? struct resource res;
>> +???? u32 res_size;
>> +???? int i;
>> +???? int ret = -1;
>> +
>> +???? if (!dev || !dev->dec_hw) {
>> +???????????? pr_err("%s param invalid\n", __func__);
>> +???????????? return -1;
>> +???? }
>> +???? pdev = dev->plat_dev;
>> +???? hw = dev->dec_hw;
>> +???? hw->dev = &pdev->dev;
>> +
>> +???? hw->dec_irq = platform_get_irq(pdev, VDEC_IRQ_1);
>> +???? if (hw->dec_irq < 0) {
>> +???????????? dev_err(&pdev->dev, "get irq failed\n");
>> +???????????? return hw->dec_irq;
>> +???? }
>> +???? ret = devm_request_threaded_irq(&pdev->dev, hw->dec_irq, 
>> vdec_irq_handler,
>> +???????????????????????????????????? vdec_threaded_isr_handler, 
>> IRQF_ONESHOT,
>> +???????????????????????????????????? "vdec-1", dev);
>> +???? if (ret) {
>> +???????????? dev_err(&pdev->dev, "failed to install irq %d (%d)",
>> +???????????????????? hw->dec_irq, ret);
>> +???????????? return -1;
>> +???? }
>> +
>> +???? for (i = 0; i < MAX_REG_BUS; i++) {
>> +???????????? if (of_address_to_resource(pdev->dev.of_node, i, &res)) {
>> +???????????????????? pr_err("of_address_to_resource %d failed\n", i);
>> +???????????????????? return -EINVAL;
>> +???????????? }
>> +
>> +???????????? res_size = resource_size(&res);
>> +???????????? hw->regs[i] = ioremap(res.start, res_size);
>> +???????????? reg_base[i] = hw->regs[i];
>> +
>> +???????????? pr_debug("%s, res start %llx, end %llx, iomap: %p\n",
>> +????????????????????? __func__, (unsigned long long)res.start,
>> +????????????????????? (unsigned long long)res.end, reg_base[i]);
>> +???? }
>> +
>> +???? hw->pm = &pm[dev->pvdec_data->power_type];
>> +???? if (hw->pm->init) {
>> +???????????? ret = hw->pm->init(hw);
>> +???????????? if (ret < 0) {
>> +???????????????????? pr_err("power mgr init failed!\n");
>> +???????????????????? return ret;
>> +???????????? }
>> +???? }
>> +???? vdec_clock_gate_init(hw);
>> +
>> +???? aml_vdec_canvas_register(hw);
>> +
>> +???? pr_debug("##Amlogic hw resource init OK##\n");
>> +
>> +???? return 0;
>> +}
>> +
>> +void dev_destroy_hw_resources(void *priv)
>> +{
>> +???? struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
>> +???? struct aml_vdec_hw *hw;
>> +
>> +???? if (!dev || !dev->dec_hw) {
>> +???????????? pr_err("%s param invalid\n", __func__);
>> +???????????? return;
>> +???? }
>> +???? hw = dev->dec_hw;
>> +
>> +???? if (hw->pm->release)
>> +???????????? hw->pm->release(hw);
>> +
>> +???? kfree(hw);
>> +???? dev->dec_hw = NULL;
>> +???? pr_debug("##Amlogic hw resource release OK##\n");
>> +}
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h
>> new file mode 100644
>> index 000000000000..ad1e613a2cf8
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_hw.h
>> @@ -0,0 +1,182 @@
>> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#ifndef _AML_VDEC_HW_H_
>> +#define _AML_VDEC_HW_H_
>> +
>> +#include <linux/module.h>
>> +#include <linux/clk.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/of.h>
>> +#include <linux/pm_domain.h>
>> +#include <linux/pm_runtime.h>
>> +#include <linux/delay.h>
>> +#include <linux/regmap.h>
>> +#include <linux/interrupt.h>
>> +#include "reg_defines.h"
>> +
>> +#define VDEC_FIFO_ALIGN???? 8
>> +#define VLD_PADDING_SIZE??? 1024
>> +
>> +#define RD_VREG(addr) read_dos_reg(addr)
>> +#define WRITE_VREG(addr, val) write_dos_reg(addr, val)
>> +#define WRITE_VREG_BITS(r, val, start, len) dos_reg_write_bits(r, 
>> val, start, len)
>> +#define CLEAR_VREG_MASK(r, mask) dos_reg_clear_mask(r, mask)
>> +#define SET_VREG_MASK(r, mask) dos_reg_set_mask(r, mask)
>
>
> Please drop this macros and use the functions directly.
Got it, I'll drop them.
>> +
>> +/**
>> + * struct aml_vdec_hw_ops - codec mode specific operations for hw
>> + * @load_firmware_ex: Load firmware for current dec specific.
>> + * @irq_handler: mandatory call when the ISR triggers
>> + * @irq_threaded_func: mandatory call for the threaded ISR
>> + * @canvas_alloc: Alloc canvas for curr frame
>> + * @canvas_free: Release canvas.
>> + * @config_canvas: Config for curr frame, such as w/h, Y/UV start 
>> addr etc.
>> + */
>> +struct aml_vdec_hw_ops {
>> +???? int (*load_firmware_ex)(void *priv, const u8 *data, u32 len);
>> +???? irqreturn_t (*irq_handler)(int irq, void *priv);
>> +???? irqreturn_t (*irq_threaded_func)(int irq, void *priv);
>> +???? int (*canvas_alloc)(u8 *canvas_index);
>> +???? void (*canvas_free)(u8 canvas_index);
>> +???? void (*config_canvas)(u8 canvas_index,
>> +?????????????????????????? ulong addr, u32 width, u32 height,
>> +?????????????????????????? u32 wrap, u32 blkmode, u32 endian);
>> +};
>> +
>> +/**
>> + * enum vdec_type_e - Type of decoder hardware.
>> + */
>> +enum vdec_type_e {
>> +???? VDEC_1 = 0,
>> +???? VDEC_HEVC,
>> +???? VDEC_MAX,
>> +};
>> +
>> +/**
>> + * enum vdec_irq_num - Definition of the irq.
>> + */
>> +enum vdec_irq_num {
>> +???? VDEC_IRQ_0 = 0,
>> +???? VDEC_IRQ_1,
>> +???? VDEC_IRQ_2,
>> +???? VDEC_IRQ_MAX,
>> +};
>> +
>> +/**
>> + * enum vdec_type_e - Type of decoder clock.
>> + */
>> +enum clk_type_e {
>> +???? VDEC = 0,
>> +???? VDEC_MUX,
>> +???? HEVCF_MUX,
>> +???? DOS_CLK_MAX,
>> +};
>> +
>> +/**
>> + * enum aml_power_type_e - Type of decoder power.
>> + */
>> +enum aml_power_type_e {
>> +???? AML_PM_PD = 0,
>> +};
>> +
>> +/**
>> + * enum mm_bus_e - Type of decoder hardware bus.
>> + */
>> +enum mm_bus_e {
>> +???? DOS_BUS = 0,
>> +???? DMC_BUS,
>> +???? MAX_REG_BUS
>> +};
>> +
>> +/**
>> + * struct gate_switch_node - clock node definition
>> + * @clk: Pointer to clk instance.
>> + * @name: Clock name used.
>> + * @mutex: Mutex lock for multi decoder instance.
>> + * @ref_count: Curr clk instance ref count.
>> + */
>> +struct gate_switch_node {
>> +???? struct clk *clk;
>> +???? const char *name;
>> +???? struct mutex mutex;
>> +???? int ref_count;
>> +};
>> +
>> +/**
>> + * struct pm_pd_s - power domain definition
>> + * @name: Power domain name.
>> + * @dev: Pointer to device structure.
>> + * @mutex: Pointer to device_link structure.
>> + * @ref_count: Curr power domain instance ref count.
>> + */
>> +struct pm_pd_s {
>> +???? u8 *name;
>> +???? struct device *dev;
>> +???? struct device_link *link;
>> +???? int ref_count;
>> +};
>> +
>> +/**
>> + * struct aml_vdec_hw - decoder hardware resources definition
>> + * @pdev: Pointer to struct platform_device.
>> + * @dev: Pointer to struct device.
>> + * @regs: Reg base for dos/dmc hardware.
>> + * @pm_mutex: Mutex for pm->pd_data.
>> + * @pm: Pointer to struct power_manager_s.
>> + * @hw_ops: Hardware resource operation functions. See struct 
>> aml_vdec_hw_ops.
>> + * @gates: Clk instance used by curr decoder context.
>> + * @dec_irq: Irq registered.
>> + * @curr_ctx: Pointer to curr decoder context.
>> + */
>> +struct aml_vdec_hw {
>> +???? struct platform_device *pdev;
>> +???? struct device *dev;
>> +???? void __iomem *regs[MAX_REG_BUS];
>> +???? struct mutex pm_mutex;
>> +???? const struct power_manager_s *pm;
>> +???? struct aml_vdec_hw_ops hw_ops;
>> +???? struct gate_switch_node gates[DOS_CLK_MAX];
>> +???? int dec_irq;
>> +???? void *curr_ctx;
>> +};
>> +
>> +/**
>> + * struct power_manager_s - Power manager & opertion function
>> + * @pd_data: Pointer to struct pm_pd_s
>> + * @init: Power manager init.
>> + * @release: Power manager release.
>> + * @power_on: Power on for decoder hw.
>> + * @power_off: Power off for decoder hw.
>> + * @power_state: Query the power state.
>> + */
>> +struct power_manager_s {
>> +???? struct pm_pd_s *pd_data;
>> +???? int (*init)(struct aml_vdec_hw *hw);
>> +???? void (*release)(struct aml_vdec_hw *hw);
>> +???? void (*power_on)(struct aml_vdec_hw *hw, int id);
>> +???? void (*power_off)(struct aml_vdec_hw *hw, int id);
>> +???? bool (*power_state)(struct aml_vdec_hw *hw, int id);
>> +};
>> +
>> +int dev_request_hw_resources(void *priv);
>> +void dev_destroy_hw_resources(void *priv);
>> +struct aml_vdec_hw *vdec_get_hw(void *priv);
>> +u32 read_dos_reg(u32 reg_addr);
>> +void write_dos_reg(u32 addr, int val);
>> +void dos_reg_write_bits(u32 reg, u32 val, int start, int len);
>> +void dos_reg_clear_mask(u32 addr, u32 mask);
>> +void dos_reg_set_mask(u32 addr, u32 mask);
>> +u32 read_dmc_reg(u32 addr);
>> +void write_dmc_reg(u32 addr, int val);
>> +int vdec_enable(struct aml_vdec_hw *hw);
>> +int vdec_disable(struct aml_vdec_hw *hw);
>> +void dos_enable(void);
>> +void aml_start_vdec_hw(void);
>> +void aml_stop_vdec_hw(void);
>> +int load_firmware(struct aml_vdec_hw *hw, const char *path);
>> +void aml_vdec_reset_core(void);
>> +
>> +#endif
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c
>> new file mode 100644
>> index 000000000000..f1f8ba1f4ff6
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.c
>> @@ -0,0 +1,37 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#include "aml_vdec_platform.h"
>> +#include "aml_vdec_drv.h"
>> +#include "aml_vdec_hw.h"
>> +#include "h264.h"
>> +
>> +#define VIDEO_DEC_H264? "s4_h264_multi.bin"
>> +
>> +const struct aml_codec_ops aml_S4_dec_ops[] = {
>> +???? [CODEC_TYPE_H264] = {
>> +???????????? .init = aml_h264_init,
>> +???????????? .exit = aml_h264_exit,
>> +???????????? .run = aml_h264_dec_run,
>> +???? },
>> +};
>> +
>> +static const struct aml_video_dec_fmt aml_S4_dec_fmts = {
>> +???? .max_height = AML_VDEC_1080P_MAX_H,
>> +???? .max_width = AML_VDEC_1080P_MAX_W,
>> +???? .align = 32,
>> +???? .is_10_bit_support = 0,
>> +};
>> +
>> +const struct aml_dev_platform_data aml_vdec_s4_pdata = {
>> +???? .dec_fmt = &aml_S4_dec_fmts,
>> +???? .codec_ops = aml_S4_dec_ops,
>> +???? .power_type = AML_PM_PD,
>> +???? .req_hw_resource = dev_request_hw_resources,
>> +???? .destroy_hw_resource = dev_destroy_hw_resources,
>> +???? .fw_path = {
>> +???????????? VIDEO_DEC_H264,
>> +???? },
>> +};
>> diff --git a/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h 
>> b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h
>> new file mode 100644
>> index 000000000000..ff0933f6f074
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/aml_vdec_platform.h
>> @@ -0,0 +1,62 @@
>> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#ifndef AML_VDEC_PLATFORM_H_
>> +#define AML_VDEC_PLATFORM_H_
>> +
>> +#include <linux/videodev2.h>
>> +
>> +#define MAX_DEC_FORMAT 3
>> +
>> +/**
>> + * struct aml_codec_ops - codec mode specific operations
>> + * @init: Used for decoder initialization.
>> + * @exit: If needed, can be used to undo the .init phase.
>> + * @run: Start a single decoding job. Called from atomic context.
>> + * Caller should ensure that a pair of buffers is ready and the
>> + * hardware is powered on and clk is enabled. Returns zero if OK,
>> + * a negative value in error cases.
>> + */
>> +struct aml_codec_ops {
>> +???? int (*init)(void *priv);
>> +???? void (*exit)(void *priv);
>> +???? int (*run)(void *priv);
>> +};
>> +
>> +/**
>> + * struct aml_video_dec_fmt - codec format required by platform
>> + * @max_height: Max decode frame height of current platform.
>> + * @max_width: Max decode frame width of current platform.
>> + * @align: Align requirement of the current platform.
>> + * @is_10_bit_support: Whether the platform supports 10 bit.
>> + */
>> +struct aml_video_dec_fmt {
>> +???? u32 max_height;
>> +???? u32 max_width;
>> +???? int align;
>> +???? int is_10_bit_support;
>> +};
>> +
>> +/**
>> + * struct aml_dev_platform_data - compatible data for each chip.
>> + * @dec_fmt: Support dec format.
>> + * @codec_ops: Codec operation function.
>> + * @req_hw_resource: Operation function to request the hardware 
>> resource.
>> + * @destroy_hw_resource: Operation function to release the hardware 
>> resource.
>> + * @power_type: Type of power that the current chip need. See 
>> aml_power_type_e.
>> + * @fw_path: Path of the firmware.bin.
>> + */
>> +struct aml_dev_platform_data {
>> +???? const struct aml_video_dec_fmt *dec_fmt;
>> +???? const struct aml_codec_ops *codec_ops;
>> +???? int (*req_hw_resource)(void *priv);
>> +???? void (*destroy_hw_resource)(void *priv);
>> +???? int power_type;
>> +???? const char *fw_path[MAX_DEC_FORMAT];
>> +};
>> +
>> +extern const struct aml_dev_platform_data aml_vdec_s4_pdata;
>> +
>> +#endif
>> diff --git a/drivers/media/platform/amlogic/vdec/h264.c 
>> b/drivers/media/platform/amlogic/vdec/h264.c
>> new file mode 100644
>> index 000000000000..ebfd10885eaa
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/h264.c
>> @@ -0,0 +1,1790 @@
>> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#include <media/v4l2-h264.h>
>> +#include <linux/vmalloc.h>
>> +#include "aml_vdec.h"
>> +#include "aml_vdec_hw.h"
>> +#include "h264.h"
>> +
>> +#define INVALID_POC 0xffffffff
>> +
>> +#define H264_SLICE_HEADER_DONE?????????????? 0x1
>> +#define H264_SLICE_DATA_DONE???????? 0x2
>> +
>> +#define DECODER_TIMEOUT_MS?????????????????? 500
>> +
>> +#define COL_BUFFER_MARGIN??????????????????? 2
>> +
>> +struct vdec_h264_stateless_ctrl_ref {
>> +???? const struct v4l2_ctrl_h264_decode_params *decode;
>> +???? const struct v4l2_ctrl_h264_scaling_matrix *scaling;
>> +???? const struct v4l2_ctrl_h264_sps *sps;
>> +???? const struct v4l2_ctrl_h264_pps *pps;
>> +};
>> +
>> +enum SliceType {
>> +???? P_SLICE = 0,
>> +???? B_SLICE = 1,
>> +???? I_SLICE = 2,
>> +???? SP_SLICE = 3,
>> +???? SI_SLICE = 4,
>> +???? MAX_SLICE_TYPES = 5
>> +};
>> +
>> +/* Used by firmware */
>> +union param {
>> +???? struct {
>> +???????????? unsigned short data[RPM_END - RPM_BEGIN];
>> +???? } l;
>> +???? struct {
>> +???????????? unsigned short dump[DPB_OFFSET];
>> +???????????? unsigned short dpb_base[FRAME_IN_DPB << 3];
>> +
>> +???????????? unsigned short dpb_max_buffer_frame;
>> +???????????? unsigned short actual_dpb_size;
>> +
>> +???????????? unsigned short colocated_buf_status;
>> +
>> +???????????? unsigned short num_forward_short_term_reference_pic;
>> +???????????? unsigned short num_short_term_reference_pic;
>> +???????????? unsigned short num_reference_pic;
>> +
>> +???????????? unsigned short current_dpb_index;
>> +???????????? unsigned short current_decoded_frame_num;
>> +???????????? unsigned short current_reference_frame_num;
>> +
>> +???????????? unsigned short l0_size;
>> +???????????? unsigned short l1_size;
>> +???????????? /**
>> +????????????? * [6:5] : nal_ref_idc
>> +????????????? * [4:0] : nal_unit_type
>> +????????????? */
>> +???????????? unsigned short NAL_info_mmco;
>> +???????????? /**
>> +????????????? * [1:0] : 00 - top field, 01 - bottom field,
>> +????????????? *???????? 10 - frame, 11 - mbaff frame
>> +????????????? */
>> +???????????? unsigned short picture_structure_mmco;
>> +???????????? unsigned short frame_num;
>> +???????????? unsigned short pic_order_cnt_lsb;
>> +
>> +???????????? unsigned short num_ref_idx_l0_active_minus1;
>> +???????????? unsigned short num_ref_idx_l1_active_minus1;
>> +
>> +???????????? unsigned short PrevPicOrderCntLsb;
>> +???????????? unsigned short PreviousFrameNum;
>> +
>> +???????????? /* 32 bits variables */
>> +???????????? unsigned short delta_pic_order_cnt_bottom[2];
>> +???????????? unsigned short delta_pic_order_cnt_0[2];
>> +???????????? unsigned short delta_pic_order_cnt_1[2];
>> +
>> +???????????? unsigned short PrevPicOrderCntMsb[2];
>> +???????????? unsigned short PrevFrameNumOffset[2];
>> +
>> +???????????? unsigned short frame_pic_order_cnt[2];
>> +???????????? unsigned short top_field_pic_order_cnt[2];
>> +???????????? unsigned short bottom_field_pic_order_cnt[2];
>> +
>> +???????????? unsigned short colocated_mv_addr_start[2];
>> +???????????? unsigned short colocated_mv_addr_end[2];
>> +???????????? unsigned short colocated_mv_wr_addr[2];
>> +???? } dpb;
>> +???? struct {
>> +???????????? unsigned short dump[MMCO_OFFSET];
>> +
>> +???????????? /* array base address for offset_for_ref_frame */
>> +???????????? unsigned short offset_for_ref_frame_base[128];
>> +
>> +???????????? /**
>> +????????????? * 0 - Index in DPB
>> +????????????? * 1 - Picture Flag
>> +????????????? *? [2] : 0 - short term reference,
>> +????????????? *????????????????????? 1 - long term reference
>> +????????????? *? [1] : bottom field
>> +????????????? *? [0] : top field
>> +????????????? * 2 - Picture Number (short term or long term) low 16 
>> bits
>> +????????????? * 3 - Picture Number (short term or long term) high 16 
>> bits
>> +????????????? */
>> +???????????? unsigned short reference_base[128];
>> +
>> +???????????? /* command and parameter, until command is 3 */
>> +???????????? unsigned short l0_reorder_cmd[REORDER_CMD_MAX];
>> +???????????? unsigned short l1_reorder_cmd[REORDER_CMD_MAX];
>> +
>> +???????????? /* command and parameter, until command is 0 */
>> +???????????? unsigned short mmco_cmd[44];
>> +
>> +???????????? unsigned short l0_base[40];
>> +???????????? unsigned short l1_base[40];
>> +???? } mmco;
>> +???? struct {
>> +???????????? /* from ucode lmem, do not change this struct */
>> +???? } p;
>> +};
>> +
>> +struct h264_decode_buf_spec {
>> +???? struct v4l2_h264_dpb_entry *dpb;
>> +???? u32 canvas_pos;
>> +???? u32 dpb_index;
>> +???? u32 poc;
>> +???? int col_buf_index;
>> +???? u8 y_canvas_index;
>> +???? u8 u_canvas_index;
>> +???? u8 v_canvas_index;
>> +???? u8 used;
>> +???? u8 long_term_flag;
>> +???? dma_addr_t y_dma_addr;
>> +???? dma_addr_t c_dma_addr;
>> +};
>> +
>> +#define REORDERING_COMMAND_MAX_SIZE? 33
>> +struct slice {
>> +???? int frame_num;
>> +???? /*modification */
>> +???? int slice_type;
>> +???? int num_ref_idx_l0;
>> +???? int num_ref_idx_l1;
>> +???? int ref_pic_list_reordering_flag[2];
>> +???? int modification_of_pic_nums_idc[2][REORDERING_COMMAND_MAX_SIZE];
>> +???? int abs_diff_pic_num_minus1[2][REORDERING_COMMAND_MAX_SIZE];
>> +???? int long_term_pic_idx[2][REORDERING_COMMAND_MAX_SIZE];
>> +???? unsigned char dec_ref_pic_marking_buffer_valid;
>> +};
>> +
>> +struct aml_h264_ctx {
>> +???? struct aml_vdec_ctx *v4l2_ctx;
>> +???? u8 init_flag;
>> +???? u8 new_pic_flag;
>> +???? u8 mc_cpu_loaded;
>> +???? u8 param_set;
>> +???? u8 colocated_buf_num;
>> +???? u8 reg_iqidct_control_init_flag;
>> +???? u32 reg_iqidct_control;
>> +???? u32 reg_vcop_ctrl_reg;
>> +???? u32 reg_rv_ai_mb_count;
>> +???? u32 vld_dec_control;
>> +???? u32 save_avscratch_f;
>> +???? u32 seq_info;
>> +???? u32 decode_pic_count;
>> +???? union param dpb_param;
>> +???? u32 dec_status;
>> +???? struct slice mslice;
>> +???? struct h264_decode_buf_spec curr_spec;
>> +???? struct h264_decode_buf_spec ref_list0[V4L2_H264_NUM_DPB_ENTRIES 
>> + 1];
>> +???? struct h264_decode_buf_spec ref_list1[V4L2_H264_NUM_DPB_ENTRIES 
>> + 1];
>> +???? struct h264_decode_buf_spec 
>> ref_list0_unreordered[V4L2_H264_NUM_DPB_ENTRIES + 1];
>> +???? struct h264_decode_buf_spec 
>> ref_list1_unreordered[V4L2_H264_NUM_DPB_ENTRIES + 1];
>> +???? u8 list_size[2];
>> +???? dma_addr_t lmem_phy_addr;
>> +???? void *lmem_addr;
>> +???? dma_addr_t mc_cpu_paddr;
>> +???? void *mc_cpu_vaddr;
>> +???? dma_addr_t cma_alloc_addr;
>> +???? void *cma_alloc_vaddr;
>> +???? dma_addr_t collated_cma_addr;
>> +???? dma_addr_t collated_cma_addr_end;
>> +???? void *collated_cma_vaddr;
>> +???? dma_addr_t workspace_offset;
>> +???? void *workspace_vaddr;
>> +???? u32 col_buf_alloc_size;
>> +???? u32 one_col_buf_size;
>> +???? u32 colocated_buf_map;
>> +???? int colocated_buf_poc[32];
>> +
>> +???? u32 frame_width;
>> +???? u32 frame_height;
>> +???? u32 mb_width;
>> +???? u32 mb_height;
>> +???? u32 mb_total;
>> +???? u32 max_num_ref_frames;
>> +
>> +???? struct vdec_h264_stateless_ctrl_ref ctrl_ref;
>> +};
>> +
>> +static inline int get_flag(u32 flag, u32 mask)
>> +{
>> +???? return (flag & mask) ? 1 : 0;
>> +}
>> +
>> +static inline void write_lmem(unsigned short *base, u32 offset, u32 
>> value)
>> +{
>> +???? base[offset] = value;
>> +}
>> +
>> +static inline uint32_t spec2canvas(struct h264_decode_buf_spec 
>> *buf_spec)
>> +{
>> +???? return (buf_spec->v_canvas_index << 16) |
>> +???????????? (buf_spec->u_canvas_index << 8) |
>> +???????????? (buf_spec->y_canvas_index << 0);
>> +}
>> +
>> +static struct h264_decode_buf_spec *find_spec_by_dpb_index(struct 
>> aml_h264_ctx *h264_ctx, int index)
>> +{
>> +???? int i;
>> +
>> +???? for (i = 0; i < h264_ctx->list_size[0]; i++) {
>> +???????????? if (index == h264_ctx->ref_list0[i].dpb_index)
>> +???????????????????? return &h264_ctx->ref_list0[i];
>> +???? }
>> +
>> +???? for (i = 0; i < h264_ctx->list_size[1]; i++) {
>> +???????????? if (index == h264_ctx->ref_list1[i].dpb_index)
>> +???????????????????? return &h264_ctx->ref_list1[i];
>> +???? }
>> +???? return NULL;
>> +}
>> +
>> +static int h264_prepare_input(struct aml_vdec_ctx *ctx)
>> +{
>> +???? struct vb2_v4l2_buffer *src;
>> +???? struct vb2_buffer *vb;
>> +???? dma_addr_t src_dma;
>> +???? u32 payload_size;
>> +???? int dummy;
>> +
>> +???? src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
>> +???? if (!src) {
>> +???????????? pr_info("no input buffer available!\n");
>> +???????????? return -1;
>> +???? }
>> +???? vb = &src->vb2_buf;
>> +???? payload_size = vb2_get_plane_payload(vb, 0);
>> +???? src_dma = vb2_dma_contig_plane_dma_addr(vb, 0);
>> +
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
>> +???? /* reset VLD fifo for all vdec */
>> +???? WRITE_VREG(DOS_SW_RESET0, (1 << 5) | (1 << 4) | (1 << 3));
>> +???? WRITE_VREG(DOS_SW_RESET0, 0);
>> +???? WRITE_VREG(POWER_CTL_VLD, 1 << 4);
>> +
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_START_PTR, src_dma);
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_END_PTR, (src_dma + payload_size));
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_CURR_PTR,
>> +??????????????? round_down(src_dma, VDEC_FIFO_ALIGN));
>> +
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 1);
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_CONTROL, 0);
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
>> +
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_RP,
>> +??????????????? round_down(src_dma, VDEC_FIFO_ALIGN));
>> +???? dummy = payload_size + VLD_PADDING_SIZE;
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_WP,
>> +??????????????? round_down((src_dma + dummy), VDEC_FIFO_ALIGN));
>> +
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 3);
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, 2);
>> +
>> +???? WRITE_VREG(VLD_MEM_VIFIFO_CONTROL,
>> +??????????????? (0x11 << 16) | (1 << 10) | (7 << 3));
>> +
>> +???? WRITE_VREG(AV_SCRATCH_1, 0x0);
>> +???? WRITE_VREG(H264_DECODE_INFO, (1 << 13));
>> +???? WRITE_VREG(H264_DECODE_SIZE, payload_size);
>> +???? WRITE_VREG(VIFF_BIT_CNT, payload_size * 8);
>> +
>> +???? return 0;
>> +}
>> +
>> +static void config_sps_params(struct aml_h264_ctx *h264_ctx,
>> +?????????????????????????? unsigned short *sps_base,
>> +?????????????????????????? const struct v4l2_ctrl_h264_sps *sps)
>> +{
>> +???? u32 cfg_tmp = 0;
>> +???? u32 frame_size;
>> +???? u32 offset = 0;
>> +???? unsigned short data_tmp[0x100];
>> +???? int i, ii;
>> +
>> +???? memset(sps_base, 0, 0x100);
>> +
>> +???? h264_ctx->frame_width = (sps->pic_width_in_mbs_minus1 + 1) << 4;
>> +???? h264_ctx->frame_height = (sps->pic_height_in_map_units_minus1 + 
>> 1) << 4;
>> +
>> +???? data_tmp[offset] = PARAM_BASE_VAL;
>> +???? offset += 2;
>> +
>> +???? data_tmp[offset++] = GET_SPS_PROFILE_IDC(sps->profile_idc);
>> +
>> +???? data_tmp[offset++] = 
>> GET_SPS_SEQ_PARAM_SET_ID(sps->seq_parameter_set_id) |
>> +???????? GET_SPS_LEVEL_IDC(sps->level_idc);
>> +
>> +???? if (sps->profile_idc >= 100) {
>> +???????????? data_tmp[offset++] = 
>> GET_SPS_CHROMA_FORMAT_IDC(sps->chroma_format_idc);
>> +
>> +???????????? data_tmp[offset++] = ((sps->chroma_format_idc ^ 1) << 1);
>> +???? }
>> +
>> +???? data_tmp[offset++] = 
>> GET_SPS_LOG2_MAX_FRAME_NUM(sps->log2_max_frame_num_minus4);
>> +???? data_tmp[offset++] = 
>> GET_SPS_PIC_ORDER_TYPE(sps->pic_order_cnt_type);
>> +
>> +???? if (sps->pic_order_cnt_type == 0) {
>> +???????????? data_tmp[offset++] =
>> + GET_SPS_PIC_ORDER_CNT_LSB(sps->log2_max_pic_order_cnt_lsb_minus4);
>> +???? } else if (sps->pic_order_cnt_type == 1) {
>> +???????????? data_tmp[offset++] =
>> +???????????????????? get_flag(sps->flags,
>> + V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO);
>> +???????????? data_tmp[offset++] =
>> + GET_SPS_OFFSET_FOR_NONREF_PIC_LOW(sps->offset_for_non_ref_pic);
>> +???????????? data_tmp[offset++] =
>> + GET_SPS_OFFSET_FOR_NONREF_PIC_HIGH(sps->offset_for_non_ref_pic);
>> +???????????? data_tmp[offset++] =
>> + 
>> GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_LOW(sps->offset_for_top_to_bottom_field);
>> +???????????? data_tmp[offset++] =
>> + 
>> GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_HIGH(sps->offset_for_top_to_bottom_field);
>> +???????????? data_tmp[offset++] = 
>> sps->num_ref_frames_in_pic_order_cnt_cycle;
>> +???? }
>> +
>> +???? data_tmp[offset++] = 
>> GET_SPS_NUM_REF_FRAMES(sps->max_num_ref_frames) |
>> +???????? GET_SPS_GAPS_ALLOWED_FLAG(get_flag(sps->flags,
>> + V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED));
>> +
>> +???? data_tmp[offset++] = 
>> GET_SPS_PIC_WIDTH_IN_MBS(sps->pic_width_in_mbs_minus1);
>> +
>> +???? data_tmp[offset++] = 
>> GET_SPS_PIC_HEIGHT_IN_MBS(sps->pic_height_in_map_units_minus1);
>> +???? data_tmp[offset++] =
>> +???????????? GET_SPS_DIRECT_8X8_FLAGS
>> +???????????????????????????? (get_flag(sps->flags,
>> + V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)) |
>> +???????????? GET_SPS_MB_ADAPTIVE_FRAME_FIELD_FLAGS
>> +???????????????????????????? (get_flag(sps->flags,
>> + V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) |
>> +???????????? GET_SPS_FRAME_MBS_ONLY_FLAGS
>> +???????????????????????????? (get_flag(sps->flags,
>> + V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY));
>> +
>> +???? for (i = 0; i < 0x100; i += 4) {
>> +???????????? for (ii = 0; ii < 4; ii++)
>> +???????????????????? sps_base[i + 3 - ii] = data_tmp[i + ii];
>> +???? }
>> +
>> +???? frame_size = (sps->pic_width_in_mbs_minus1 + 1) * 
>> (sps->pic_height_in_map_units_minus1 + 1);
>> +???? cfg_tmp = (get_flag(sps->flags, 
>> V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) << 31) |
>> +???????????????????????????? (sps->max_num_ref_frames << 24) | 
>> (frame_size << 8) |
>> +???????????????????????????? (sps->pic_width_in_mbs_minus1 + 1);
>> +???? WRITE_VREG(AV_SCRATCH_1, cfg_tmp);
>> +???? h264_ctx->seq_info = cfg_tmp;
>> +
>> +???? cfg_tmp = 0;
>> +???? cfg_tmp = (get_flag(sps->flags, 
>> V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE) << 15) |
>> +???????????????????????????? (sps->chroma_format_idc);
>> +???? WRITE_VREG(AV_SCRATCH_2, cfg_tmp);
>> +
>> +???? cfg_tmp = 0;
>> +???? cfg_tmp = (sps->max_num_ref_frames << 8) | (sps->level_idc);
>> +???? WRITE_VREG(AV_SCRATCH_B, cfg_tmp);
>> +
>> +???? cfg_tmp = ((sps->level_idc & 0xff) << 7) |
>> +???????? (get_flag(sps->flags, V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) << 
>> 2);
>> +???? WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) | cfg_tmp);
>> +
>> +???? h264_ctx->mb_width = (sps->pic_width_in_mbs_minus1 + 4) & 
>> 0xfffffffc;
>> +???? h264_ctx->mb_height = (sps->pic_height_in_map_units_minus1 + 4) 
>> & 0xfffffffc;
>> +???? h264_ctx->mb_total = h264_ctx->mb_width * h264_ctx->mb_height;
>> +???? h264_ctx->max_num_ref_frames = sps->max_num_ref_frames;
>> +}
>> +
>> +static void config_pps_params(struct aml_h264_ctx *h264_ctx,
>> +?????????????????????????? unsigned short *pps_base,
>> +?????????????????????????? const struct v4l2_ctrl_h264_pps *pps)
>> +{
>> +???? u32 offset = 0;
>> +???? unsigned short data_tmp[0x100];
>> +???? u32 max_reference_size = V4L2_H264_NUM_DPB_ENTRIES;
>> +???? u32 max_list_size;
>> +???? int i, ii;
>> +
>> +???? memset(pps_base, 0, 0x100);
>> +
>> +???? data_tmp[offset++] = PARAM_BASE_VAL;
>> +
>> +???? data_tmp[offset++] =
>> + GET_PPS_PIC_PARAM_SET_ID(pps->pic_parameter_set_id) |
>> +???????? GET_PPS_SEQ_PARAM_SET_ID(pps->seq_parameter_set_id) |
>> +???????? GET_PPS_ENTROPY_CODING_MODE_FLAG
>> +???????????????????? (get_flag(pps->flags,
>> + V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)) |
>> +???????? GET_PPS_PIC_ORDER_PRESENT_FLAG
>> +???????????????????? (get_flag(pps->flags,
>> + V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT));
>> +
>> +???? data_tmp[offset++] =
>> + GET_PPS_WEIGHTED_BIPRED_IDC(pps->weighted_bipred_idc) |
>> +???????????? GET_PPS_WEIGHTED_PRED_FLAG(get_flag(pps->flags,
>> + V4L2_H264_PPS_FLAG_WEIGHTED_PRED)) |
>> + 
>> GET_PPS_NUM_IDX_REF_L1_MINUS1(pps->num_ref_idx_l1_default_active_minus1) 
>> |
>> + 
>> GET_PPS_NUM_IDX_REF_L0_MINUS1(pps->num_ref_idx_l0_default_active_minus1);
>> +
>> +???? data_tmp[offset++] = 
>> GET_PPS_INIT_QS_MINUS26(pps->pic_init_qs_minus26) |
>> +???????? GET_PPS_INIT_QP_MINUS26(pps->pic_init_qp_minus26);
>> +
>> +???? data_tmp[offset] =
>> + GET_PPS_CHROMA_QP_INDEX_OFFSET(pps->chroma_qp_index_offset) |
>> +???????? GET_PPS_DEBLOCK_FILTER_CTRL_PRESENT_FLAG
>> +???????????????????????????? (get_flag(pps->flags,
>> + V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)) |
>> +???????? GET_PPS_CONSTRAIN_INTRA_PRED_FLAG
>> +???????????????????????????? (get_flag(pps->flags,
>> + V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)) |
>> +???????? GET_PPS_REDUNDANT_PIC_CNT_PRESENT_FLAG
>> +???????????????????????????? (get_flag(pps->flags,
>> + V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT));
>> +???? if (get_flag
>> +???????? (pps->flags,
>> +????????? V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE |
>> +????????? V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
>> +???????????? data_tmp[offset] |= (1 << 11);
>> +???? offset++;
>> +
>> +???? data_tmp[offset++] =
>> +???????? GET_PPS_SCALING_MATRIX_PRESENT_FLAG(get_flag
>> +???????????????????????????????????????????? (pps->flags,
>> + V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)) |
>> +???????? GET_PPS_TRANSFORM_8X8_FLAG(get_flag
>> +??????????????????????????????????? (pps->flags,
>> + V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE));
>> +
>> +???? data_tmp[offset++] =
>> + 
>> GET_PPS_GET_SECOND_CHROMA_QP_OFFSET(pps->second_chroma_qp_index_offset);
>> +
>> +???? max_list_size = (pps->num_ref_idx_l1_default_active_minus1 + 1) +
>> +???????? (pps->num_ref_idx_l0_default_active_minus1 + 1);
>> +
>> +???? h264_ctx->max_num_ref_frames = max_list_size > 
>> h264_ctx->max_num_ref_frames ?
>> +???????????????????????????????????????????? max_list_size : 
>> h264_ctx->max_num_ref_frames;
>> +
>> +???? WRITE_VREG(AV_SCRATCH_0, ((h264_ctx->max_num_ref_frames + 1) << 
>> 24) |
>> +??????????????? (max_reference_size << 16) | (max_reference_size << 
>> 8));
>> +
>> +???? for (i = 0; i < 0x100; i += 4) {
>> +???????????? for (ii = 0; ii < 4; ii++)
>> +???????????????????? pps_base[i + 3 - ii] = data_tmp[i + ii];
>> +???? }
>> +}
>> +
>> +static void h264_config_params(struct aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)ctx->codec_priv;
>> +???? unsigned short *p_sps_base, *p_pps_base;
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +???? const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
>> +???? const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
>> +
>> +???? p_sps_base = (unsigned short *)(h264_ctx->workspace_vaddr +
>> +???????????? MEM_SPS_BASE + sps->seq_parameter_set_id * 0x400);
>> +???? p_pps_base = (unsigned short *)(h264_ctx->workspace_vaddr +
>> +???????????? MEM_PPS_BASE + pps->pic_parameter_set_id * 0x200);
>> +
>> +???? config_sps_params(h264_ctx, p_sps_base, sps);
>> +???? config_pps_params(h264_ctx, p_pps_base, pps);
>> +}
>> +
>> +static void config_decode_canvas(struct aml_vdec_hw *hw,
>> +????????????????????????????? struct h264_decode_buf_spec *buf_spec,
>> +????????????????????????????? u32 mb_width, u32 mb_height)
>> +{
>> +???? int canvas_alloc_result = 0;
>> +???? int blkmode = 0x0;
>> +
>> +???? canvas_alloc_result = 
>> hw->hw_ops.canvas_alloc(&buf_spec->y_canvas_index);
>> +???? canvas_alloc_result = 
>> hw->hw_ops.canvas_alloc(&buf_spec->u_canvas_index);
>> +???? buf_spec->v_canvas_index = buf_spec->u_canvas_index;
>> +
>> +???? if (!canvas_alloc_result) {
>> +???????????? /* config y canvas */
>> + hw->hw_ops.config_canvas(buf_spec->y_canvas_index,
>> +????????????????????????????????????? buf_spec->y_dma_addr, mb_width 
>> << 4,
>> +????????????????????????????????????? mb_height << 4, 0, blkmode, 7);
>> +???????????? WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, (1 << 11) |??????? 
>> /* canvas_blk32_wr */
>> +??????????????????????? (blkmode << 10) |??? /* canvas_blk32 */
>> +??????????????????????? (1 << 8) |?? /* canvas_index_wr */
>> +??????????????????????? (buf_spec->y_canvas_index << 0)????? /* 
>> canvas index */
>> +???????????????? );
>> +
>> +???????????? /* config uv canvas */
>> + hw->hw_ops.config_canvas(buf_spec->u_canvas_index,
>> +????????????????????????????????????? buf_spec->c_dma_addr, mb_width 
>> << 4,
>> +????????????????????????????????????? mb_height << 3, 0, blkmode, 7);
>> +???????????? WRITE_VREG(VDEC_ASSIST_CANVAS_BLK32, (1 << 11) |??????? 
>> /* canvas_blk32_wr */
>> +??????????????????????? (blkmode << 10) |??? /* canvas_blk32 */
>> +??????????????????????? (1 << 8) |?? /* canvas_index_wr */
>> +??????????????????????? (buf_spec->u_canvas_index << 0)????? /* 
>> canvas index */
>> +???????????????? );
>> +
>> +???????????? WRITE_VREG(ANC0_CANVAS_ADDR + buf_spec->canvas_pos,
>> +??????????????????????? spec2canvas(buf_spec));
>> +???? }
>> +}
>> +
>> +static int allocate_colocate_buf(struct aml_h264_ctx *h264_ctx, int 
>> poc)
>> +{
>> +???? int i;
>> +
>> +???? for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
>> +???????????? if (((h264_ctx->colocated_buf_map >> i) & 0x1) == 0) {
>> +???????????????????? h264_ctx->colocated_buf_map |= (1 << i);
>> +???????????????????? break;
>> +???????????? }
>> +???? }
>> +
>> +???? if (i == h264_ctx->colocated_buf_num)
>> +???????????? return -1;
>> +
>> +???? h264_ctx->colocated_buf_poc[i] = poc;
>> +???? pr_debug("%s colocated_buf_index %d poc %d\n", __func__, i,
>> +????????????? h264_ctx->colocated_buf_poc[i]);
>> +
>> +???? return i;
>> +}
>> +
>> +static void release_colocate_buf(struct aml_h264_ctx *h264_ctx, int 
>> index)
>> +{
>> +???? if (index >= 0) {
>> +???????????? if (index >= h264_ctx->colocated_buf_num) {
>> +???????????????????? pr_debug
>> +???????????????????????? ("%s error, index %d is bigger than buf 
>> count %d\n",
>> +????????????????????????? __func__, index, 
>> h264_ctx->max_num_ref_frames);
>> +???????????? } else {
>> +???????????????????? if (((h264_ctx->colocated_buf_map >> index) & 
>> 0x1) == 0x1) {
>> +???????????????????????????? h264_ctx->colocated_buf_map &= (~(1 << 
>> index));
>> +???????????????????????????? pr_debug
>> +???????????????????????????????? ("%s colocated_buf_index %d 
>> released poc %d\n",
>> +????????????????????????????????? __func__, index,
>> + h264_ctx->colocated_buf_poc[index]);
>> +???????????????????? }
>> +???????????????????? h264_ctx->colocated_buf_poc[index] = INVALID_POC;
>> +???????????? }
>> +???? }
>> +}
>> +
>> +static int get_col_buf_index_by_poc(struct aml_h264_ctx *h264_ctx, 
>> int poc)
>> +{
>> +???? int idx;
>> +
>> +???? for (idx = 0; idx < h264_ctx->colocated_buf_num; idx++) {
>> +???????????? if (h264_ctx->colocated_buf_poc[idx] == poc)
>> +???????????????????? break;
>> +???? }
>> +
>> +???? if (idx == h264_ctx->colocated_buf_num)
>> +???????????? idx = -1;
>> +
>> +???? return idx;
>> +}
>> +
>> +static int alloc_colocate_cma(struct aml_h264_ctx *h264_ctx,
>> +?????????????????????????? struct aml_vdec_ctx *ctx)
>> +{
>> +???? int alloc_size = 0;
>> +???? int i;
>> +???? struct aml_vdec_hw *hw;
>> +
>> +???? if (h264_ctx->collated_cma_vaddr)
>> +???????????? return 0;
>> +
>> +???? hw = vdec_get_hw(ctx->dev);
>> +???? if (!hw)
>> +???????????? return -1;
>> +
>> +???? /* 96 :col buf size for each mb */
>> +???? h264_ctx->one_col_buf_size = h264_ctx->mb_total * 96;
>> +???? alloc_size = PAGE_ALIGN(h264_ctx->one_col_buf_size *
>> +???????????????????? (h264_ctx->max_num_ref_frames + 
>> COL_BUFFER_MARGIN));
>> +???? h264_ctx->collated_cma_vaddr = dma_alloc_coherent(hw->dev, 
>> alloc_size,
>> + &h264_ctx->collated_cma_addr, GFP_KERNEL);
>> +???? if (!h264_ctx->collated_cma_vaddr)
>> +???????????? return -ENOMEM;
>> +
>> +???? pr_debug
>> +???????? ("collated_cma_addr = 0x%llx, one_col_buf_size = %x 
>> alloc_size = %x\n",
>> +????????? h264_ctx->collated_cma_addr, h264_ctx->one_col_buf_size,
>> +????????? alloc_size);
>> +???? h264_ctx->collated_cma_addr_end =
>> +???????? h264_ctx->collated_cma_addr + alloc_size;
>> +???? memset(h264_ctx->collated_cma_vaddr, 0, alloc_size);
>> +???? h264_ctx->col_buf_alloc_size = alloc_size;
>> +???? h264_ctx->colocated_buf_map = 0;
>> +???? h264_ctx->colocated_buf_num = h264_ctx->max_num_ref_frames + 
>> COL_BUFFER_MARGIN;
>> +
>> +???? /* 32 : max index of co-locate buffer */
>> +???? for (i = 0; i < 32; i++)
>> +???????????? h264_ctx->colocated_buf_poc[i] = INVALID_POC;
>> +
>> +???? return 0;
>> +}
>> +
>> +static void config_p_reflist(struct aml_h264_ctx *h264_ctx,
>> +????????????????????????? struct v4l2_h264_reference *v4l2_p0_reflist,
>> +????????????????????????? u32 list_size)
>> +{
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +???? struct v4l2_ctrl_h264_decode_params *decode =
>> +???????? (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
>> +???? struct v4l2_h264_dpb_entry *dpb = decode->dpb;
>> +???? u8 index;
>> +???? int i;
>> +
>> +???? for (i = 0; i < list_size; i++) {
>> +???????????? index = v4l2_p0_reflist[i].index;
>> +???????????? h264_ctx->ref_list0[i].used = 1;
>> +???????????? h264_ctx->ref_list0[i].dpb = &dpb[index];
>> +???????????? h264_ctx->ref_list0[i].poc = 
>> dpb[index].top_field_order_cnt;
>> +???????????? h264_ctx->ref_list0[i].long_term_flag =
>> +???????????????? dpb[index].flags & 
>> V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
>> +???????????? h264_ctx->ref_list0[i].dpb_index = index;
>> +???? }
>> +???? h264_ctx->list_size[0] = i;
>> +}
>> +
>> +static void config_b_reflist(struct aml_h264_ctx *h264_ctx,
>> +????????????????????????? struct v4l2_h264_reference *v4l2_b0_reflist,
>> +????????????????????????? struct v4l2_h264_reference *v4l2_b1_reflist,
>> +????????????????????????? u32 list_size)
>> +{
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +???? struct v4l2_ctrl_h264_decode_params *decode =
>> +???????? (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
>> +???? struct v4l2_h264_dpb_entry *dpb = decode->dpb;
>> +???? u8 index;
>> +???? int i, j;
>> +
>> +???? for (i = 0; i < list_size; i++) {
>> +???????????? index = v4l2_b0_reflist[i].index;
>> +???????????? if (dpb[index].top_field_order_cnt > 
>> decode->top_field_order_cnt) {
>> +???????????????????? h264_ctx->list_size[0] = i;
>> +???????????????????? break;
>> +???????????? }
>> +???????????? h264_ctx->ref_list0[i].used = 1;
>> +???????????? h264_ctx->ref_list0[i].dpb = &dpb[index];
>> +???????????? h264_ctx->ref_list0[i].poc = 
>> dpb[index].top_field_order_cnt;
>> +???????????? h264_ctx->ref_list0[i].long_term_flag =
>> +???????????????? dpb[index].flags & 
>> V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
>> +???????????? h264_ctx->ref_list0[i].col_buf_index =
>> +???????????????????? get_col_buf_index_by_poc(h264_ctx, 
>> dpb[index].top_field_order_cnt);
>> +???????????? h264_ctx->ref_list0[i].dpb_index = index;
>> +???? }
>> +
>> +???? for (j = 0; j < list_size; j++) {
>> +???????????? index = v4l2_b1_reflist[j].index;
>> +???????????? if (dpb[index].top_field_order_cnt < 
>> decode->top_field_order_cnt) {
>> +???????????????????? h264_ctx->list_size[1] = j;
>> +???????????????????? break;
>> +???????????? }
>> +???????????? h264_ctx->ref_list1[j].used = 1;
>> +???????????? h264_ctx->ref_list1[j].dpb = &dpb[index];
>> +???????????? h264_ctx->ref_list1[j].poc = 
>> dpb[index].top_field_order_cnt;
>> +???????????? h264_ctx->ref_list1[j].long_term_flag =
>> +???????????????? dpb[index].flags & 
>> V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM ? true : false;
>> +???????????? h264_ctx->ref_list1[j].col_buf_index =
>> +???????????????????? get_col_buf_index_by_poc(h264_ctx, 
>> dpb[index].top_field_order_cnt);
>> +???????????? h264_ctx->ref_list1[j].dpb_index = index;
>> +???? }
>> +
>> +???? if ((h264_ctx->list_size[1] + h264_ctx->list_size[0]) < list_size)
>> +???????????? pr_info("ref list incorrect list0 %d list0 %d 
>> list_size%d\n",
>> +???????????????????? h264_ctx->list_size[0], h264_ctx->list_size[1], 
>> list_size);
>> +}
>> +
>> +static int poc_is_in_dpb(int poc, const struct v4l2_h264_dpb_entry 
>> *dpb)
>> +{
>> +???? int i;
>> +???? int ret = 0;
>> +
>> +???? for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
>> +???????????? if (poc == dpb[i].top_field_order_cnt) {
>> +???????????????????? ret = 1;
>> +???????????????????? pr_debug("%s find poc %d col index %x inDPB\n", 
>> __func__, poc, i);
>> +???????????????????? break;
>> +???????????? }
>> +???? }
>> +
>> +???? return ret;
>> +}
>> +
>> +static int get_ref_list_size(struct aml_h264_ctx *h264_ctx, int 
>> cur_list)
>> +{
>> +???? unsigned short override_flag = 
>> h264_ctx->dpb_param.l.data[REF_IDC_OVERRIDE_FLAG];
>> +???? int num_ref_idx_lx_active_minus1;
>> +
>> +???? if (cur_list == 0) {
>> +???????????? num_ref_idx_lx_active_minus1 =
>> + h264_ctx->ctrl_ref.pps->num_ref_idx_l0_default_active_minus1;
>> +???????????? if (override_flag)
>> +???????????????????? num_ref_idx_lx_active_minus1 =
>> + h264_ctx->dpb_param.dpb.num_ref_idx_l0_active_minus1;
>> +???? } else {
>> +???????????? num_ref_idx_lx_active_minus1 =
>> + h264_ctx->ctrl_ref.pps->num_ref_idx_l1_default_active_minus1;
>> +???? }
>> +???? pr_debug("%s get list %d size %d\n", __func__, cur_list, 
>> num_ref_idx_lx_active_minus1 + 1);
>> +
>> +???? return num_ref_idx_lx_active_minus1 + 1;
>> +}
>> +
>> +static int get_refidx_by_picnum(struct aml_h264_ctx *h264_ctx, int 
>> pic_num,
>> +???????????????????????????? int curr_list)
>> +{
>> +???? int i;
>> +???? struct h264_decode_buf_spec *ref_list;
>> +
>> +???? if (curr_list == 0)
>> +???????????? ref_list = &h264_ctx->ref_list0[0];
>> +???? else
>> +???????????? ref_list = &h264_ctx->ref_list1[0];
>> +
>> +???? for (i = 0; ref_list[i].dpb; i++) {
>> +???????????? if (pic_num == ref_list[i].dpb->pic_num)
>> +???????????????????? return i;
>> +???? }
>> +
>> +???? return -1;
>> +}
>> +
>> +static struct h264_decode_buf_spec *get_st_refpic_by_num(struct 
>> aml_h264_ctx *h264_ctx,
>> +????????????????????????????????????????????????????? int pic_num, 
>> int curr_list)
>> +{
>> +???? int i;
>> +???? struct h264_decode_buf_spec *ref_list;
>> +
>> +???? if (curr_list == 0)
>> +???????????? ref_list = &h264_ctx->ref_list0_unreordered[0];
>> +???? else
>> +???????????? ref_list = &h264_ctx->ref_list1_unreordered[0];
>> +
>> +???? for (i = 0; ref_list[i].dpb; i++) {
>> +???????????? if (pic_num == ref_list[i].dpb->pic_num && 
>> ref_list[i].long_term_flag == 0)
>> +???????????????????? return &ref_list[i];
>> +???? }
>> +
>> +???? return NULL;
>> +}
>> +
>> +static struct h264_decode_buf_spec *get_lt_refpic_by_num(struct 
>> aml_h264_ctx *h264_ctx,
>> +????????????????????????????????????????????????????? int pic_num, 
>> int curr_list)
>> +{
>> +???? int i;
>> +???? struct h264_decode_buf_spec *ref_list;
>> +
>> +???? if (curr_list == 0)
>> +???????????? ref_list = &h264_ctx->ref_list0_unreordered[0];
>> +???? else
>> +???????????? ref_list = &h264_ctx->ref_list1_unreordered[0];
>> +
>> +???? for (i = 0; ref_list[i].dpb; i++) {
>> +???????????? if (pic_num == ref_list[i].dpb->pic_num && 
>> ref_list[i].long_term_flag == 1)
>> +???????????????????? return &ref_list[i];
>> +???? }
>> +
>> +???? return NULL;
>> +}
>> +
>> +static void reorder_short_term(struct slice *curr_slice, int cur_list,
>> +??????????????????????????? int pic_num_lx, int *ref_idx_lx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = container_of(curr_slice, struct 
>> aml_h264_ctx, mslice);
>> +???? int c_idx, n_idx;
>> +???? int num_ref_idx_lx_active;
>> +???? struct h264_decode_buf_spec *pic_lx = NULL;
>> +???? struct h264_decode_buf_spec *ref_list_reordered;
>> +
>> +???? if (cur_list == 0)
>> +???????????? ref_list_reordered = &h264_ctx->ref_list0[0];
>> +???? else
>> +???????????? ref_list_reordered = &h264_ctx->ref_list1[0];
>> +
>> +???? num_ref_idx_lx_active = get_ref_list_size(h264_ctx, cur_list);
>> +
>> +???? /* find short-term ref frame with pic_num is pic_num_lx */
>> +???? pic_lx = get_st_refpic_by_num(h264_ctx, pic_num_lx, cur_list);
>> +???? if (!pic_lx) {
>> +???????????? pr_debug("cannot find st pic_lx for %d\n", pic_num_lx);
>> +???????????? return;
>> +???? }
>> +
>> +???? if (*ref_idx_lx == get_refidx_by_picnum(h264_ctx, pic_num_lx, 
>> cur_list)) {
>> +???????????? pr_debug("no need to move pic lx %d\n", *ref_idx_lx);
>> +???????????? *ref_idx_lx = *ref_idx_lx + 1;
>> +???????????? return;
>> +???? }
>> +
>> +???? for (c_idx = num_ref_idx_lx_active; c_idx > *ref_idx_lx; c_idx--)
>> +???????????? memcpy(&ref_list_reordered[c_idx], 
>> &ref_list_reordered[c_idx - 1],
>> +??????????????????? sizeof(struct h264_decode_buf_spec));
>> +
>> +???? memcpy(&ref_list_reordered[*ref_idx_lx], pic_lx, sizeof(struct 
>> h264_decode_buf_spec));
>> +???? pr_debug("%s 1 : RefPicListX[%d ] = pic %p pic_num(%d)\n", 
>> __func__,
>> +????????????? *ref_idx_lx, pic_lx, 
>> ref_list_reordered[*ref_idx_lx].dpb->pic_num);
>> +???? *ref_idx_lx = *ref_idx_lx + 1;
>> +
>> +???? n_idx = *ref_idx_lx;
>> +???? for (c_idx = *ref_idx_lx; c_idx <= num_ref_idx_lx_active; 
>> c_idx++) {
>> +???????????? if (ref_list_reordered[c_idx].long_term_flag || 
>> !ref_list_reordered[c_idx].dpb ||
>> +???????????????? ref_list_reordered[c_idx].dpb->pic_num != pic_num_lx)
>> +???????????????????? memcpy(&ref_list_reordered[n_idx++], 
>> &ref_list_reordered[c_idx],
>> +??????????????????????????? sizeof(struct h264_decode_buf_spec));
>> +???? }
>> +
>> +???? h264_ctx->list_size[cur_list] = num_ref_idx_lx_active;
>> +}
>> +
>> +static void reorder_long_term(struct slice *curr_slice, int cur_list,
>> +?????????????????????????? int lt_pic_num, int *ref_idx_lx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = container_of(curr_slice, struct 
>> aml_h264_ctx, mslice);
>> +???? int num_ref_idx_lx_active;
>> +???? int c_idx, n_idx;
>> +???? struct h264_decode_buf_spec *ref_list;
>> +???? struct h264_decode_buf_spec *pic_lt = NULL;
>> +
>> +???? if (cur_list == 0)
>> +???????????? ref_list = &h264_ctx->ref_list0[0];
>> +???? else
>> +???????????? ref_list = &h264_ctx->ref_list1[0];
>> +
>> +???? num_ref_idx_lx_active = get_ref_list_size(h264_ctx, cur_list);
>> +
>> +???? /* find long-term ref frame with pic_num is lt_pic_num */
>> +???? pic_lt = get_lt_refpic_by_num(h264_ctx, lt_pic_num, cur_list);
>> +???? if (!pic_lt) {
>> +???????????? pr_debug("cannot find lt pic_lx for %d\n", lt_pic_num);
>> +???????????? return;
>> +???? }
>> +
>> +???? if (*ref_idx_lx == get_refidx_by_picnum(h264_ctx, lt_pic_num, 
>> cur_list)) {
>> +???????????? pr_debug("no need to move pic lx %d\n", *ref_idx_lx);
>> +???????????? *ref_idx_lx = *ref_idx_lx + 1;
>> +???????????? return;
>> +???? }
>> +
>> +???? for (c_idx = num_ref_idx_lx_active; c_idx > *ref_idx_lx; c_idx--)
>> +???????????? memcpy(&ref_list[c_idx], &ref_list[c_idx - 1], 
>> sizeof(struct h264_decode_buf_spec));
>> +
>> +???? memcpy(&ref_list[*ref_idx_lx], pic_lt, sizeof(struct 
>> h264_decode_buf_spec));
>> +???? pr_debug("%s 1 : RefPicListX[%d ] = pic %p pic_num(%d)\n", 
>> __func__,
>> +????????????? *ref_idx_lx, pic_lt, ref_list[*ref_idx_lx].dpb->pic_num);
>> +???? *ref_idx_lx = *ref_idx_lx + 1;
>> +
>> +???? n_idx = *ref_idx_lx;
>> +???? /* Pointer dpb is NULL means this is a dummy frame store */
>> +???? for (c_idx = *ref_idx_lx; c_idx <= num_ref_idx_lx_active; 
>> c_idx++) {
>> +???????????? if (!ref_list[c_idx].long_term_flag || 
>> !ref_list[c_idx].dpb ||
>> +???????????????? ref_list[c_idx].dpb->pic_num != lt_pic_num)
>> +???????????????????? memcpy(&ref_list[n_idx++], &ref_list[c_idx],
>> +??????????????????????????? sizeof(struct h264_decode_buf_spec));
>> +???? }
>> +
>> +???? h264_ctx->list_size[cur_list] = num_ref_idx_lx_active;
>> +}
>> +
>> +static void get_modification_cmd(unsigned short *reorder_cmd, struct 
>> slice *curr_slice, int list)
>> +{
>> +???? int i, j, val;
>> +
>> +???? val = curr_slice->ref_pic_list_reordering_flag[list];
>> +???? if (val) {
>> +???????????? i = 0;
>> +???????????? j = 0;
>> +???????????? do {
>> + curr_slice->modification_of_pic_nums_idc[list][i] =
>> +???????????????????????????? reorder_cmd[j++];
>> +???????????????????? if (j >= REORDER_CMD_MAX) {
>> + curr_slice->modification_of_pic_nums_idc[list][i] = 0;
>> +???????????????????????????? break;
>> +???????????????????? }
>> +
>> +???????????????????? val = 
>> curr_slice->modification_of_pic_nums_idc[list][i];
>> +???????????????????? if (val == 0 || val == 1)
>> + curr_slice->abs_diff_pic_num_minus1[list][i] = reorder_cmd[j++];
>> +???????????????????? else if (val == 2)
>> + curr_slice->long_term_pic_idx[list][i] = reorder_cmd[j++];
>> +
>> +???????????????????? i++;
>> +
>> +???????????????????? if (i >= REORDERING_COMMAND_MAX_SIZE) {
>> + curr_slice->ref_pic_list_reordering_flag[list] = 0;
>> +???????????????????????????? break;
>> +???????????????????? };
>> +???????????????????? if (j > REORDER_CMD_MAX) {
>> + curr_slice->ref_pic_list_reordering_flag[list] = 0;
>> +???????????????????????????? break;
>> +???????????????????? };
>> +???????????? } while (val != 3);
>> +???? }
>> +}
>> +
>> +static void reorder_pics(struct aml_h264_ctx *h264_ctx, struct slice 
>> *curr_slice, int cur_list)
>> +{
>> +???? int *modification_of_pic_nums_idc =
>> + curr_slice->modification_of_pic_nums_idc[cur_list];
>> +???? int *abs_diff_pic_num_minus1 =
>> +???????????? curr_slice->abs_diff_pic_num_minus1[cur_list];
>> +???? int *long_term_pic_idx = curr_slice->long_term_pic_idx[cur_list];
>> +???? int pic_num_lx_nowarp, pic_num_lx_pred, pic_num_lx;
>> +???? int curr_pic_num = curr_slice->frame_num;
>> +???? int max_pic_num = 1 << (4 + 
>> h264_ctx->ctrl_ref.sps->log2_max_frame_num_minus4);
>> +???? int ref_idx_lx = 0;
>> +???? int nowarp_tmp = 0;
>> +???? int i;
>> +
>> +???? pic_num_lx_pred = curr_pic_num;
>> +???? for (i = 0; i < REORDERING_COMMAND_MAX_SIZE && 
>> modification_of_pic_nums_idc[i] != 3; i++) {
>> +???????????? if (modification_of_pic_nums_idc[i] > 3) {
>> +???????????????????? pr_info("error, Invalid 
>> modification_of_pic_nums_idc command\n");
>> +???????????????????? break;
>> +???????????? }
>> +
>> +???????????? if (modification_of_pic_nums_idc[i] < 2) {
>> +???????????????????? if (modification_of_pic_nums_idc[i] == 0) {
>> +???????????????????????????? nowarp_tmp = pic_num_lx_pred - 
>> (abs_diff_pic_num_minus1[i] + 1);
>> +???????????????????????????? pic_num_lx_nowarp = nowarp_tmp + 
>> (nowarp_tmp < 0 ? max_pic_num : 0);
>> +???????????????????? } else if (modification_of_pic_nums_idc[i] == 1) {
>> +???????????????????????????? nowarp_tmp = pic_num_lx_pred + 
>> (abs_diff_pic_num_minus1[i] + 1);
>> +???????????????????????????? pic_num_lx_nowarp = nowarp_tmp -
>> +???????????????????????????????????? (nowarp_tmp > max_pic_num ? 
>> max_pic_num : 0);
>> +???????????????????? }
>> +???????????????????? pic_num_lx_pred = pic_num_lx_nowarp;
>> +???????????????????? if (pic_num_lx_nowarp > curr_pic_num)
>> +???????????????????????????? pic_num_lx = pic_num_lx_nowarp - 
>> max_pic_num;
>> +???????????????????? else
>> +???????????????????????????? pic_num_lx = pic_num_lx_nowarp;
>> +
>> +???????????????????? reorder_short_term(curr_slice, cur_list, 
>> pic_num_lx, &ref_idx_lx);
>> +???????????? } else {
>> +???????????????????? reorder_long_term(curr_slice, cur_list, 
>> long_term_pic_idx[i], &ref_idx_lx);
>> +???????????? }
>> +???? }
>> +}
>> +
>> +static void copy_ref_list(struct aml_h264_ctx *h264_ctx, int curr_list)
>> +{
>> +???? if (curr_list == 0)
>> +???????????? memcpy(h264_ctx->ref_list0_unreordered, 
>> h264_ctx->ref_list0,
>> +??????????????????? sizeof(h264_ctx->ref_list0));
>> +???? else
>> +???????????? memcpy(h264_ctx->ref_list1_unreordered, 
>> h264_ctx->ref_list0,
>> +??????????????????? sizeof(h264_ctx->ref_list1));
>> +}
>> +
>> +static void h264_reorder_reflists(struct aml_h264_ctx *h264_ctx)
>> +{
>> +???? unsigned short *reorder_cmd;
>> +???? struct slice *curr_slice = &h264_ctx->mslice;
>> +
>> +???? memset(curr_slice, 0, sizeof(struct slice));
>> +???? /* parsed by ucode */
>> +???? curr_slice->slice_type = h264_ctx->dpb_param.l.data[SLICE_TYPE];
>> +???? curr_slice->num_ref_idx_l0 = 
>> h264_ctx->dpb_param.dpb.num_ref_idx_l0_active_minus1 + 1;
>> +???? curr_slice->num_ref_idx_l1 = 
>> h264_ctx->dpb_param.dpb.num_ref_idx_l1_active_minus1 + 1;
>> +???? curr_slice->frame_num = h264_ctx->ctrl_ref.decode->frame_num;
>> +
>> +???? if (curr_slice->slice_type != I_SLICE && curr_slice->slice_type 
>> != SI_SLICE) {
>> +???????????? reorder_cmd = &h264_ctx->dpb_param.mmco.l0_reorder_cmd[0];
>> +???????????? /* 3:parsed by ucode, means no reorder needed */
>> +???????????? if (reorder_cmd[0] != 3)
>> + curr_slice->ref_pic_list_reordering_flag[0] = 1;
>> +???????????? else
>> + curr_slice->ref_pic_list_reordering_flag[0] = 0;
>> +
>> +???????????? get_modification_cmd(reorder_cmd, curr_slice, 0);
>> +???? }
>> +
>> +???? if (curr_slice->slice_type == B_SLICE) {
>> +???????????? reorder_cmd = &h264_ctx->dpb_param.mmco.l1_reorder_cmd[0];
>> +???????????? /* 3:parsed by ucode, means no reorder needed */
>> +???????????? if (reorder_cmd[0] != 3)
>> + curr_slice->ref_pic_list_reordering_flag[1] = 1;
>> +???????????? else
>> + curr_slice->ref_pic_list_reordering_flag[1] = 0;
>> +
>> +???????????? get_modification_cmd(reorder_cmd, curr_slice, 1);
>> +???? }
>> +
>> +???? if (curr_slice->slice_type != I_SLICE &&
>> +???????? curr_slice->slice_type != SI_SLICE &&
>> +???????? curr_slice->ref_pic_list_reordering_flag[0] != 0) {
>> +???????????? copy_ref_list(h264_ctx, 0);
>> +???????????? reorder_pics(h264_ctx, curr_slice, 0);
>> +???? }
>> +
>> +???? if (curr_slice->slice_type == B_SLICE && 
>> curr_slice->ref_pic_list_reordering_flag[1] != 0) {
>> +???????????? copy_ref_list(h264_ctx, 1);
>> +???????????? reorder_pics(h264_ctx, curr_slice, 1);
>> +???? }
>> +}
>> +
>> +static void h264_config_ref_lists(struct aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)ctx->codec_priv;
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +???? struct v4l2_ctrl_h264_decode_params *decode =
>> +???????????? (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
>> +???? struct v4l2_ctrl_h264_sps *sps = (struct v4l2_ctrl_h264_sps 
>> *)ctrls->sps;
>> +???? const struct v4l2_h264_dpb_entry *dpb = decode->dpb;
>> +???? struct v4l2_h264_reflist_builder builder;
>> +???? struct v4l2_h264_reference 
>> v4l2_p0_reflist[V4L2_H264_REF_LIST_LEN];
>> +???? struct v4l2_h264_reference 
>> v4l2_b0_reflist[V4L2_H264_REF_LIST_LEN];
>> +???? struct v4l2_h264_reference 
>> v4l2_b1_reflist[V4L2_H264_REF_LIST_LEN];
>> +
>> +???? if (decode->flags == V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC)
>> +???????????? return;
>> +
>> +???? v4l2_h264_init_reflist_builder(&builder, decode, sps, dpb);
>> +???? pr_debug("%s num_valid = %d", __func__, builder.num_valid);
>> +
>> +???? if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_PFRAME) {
>> +???????????? v4l2_h264_build_p_ref_list(&builder, v4l2_p0_reflist);
>> +???????????? config_p_reflist(h264_ctx, v4l2_p0_reflist, 
>> builder.num_valid);
>> +???? } else if (decode->flags & V4L2_H264_DECODE_PARAM_FLAG_BFRAME) {
>> +???????????? v4l2_h264_build_b_ref_lists(&builder, v4l2_b0_reflist, 
>> v4l2_b1_reflist);
>> +???????????? config_b_reflist(h264_ctx, v4l2_b0_reflist, 
>> v4l2_b1_reflist, builder.num_valid);
>> +???? }
>> +}
>> +
>> +static void clear_unused_col_buf(struct aml_h264_ctx *h264_ctx,
>> +????????????????????????????? struct v4l2_ctrl_h264_decode_params 
>> *decode)
>> +{
>> +???? int i, col_poc;
>> +
>> +???? /* flush all col buffers when IDR */
>> +???? if (decode->flags == V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC) {
>> +???????????? /* 32 : max index of co-locate buffer */
>> +???????????? for (i = 0; i < 32; i++)
>> +???????????????????? release_colocate_buf(h264_ctx, i);
>> +???????????? return;
>> +???? }
>> +
>> +???? for (i = 0; i < h264_ctx->colocated_buf_num; i++) {
>> +???????????? col_poc = h264_ctx->colocated_buf_poc[i];
>> +???????????? if (col_poc != INVALID_POC && (poc_is_in_dpb(col_poc, 
>> decode->dpb) != 1))
>> +???????????????????? release_colocate_buf(h264_ctx, i);
>> +???? }
>> +}
>> +
>> +static void h264_config_decode_spec(struct aml_vdec_hw *hw, struct 
>> aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)hw->curr_ctx;
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +???? struct v4l2_ctrl_h264_decode_params *decode =
>> +???????????? (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
>> +???? struct h264_decode_buf_spec *buf_spec;
>> +???? struct vb2_buffer *vb;
>> +???? struct vb2_v4l2_buffer *vb2_v4l2;
>> +???? struct vb2_queue *vq;
>> +???? int i;
>> +
>> +???? clear_unused_col_buf(h264_ctx, decode);
>> +
>> +???? vb2_v4l2 = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
>> +???? vb = &vb2_v4l2->vb2_buf;
>> +
>> +???? h264_ctx->curr_spec.y_dma_addr = 
>> vb2_dma_contig_plane_dma_addr(vb, 0);
>> +???? if (ctx->pic_info.plane_num > 1)
>> +???????????? h264_ctx->curr_spec.c_dma_addr = 
>> vb2_dma_contig_plane_dma_addr(vb, 1);
>> +???? else
>> +???????????? h264_ctx->curr_spec.c_dma_addr =
>> +???????????????????????????? h264_ctx->curr_spec.y_dma_addr + 
>> ctx->pic_info.fb_size[0];
>> +???? h264_ctx->curr_spec.canvas_pos = 0;
>> +???? h264_ctx->curr_spec.col_buf_index =
>> +???????????? allocate_colocate_buf(h264_ctx, 
>> decode->top_field_order_cnt);
>> +???? h264_ctx->curr_spec.poc = decode->top_field_order_cnt;
>> +???? config_decode_canvas(hw, &h264_ctx->curr_spec, 
>> h264_ctx->mb_width, h264_ctx->mb_height);
>> +
>> +???? h264_config_ref_lists(ctx);
>> +
>> +???? vq = v4l2_m2m_get_vq(ctx->m2m_ctx, 
>> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
>> +
>> +???? for (i = 0; i < V4L2_H264_NUM_DPB_ENTRIES; i++) {
>> +???????????? struct v4l2_h264_dpb_entry *dpb = &decode->dpb[i];
>> +
>> +???????????? if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
>> +???????????????????? continue;
>> +
>> +???????????? buf_spec = find_spec_by_dpb_index(h264_ctx, i);
>> +???????????? if (buf_spec) {
>> +???????????????????? buf_spec->canvas_pos = i + 1;
>> +???????????????????? vb = vb2_find_buffer(vq, dpb->reference_ts);
>> +???????????????????? if (!vb) {
>> +???????????????????????????? pr_err("ref pic for ts %llu lost\n", 
>> dpb->reference_ts);
>> +???????????????????????????? continue;
>> +???????????????????? }
>> +
>> +???????????????????? buf_spec->y_dma_addr =
>> +???????????????????????????? vb2_dma_contig_plane_dma_addr(vb, 0);
>> +???????????????????? if (ctx->pic_info.plane_num > 1)
>> +???????????????????????????? buf_spec->c_dma_addr = 
>> vb2_dma_contig_plane_dma_addr(vb, 1);
>> +???????????????????? else
>> +???????????????????????????? buf_spec->c_dma_addr =
>> +???????????????????????????????????? buf_spec->y_dma_addr + 
>> ctx->pic_info.fb_size[0];
>> +???????????????????? config_decode_canvas(hw, buf_spec, 
>> h264_ctx->mb_width, h264_ctx->mb_height);
>> +???????????????????? pr_debug
>> +???????????????????????? ("config canvas for poc %d canvas %d 
>> y_dma_addr 0x%llx\n",
>> + buf_spec->dpb->top_field_order_cnt,
>> +????????????????????????? buf_spec->canvas_pos, buf_spec->y_dma_addr);
>> +???????????? }
>> +???? }
>> +
>> +???? h264_reorder_reflists(h264_ctx);
>> +}
>> +
>> +static int h264_config_decode_buf(struct aml_vdec_hw *hw, struct 
>> aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)hw->curr_ctx;
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +???? struct v4l2_ctrl_h264_decode_params *decode =
>> +???????????? (struct v4l2_ctrl_h264_decode_params *)ctrls->decode;
>> +???? unsigned long canvas_adr;
>> +???? unsigned int ref_cfg;
>> +???? unsigned int ref_cfg_once = 0;
>> +???? unsigned int type_cfg = 0x3; /* 0x3: frame type */
>> +???? unsigned int colocate_adr_offset, colocate_wr_adr;
>> +???? unsigned int info0;
>> +???? unsigned int info1;
>> +???? unsigned int info2;
>> +???? int i, j;
>> +???? int h264_buffer_info_data_write_count;
>> +???? u8 canvas_pos;
>> +???? u8 use_mode_8x8_flag;
>> +
>> +???? WRITE_VREG(H264_CURRENT_POC_IDX_RESET, 0);
>> +???? WRITE_VREG(H264_CURRENT_POC, decode->top_field_order_cnt);
>> +???? WRITE_VREG(H264_CURRENT_POC, decode->top_field_order_cnt);
>> +???? WRITE_VREG(H264_CURRENT_POC, decode->bottom_field_order_cnt);
>> +???? WRITE_VREG(CURR_CANVAS_CTRL, h264_ctx->curr_spec.canvas_pos << 
>> 24);
>> +???? canvas_adr = RD_VREG(CURR_CANVAS_CTRL) & 0xffffff;
>> +???? pr_debug("canvas_pos = %d canvas_adr 0x%lx\n", 
>> h264_ctx->curr_spec.canvas_pos, canvas_adr);
>> +
>> +???? WRITE_VREG(REC_CANVAS_ADDR, canvas_adr);
>> +???? WRITE_VREG(DBKR_CANVAS_ADDR, canvas_adr);
>> +???? WRITE_VREG(DBKW_CANVAS_ADDR, canvas_adr);
>> +
>> +???? WRITE_VREG(H264_BUFFER_INFO_INDEX, 16);
>> +???? info0 = 0xf480;
>> +???? info1 = decode->top_field_order_cnt;
>> +???? info2 = decode->bottom_field_order_cnt;
>> +???? if (decode->bottom_field_order_cnt < decode->top_field_order_cnt)
>> +???????????? info0 |= 0x100;
>> +
>> +???? WRITE_VREG(H264_BUFFER_INFO_DATA, info0 | 0xf);
>> +???? WRITE_VREG(H264_BUFFER_INFO_DATA, info1);
>> +???? WRITE_VREG(H264_BUFFER_INFO_DATA, info2);
>> +
>> +???? for (j = 0; j < V4L2_H264_NUM_DPB_ENTRIES; j++) {
>> +???????????? struct v4l2_h264_dpb_entry *dpb = &decode->dpb[j];
>> +
>> +???????????? info0 = 0;
>> +???????????? info1 = 0;
>> +???????????? info2 = 0;
>> +???????????? if (dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE) {
>> +???????????????????? info0 = 0xf480;
>> +???????????????????? if (decode->bottom_field_order_cnt < 
>> decode->top_field_order_cnt)
>> +???????????????????????????? info0 |= 0x100;
>> +???????????????????? info1 = dpb->top_field_order_cnt;
>> +???????????????????? info2 = dpb->bottom_field_order_cnt;
>> +???????????????????? if (dpb->flags & 
>> V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
>> +???????????????????????????? info0 |= ((1 << 5) | (1 << 4));
>> +???????????? }
>> +???????????? WRITE_VREG(H264_BUFFER_INFO_DATA, info0);
>> +???????????? WRITE_VREG(H264_BUFFER_INFO_DATA, info1);
>> +???????????? WRITE_VREG(H264_BUFFER_INFO_DATA, info2);
>> +???? }
>> +
>> +???? WRITE_VREG(H264_BUFFER_INFO_INDEX, 0);
>> +???? /* when frame width <= 256, Disable DDR_BYTE64_CACHE */
>> +???? if (ctx->pic_info.coded_width <= 256) {
>> +???????????? SET_VREG_MASK(IQIDCT_CONTROL, (1 << 16));
>> +???????????? WRITE_VREG(DCAC_DDR_BYTE64_CTL,
>> +??????????????????????? (RD_VREG(DCAC_DDR_BYTE64_CTL) & (~0xf)) | 0xa);
>> +???? } else {
>> +???????????? CLEAR_VREG_MASK(IQIDCT_CONTROL, (1 << 16));
>> +???? }
>> +
>> +???? ref_cfg = 0;
>> +???? j = 0;
>> +
>> +???? if (h264_ctx->list_size[0] > 0) {
>> +???????????? for (i = 0; i < h264_ctx->list_size[0]; i++) {
>> +???????????????????? canvas_pos = h264_ctx->ref_list0[i].canvas_pos;
>> +???????????????????? /* bit 0:3 canvas_pos bit 5:6 frame struct cfg */
>> +???????????????????? ref_cfg_once = (canvas_pos & 0x1f) | (type_cfg 
>> << 5);
>> +???????????????????? ref_cfg <<= 8;
>> +???????????????????? ref_cfg |= ref_cfg_once;
>> +???????????????????? j++;
>> +
>> +???????????????????? if (j == 4) {
>> +???????????????????????????? WRITE_VREG(H264_BUFFER_INFO_DATA, 
>> ref_cfg);
>> +???????????????????????????? pr_debug("H264_BUFFER_INFO_DATA: %x\n", 
>> ref_cfg);
>> + h264_buffer_info_data_write_count++;
>> +???????????????????????????? j = 0;
>> +???????????????????? }
>> +???????????? }
>> +
>> +???????????? if (j != 0) {
>> +???????????????????? while (j != 4) {
>> +???????????????????????????? ref_cfg <<= 8;
>> +???????????????????????????? ref_cfg |= ref_cfg_once;
>> +???????????????????????????? j++;
>> +???????????????????? }
>> +???????????????????? WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
>> +???????????????????? pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
>> +???????????????????? h264_buffer_info_data_write_count++;
>> +???????????? }
>> +???????????? ref_cfg = (ref_cfg_once << 24) | (ref_cfg_once << 16) |
>> +???????????????????? (ref_cfg_once << 8) | ref_cfg_once;
>> +???????????? for (j = h264_buffer_info_data_write_count; j < 8; j++)
>> +???????????????????? WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
>> +???? }
>> +
>> +???? WRITE_VREG(H264_BUFFER_INFO_INDEX, 8);
>> +???? j = 0;
>> +???? ref_cfg = 0;
>> +
>> +???? if (h264_ctx->list_size[1] > 0) {
>> +???????????? for (i = 0; i < h264_ctx->list_size[1]; i++) {
>> +???????????????????? canvas_pos = h264_ctx->ref_list1[i].canvas_pos;
>> +???????????????????? ref_cfg_once = (canvas_pos & 0x1f) | (type_cfg 
>> << 5);
>> +???????????????????? ref_cfg <<= 8;
>> +???????????????????? ref_cfg |= ref_cfg_once;
>> +???????????????????? j++;
>> +
>> +???????????????????? if (j == 4) {
>> +???????????????????????????? WRITE_VREG(H264_BUFFER_INFO_DATA, 
>> ref_cfg);
>> +???????????????????????????? pr_debug("H264_BUFFER_INFO_DATA: %x\n", 
>> ref_cfg);
>> +???????????????????????????? j = 0;
>> +???????????????????? }
>> +???????????? }
>> +???? }
>> +
>> +???? if (j != 0) {
>> +???????????? while (j != 4) {
>> +???????????????????? ref_cfg <<= 8;
>> +???????????????????? ref_cfg |= ref_cfg_once;
>> +???????????????????? j++;
>> +???????????? }
>> +???????????? pr_debug("H264_BUFFER_INFO_DATA: %x\n", ref_cfg);
>> +???????????? WRITE_VREG(H264_BUFFER_INFO_DATA, ref_cfg);
>> +???? }
>> +
>> +???? if (get_flag(ctrls->sps->flags, 
>> V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY) &&
>> +???????? get_flag(ctrls->sps->flags, 
>> V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE))
>> +???????????? use_mode_8x8_flag = 1;
>> +???? else
>> +???????????? use_mode_8x8_flag = 0;
>> +
>> +???? while ((RD_VREG(H264_CO_MB_RW_CTL) >> 11) & 0x1)
>> +???????????? continue;
>> +
>> +???? /* col buf for curr frame */
>> +???? colocate_adr_offset = 0;
>> +???? if (h264_ctx->curr_spec.col_buf_index >= 0 &&
>> +???????? h264_ctx->curr_spec.col_buf_index < 
>> h264_ctx->colocated_buf_num) {
>> +???????????? colocate_wr_adr = h264_ctx->collated_cma_addr +
>> +???????????????????? ((h264_ctx->one_col_buf_size * 
>> h264_ctx->curr_spec.col_buf_index) >>
>> +???????????????????? (use_mode_8x8_flag ? 2 : 0));
>> +???????????? if (colocate_wr_adr + h264_ctx->one_col_buf_size >
>> +???????????????? h264_ctx->collated_cma_addr_end) {
>> +???????????????????? pr_err
>> +???????????????????????? ("Error, colocate buf is not enough, index 
>> is %d\n",
>> + h264_ctx->curr_spec.col_buf_index);
>> +???????????????????? return -1;
>> +???????????? }
>> +???????????? WRITE_VREG(H264_CO_MB_WR_ADDR,
>> +??????????????????????? (colocate_wr_adr + colocate_adr_offset));
>> +???????????? pr_debug("col buffer addr = 0x%x col_buf_index %d\n",
>> +????????????????????? (colocate_wr_adr + colocate_adr_offset),
>> +????????????????????? h264_ctx->curr_spec.col_buf_index);
>> +???? } else {
>> +???????????? WRITE_VREG(H264_CO_MB_WR_ADDR, 0xffffffff);
>> +???????????? pr_debug("col buffer addr = 0xffffffff\n");
>> +???? }
>> +
>> +???? if (h264_ctx->list_size[1] > 0) {
>> +???????????? struct h264_decode_buf_spec *colocate_pic = 
>> &h264_ctx->ref_list1[0];
>> +???????????? struct h264_decode_buf_spec *curr_pic = 
>> &h264_ctx->curr_spec;
>> +???????????? int l10_structure = 2; /* for pic struct == FRAME, 
>> default to 2 */
>> +???????????? int cur_colocate_ref_type;
>> +???????????? unsigned int colocate_rd_adr;
>> +???????????? unsigned int colocate_rd_adr_offset = 0;
>> +???????????? unsigned int val;
>> +
>> +???????????? cur_colocate_ref_type =
>> +???????????????????? (abs(curr_pic->poc - 
>> colocate_pic->dpb->top_field_order_cnt) <
>> +???????????????????? abs(curr_pic->poc - 
>> colocate_pic->dpb->bottom_field_order_cnt)) ?
>> +???????????????????? 0 : 1;
>> +
>> +???????????? if (colocate_pic->col_buf_index >= 0 &&
>> +???????????????? colocate_pic->col_buf_index < 
>> h264_ctx->colocated_buf_num) {
>> +???????????????????? colocate_rd_adr = h264_ctx->collated_cma_addr +
>> +???????????????????????????? ((h264_ctx->one_col_buf_size * 
>> colocate_pic->col_buf_index) >>
>> +???????????????????????????? (use_mode_8x8_flag ? 2 : 0));
>> +???????????????????? if (colocate_rd_adr + h264_ctx->one_col_buf_size >
>> +???????????????????????? h264_ctx->collated_cma_addr_end) {
>> +???????????????????????????? pr_err
>> +???????????????????????????????? ("Error, colocate rd buf is not 
>> enough, index is %d\n",
>> + colocate_pic->col_buf_index);
>> +???????????????????????????? return -1;
>> +???????????????????? }
>> +???????????????????? val? = ((colocate_rd_adr_offset + 
>> colocate_rd_adr) >> 3) |
>> +???????????????????????????? (cur_colocate_ref_type << 29) |
>> +???????????????????????????? (l10_structure << 30);
>> +???????????????????? WRITE_VREG(H264_CO_MB_RD_ADDR, val);
>> +???????????? } else {
>> +???????????????????? pr_err
>> +???????????????????????? ("Error, reference pic has no colocated buf 
>> poc %d\n",
>> +????????????????????????? curr_pic->poc);
>> +???????????????????? return -1;
>> +???????????? }
>> +???? }
>> +
>> +???? return 0;
>> +}
>> +
>> +static void h264_release_decode_spec(struct aml_vdec_hw *hw, struct 
>> aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)hw->curr_ctx;
>> +???? int i;
>> +???? struct h264_decode_buf_spec *buf;
>> +
>> + hw->hw_ops.canvas_free(h264_ctx->curr_spec.y_canvas_index);
>> + hw->hw_ops.canvas_free(h264_ctx->curr_spec.v_canvas_index);
>> +
>> +???? if (h264_ctx->list_size[0] > 0) {
>> +???????????? for (i = 0; i < h264_ctx->list_size[0]; i++) {
>> +???????????????????? buf = &h264_ctx->ref_list0[i];
>> +???????????????????? if (buf->used) {
>> +???????????????????????????? buf->canvas_pos = 0;
>> +???????????????????????????? buf->dpb = NULL;
>> + hw->hw_ops.canvas_free(buf->y_canvas_index);
>> + hw->hw_ops.canvas_free(buf->u_canvas_index);
>> +???????????????????????????? buf->used = 0;
>> +???????????????????? }
>> +???????????? }
>> +???????????? h264_ctx->list_size[0] = 0;
>> +???? }
>> +
>> +???? if (h264_ctx->list_size[1] > 0) {
>> +???????????? for (i = 0; i < h264_ctx->list_size[1]; i++) {
>> +???????????????????? buf = &h264_ctx->ref_list1[i];
>> +???????????????????? if (buf->used) {
>> +???????????????????????????? buf->canvas_pos = 0;
>> +???????????????????????????? buf->dpb = NULL;
>> + hw->hw_ops.canvas_free(buf->y_canvas_index);
>> + hw->hw_ops.canvas_free(buf->u_canvas_index);
>> +???????????????????????????? buf->used = 0;
>> +???????????????????? }
>> +???????????? }
>> +???????????? h264_ctx->list_size[1] = 0;
>> +???? }
>> +}
>> +
>> +static void save_reg_status(struct aml_h264_ctx *h264_ctx)
>> +{
>> +???? h264_ctx->reg_iqidct_control = RD_VREG(IQIDCT_CONTROL);
>> +???? h264_ctx->reg_iqidct_control_init_flag = 1;
>> +???? h264_ctx->reg_vcop_ctrl_reg = RD_VREG(VCOP_CTRL_REG);
>> +???? h264_ctx->reg_rv_ai_mb_count = RD_VREG(RV_AI_MB_COUNT);
>> +???? h264_ctx->vld_dec_control = RD_VREG(VLD_DECODE_CONTROL);
>> +}
>> +
>> +static irqreturn_t h264_isr(int irq, void *priv)
>> +{
>> +???? WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
>> +
>> +???? return IRQ_WAKE_THREAD;
>> +}
>> +
>> +static irqreturn_t h264_threaded_isr_func(int irq, void *priv)
>> +{
>> +???? int dec_status = RD_VREG(DPB_STATUS_REG);
>> +???? struct aml_vdec_dev *dev = (struct aml_vdec_dev *)priv;
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)dev->dec_hw->curr_ctx;
>> +???? struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)dev->dec_ctx;
>> +???? struct aml_vdec_hw *hw = (struct aml_vdec_hw *)dev->dec_hw;
>> +???? unsigned short *p = (unsigned short *)h264_ctx->lmem_addr;
>> +???? int i, ii;
>> +
>> +???? h264_ctx->dec_status = dec_status;
>> +???? pr_debug
>> +???????? ("%s, dec_status 0x%x VIFF_BIT_CNT 0x%x MBY_MBX 0x%x 
>> VLD_SHIFT_STATUS 0x%x\n",
>> +????????? __func__, dec_status, RD_VREG(VIFF_BIT_CNT), 
>> RD_VREG(MBY_MBX),
>> +????????? RD_VREG(VLD_SHIFT_STATUS));
>> +
>> +???? h264_ctx->save_avscratch_f = RD_VREG(AV_SCRATCH_F);
>> +
>> +???? switch (dec_status) {
>> +???? case H264_SLICE_HEADER_DONE:
>> +???????????? for (i = 0; i < 0x400; i += 4)
>> +???????????????????? for (ii = 0; ii < 4; ii++)
>> +???????????????????????????? h264_ctx->dpb_param.l.data[i + ii] = 
>> p[i + 3 - ii];
>> +???????????? save_reg_status(h264_ctx);
>> +???????????? if (h264_ctx->new_pic_flag == 1)
>> +???????????????????? h264_config_decode_spec(hw, ctx);
>> +
>> +???????????? if (h264_config_decode_buf(hw, ctx) < 0) {
>> +???????????????????? h264_release_decode_spec(hw, ctx);
>> +???????????????????? ctx->int_cond = 1;
>> +???????????????????? wake_up_interruptible(&ctx->queue);
>> +???????????????????? goto irq_handled;
>> +???????????? }
>> +???????????? if (h264_ctx->new_pic_flag == 1) {
>> +???????????????????? WRITE_VREG(DPB_STATUS_REG, 
>> H264_ACTION_DECODE_NEWPIC);
>> +???????????????????? pr_debug("action decode new pic\n");
>> +???????????????????? h264_ctx->new_pic_flag = 0;
>> +???????????? } else {
>> +???????????????????? WRITE_VREG(DPB_STATUS_REG, 
>> H264_ACTION_DECODE_SLICE);
>> +???????????????????? pr_debug("action decode new slice\n");
>> +???????????? }
>> +???????????? break;
>> +???? case H264_SLICE_DATA_DONE:
>> +???????????? h264_release_decode_spec(hw, ctx);
>> +???????????? h264_ctx->decode_pic_count++;
>> +???????????? ctx->int_cond = 1;
>> +???????????? wake_up_interruptible(&ctx->queue);
>> +???????????? break;
>> +???? default:
>> +???????????? h264_release_decode_spec(hw, ctx);
>> +???????????? ctx->int_cond = 1;
>> +???????????? wake_up_interruptible(&ctx->queue);
>> +???????????? break;
>> +???? }
>> +irq_handled:
>> +???? return IRQ_HANDLED;
>> +}
>> +
>> +static int h264_restore_hw_ctx(struct aml_vdec_ctx *ctx)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx =
>> +???????????? (struct aml_h264_ctx *)ctx->codec_priv;
>> +
>> +???? WRITE_VREG(POWER_CTL_VLD,
>> +??????????????? (RD_VREG(POWER_CTL_VLD) | (0 << 10) | (1 << 9) | (1 
>> << 6)));
>> +
>> +???? WRITE_VREG(PSCALE_CTRL, 0);
>> +
>> +???? /* clear mailbox interrupt */
>> +???? WRITE_VREG(VDEC_ASSIST_MBOX1_CLR_REG, 1);
>> +
>> +???? /* enable mailbox interrupt */
>> +???? WRITE_VREG(VDEC_ASSIST_MBOX1_MASK, 1);
>> +
>> +???? SET_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 17));
>> +???? if (ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == 
>> V4L2_PIX_FMT_NV21 ||
>> +???????? ctx->q_data[AML_Q_DATA_DST].fmt->fourcc == V4L2_PIX_FMT_NV21M)
>> +???????????? SET_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 16));
>> +???? else
>> +???????????? CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 16));
>> +
>> +???? SET_VREG_MASK(MDEC_PIC_DC_CTRL, (0xbf << 24));
>> +???? CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (0xbf << 24));
>> +???? CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, (1 << 31));
>> +
>> +???? CLEAR_VREG_MASK(MDEC_PIC_DC_MUX_CTRL, 1 << 31);
>> +???? WRITE_VREG(MDEC_EXTIF_CFG1, 0);
>> +???? WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
>> +
>> +???? WRITE_VREG(DPB_STATUS_REG, 0);
>> +
>> +???? WRITE_VREG(LMEM_DUMP_ADR, h264_ctx->lmem_phy_addr);
>> +???? WRITE_VREG(FRAME_COUNTER_REG, h264_ctx->decode_pic_count);
>> +???? WRITE_VREG(AV_SCRATCH_8, h264_ctx->workspace_offset);
>> +???? WRITE_VREG(AV_SCRATCH_G, h264_ctx->mc_cpu_paddr);
>> +
>> +???? WRITE_VREG(AV_SCRATCH_F, ((h264_ctx->save_avscratch_f & 
>> 0xffffffc3) | (1 << 4)));
>> +???? CLEAR_VREG_MASK(AV_SCRATCH_F, 1 << 6);
>> +
>> +???? WRITE_VREG(MDEC_PIC_DC_THRESH, 0x404038aa);
>> +
>> +???? if (h264_ctx->reg_iqidct_control_init_flag == 0)
>> +???????????? WRITE_VREG(IQIDCT_CONTROL, 0x200);
>> +
>> +???? if (h264_ctx->reg_iqidct_control)
>> +???????????? WRITE_VREG(IQIDCT_CONTROL, h264_ctx->reg_iqidct_control);
>> +
>> +???? if (h264_ctx->reg_vcop_ctrl_reg)
>> +???????????? WRITE_VREG(VCOP_CTRL_REG, h264_ctx->reg_vcop_ctrl_reg);
>> +
>> +???? if (h264_ctx->vld_dec_control)
>> +???????????? WRITE_VREG(VLD_DECODE_CONTROL, h264_ctx->vld_dec_control);
>> +
>> +???? pr_debug
>> +???????? ("IQIDCT_CONTROL = 0x%x, VCOP_CTRL_REG 0x%x 
>> VLD_DECODE_CONTROL 0x%x\n",
>> +????????? RD_VREG(IQIDCT_CONTROL), RD_VREG(VCOP_CTRL_REG),
>> +????????? RD_VREG(VLD_DECODE_CONTROL));
>> +
>> +???? return 0;
>> +}
>> +
>> +static void *aml_h264_get_ctrl(struct v4l2_ctrl_handler *hdl, u32 id)
>> +{
>> +???? struct v4l2_ctrl *ctrl;
>> +
>> +???? ctrl = v4l2_ctrl_find(hdl, id);
>> +???? return ctrl ? ctrl->p_cur.p : NULL;
>> +}
>> +
>> +static int aml_h264_get_stateless_ctrl_ref(struct aml_h264_ctx 
>> *h264_ctx)
>> +{
>> +???? struct aml_vdec_ctx *ctx = h264_ctx->v4l2_ctx;
>> +???? struct vdec_h264_stateless_ctrl_ref *ctrls = &h264_ctx->ctrl_ref;
>> +
>> +???? ctrls->sps =
>> +???????????? (struct v4l2_ctrl_h264_sps 
>> *)aml_h264_get_ctrl(&ctx->ctrl_handler,
>> +???????????????????? V4L2_CID_STATELESS_H264_SPS);
>> +???? if (WARN_ON(!ctrls->sps))
>> +???????????? return -EINVAL;
>> +
>> +???? ctrls->pps =
>> +???????????? (struct v4l2_ctrl_h264_pps 
>> *)aml_h264_get_ctrl(&ctx->ctrl_handler,
>> +???????????????????? V4L2_CID_STATELESS_H264_PPS);
>> +???? if (WARN_ON(!ctrls->pps))
>> +???????????? return -EINVAL;
>> +
>> +???? ctrls->decode =
>> +???????????? (struct v4l2_ctrl_h264_decode_params 
>> *)aml_h264_get_ctrl(&ctx->ctrl_handler,
>> +???????????????????? V4L2_CID_STATELESS_H264_DECODE_PARAMS);
>> +???? if (WARN_ON(!ctrls->decode))
>> +???????????? return -EINVAL;
>> +
>> +???? ctrls->scaling =
>> +???????????? (struct v4l2_ctrl_h264_scaling_matrix 
>> *)aml_h264_get_ctrl(&ctx->ctrl_handler,
>> +???????????????????? V4L2_CID_STATELESS_H264_SCALING_MATRIX);
>> +???? if (WARN_ON(!ctrls->scaling))
>> +???????????? return -EINVAL;
>> +
>> +???? return 0;
>> +}
>> +
>> +static void copy_mc_cpu_fw(void *mc_cpu_addr, const u8 *data)
>> +{
>> +???? /*header */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_HEADER,
>> +??????????? data + 0x4000, MC_SWAP_SIZE);
>> +???? /*data */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_DATA,
>> +??????????? data + 0x2000, MC_SWAP_SIZE);
>> +???? /*mmco */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MMCO,
>> +??????????? data + 0x6000, MC_SWAP_SIZE);
>> +???? /*list */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_LIST,
>> +??????????? data + 0x3000, MC_SWAP_SIZE);
>> +???? /*slice */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_SLICE,
>> +??????????? data + 0x5000, MC_SWAP_SIZE);
>> +???? /*main */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN, data, 0x2000);
>> +???? /*data */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN + 0x2000,
>> +??????????? data + 0x2000, 0x1000);
>> +???? /*slice */
>> +???? memcpy((u8 *)mc_cpu_addr + MC_OFFSET_MAIN + 0x3000,
>> +??????????? data + 0x5000, 0x1000);
>> +}
>> +
>> +static int aml_h264_load_fw_ext(void *priv, const u8 *data, u32 len)
>> +{
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx *)priv;
>> +???? struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx 
>> *)h264_ctx->v4l2_ctx;
>> +???? struct aml_vdec_hw *dec_hw;
>> +
>> +???? if (h264_ctx->mc_cpu_loaded)
>> +???????????? return 0;
>> +
>> +???? dec_hw = vdec_get_hw(ctx->dev);
>> +???? if (!dec_hw)
>> +???????????? return -1;
>> +
>> +???? if (len > MC_TOTAL_SIZE) {
>> +???????????? pr_info("size of mc_cpu_fw id invalid\n");
>> +???????????? return -1;
>> +???? }
>> +
>> +???? h264_ctx->mc_cpu_vaddr = dma_alloc_coherent(dec_hw->dev, 
>> MC_TOTAL_SIZE,
>> + &h264_ctx->mc_cpu_paddr,
>> +???????????????????????????????????????????????? GFP_KERNEL);
>> +???? if (!h264_ctx->mc_cpu_vaddr)
>> +???????????? return -ENOMEM;
>> +
>> +???? copy_mc_cpu_fw(h264_ctx->mc_cpu_vaddr, data);
>> +
>> +???? h264_ctx->mc_cpu_loaded = true;
>> +
>> +???? pr_debug("h264 mccpu fw loaded\n");
>> +
>> +???? return 0;
>> +}
>> +
>> +int aml_h264_init(void *priv)
>> +{
>> +???? struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
>> +???? struct aml_vdec_hw *dec_hw;
>> +???? struct aml_h264_ctx *h264_ctx;
>> +???? int ret = 0;
>> +
>> +???? h264_ctx = kzalloc(sizeof(*h264_ctx), GFP_KERNEL);
>> +???? if (!h264_ctx)
>> +???????????? return -ENOMEM;
>> +
>> +???? h264_ctx->v4l2_ctx = ctx;
>> +???? dec_hw = vdec_get_hw(ctx->dev);
>> +???? if (!dec_hw)
>> +???????????? return -1;
>> +
>> +???? h264_ctx->mc_cpu_loaded = false;
>> +???? dec_hw->hw_ops.irq_handler = h264_isr;
>> +???? dec_hw->hw_ops.irq_threaded_func = h264_threaded_isr_func;
>> +???? dec_hw->hw_ops.load_firmware_ex = aml_h264_load_fw_ext;
>> +
>> +???? h264_ctx->lmem_addr = dma_alloc_coherent(dec_hw->dev, 
>> LMEM_DUMP_SIZE,
>> + &h264_ctx->lmem_phy_addr,
>> +????????????????????????????????????????????? GFP_KERNEL);
>> +???? if (!h264_ctx->lmem_addr) {
>> +???????????? ret = -ENOMEM;
>> +???????????? goto err_alloc_lmem;
>> +???? }
>> +
>> +???? h264_ctx->cma_alloc_vaddr =
>> +???????? dma_alloc_coherent(dec_hw->dev, V_BUF_ADDR_OFFSET,
>> +??????????????????????????? &h264_ctx->cma_alloc_addr, GFP_KERNEL);
>> +???? if (!h264_ctx->cma_alloc_vaddr) {
>> +???????????? ret = -ENOMEM;
>> +???????????? goto err_alloc_workspace;
>> +???? }
>> +
>> +???? h264_ctx->workspace_offset = h264_ctx->cma_alloc_addr + 
>> DCAC_READ_MARGIN;
>> +???? h264_ctx->workspace_vaddr = h264_ctx->cma_alloc_vaddr + 
>> DCAC_READ_MARGIN;
>> +
>> +???? ctx->codec_priv = h264_ctx;
>> +???? dec_hw->curr_ctx = h264_ctx;
>> +???? h264_ctx->col_buf_alloc_size = 0;
>> +???? h264_ctx->init_flag = 0;
>> +???? h264_ctx->new_pic_flag = 0;
>> +???? h264_ctx->param_set = 0;
>> +???? h264_ctx->reg_iqidct_control_init_flag = 0;
>> +???? h264_ctx->decode_pic_count = 0;
>> +
>> +???? return 0;
>> +
>> +err_alloc_workspace:
>> +???? dma_free_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
>> +?????????????????????? h264_ctx->lmem_addr, h264_ctx->lmem_phy_addr);
>> +err_alloc_lmem:
>> +???? kfree(h264_ctx);
>> +
>> +???? return ret;
>> +}
>> +
>> +void aml_h264_exit(void *priv)
>> +{
>> +???? struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)ctx->codec_priv;
>> +???? struct aml_vdec_hw *dec_hw;
>> +
>> +???? if (!h264_ctx) {
>> +???????????? pr_info("h264 decoder is already destroyed or not 
>> created!\n");
>> +???????????? return;
>> +???? }
>> +???? dec_hw = vdec_get_hw(ctx->dev);
>> +???? h264_ctx->param_set = 0;
>> +
>> +???? if (ctx->dos_clk_en)
>> +???????????? aml_stop_vdec_hw();
>> +
>> +???? if (h264_ctx->collated_cma_vaddr) {
>> +???????????? dma_free_coherent(dec_hw->dev, 
>> h264_ctx->col_buf_alloc_size,
>> +?????????????????????????????? h264_ctx->collated_cma_vaddr,
>> +?????????????????????????????? h264_ctx->collated_cma_addr);
>> +???????????? h264_ctx->col_buf_alloc_size = 0;
>> +???? }
>> +
>> +???? if (h264_ctx->mc_cpu_vaddr) {
>> +???????????? dma_free_coherent(dec_hw->dev, MC_TOTAL_SIZE,
>> +?????????????????????????????? h264_ctx->mc_cpu_vaddr,
>> +?????????????????????????????? h264_ctx->mc_cpu_paddr);
>> +???????????? h264_ctx->mc_cpu_loaded = false;
>> +???? }
>> +
>> +???? if (h264_ctx->lmem_addr)
>> +???????????? dma_free_coherent(dec_hw->dev, LMEM_DUMP_SIZE,
>> +?????????????????????????????? h264_ctx->lmem_addr, 
>> h264_ctx->lmem_phy_addr);
>> +
>> +???? if (h264_ctx->cma_alloc_vaddr)
>> +???????????? dma_free_coherent(dec_hw->dev, V_BUF_ADDR_OFFSET,
>> +?????????????????????????????? h264_ctx->cma_alloc_vaddr,
>> +?????????????????????????????? h264_ctx->cma_alloc_addr);
>> +
>> +???? kfree(ctx->codec_priv);
>> +???? dec_hw->curr_ctx = NULL;
>> +???? ctx->codec_priv = NULL;
>> +}
>> +
>> +static void config_decode_mode(struct aml_h264_ctx *h264_ctx)
>> +{
>> +???? WRITE_VREG(H264_DECODE_MODE, 0x1);? /*decode mode framebase*/
>> +???? WRITE_VREG(HEAD_PADDING_REG, 0);
>> +???? WRITE_VREG(H264_DECODE_SEQINFO, h264_ctx->seq_info);
>> +???? WRITE_VREG(INIT_FLAG_REG, 1);
>> +}
>> +
>> +int aml_h264_dec_run(void *priv)
>> +{
>> +???? struct aml_vdec_ctx *ctx = (struct aml_vdec_ctx *)priv;
>> +???? struct aml_h264_ctx *h264_ctx = (struct aml_h264_ctx 
>> *)ctx->codec_priv;
>> +???? int ret = -1;
>> +???? int i;
>> +
>> +???? ret = aml_h264_get_stateless_ctrl_ref(h264_ctx);
>> +???? if (ret < 0) {
>> +???????????? pr_err("not ctrl ref for h264 decoder\n");
>> +???????????? return ret;
>> +???? }
>> +
>> +???? h264_config_params(ctx);
>> +
>> +???? if (h264_prepare_input(ctx) < 0)
>> +???????????? return ret;
>> +
>> +???? if (alloc_colocate_cma(h264_ctx, ctx) < 0)
>> +???????????? return ret;
>> +
>> +???? h264_restore_hw_ctx(ctx);
>> +
>> +???? config_decode_mode(h264_ctx);
>> +???? /* enable stream input hardware */
>> +???? SET_VREG_MASK(VLD_MEM_VIFIFO_CONTROL, (1 << 2) | (1 << 1));
>> +???? /* enable hardware timer */
>> +???? WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) | (1 << 16));
>> +???? WRITE_VREG(MDEC_EXTIF_CFG2, RD_VREG(MDEC_EXTIF_CFG2) | 0x20);
>> +???? WRITE_VREG(NAL_SEARCH_CTL, RD_VREG(NAL_SEARCH_CTL) & (~0x2));
>> +???? CLEAR_VREG_MASK(VDEC_ASSIST_MMC_CTRL1, 1 << 3);
>> +
>> +???? aml_start_vdec_hw();
>> +???? h264_ctx->init_flag = 1;
>> +???? h264_ctx->new_pic_flag = 1;
>> +
>> +???? WRITE_VREG(DPB_STATUS_REG, H264_ACTION_SEARCH_HEAD);
>> +
>> +???? ret = wait_event_interruptible_timeout(ctx->queue, ctx->int_cond,
>> + msecs_to_jiffies(DECODER_TIMEOUT_MS));
>> +???? ctx->int_cond = 0;
>> +???? if (!ret) {
>> +???????????? ret = -1;
>> +???????????? pr_err("dec timeout=%u\n", DECODER_TIMEOUT_MS);
>> +???????????? for (i = 0; i < 16; i++) {????? /* 16 : show ucode PC 
>> 16 times when timeout */
>> +???????????????????? pr_info("decoder timeout, pc 0x%x\n", 
>> RD_VREG(MPC_E));
>> +???????????????????? usleep_range(10, 20);
>> +???????????? }
>> +???? } else if (-ERESTARTSYS == ret) {
>> +???????????? ret = -1;
>> +???????????? pr_err("dec inter fail\n");
>> +???? }
>> +
>> +???? aml_stop_vdec_hw();
>> +???? h264_ctx->init_flag = 0;
>> +
>> +???? return ret;
>> +}
>> diff --git a/drivers/media/platform/amlogic/vdec/h264.h 
>> b/drivers/media/platform/amlogic/vdec/h264.h
>> new file mode 100644
>> index 000000000000..3d3a35a641c9
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/h264.h
>> @@ -0,0 +1,300 @@
>> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +#ifndef _H264_H_
>> +#define _H264_H_
>> +
>> +#define RPM_BEGIN?????????? 0x0
>> +#define FRAME_IN_DPB??????? 24
>> +#define RPM_END???????????? 0x400
>> +#define DPB_OFFSET????????? 0x100
>> +#define MMCO_OFFSET???????? 0x200
>> +#define SPS_OFFSET????????? 0x100
>> +#define PPS_OFFSET????????? 0x300
>> +#define PARAM_BASE_VAL????? 0x414d
>> +#define MEM_MMCO_BASE?????? 0x01c3000
>> +#define MEM_SPS_BASE??????? 0x01c3c00
>> +#define MEM_PPS_BASE??????? 0x01cbc00
>> +#define MC_TOTAL_SIZE?????? ((20 + 16) * SZ_1K)
>> +#define MC_SWAP_SIZE??????? (4 * SZ_1K)
>> +#define LMEM_DUMP_SIZE????? 4096
>> +#define V_BUF_ADDR_OFFSET?? (0x200000 + 0x8000 + 0x20000 + 0x1000)
>> +#define DCAC_READ_MARGIN??? (64 * 1024)
>> +#define MC_OFFSET_HEADER??? 0x0000
>> +#define MC_OFFSET_DATA????? 0x1000
>> +#define MC_OFFSET_MMCO????? 0x2000
>> +#define MC_OFFSET_LIST????? 0x3000
>> +#define MC_OFFSET_SLICE???? 0x4000
>> +#define MC_OFFSET_MAIN????? 0x5000
>> +
>> +/* Rename the dos regs */
>> +#define H264_DECODE_INFO??? M4_CONTROL_REG
>> +#define INIT_FLAG_REG?????? AV_SCRATCH_2
>> +#define HEAD_PADDING_REG???? AV_SCRATCH_3
>> +#define UCODE_WATCHDOG_REG?? AV_SCRATCH_7
>> +#define LMEM_DUMP_ADR?????? AV_SCRATCH_L
>> +#define DEBUG_REG1????????? AV_SCRATCH_M
>> +#define DEBUG_REG2????????? AV_SCRATCH_N
>> +#define FRAME_COUNTER_REG?????? AV_SCRATCH_I
>> +#define RPM_CMD_REG????????? AV_SCRATCH_A
>> +#define H264_DECODE_SIZE??? AV_SCRATCH_E
>> +#define H264_DECODE_MODE??? AV_SCRATCH_4
>> +#define H264_DECODE_SEQINFO??? AV_SCRATCH_5
>> +/**
>> + * NAL_SEARCH_CTL: bit 0, enable itu_t35
>> + * NAL_SEARCH_CTL: bit 1, enable mmu
>> + * NAL_SEARCH_CTL: bit 2, detect frame_mbs_only_flag whether switch 
>> resolution
>> + * NAL_SEARCH_CTL: bit 3, recover the correct sps pps
>> + * NAL_SEARCH_CTL: bit 7-14,level_idc
>> + * NAL_SEARCH_CTL: bit 15,bitstream_restriction_flag
>> + */
>> +#define NAL_SEARCH_CTL????? AV_SCRATCH_9
>> +#define DPB_STATUS_REG????? AV_SCRATCH_J
>> +#define ERROR_STATUS_REG??? AV_SCRATCH_9
>> +
>> +#define H264_BUFFER_INFO_INDEX????? PMV3_X?? /* 0xc24 */
>> +#define H264_BUFFER_INFO_DATA?????? PMV2_X?? /* 0xc22 */
>> +#define H264_CURRENT_POC_IDX_RESET? LAST_SLICE_MV_ADDR?????? /* 
>> 0xc30 */
>> +#define H264_CURRENT_POC??????????? LAST_MVY /* 0xc32 shared with 
>> conceal MV */
>> +#define H264_CO_MB_WR_ADDR????????? VLD_C38
>> +#define H264_CO_MB_RD_ADDR????????? VLD_C39
>> +#define H264_CO_MB_RW_CTL?????????? VLD_C3D
>> +#define MBY_MBX???????????????????? MB_MOTION_MODE
>> +
>> +#define H264_ACTION_SEARCH_HEAD???? 0xf0
>> +#define H264_ACTION_DECODE_SLICE??? 0xf1
>> +#define H264_ACTION_CONFIG_DONE???? 0xf2
>> +#define H264_ACTION_DECODE_NEWPIC?? 0xf3
>> +#define H264_ACTION_DECODE_START??? 0xff
>> +
>> +/* RPM memory definition */
>> +#define FIXED_FRAME_RATE_FLAG 0X21
>> +#define OFFSET_DELIMITER_LO 0x2f
>> +#define OFFSET_DELIMITER_HI 0x30
>> +#define REF_IDC_OVERRIDE_FLAG 0x35
>> +#define SLICE_IPONLY_BREAK 0X5C
>> +#define PREV_MAX_REFERENCE_FRAME_NUM 0X5D
>> +#define EOS 0X5E
>> +#define FRAME_PACKING_TYPE 0X5F
>> +#define OLD_POC_PAR_1 0X60
>> +#define OLD_POC_PAR_2 0X61
>> +#define PREV_MBX 0X62
>> +#define PREV_MBY 0X63
>> +#define ERROR_SKIP_MB_NUM 0X64
>> +#define ERROR_MB_STATUS 0X65
>> +#define L0_PIC0_STATUS 0X66
>> +#define TIMEOUT_COUNTER 0X67
>> +#define BUFFER_SIZE 0X68
>> +#define BUFFER_SIZE_HI 0X69
>> +#define CROPPING_LEFT_RIGHT 0X6A
>> +#define CROPPING_TOP_BOTTOM 0X6B
>> +/**
>> + * sps_flags2:
>> + * bit 3, bitstream_restriction_flag
>> + * bit 2, pic_struct_present_flag
>> + * bit 1, vcl_hrd_parameters_present_flag
>> + * bit 0, nal_hrd_parameters_present_flag
>> + */
>> +#define SPS_FLAGS2 0x6C
>> +#define NUM_REORDER_FRAMES 0x6D
>> +#define MAX_BUFFER_FRAME 0X6E
>> +
>> +#define NON_CONFORMING_STREAM 0X70
>> +#define RECOVERY_POINT 0X71
>> +#define POST_CANVAS 0X72
>> +#define POST_CANVAS_H 0X73
>> +#define SKIP_PIC_COUNT 0X74
>> +#define TARGET_NUM_SCALING_LIST 0X75
>> +#define FF_POST_ONE_FRAME 0X76
>> +#define PREVIOUS_BIT_CNT 0X77
>> +#define MB_NOT_SHIFT_COUNT 0X78
>> +#define PIC_STATUS 0X79
>> +#define FRAME_COUNTER 0X7A
>> +#define NEW_SLICE_TYPE 0X7B
>> +#define NEW_PICTURE_STRUCTURE 0X7C
>> +#define NEW_FRAME_NUM 0X7D
>> +#define NEW_IDR_PIC_ID 0X7E
>> +#define IDR_PIC_ID 0X7F
>> +
>> +/* h264 LOCAL */
>> +#define NAL_UNIT_TYPE 0X80
>> +#define NAL_REF_IDC 0X81
>> +#define SLICE_TYPE 0X82
>> +#define LOG2_MAX_FRAME_NUM 0X83
>> +#define FRAME_MBS_ONLY_FLAG 0X84
>> +#define PIC_ORDER_CNT_TYPE 0X85
>> +#define LOG2_MAX_PIC_ORDER_CNT_LSB 0X86
>> +#define PIC_ORDER_PRESENT_FLAG 0X87
>> +#define REDUNDANT_PIC_CNT_PRESENT_FLAG 0X88
>> +#define PIC_INIT_QP_MINUS26 0X89
>> +#define DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG 0X8A
>> +#define NUM_SLICE_GROUPS_MINUS1 0X8B
>> +#define MODE_8X8_FLAGS 0X8C
>> +#define ENTROPY_CODING_MODE_FLAG 0X8D
>> +#define SLICE_QUANT 0X8E
>> +#define TOTAL_MB_HEIGHT 0X8F
>> +#define PICTURE_STRUCTURE 0X90
>> +#define TOP_INTRA_TYPE 0X91
>> +#define RV_AI_STATUS 0X92
>> +#define AI_READ_START 0X93
>> +#define AI_WRITE_START 0X94
>> +#define AI_CUR_BUFFER 0X95
>> +#define AI_DMA_BUFFER 0X96
>> +#define AI_READ_OFFSET 0X97
>> +#define AI_WRITE_OFFSET 0X98
>> +#define AI_WRITE_OFFSET_SAVE 0X99
>> +#define RV_AI_BUFF_START 0X9A
>> +#define I_PIC_MB_COUNT 0X9B
>> +#define AI_WR_DCAC_DMA_CTRL 0X9C
>> +#define SLICE_MB_COUNT 0X9D
>> +#define PICTYPE 0X9E
>> +#define SLICE_GROUP_MAP_TYPE 0X9F
>> +#define MB_TYPE 0XA0
>> +#define MB_AFF_ADDED_DMA 0XA1
>> +#define PREVIOUS_MB_TYPE 0XA2
>> +#define WEIGHTED_PRED_FLAG 0XA3
>> +#define WEIGHTED_BIPRED_IDC 0XA4
>> +/* bit 3:2 - PICTURE_STRUCTURE
>> + * bit 1 - MB_ADAPTIVE_FRAME_FIELD_FLAG
>> + * bit 0 - FRAME_MBS_ONLY_FLAG
>> + */
>> +#define MBFF_INFO 0XA5
>> +#define TOP_INTRA_TYPE_TOP 0XA6
>> +#define RV_AI_BUFF_INC 0xA7
>> +#define DEFAULT_MB_INFO_LO 0xA8
>> +/* 0 -- no need to read
>> + * 1 -- need to wait Left
>> + * 2 -- need to read Intra
>> + * 3 -- need to read back MV
>> + */
>> +#define NEED_READ_TOP_INFO 0xA9
>> +/* 0 -- idle
>> + * 1 -- wait Left
>> + * 2 -- reading top Intra
>> + * 3 -- reading back MV
>> + */
>> +#define READ_TOP_INFO_STATE 0xAA
>> +#define DCAC_MBX 0xAB
>> +#define TOP_MB_INFO_OFFSET 0xAC
>> +#define TOP_MB_INFO_RD_IDX 0xAD
>> +#define TOP_MB_INFO_WR_IDX 0xAE
>> +
>> +#define VLD_NO_WAIT?? 0
>> +#define VLD_WAIT_BUFFER 1
>> +#define VLD_WAIT_HOST?? 2
>> +#define VLD_WAIT_GAP 3
>> +
>> +#define VLD_WAITING 0xAF
>> +
>> +#define MB_X_NUM 0xB0
>> +#define MB_HEIGHT 0xB2
>> +#define MBX 0xB3
>> +#define TOTAL_MBY 0xB4
>> +#define INTR_MSK_SAVE 0xB5
>> +#define NEED_DISABLE_PPE 0xB6
>> +#define IS_NEW_PICTURE 0XB7
>> +#define PREV_NAL_REF_IDC 0XB8
>> +#define PREV_NAL_UNIT_TYPE 0XB9
>> +#define FRAME_MB_COUNT 0XBA
>> +#define SLICE_GROUP_UCODE 0XBB
>> +#define SLICE_GROUP_CHANGE_RATE 0XBC
>> +#define SLICE_GROUP_CHANGE_CYCLE_LEN 0XBD
>> +#define DELAY_LENGTH 0XBE
>> +#define PICTURE_STRUCT 0XBF
>> +#define DCAC_PREVIOUS_MB_TYPE 0xC1
>> +
>> +#define TIME_STAMP 0XC2
>> +#define H_TIME_STAMP 0XC3
>> +#define VPTS_MAP_ADDR 0XC4
>> +#define H_VPTS_MAP_ADDR 0XC5
>> +#define PIC_INSERT_FLAG 0XC7
>> +#define TIME_STAMP_START 0XC8
>> +#define TIME_STAMP_END 0XDF
>> +#define OFFSET_FOR_NON_REF_PIC 0XE0
>> +#define OFFSET_FOR_TOP_TO_BOTTOM_FIELD 0XE2
>> +#define MAX_REFERENCE_FRAME_NUM 0XE4
>> +#define FRAME_NUM_GAP_ALLOWED 0XE5
>> +#define NUM_REF_FRAMES_IN_PIC_ORDER_CNT_CYCLE 0XE6
>> +#define PROFILE_IDC_MMCO 0XE7
>> +#define LEVEL_IDC_MMCO 0XE8
>> +#define FRAME_SIZE_IN_MB 0XE9
>> +#define DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG 0XEA
>> +#define PPS_NUM_REF_IDX_L0_ACTIVE_MINUS1 0XEB
>> +#define PPS_NUM_REF_IDX_L1_ACTIVE_MINUS1 0XEC
>> +#define CURRENT_SPS_ID 0XED
>> +#define CURRENT_PPS_ID 0XEE
>> +/* bit 0 - sequence parameter set may change
>> + * bit 1 - picture parameter set may change
>> + * bit 2 - new dpb just inited
>> + * bit 3 - IDR picture not decoded yet
>> + * bit 5:4 - 0: mb level code loaded 1: picture
>> + * level code loaded 2: slice level code loaded
>> + */
>> +#define DECODE_STATUS 0XEF
>> +#define FIRST_MB_IN_SLICE 0XF0
>> +#define PREV_MB_WIDTH 0XF1
>> +#define PREV_FRAME_SIZE_IN_MB 0XF2
>> +/* bit 0 - aspect_ratio_info_present_flag
>> + * bit 1 - timing_info_present_flag
>> + * bit 2 - nal_hrd_parameters_present_flag
>> + * bit 3 - vcl_hrd_parameters_present_flag
>> + * bit 4 - pic_struct_present_flag
>> + * bit 5 - bitstream_restriction_flag
>> + */
>> +#define VUI_STATUS 0XF4
>> +#define ASPECT_RATIO_IDC 0XF5
>> +#define ASPECT_RATIO_SAR_WIDTH 0XF6
>> +#define ASPECT_RATIO_SAR_HEIGHT 0XF7
>> +#define NUM_UNITS_IN_TICK 0XF8
>> +#define TIME_SCALE 0XFA
>> +#define CURRENT_PIC_INFO 0XFC
>> +#define DPB_BUFFER_INFO 0XFD
>> +#define REFERENCE_POOL_INFO 0XFE
>> +#define REFERENCE_LIST_INFO 0XFF
>> +
>> +#define REORDER_CMD_MAX???????????? 66
>> +
>> +/* config parameters to DDR lmem */
>> +#define GET_SPS_PROFILE_IDC(x)?????? (((x) & 0xff) << 8)
>> +#define GET_SPS_LEVEL_IDC(x)???????? ((x) & 0xff)
>> +#define GET_SPS_SEQ_PARAM_SET_ID(x)?????? (((x) & 0x1f) << 8)
>> +#define GET_SPS_CHROMA_FORMAT_IDC(x)????? ((x) << 8)
>> +#define GET_SPS_NUM_REF_FRAMES(x)???????? ((x) & 0xff)
>> +#define GET_SPS_GAPS_ALLOWED_FLAG(x)????? ((x) << 8)
>> +#define GET_SPS_LOG2_MAX_FRAME_NUM(x)???? ((x) + 4)
>> +#define GET_SPS_PIC_ORDER_CNT_LSB(x)????? ((x) + 4)
>> +#define GET_SPS_PIC_ORDER_TYPE(x)???????? (x)
>> +#define GET_SPS_OFFSET_FOR_NONREF_PIC_HIGH(x)????? (((x) & 
>> 0xffff0000) >> 16)
>> +#define GET_SPS_OFFSET_FOR_NONREF_PIC_LOW(x)???????? ((x) & 0xffff)
>> +#define GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_HIGH(x)????? (((x) & 
>> 0xffff0000) >> 16)
>> +#define GET_SPS_OFFSET_FOR_TOP_BOT_FIELD_LOW(x)???????? ((x) & 0xffff)
>> +#define GET_SPS_PIC_WIDTH_IN_MBS(x)?????? ((x) + 1)
>> +#define GET_SPS_PIC_HEIGHT_IN_MBS(x)????? ((x) + 1)
>> +#define GET_SPS_DIRECT_8X8_FLAGS(x)?????? (((x) & 0x1) << 2)
>> +#define GET_SPS_MB_ADAPTIVE_FRAME_FIELD_FLAGS(x)?????? (((x) & 0x1) 
>> << 1)
>> +#define GET_SPS_FRAME_MBS_ONLY_FLAGS(x)?? ((x) & 0x1)
>> +
>> +#define GET_PPS_PIC_PARAM_SET_ID(x)?????? ((x) & 0xff)
>> +#define GET_PPS_SEQ_PARAM_SET_ID(x)?????? (((x) & 0x1f) << 8)
>> +#define GET_PPS_ENTROPY_CODING_MODE_FLAG(x)? (((x) & 0x1) << 13)
>> +#define GET_PPS_PIC_ORDER_PRESENT_FLAG(x)??? (((x) & 0x1) << 14)
>> +#define GET_PPS_NUM_IDX_REF_L0_MINUS1(x)?????? ((x) & 0x1f)
>> +#define GET_PPS_NUM_IDX_REF_L1_MINUS1(x)?????? (((x) & 0x1f) << 5)
>> +#define GET_PPS_WEIGHTED_PRED_FLAG(x)???????? (((x) & 0x1) << 10)
>> +#define GET_PPS_WEIGHTED_BIPRED_IDC(x)??????? (((x) & 0x3) << 11)
>> +#define GET_PPS_INIT_QS_MINUS26(x)?????????? (((x) & 0xff) << 8)
>> +#define GET_PPS_INIT_QP_MINUS26(x)?????????? ((x) & 0xff)
>> +#define GET_PPS_CHROMA_QP_INDEX_OFFSET(x)?? ((x) & 0xff)
>> +#define GET_PPS_DEBLOCK_FILTER_CTRL_PRESENT_FLAG(x)?? (((x) & 0x1) 
>> << 8)
>> +#define GET_PPS_CONSTRAIN_INTRA_PRED_FLAG(x)????????? (((x) & 0x1) 
>> << 9)
>> +#define GET_PPS_REDUNDANT_PIC_CNT_PRESENT_FLAG(x)???? (((x) & 0x1) 
>> << 10)
>> +#define GET_PPS_SCALING_MATRIX_PRESENT_FLAG(x)??????? (((x) & 0x1) 
>> << 1)
>> +#define GET_PPS_TRANSFORM_8X8_FLAG(x)???????????????? ((x) & 0x1)
>> +#define GET_PPS_GET_SECOND_CHROMA_QP_OFFSET(x)??????? (x)
>> +
>> +int aml_h264_init(void *priv);
>> +void aml_h264_exit(void *priv);
>> +int aml_h264_dec_run(void *priv);
>> +
>> +#endif
>> diff --git a/drivers/media/platform/amlogic/vdec/reg_defines.h 
>> b/drivers/media/platform/amlogic/vdec/reg_defines.h
>> new file mode 100644
>> index 000000000000..6b1900ecbedb
>> --- /dev/null
>> +++ b/drivers/media/platform/amlogic/vdec/reg_defines.h
>> @@ -0,0 +1,175 @@
>> +/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
>> +/*
>> + * Copyright (C) 2025 Amlogic, Inc. All rights reserved
>> + */
>> +
>> +#ifndef _REG_DEFINES_H_
>> +#define _REG_DEFINES_H_
>> +
>> +#define VDEC_ASSIST_MMC_CTRL0??????? 0x0001
>> +#define VDEC_ASSIST_MMC_CTRL1??????? 0x0002
>> +
>> +#define VDEC_ASSIST_CANVAS_BLK32???? 0x0005
>> +
>> +#define VDEC_ASSIST_MBOX1_CLR_REG??? 0x0075
>> +#define VDEC_ASSIST_MBOX1_MASK?????? 0x0076
>> +
>> +#define MPSR???????????????????????? 0x0301
>> +#define MPC_P??????????????????????? 0x0306
>> +#define MPC_D??????????????????????? 0x0307
>> +#define MPC_E??????????????????????? 0x0308
>> +#define MPC_W??????????????????????? 0x0309
>> +#define CPSR???????????????????????? 0x0321
>> +#define IMEM_DMA_CTRL??????????????? 0x0340
>> +#define IMEM_DMA_ADR???????????????? 0x0341
>> +#define IMEM_DMA_COUNT?????????????? 0x0342
>> +#define WRRSP_IMEM?????????????????? 0x0343
>> +#define LMEM_DMA_CTRL??????????????? 0x0350
>> +#define WRRSP_LMEM?????????????????? 0x0353
>> +
>> +#define PSCALE_CTRL????????????????? 0x0911
>> +#define GCLK_EN????????????????????? 0x0983
>> +#define MDEC_PIC_DC_CTRL???????????? 0x098e
>> +#define MDEC_PIC_DC_MUX_CTRL???????? 0x098d
>> +#define ANC0_CANVAS_ADDR???????????? 0x0990
>> +#define ANC1_CANVAS_ADDR???????????? 0x0991
>> +#define ANC2_CANVAS_ADDR???????????? 0x0992
>> +#define ANC3_CANVAS_ADDR???????????? 0x0993
>> +#define ANC4_CANVAS_ADDR???????????? 0x0994
>> +#define ANC5_CANVAS_ADDR???????????? 0x0995
>> +#define ANC6_CANVAS_ADDR???????????? 0x0996
>> +#define ANC7_CANVAS_ADDR???????????? 0x0997
>> +#define ANC8_CANVAS_ADDR???????????? 0x0998
>> +#define ANC9_CANVAS_ADDR???????????? 0x0999
>> +#define ANC10_CANVAS_ADDR??????????? 0x099a
>> +#define ANC11_CANVAS_ADDR??????????? 0x099b
>> +#define ANC12_CANVAS_ADDR??????????? 0x099c
>> +#define ANC13_CANVAS_ADDR??????????? 0x099d
>> +#define ANC14_CANVAS_ADDR??????????? 0x099e
>> +#define ANC15_CANVAS_ADDR??????????? 0x099f
>> +#define ANC16_CANVAS_ADDR??????????? 0x09a0
>> +#define ANC17_CANVAS_ADDR??????????? 0x09a1
>> +#define ANC18_CANVAS_ADDR??????????? 0x09a2
>> +#define ANC19_CANVAS_ADDR??????????? 0x09a3
>> +#define ANC20_CANVAS_ADDR??????????? 0x09a4
>> +#define ANC21_CANVAS_ADDR??????????? 0x09a5
>> +#define ANC22_CANVAS_ADDR??????????? 0x09a6
>> +#define ANC23_CANVAS_ADDR??????????? 0x09a7
>> +#define ANC24_CANVAS_ADDR??????????? 0x09a8
>> +#define ANC25_CANVAS_ADDR??????????? 0x09a9
>> +#define ANC26_CANVAS_ADDR??????????? 0x09aa
>> +#define ANC27_CANVAS_ADDR??????????? 0x09ab
>> +#define ANC28_CANVAS_ADDR??????????? 0x09ac
>> +#define ANC29_CANVAS_ADDR??????????? 0x09ad
>> +#define ANC30_CANVAS_ADDR??????????? 0x09ae
>> +#define ANC31_CANVAS_ADDR??????????? 0x09af
>> +#define DBKR_CANVAS_ADDR???????????? 0x09b0
>> +#define DBKW_CANVAS_ADDR???????????? 0x09b1
>> +#define REC_CANVAS_ADDR????????????? 0x09b2
>> +#define CURR_CANVAS_CTRL???????????? 0x09b3
>> +#define MDEC_PIC_DC_THRESH?????????? 0x09b8
>> +#define AV_SCRATCH_0???????????????? 0x09c0
>> +#define AV_SCRATCH_1???????????????? 0x09c1
>> +#define AV_SCRATCH_2???????????????? 0x09c2
>> +#define AV_SCRATCH_3???????????????? 0x09c3
>> +#define AV_SCRATCH_4???????????????? 0x09c4
>> +#define AV_SCRATCH_5???????????????? 0x09c5
>> +#define AV_SCRATCH_6???????????????? 0x09c6
>> +#define AV_SCRATCH_7???????????????? 0x09c7
>> +#define AV_SCRATCH_8???????????????? 0x09c8
>> +#define AV_SCRATCH_9???????????????? 0x09c9
>> +#define AV_SCRATCH_A???????????????? 0x09ca
>> +#define AV_SCRATCH_B???????????????? 0x09cb
>> +#define AV_SCRATCH_C???????????????? 0x09cc
>> +#define AV_SCRATCH_D???????????????? 0x09cd
>> +#define AV_SCRATCH_E???????????????? 0x09ce
>> +#define AV_SCRATCH_F???????????????? 0x09cf
>> +#define AV_SCRATCH_G???????????????? 0x09d0
>> +#define AV_SCRATCH_H???????????????? 0x09d1
>> +#define AV_SCRATCH_I???????????????? 0x09d2
>> +#define AV_SCRATCH_J???????????????? 0x09d3
>> +#define AV_SCRATCH_K???????????????? 0x09d4
>> +#define AV_SCRATCH_L???????????????? 0x09d5
>> +#define AV_SCRATCH_M???????????????? 0x09d6
>> +#define AV_SCRATCH_N???????????????? 0x09d7
>> +#define WRRSP_VLD??????????????????? 0x09da
>> +#define MDEC_DOUBLEW_CFG0??????????? 0x09db
>> +#define MDEC_DOUBLEW_CFG1??????????? 0x09dc
>> +#define MDEC_DOUBLEW_CFG2??????????? 0x09dd
>> +#define MDEC_DOUBLEW_CFG3??????????? 0x09de
>> +#define MDEC_DOUBLEW_CFG4??????????? 0x09df
>> +#define MDEC_DOUBLEW_CFG5??????????? 0x09e0
>> +#define MDEC_DOUBLEW_CFG6??????????? 0x09e1
>> +#define MDEC_DOUBLEW_CFG7??????????? 0x09e2
>> +#define MDEC_DOUBLEW_STATUS????????? 0x09e3
>> +#define MDEC_EXTIF_CFG0????????????? 0x09e4
>> +
>> +#define MDEC_EXTIF_CFG1????????????? 0x09e5
>> +#define MDEC_EXTIF_CFG2????????????? 0x09e6
>> +
>> +#define POWER_CTL_VLD??????????????? 0x0c08
>> +#define VLD_DECODE_CONTROL?????????? 0x0c18
>> +
>> +#define PMV1_X?????????????????????? 0x0c20
>> +#define PMV1_Y?????????????????????? 0x0c21
>> +#define PMV2_X?????????????????????? 0x0c22
>> +#define PMV2_Y?????????????????????? 0x0c23
>> +#define PMV3_X?????????????????????? 0x0c24
>> +#define PMV3_Y?????????????????????? 0x0c25
>> +#define PMV4_X?????????????????????? 0x0c26
>> +#define PMV4_Y?????????????????????? 0x0c27
>> +#define M4_TABLE_SELECT????????????? 0x0c28
>> +#define M4_CONTROL_REG?????????????? 0x0c29
>> +#define BLOCK_NUM??????????????????? 0x0c2a
>> +#define PATTERN_CODE???????????????? 0x0c2b
>> +#define MB_INFO????????????????????? 0x0c2c
>> +#define VLD_DC_PRED????????????????? 0x0c2d
>> +#define VLD_ERROR_MASK?????????????? 0x0c2e
>> +#define VLD_DC_PRED_C??????????????? 0x0c2f
>> +#define LAST_SLICE_MV_ADDR?????????? 0x0c30
>> +#define LAST_MVX???????????????????? 0x0c31
>> +#define LAST_MVY???????????????????? 0x0c32
>> +
>> +#define MB_MOTION_MODE?????????????? 0x0c07
>> +#define VIFF_BIT_CNT???????????????? 0x0c1a
>> +#define M4_CONTROL_REG?????????????? 0x0c29
>> +#define VLD_C38????????????????????? 0x0c38
>> +#define VLD_C39????????????????????? 0x0c39
>> +#define VLD_SHIFT_STATUS???????????? 0x0c3b
>> +#define VLD_C3D????????????????????? 0x0c3d
>> +#define VLD_MEM_VIFIFO_START_PTR???? 0x0c40
>> +#define VLD_MEM_VIFIFO_CURR_PTR????? 0x0c41
>> +#define VLD_MEM_VIFIFO_END_PTR?????? 0x0c42
>> +#define VLD_MEM_VIFIFO_BYTES_AVAIL?? 0x0c43
>> +#define VLD_MEM_VIFIFO_CONTROL?????? 0x0c44
>> +#define VLD_MEM_VIFIFO_WP??????????? 0x0c45
>> +#define VLD_MEM_VIFIFO_RP??????????? 0x0c46
>> +#define VLD_MEM_VIFIFO_LEVEL???????? 0x0c47
>> +#define VLD_MEM_VIFIFO_BUF_CNTL????? 0x0c48
>> +
>> +#define VCOP_CTRL_REG??????????????? 0x0e00
>> +#define RV_AI_MB_COUNT?????????????? 0x0e0c
>> +#define IQIDCT_CONTROL?????????????? 0x0e0e
>> +#define DCAC_DDR_BYTE64_CTL????????? 0x0e1d
>> +
>> +#define VDEC2_IMEM_DMA_CTRL????????? 0x2340
>> +#define VDEC2_IMEM_DMA_ADR?????????? 0x2341
>> +#define VDEC2_IMEM_DMA_COUNT???????? 0x2342
>> +
>> +#define DOS_SW_RESET0??????????????? 0x3f00
>> +#define DOS_GCLK_EN0???????????????? 0x3f01
>> +#define DOS_GCLK_EN1???????????????? 0x3f09
>> +#define DOS_GCLK_EN3???????????????? 0x3f35
>> +
>> +#define DOS_MEM_PD_VDEC????????????? 0x3f30
>> +#define DOS_MEM_PD_VDEC2???????????? 0x3f31
>> +#define DOS_MEM_PD_HCODEC??????????? 0x3f32
>> +/*add from M8M2*/
>> +#define DOS_MEM_PD_HEVC????????????? 0x3f33
>> +
>> +#define DOS_SW_RESET3??????????????? 0x3f34
>> +#define DOS_GCLK_EN3???????????????? 0x3f35
>> +#define DOS_HEVC_INT_EN????????????? 0x3f36
>> +
>> +#endif
>> +
>>
> Thanks,
> Neil

Best regards

Zhentao



From zhentao.guo at amlogic.com  Tue Oct 28 05:23:43 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Tue, 28 Oct 2025 20:23:43 +0800
Subject: [PATCH 1/3] dt-bindings: vdec: Add binding document of Amlogic
 decoder accelerator
In-Reply-To: <606da3b1-f042-4cc1-89d0-4feb257f032f@kernel.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <20251027-b4-s4-vdec-upstream-v1-1-620401813b5d@amlogic.com>
 <b989fba3-223d-498a-8efe-7a60e26cf0db@kernel.org>
 <40830266-692a-4731-8957-4462d4993746@amlogic.com>
 <606da3b1-f042-4cc1-89d0-4feb257f032f@kernel.org>
Message-ID: <fd77eb21-4324-4f86-858c-c6b5a63f68c7@amlogic.com>


? 2025/10/28 19:33, Krzysztof Kozlowski ??:
> [ EXTERNAL EMAIL ]
>
> On 28/10/2025 12:14, Zhentao Guo wrote:
>>>> +properties:
>>>> +  compatible:
>>>> +    const: amlogic,s4-vcodec-dec
>>>> +
>>>> +  reg:
>>>> +    maxItems: 2
>>>> +
>>>> +  reg-names:
>>>> +    items:
>>>> +      - const: dosbus
>>>> +      - const: dmcbus
>>> Is "bus" really name of this in datasheet?
>> No, it is not from the datasheet, in fact it was inherited from the
>> older SOCs. Do you have any suggestions about this?
> dos, dmc
Got it, thanks!
>
>>>> +
>>>> +  interrupts:
>>>> +    maxItems: 3
>>>> +
>>>> +  interrupt-names:
>>>> +    items:
>>>> +      - const: mailbox_0
>>>> +      - const: mailbox_1
>>>> +      - const: mailbox_2
>>> Useless names, so just drop interrupt-names property.
>> Yes, we don't need the interrupt names. I'll drop them.
>>>> +
>>>> +  clocks:
>>>> +    maxItems: 3
>>>> +
>>>> +  clock-names:
>>>> +    items:
>>>> +      - const: vdec
>>>> +      - const: clk_vdec_mux
>>>> +      - const: clk_hevcf_mux
>>>> +
>>>> +  power-domains:
>>>> +    maxItems: 2
>>>> +
>>>> +  power-domain-names:
>>>> +    items:
>>>> +      - const: pwrc-vdec
>>> Drop pwrc
>>>
>>>> +      - const: pwrc-hevc
>>> Drop pwrc
>> Ok, I'll drop the two pwrc(s) above.
>>> Missing iommus. I really doubt hardware works without IOMMU.
>> IOMMU is not supported by Amlogic SOCs, the decoder hardware needs to
>> use contiguous memory.
> I assume you speak about hardware, not drivers, so it is fine.
Yes, I mean the IOMMU hardware above.
>
> Best regards,
> Krzysztof

Thank you

Zhentao



From helgaas at kernel.org  Tue Oct 28 15:16:07 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Tue, 28 Oct 2025 17:16:07 -0500
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <DM4PR05MB102705BB2124288C68EEFDA04C7FCA@DM4PR05MB10270.namprd05.prod.outlook.com>
Message-ID: <20251028221607.GA1533456@bhelgaas>

On Tue, Oct 28, 2025 at 02:19:13AM +0800, Linnaea Lavia wrote:

> On 6.18-rc3 with the change the link does not come up without pcie_aspm=off.

Thanks for testing this!

I think there are two problems:

  1) On v6.18-rc2, the meson-pcie probe failed with:

       meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]

     so we didn't even try to bring up the link.  I think this was
     fixed in v6.18-rc3 by a1978b692a39 ("PCI: dwc: Use custom pci_ops
     for root bus DBI vs ECAM config access").

  2) On v6.18-rc3, we brought up the link and enumerated 01:00.0, but
     as soon as we tried to enable ASPM L1, the link stopped working:

> [    5.396341] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
> [    5.474722] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
> [    5.480590] [     T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
> [    5.484394] [     T50] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
> [    5.511625] [     T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
> [    5.578507] [     T50] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
> [    5.587460] [     T50] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
> [    5.656009] [     T50] pci 0000:01:00.0: ASPM: default states L1
> [    5.701063] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
> [    5.724147] [     T50] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
> [    5.779528] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
> [    5.822074] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
> [    5.864902] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
> [    5.907448] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
> [??? 5.987517] [???? T50] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
> [??? 6.081421] [???? T50] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)

Can you try the patch below on top of v6.18-rc3?  It should prevent
enabling ASPM L1.  Can you also collect the output of "sudo lspci -vv"
on some working kernel?

I'm a little concerned that [16c3:abcd] is too general because it
looks like that ID has really been abused by vendors:
https://patchwork.kernel.org/patch/10798497/

I wonder if there's a way for meson-pcie to write a corrected
Vendor/Device ID in the Root Port so we could make a quirk that's
specific to the Meson controller.

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 214ed060ca1b..9cd12924b5cb 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
  * disable both L0s and L1 for now to be safe.
  */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
 
 /*
  * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain


From linnaea-von-lavia at live.com  Wed Oct 29 03:50:46 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Wed, 29 Oct 2025 18:50:46 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <20251028221607.GA1533456@bhelgaas>
References: <20251028221607.GA1533456@bhelgaas>
Message-ID: <DM4PR05MB1027063F8AA9069B66A632C2EC7FAA@DM4PR05MB10270.namprd05.prod.outlook.com>

On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
> On Tue, Oct 28, 2025 at 02:19:13AM +0800, Linnaea Lavia wrote:
> 
>> On 6.18-rc3 with the change the link does not come up without pcie_aspm=off.
> 
> Thanks for testing this!
> 
> I think there are two problems:
> 
>    1) On v6.18-rc2, the meson-pcie probe failed with:
> 
>         meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
> 
>       so we didn't even try to bring up the link.  I think this was
>       fixed in v6.18-rc3 by a1978b692a39 ("PCI: dwc: Use custom pci_ops
>       for root bus DBI vs ECAM config access").

On vanilla 6.18-rc3 probing still fails with the same error.
I'm booting with additional patches from
https://lore.kernel.org/linux-pci/DM4PR05MB102709E0A9C0CF0D62AEC3524C7F1A at DM4PR05MB10270.namprd05.prod.outlook.com/

>    2) On v6.18-rc3, we brought up the link and enumerated 01:00.0, but
>       as soon as we tried to enable ASPM L1, the link stopped working:
> 
>> [    5.396341] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
>> [    5.474722] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [    5.480590] [     T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
>> [    5.484394] [     T50] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
>> [    5.511625] [     T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
>> [    5.578507] [     T50] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
>> [    5.587460] [     T50] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
>> [    5.656009] [     T50] pci 0000:01:00.0: ASPM: default states L1
>> [    5.701063] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [    5.724147] [     T50] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
>> [    5.779528] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [    5.822074] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [    5.864902] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [    5.907448] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
>> [??? 5.987517] [???? T50] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
>> [??? 6.081421] [???? T50] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)
> 
> Can you try the patch below on top of v6.18-rc3?  It should prevent
> enabling ASPM L1.  Can you also collect the output of "sudo lspci -vv"
> on some working kernel?
> 
> I'm a little concerned that [16c3:abcd] is too general because it
> looks like that ID has really been abused by vendors:
> https://patchwork.kernel.org/patch/10798497/
> 
> I wonder if there's a way for meson-pcie to write a corrected
> Vendor/Device ID in the Root Port so we could make a quirk that's
> specific to the Meson controller.
> 
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 214ed060ca1b..9cd12924b5cb 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>    * disable both L0s and L1 for now to be safe.
>    */
>   DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>   
>   /*
>    * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain

I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.

# dmesg | grep -i -e pci -e iwlwifi -e aspm
[    0.128511] [      T1] PCI: CLS 0 bytes, default 64
[    5.317257] [     T46] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.326946] [     T46] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.342763] [     T46] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.349971] [     T46] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.365746] [     T46] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.412380] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.428546] [     T46] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.437432] [     T46] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.443332] [     T46] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.449420] [     T46] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.458553] [     T46] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.467944] [     T46] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.471907] [     T46] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.478740] [     T46] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.484611] [     T46] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.484626] [     T46] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.506118] [     T46] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.506238] [     T46] pci 0000:00:00.0: supports D1
[    5.518667] [     T46] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.545255] [     T46] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.552744] [     T46] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.569336] [     T46] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.585775] [     T46] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.600929] [     T46] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.614576] [     T46] pci 0000:01:00.0: ASPM: default states L1
[    5.660049] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.660155] [     T46] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.660168] [     T46] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.660180] [     T46] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.701644] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.743113] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.784552] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.825987] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.826012] [     T46] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
[    5.867488] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.920348] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.928302] [     T46] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)
[    5.977964] [     T46] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.979072] [     T46] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.984964] [     T46] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    5.992437] [     T46] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    5.998751] [     T46] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    6.005694] [     T46] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    6.012641] [     T46] pci 0000:00:00.0: Disabling ASPM L0s/L1
[    6.018859] [     T46] pcieport 0000:00:00.0: PME: Signaling with IRQ 22
[    6.025864] [     T46] pcieport 0000:00:00.0: AER: enabled with IRQ 22
[   11.554656] [    T500] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.597429] [    T500] meson-pcie fc000000.pcie: error: wait linkup timeout
[   11.598989] [    T500] iwlwifi 0000:01:00.0: of_irq_parse_pci: failed with rc=134

lspci -vv also showed ASPM enabled.

# lspci -vv
00:00.0 PCI bridge: Synopsys, Inc. DWC_usb3 / PCIe bridge (rev 01) (prog-if 00 [Normal decode])
         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx+
         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
         Latency: 0
         Interrupt: pin A routed to IRQ 22
         Bus: primary=00, secondary=01, subordinate=ff, sec-latency=0
         I/O behind bridge: [disabled] [16-bit]
         Memory behind bridge: fc700000-fc7fffff [size=1M] [32-bit]
         Prefetchable memory behind bridge: [disabled] [32-bit]
         Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
         Expansion ROM at fc800000 [virtual] [disabled] [size=64K]
         BridgeCtl: Parity- SERR+ NoISA- VGA- VGA16- MAbort- >Reset- FastB2B-
                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
         Capabilities: [40] Power Management version 3
                 Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold+)
                 Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
         Capabilities: [50] MSI: Enable+ Count=1/1 Maskable- 64bit+
                 Address: 0000000009f0f000  Data: 0000
         Capabilities: [70] Express (v2) Root Port (Slot-), IntMsgNum 0
                 DevCap: MaxPayload 256 bytes, PhantFunc 0
                         ExtTag- RBE+ TEE-IO-
                 DevCtl: CorrErr+ NonFatalErr+ FatalErr+ UnsupReq+
                         RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
                         MaxPayload 128 bytes, MaxReadReq 256 bytes
                 DevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr+ TransPend-
                 LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <1us, L1 <2us
                         ClockPM- Surprise- LLActRep+ BwNot+ ASPMOptComp+
                 LnkCtl: ASPM L1 Enabled; RCB 64 bytes, LnkDisable- CommClk+
                         ExtSynch- ClockPM- AutWidDis- BWInt+ AutBWInt+
                 LnkSta: Speed 5GT/s, Width x1
                         TrErr- Train- SlotClk+ DLActive+ BWMgmt- ABWMgmt-
                 RootCap: CRSVisible+
                 RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna+ CRSVisible+
                 RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                 DevCap2: Completion Timeout: Range ABCD, TimeoutDis+ NROPrPrP+ LTR-
                          10BitTagComp- 10BitTagReq- OBFF Not Supported, ExtFmt- EETLPPrefix-
                          EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-
                          FRS- LN System CLS Not Supported, TPHComp- ExtTPHComp- ARIFwd-
                          AtomicOpsCap: Routing- 32bit- 64bit- 128bitCAS-
                 DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis- ARIFwd-
                          AtomicOpsCtl: ReqEn- EgressBlck-
                          IDOReq- IDOCompl- LTR- EmergencyPowerReductionReq-
                          10BitTagReq- OBFF Disabled, EETLPPrefixBlk-
                 LnkCap2: Supported Link Speeds: 2.5-5GT/s, Crosslink- Retimer- 2Retimers- DRS-
                 LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                          Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                          Compliance Preset/De-emphasis: -6dB de-emphasis, 0dB preshoot
                 LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete- EqualizationPhase1-
                          EqualizationPhase2- EqualizationPhase3- LinkEqualizationRequest-
                          Retimer- 2Retimers- CrosslinkRes: unsupported
         Capabilities: [100 v2] Advanced Error Reporting
                 UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr- CorrIntErr- HeaderOF-
                 CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr+ HeaderOF+
                 AERCap: First Error Pointer: 00, ECRCGenCap+ ECRCGenEn- ECRCChkCap+ ECRCChkEn-
                         MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
                 HeaderLog: 00000000 00000000 00000000 00000000
                 RootCmd: CERptEn+ NFERptEn+ FERptEn+
                 RootSta: CERcvd- MultCERcvd- UERcvd- MultUERcvd-
                          FirstFatal- NonFatalMsg- FatalMsg- IntMsgNum 0
                 ErrorSrc: ERR_COR: 0000 ERR_FATAL/NONFATAL: 0000
         Capabilities: [148 v1] L1 PM Substates
                 L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2- ASPM_L1.1+ L1_PM_Substates+
                           PortCommonModeRestoreTime=55us PortTPowerOnTime=12us
                 L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2- ASPM_L1.1-
                            T_CommonMode=55us
                 L1SubCtl2: T_PwrOn=18us
         Kernel driver in use: pcieport
         Kernel modules: shpchp

01:00.0 Network controller: Intel Corporation Wi-Fi 6E(802.11ax) AX210/AX1675* 2x2 [Typhoon Peak] (rev 1a)
         Subsystem: Intel Corporation Wi-Fi 6 AX210 160MHz
         !!! Unknown header type 7f
         Region 0: Memory at fc700000 (64-bit, non-prefetchable) [size=16K]
         Kernel modules: iwlwifi

On 6.17.4 ASPM is disabled and runs fine. Same with booting with pcie_aspm=off on 6.18-rc3.

# dmesg | grep -i -e pci -e iwlwifi -e aspm
[    0.130646] [      T1] PCI: CLS 0 bytes, default 64
[    5.293543] [     T50] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.311673] [     T50] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.327280] [     T50] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.334502] [     T50] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.348164] [     T50] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.394829] [     T50] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.402776] [     T50] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.407944] [     T50] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.413924] [     T50] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.417269] [     T50] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.432718] [     T50] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.452231] [     T50] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.455854] [     T50] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.455869] [     T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.455878] [     T50] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.455885] [     T50] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.455892] [     T50] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.456855] [     T50] pci 0000:00:00.0: supports D1
[    5.467372] [     T50] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.494508] [     T50] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.499799] [     T50] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.522939] [     T50] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.554392] [     T50] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.568852] [     T50] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.593133] [     T50] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.606402] [     T50] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.620315] [     T50] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.633022] [     T50] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.644676] [     T50] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    5.656118] [     T50] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    5.669110] [     T50] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    5.669122] [     T50] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    5.683041] [     T50] pcieport 0000:00:00.0: PME: Signaling with IRQ 25
[    5.697591] [     T50] pcieport 0000:00:00.0: AER: enabled with IRQ 25
[   11.028699] [    T506] iwlwifi 0000:01:00.0: enabling device (0000 -> 0002)
[   11.117043] [    T506] iwlwifi 0000:01:00.0: Detected crf-id 0x400410, cnv-id 0x400410 wfpm id 0x80000000
[   11.120720] [    T506] iwlwifi 0000:01:00.0: PCI dev 2725/0024, rev=0x420, rfid=0x10d000
[   11.134491] [    T506] iwlwifi 0000:01:00.0: Detected Intel(R) Wi-Fi 6E AX210 160MHz
[   11.224884] [     T75] iwlwifi 0000:01:00.0: loaded firmware version 89.af655058.0 ty-a0-gf-a0-89.ucode op_mode iwlmvm

# lspci -vv
00:00.0 PCI bridge: Synopsys, Inc. DWC_usb3 / PCIe bridge (rev 01) (prog-if 00 [Normal decode])
         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx+
         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
         Latency: 0
         Interrupt: pin A routed to IRQ 25
         Bus: primary=00, secondary=01, subordinate=ff, sec-latency=0
         I/O behind bridge: [disabled] [16-bit]
         Memory behind bridge: fc700000-fc7fffff [size=1M] [32-bit]
         Prefetchable memory behind bridge: [disabled] [32-bit]
         Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
         Expansion ROM at fc800000 [virtual] [disabled] [size=64K]
         BridgeCtl: Parity- SERR+ NoISA- VGA- VGA16- MAbort- >Reset- FastB2B-
                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
         Capabilities: [40] Power Management version 3
                 Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold+)
                 Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
         Capabilities: [50] MSI: Enable+ Count=1/1 Maskable- 64bit+
                 Address: 0000000003c9c000  Data: 0000
         Capabilities: [70] Express (v2) Root Port (Slot-), IntMsgNum 0
                 DevCap: MaxPayload 256 bytes, PhantFunc 0
                         ExtTag- RBE+ TEE-IO-
                 DevCtl: CorrErr+ NonFatalErr+ FatalErr+ UnsupReq+
                         RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
                         MaxPayload 128 bytes, MaxReadReq 256 bytes
                 DevSta: CorrErr+ NonFatalErr- FatalErr- UnsupReq- AuxPwr+ TransPend-
                 LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <1us, L1 <2us
                         ClockPM- Surprise- LLActRep+ BwNot+ ASPMOptComp+
                 LnkCtl: ASPM Disabled; RCB 64 bytes, LnkDisable- CommClk+
                         ExtSynch- ClockPM- AutWidDis- BWInt+ AutBWInt+
                 LnkSta: Speed 5GT/s, Width x1
                         TrErr- Train- SlotClk+ DLActive+ BWMgmt- ABWMgmt-
                 RootCap: CRSVisible+
                 RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna+ CRSVisible+
                 RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                 DevCap2: Completion Timeout: Range ABCD, TimeoutDis+ NROPrPrP+ LTR-
                          10BitTagComp- 10BitTagReq- OBFF Not Supported, ExtFmt- EETLPPrefix-
                          EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-
                          FRS- LN System CLS Not Supported, TPHComp- ExtTPHComp- ARIFwd-
                          AtomicOpsCap: Routing- 32bit- 64bit- 128bitCAS-
                 DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis- ARIFwd-
                          AtomicOpsCtl: ReqEn- EgressBlck-
                          IDOReq- IDOCompl- LTR- EmergencyPowerReductionReq-
                          10BitTagReq- OBFF Disabled, EETLPPrefixBlk-
                 LnkCap2: Supported Link Speeds: 2.5-5GT/s, Crosslink- Retimer- 2Retimers- DRS-
                 LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                          Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                          Compliance Preset/De-emphasis: -6dB de-emphasis, 0dB preshoot
                 LnkSta2: Current De-emphasis Level: -3.5dB, EqualizationComplete- EqualizationPhase1-
                          EqualizationPhase2- EqualizationPhase3- LinkEqualizationRequest-
                          Retimer- 2Retimers- CrosslinkRes: unsupported
         Capabilities: [100 v2] Advanced Error Reporting
                 UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 CESta:  RxErr+ BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr- CorrIntErr- HeaderOF-
                 CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr+ HeaderOF+
                 AERCap: First Error Pointer: 00, ECRCGenCap+ ECRCGenEn- ECRCChkCap+ ECRCChkEn-
                         MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
                 HeaderLog: 00000000 00000000 00000000 00000000
                 RootCmd: CERptEn+ NFERptEn+ FERptEn+
                 RootSta: CERcvd+ MultCERcvd+ UERcvd- MultUERcvd-
                          FirstFatal- NonFatalMsg- FatalMsg- IntMsgNum 0
                 ErrorSrc: ERR_COR: 0000 ERR_FATAL/NONFATAL: 0000
         Capabilities: [148 v1] L1 PM Substates
                 L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2- ASPM_L1.1+ L1_PM_Substates+
                           PortCommonModeRestoreTime=55us PortTPowerOnTime=12us
                 L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2- ASPM_L1.1-
                            T_CommonMode=55us
                 L1SubCtl2: T_PwrOn=18us
         Kernel driver in use: pcieport

01:00.0 Network controller: Intel Corporation Wi-Fi 6E(802.11ax) AX210/AX1675* 2x2 [Typhoon Peak] (rev 1a)
         Subsystem: Intel Corporation Wi-Fi 6 AX210 160MHz
         Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
         Latency: 0
         Interrupt: pin A routed to IRQ 24
         Region 0: Memory at fc700000 (64-bit, non-prefetchable) [size=16K]
         Capabilities: [c8] Power Management version 3
                 Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
                 Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
         Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
                 Address: 0000000000000000  Data: 0000
         Capabilities: [40] Express (v2) Endpoint, IntMsgNum 0
                 DevCap: MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 unlimited
                         ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+ SlotPowerLimit 0W TEE-IO-
                 DevCtl: CorrErr+ NonFatalErr+ FatalErr+ UnsupReq+
                         RlxdOrd+ ExtTag- PhantFunc- AuxPwr+ NoSnoop+ FLReset-
                         MaxPayload 128 bytes, MaxReadReq 128 bytes
                 DevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr+ TransPend-
                 LnkCap: Port #4, Speed 5GT/s, Width x1, ASPM L1, Exit Latency L1 <8us
                         ClockPM+ Surprise- LLActRep- BwNot- ASPMOptComp+
                 LnkCtl: ASPM Disabled; RCB 64 bytes, LnkDisable- CommClk+
                         ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
                 LnkSta: Speed 5GT/s, Width x1
                         TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
                 DevCap2: Completion Timeout: Range B, TimeoutDis+ NROPrPrP- LTR+
                          10BitTagComp- 10BitTagReq- OBFF Via WAKE#, ExtFmt- EETLPPrefix-
                          EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-
                          FRS- TPHComp- ExtTPHComp-
                          AtomicOpsCap: 32bit- 64bit- 128bitCAS-
                 DevCtl2: Completion Timeout: 16ms to 55ms, TimeoutDis-
                          AtomicOpsCtl: ReqEn-
                          IDOReq- IDOCompl- LTR- EmergencyPowerReductionReq-
                          10BitTagReq- OBFF Disabled, EETLPPrefixBlk-
                 LnkCap2: Supported Link Speeds: 2.5-5GT/s, Crosslink- Retimer- 2Retimers- DRS-
                 LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                          Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                          Compliance Preset/De-emphasis: -6dB de-emphasis, 0dB preshoot
                 LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete- EqualizationPhase1-
                          EqualizationPhase2- EqualizationPhase3- LinkEqualizationRequest-
                          Retimer- 2Retimers- CrosslinkRes: unsupported
         Capabilities: [80] MSI-X: Enable+ Count=16 Masked-
                 Vector table: BAR=0 offset=00002000
                 PBA: BAR=0 offset=00003000
         Capabilities: [100 v1] Advanced Error Reporting
                 UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr- CorrIntErr- HeaderOF-
                 CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr- HeaderOF-
                 AERCap: First Error Pointer: 00, ECRCGenCap- ECRCGenEn- ECRCChkCap- ECRCChkEn-
                         MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
                 HeaderLog: 00000000 00000000 00000000 00000000
         Capabilities: [14c v1] Latency Tolerance Reporting
                 Max snoop latency: 0ns
                 Max no snoop latency: 0ns
         Capabilities: [154 v1] L1 PM Substates
                 L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2+ ASPM_L1.1+ L1_PM_Substates+
                           PortCommonModeRestoreTime=30us PortTPowerOnTime=18us
                 L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2- ASPM_L1.1-
                            T_CommonMode=0us LTR1.2_Threshold=79872ns
                 L1SubCtl2: T_PwrOn=18us
         Kernel driver in use: iwlwifi
         Kernel modules: iwlwifi



From helgaas at kernel.org  Wed Oct 29 10:15:42 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Wed, 29 Oct 2025 12:15:42 -0500
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <DM4PR05MB1027063F8AA9069B66A632C2EC7FAA@DM4PR05MB10270.namprd05.prod.outlook.com>
Message-ID: <20251029171542.GA1566240@bhelgaas>

On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
> On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:

> > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > index 214ed060ca1b..9cd12924b5cb 100644
> > --- a/drivers/pci/quirks.c
> > +++ b/drivers/pci/quirks.c
> > @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
> >    * disable both L0s and L1 for now to be safe.
> >    */
> >   DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> > +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
> >   /*
> >    * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
> 
> I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.

Sorry, my fault, I should have made that fixup run earlier, so the
patch should be this instead:

diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 214ed060ca1b..4fc04015ca0c 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
  * disable both L0s and L1 for now to be safe.
  */
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);


From devnull+chuan.liu.amlogic.com at kernel.org  Wed Oct 29 22:24:13 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Thu, 30 Oct 2025 13:24:13 +0800
Subject: [PATCH v2 3/5] clk: amlogic: Add handling for PLL lock failure
In-Reply-To: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
Message-ID: <20251030-optimize_pll_driver-v2-3-37273f5b25ab@amlogic.com>

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

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 at amlogic.com>
---
 drivers/clk/meson/clk-pll.c | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index f81ebf6cc981..6c794adb8ccd 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);
@@ -397,29 +414,17 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 		meson_parm_write(clk->map, &pll->l_detect, 0);
 	}
 
-	if (meson_clk_pll_wait_lock(hw))
+	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));
+
 		return -EIO;
+	}
 
 	return 0;
 }
 
-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_set_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long parent_rate)
 {

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Wed Oct 29 22:24:11 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Thu, 30 Oct 2025 13:24:11 +0800
Subject: [PATCH v2 1/5] clk: amlogic: Fix out-of-range PLL frequency
 setting
In-Reply-To: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
Message-ID: <20251030-optimize_pll_driver-v2-1-37273f5b25ab@amlogic.com>

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

If the calculated 'm' falls into the range:

    pll->range->max < m < (1 << pll->m.width)

Here an incorrect 'm' value could be obtained, so an additional
condition is added to ensure that the calculated 'm' stays within a
valid range.

Fixes: 8eed1db1adec6 ("clk: meson: pll: update driver for the g12a")
Signed-off-by: Chuan Liu <chuan.liu at 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..629f6af18ea1 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 || *m >= (1 << pll->m.width))
 		return -EINVAL;
 
 	return 0;

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Wed Oct 29 22:24:15 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Thu, 30 Oct 2025 13:24:15 +0800
Subject: [PATCH v2 5/5] clk: amlogic: Change the active level of l_detect
In-Reply-To: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
Message-ID: <20251030-optimize_pll_driver-v2-5-37273f5b25ab@amlogic.com>

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

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

The enable signal is normally active-high. This design ensures that
the module remains disabled during the power-on process, preventing
power fluctuations from affecting its operating state.

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

Here, a flag CLK_MESON_PLL_L_DETECT_N is added to handle cases like
A1, where the signal is active-low.

Signed-off-by: Chuan Liu <chuan.liu at 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 c6eebde1f516..d729e933aa1c 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




From devnull+chuan.liu.amlogic.com at kernel.org  Wed Oct 29 22:24:12 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Thu, 30 Oct 2025 13:24:12 +0800
Subject: [PATCH v2 2/5] clk: amlogic: Improve the issue of PLL lock
 failures
In-Reply-To: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
Message-ID: <20251030-optimize_pll_driver-v2-2-37273f5b25ab@amlogic.com>

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

Due to factors such as temperature and process variations, the
internal circuits of the PLL may require a longer time to reach a
steady state, which can result in occasional lock failures on some
SoCs under low-temperature conditions.

After enabling the PLL and releasing its reset, a 20 us delay is
added at each step to provide enough time for the internal PLL
circuit to stabilize, thus reducing the probability of PLL lock
failure.

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

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 629f6af18ea1..f81ebf6cc981 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -368,11 +368,16 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 
 	/* Enable the pll */
 	meson_parm_write(clk->map, &pll->en, 1);
+	/* Wait for Bandgap and LDO to power up and stabilize */
+	udelay(20);
 
 	/* Take the pll out reset */
 	if (MESON_PARM_APPLICABLE(&pll->rst))
 		meson_parm_write(clk->map, &pll->rst, 0);
 
+	/* Wait for PLL loop stabilization */
+	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

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Wed Oct 29 22:24:14 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Thu, 30 Oct 2025 13:24:14 +0800
Subject: [PATCH v2 4/5] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
Message-ID: <20251030-optimize_pll_driver-v2-4-37273f5b25ab@amlogic.com>

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

l_detect controls the enablement of the PLL lock detection module.
It should remain disabled while the internal PLL circuits are
reaching a steady state; otherwise, the lock signal may be falsely
triggered high.

Before enabling the internal power supply of the PLL, l_detect should
be disabled. After the PLL?s internal circuits have stabilized,
l_detect should be enabled to prevent false lock signal triggers.

Currently, only A1 supports both l_detect and current_en, so this
patch will only affect A1.

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

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 6c794adb8ccd..c6eebde1f516 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -383,36 +383,38 @@ 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);
 	/* Wait for Bandgap and LDO to power up and stabilize */
 	udelay(20);
 
-	/* Take the pll out reset */
-	if (MESON_PARM_APPLICABLE(&pll->rst))
-		meson_parm_write(clk->map, &pll->rst, 0);
-
-	/* Wait for PLL loop stabilization */
-	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, delay for 20us
 	 * 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);
+		udelay(20);
 	}
 
-	if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
-		meson_parm_write(clk->map, &pll->l_detect, 1);
+	/* Take the pll out reset */
+	if (MESON_PARM_APPLICABLE(&pll->rst))
+		meson_parm_write(clk->map, &pll->rst, 0);
+
+	/* Wait for PLL loop stabilization */
+	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_clk_pll_wait_lock(hw)) {
 		/* disable PLL when PLL lock failed. */

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Wed Oct 29 22:24:10 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Thu, 30 Oct 2025 13:24:10 +0800
Subject: [PATCH v2 0/5] clk: amlogic: optimize the PLL driver
Message-ID: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>

This patch series consists of four topics involving the amlogic PLL
driver:
- Fix out-of-range PLL frequency setting
- Improve the issue of PLL lock failures
- Add handling for PLL lock failure
- Optimize PLL enable timing
- Change the active level of l_detect

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

The PLL timing optimization changes were merged into our internal
repository quite some time ago and have been verified on a large
number of SoCs :
- Already supported upstream: G12A, G12B, SM1, S4, A1, C3
- Planned for upstream support: T7, A5, A4, S7, S7D, S6, etc.

Based on the upstream code base, I have performed functional testing
on G12A, A1, A5, A4, T7, S7, S7D, and S6, all of which passed.

Additionally, stress testing using scripts was conducted on A5 and
A1, with over 40,000 and 50,000 iterations respectively, and no
abnormalities were observed. Below is a portion of the stress test
log (CLOCK_ALLOW_WRITE_DEBUGFS has been manually enabled):

- For A5:
  # echo 491520000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
  # cnt=0
  # while true; do
  >     echo "------------ cnt=$cnt -----------"
  >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
  >     if [ "$en" != "1" ]; then
  >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
  >         break
  >     fi
  > 
  >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     cnt=$((cnt + 1))
  >     echo -e "sleep time: 1 s."
  >     sleep 1
  > done &
  # ------------ cnt=0 -----------
  sleep time: 1 s.
  ------------ cnt=1 -----------
  sleep time: 1 s.
  ------------ cnt=2 -----------
  sleep time: 1 s.
  ...
  ------------ cnt=42076 -----------
  sleep time: 1 s.

- For A1:
  # echo 983040000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
  # cnt=0
  # while true; do
  >     echo "------------ cnt=$cnt -----------"
  >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
  >     if [ "$en" != "1" ]; then
  >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
  >         break
  >     fi
  > 
  >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     cnt=$((cnt + 1))
  >     echo -e "sleep time: 1 s."
  >     sleep 1
  > done &
  # ------------ cnt=0 -----------
  sleep time: 1 s.
  ------------ cnt=1 -----------
  sleep time: 1 s.
  ------------ cnt=2 -----------
  sleep time: 1 s.
  ...
  ------------ cnt=55051 -----------
  sleep time: 1 s.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
Changes in v2:
- Modify the judgment condition of 'm' out of range.
- Split the PLL timing optimization patch to make it easier to review.
- Link to v1: https://lore.kernel.org/r/20251022-optimize_pll_driver-v1-0-a275722fb6f4 at amlogic.com

---
Chuan Liu (5):
      clk: amlogic: Fix out-of-range PLL frequency setting
      clk: amlogic: Improve the issue of PLL lock failures
      clk: amlogic: Add handling for PLL lock failure
      clk: amlogic: Optimize PLL enable timing
      clk: amlogic: Change the active level of l_detect

 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 at amlogic.com>




From jbrunet at baylibre.com  Thu Oct 30 01:32:26 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 30 Oct 2025 09:32:26 +0100
Subject: [PATCH v2 3/5] clk: amlogic: Add handling for PLL lock failure
In-Reply-To: <20251030-optimize_pll_driver-v2-3-37273f5b25ab@amlogic.com>
	(Chuan Liu via's message of "Thu, 30 Oct 2025 13:24:13 +0800")
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
	<20251030-optimize_pll_driver-v2-3-37273f5b25ab@amlogic.com>
Message-ID: <1jikfwzt5x.fsf@starbuckisacylon.baylibre.com>

On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:

> From: Chuan Liu <chuan.liu at amlogic.com>
>
> 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 at amlogic.com>
> ---
>  drivers/clk/meson/clk-pll.c | 41 +++++++++++++++++++++++------------------
>  1 file changed, 23 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index f81ebf6cc981..6c794adb8ccd 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);
> @@ -397,29 +414,17 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>  		meson_parm_write(clk->map, &pll->l_detect, 0);
>  	}
>  
> -	if (meson_clk_pll_wait_lock(hw))
> +	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));
> +

This is something that's likely to spam, so pr_warn_once() (if you must warn)
and I don't think 3 "!" are necessary to convey the message.

>  		return -EIO;
> +	}
>  
>  	return 0;
>  }
>  
> -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_set_rate(struct clk_hw *hw, unsigned long rate,
>  				  unsigned long parent_rate)
>  {

-- 
Jerome


From jbrunet at baylibre.com  Thu Oct 30 01:38:29 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 30 Oct 2025 09:38:29 +0100
Subject: [PATCH v2 4/5] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <20251030-optimize_pll_driver-v2-4-37273f5b25ab@amlogic.com>
	(Chuan Liu via's message of "Thu, 30 Oct 2025 13:24:14 +0800")
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
	<20251030-optimize_pll_driver-v2-4-37273f5b25ab@amlogic.com>
Message-ID: <1ja518zsvu.fsf@starbuckisacylon.baylibre.com>

On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:

> From: Chuan Liu <chuan.liu at amlogic.com>
>
> l_detect controls the enablement of the PLL lock detection module.
> It should remain disabled while the internal PLL circuits are
> reaching a steady state; otherwise, the lock signal may be falsely
> triggered high.
>
> Before enabling the internal power supply of the PLL, l_detect should
> be disabled. After the PLL?s internal circuits have stabilized,
> l_detect should be enabled to prevent false lock signal triggers.

You to reformat this description. It feel that both paragraph are saying
the same thing.

>
> Currently, only A1 supports both l_detect and current_en, so this
> patch will only affect A1.
>
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
>  drivers/clk/meson/clk-pll.c | 28 +++++++++++++++-------------
>  1 file changed, 15 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 6c794adb8ccd..c6eebde1f516 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -383,36 +383,38 @@ 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);
>  	/* Wait for Bandgap and LDO to power up and stabilize */
>  	udelay(20);
>  
> -	/* Take the pll out reset */
> -	if (MESON_PARM_APPLICABLE(&pll->rst))
> -		meson_parm_write(clk->map, &pll->rst, 0);

Why is the reset moving around ? nothing is said in the description about
that

> -
> -	/* Wait for PLL loop stabilization */
> -	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, delay for 20us
>  	 * 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);
> +		udelay(20);
>  	}
>  
> -	if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
> -		meson_parm_write(clk->map, &pll->l_detect, 1);
> +	/* Take the pll out reset */
> +	if (MESON_PARM_APPLICABLE(&pll->rst))
> +		meson_parm_write(clk->map, &pll->rst, 0);
> +
> +	/* Wait for PLL loop stabilization */
> +	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_clk_pll_wait_lock(hw)) {
>  		/* disable PLL when PLL lock failed. */

-- 
Jerome


From jbrunet at baylibre.com  Thu Oct 30 01:40:43 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 30 Oct 2025 09:40:43 +0100
Subject: [PATCH v2 5/5] clk: amlogic: Change the active level of l_detect
In-Reply-To: <20251030-optimize_pll_driver-v2-5-37273f5b25ab@amlogic.com>
	(Chuan Liu via's message of "Thu, 30 Oct 2025 13:24:15 +0800")
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
	<20251030-optimize_pll_driver-v2-5-37273f5b25ab@amlogic.com>
Message-ID: <1j4irgzss4.fsf@starbuckisacylon.baylibre.com>

On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:

> From: Chuan Liu <chuan.liu at amlogic.com>
>
> l_detect controls the enable/disable of the PLL lock-detect module.
>
> The enable signal is normally active-high. This design ensures that
> the module remains disabled during the power-on process, preventing
> power fluctuations from affecting its operating state.
>
> For A1, the l_detect signal is active-low:
> 0 -> Enable lock-detect module;
> 1 -> Disable lock-detect module.
>
> Here, a flag CLK_MESON_PLL_L_DETECT_N is added to handle cases like
> A1, where the signal is active-low.

Given that A1 is the only ship supporting l_detect, this change is not
necessary.

Not now at least.

>
> Signed-off-by: Chuan Liu <chuan.liu at 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 c6eebde1f516..d729e933aa1c 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;

-- 
Jerome


From jbrunet at baylibre.com  Thu Oct 30 01:41:07 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 30 Oct 2025 09:41:07 +0100
Subject: [PATCH v2 2/5] clk: amlogic: Improve the issue of PLL lock
 failures
In-Reply-To: <20251030-optimize_pll_driver-v2-2-37273f5b25ab@amlogic.com>
	(Chuan Liu via's message of "Thu, 30 Oct 2025 13:24:12 +0800")
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
	<20251030-optimize_pll_driver-v2-2-37273f5b25ab@amlogic.com>
Message-ID: <1jy0osye70.fsf@starbuckisacylon.baylibre.com>

On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:

> From: Chuan Liu <chuan.liu at amlogic.com>
>
> Due to factors such as temperature and process variations, the
> internal circuits of the PLL may require a longer time to reach a
> steady state, which can result in occasional lock failures on some
> SoCs under low-temperature conditions.
>
> After enabling the PLL and releasing its reset, a 20 us delay is
> added at each step to provide enough time for the internal PLL
> circuit to stabilize, thus reducing the probability of PLL lock
> failure.
>
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
>  drivers/clk/meson/clk-pll.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 629f6af18ea1..f81ebf6cc981 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -368,11 +368,16 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>  
>  	/* Enable the pll */
>  	meson_parm_write(clk->map, &pll->en, 1);

New line

> +	/* Wait for Bandgap and LDO to power up and stabilize */
> +	udelay(20);
>  
>  	/* Take the pll out reset */
>  	if (MESON_PARM_APPLICABLE(&pll->rst))
>  		meson_parm_write(clk->map, &pll->rst, 0);
>  
> +	/* Wait for PLL loop stabilization */
> +	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

-- 
Jerome


From jbrunet at baylibre.com  Thu Oct 30 01:45:41 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Thu, 30 Oct 2025 09:45:41 +0100
Subject: [PATCH 2/3] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <61c2738d-7291-4a45-aa73-f18528c81ba8@amlogic.com> (Chuan Liu's
	message of "Wed, 22 Oct 2025 22:07:43 +0800")
References: <20251022-optimize_pll_driver-v1-0-a275722fb6f4@amlogic.com>
	<20251022-optimize_pll_driver-v1-2-a275722fb6f4@amlogic.com>
	<1j347b403i.fsf@starbuckisacylon.baylibre.com>
	<61c2738d-7291-4a45-aa73-f18528c81ba8@amlogic.com>
Message-ID: <1jsef0ydze.fsf@starbuckisacylon.baylibre.com>

On Wed 22 Oct 2025 at 22:07, Chuan Liu <chuan.liu at 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 at kernel.org> wrote:
>> 
>>> From: Chuan Liu <chuan.liu at 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 at 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


From chuan.liu at amlogic.com  Thu Oct 30 02:09:07 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Thu, 30 Oct 2025 17:09:07 +0800
Subject: [PATCH v2 2/5] clk: amlogic: Improve the issue of PLL lock
 failures
In-Reply-To: <1jy0osye70.fsf@starbuckisacylon.baylibre.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
 <20251030-optimize_pll_driver-v2-2-37273f5b25ab@amlogic.com>
 <1jy0osye70.fsf@starbuckisacylon.baylibre.com>
Message-ID: <c9920642-a4d2-41a1-a3ed-2af12a712e24@amlogic.com>

Hi Jerome,

On 10/30/2025 4:41 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu at amlogic.com>
>>
>> Due to factors such as temperature and process variations, the
>> internal circuits of the PLL may require a longer time to reach a
>> steady state, which can result in occasional lock failures on some
>> SoCs under low-temperature conditions.
>>
>> After enabling the PLL and releasing its reset, a 20 us delay is
>> added at each step to provide enough time for the internal PLL
>> circuit to stabilize, thus reducing the probability of PLL lock
>> failure.
>>
>> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
>> ---
>>   drivers/clk/meson/clk-pll.c | 5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>> index 629f6af18ea1..f81ebf6cc981 100644
>> --- a/drivers/clk/meson/clk-pll.c
>> +++ b/drivers/clk/meson/clk-pll.c
>> @@ -368,11 +368,16 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>>
>>        /* Enable the pll */
>>        meson_parm_write(clk->map, &pll->en, 1);
> 
> New line

Ok, fix it in the next version.

> 
>> +     /* Wait for Bandgap and LDO to power up and stabilize */
>> +     udelay(20);
>>
>>        /* Take the pll out reset */
>>        if (MESON_PARM_APPLICABLE(&pll->rst))
>>                meson_parm_write(clk->map, &pll->rst, 0);
>>
>> +     /* Wait for PLL loop stabilization */
>> +     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
> 
> --
> Jerome



From chuan.liu at amlogic.com  Thu Oct 30 02:15:22 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Thu, 30 Oct 2025 17:15:22 +0800
Subject: [PATCH v2 3/5] clk: amlogic: Add handling for PLL lock failure
In-Reply-To: <1jikfwzt5x.fsf@starbuckisacylon.baylibre.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
 <20251030-optimize_pll_driver-v2-3-37273f5b25ab@amlogic.com>
 <1jikfwzt5x.fsf@starbuckisacylon.baylibre.com>
Message-ID: <4f245c6a-5a03-4321-bbf8-61249a7a550f@amlogic.com>

Hi Jerome,

On 10/30/2025 4:32 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu at amlogic.com>
>>
>> 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 at amlogic.com>
>> ---
>>   drivers/clk/meson/clk-pll.c | 41 +++++++++++++++++++++++------------------
>>   1 file changed, 23 insertions(+), 18 deletions(-)
>>
>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>> index f81ebf6cc981..6c794adb8ccd 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);
>> @@ -397,29 +414,17 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>>                meson_parm_write(clk->map, &pll->l_detect, 0);
>>        }
>>
>> -     if (meson_clk_pll_wait_lock(hw))
>> +     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));
>> +
> 
> This is something that's likely to spam, so pr_warn_once() (if you must warn)
> and I don't think 3 "!" are necessary to convey the message.
> 

In the next version, I'll remove the "!", and replace pr_warn to
pr_warn_once.

Some drivers that reference the clock may not check the function?s
return value (even though that's not ideal), so adding this warning
makes the issue more noticeable.

>>                return -EIO;
>> +     }
>>
>>        return 0;
>>   }
>>
>> -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_set_rate(struct clk_hw *hw, unsigned long rate,
>>                                  unsigned long parent_rate)
>>   {
> 
> --
> Jerome



From chuan.liu at amlogic.com  Thu Oct 30 02:23:29 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Thu, 30 Oct 2025 17:23:29 +0800
Subject: [PATCH v2 4/5] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <1ja518zsvu.fsf@starbuckisacylon.baylibre.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
 <20251030-optimize_pll_driver-v2-4-37273f5b25ab@amlogic.com>
 <1ja518zsvu.fsf@starbuckisacylon.baylibre.com>
Message-ID: <1c1b699a-6ebe-4c6c-b818-44da8e1bd79c@amlogic.com>

Hi Jerome,

On 10/30/2025 4:38 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu at amlogic.com>
>>
>> l_detect controls the enablement of the PLL lock detection module.
>> It should remain disabled while the internal PLL circuits are
>> reaching a steady state; otherwise, the lock signal may be falsely
>> triggered high.
>>
>> Before enabling the internal power supply of the PLL, l_detect should
>> be disabled. After the PLL?s internal circuits have stabilized,
>> l_detect should be enabled to prevent false lock signal triggers.
> 
> You to reformat this description. It feel that both paragraph are saying
> the same thing.
> 

Ok, drop it.

>>
>> Currently, only A1 supports both l_detect and current_en, so this
>> patch will only affect A1.
>>
>> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
>> ---
>>   drivers/clk/meson/clk-pll.c | 28 +++++++++++++++-------------
>>   1 file changed, 15 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>> index 6c794adb8ccd..c6eebde1f516 100644
>> --- a/drivers/clk/meson/clk-pll.c
>> +++ b/drivers/clk/meson/clk-pll.c
>> @@ -383,36 +383,38 @@ 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);
>>        /* Wait for Bandgap and LDO to power up and stabilize */
>>        udelay(20);
>>
>> -     /* Take the pll out reset */
>> -     if (MESON_PARM_APPLICABLE(&pll->rst))
>> -             meson_parm_write(clk->map, &pll->rst, 0);
> 
> Why is the reset moving around ? nothing is said in the description about
> that
> 

The function of current_en in the PLL is similar to en. It's more
reliable to assert the reset signal after current_en is set high.

I'll update the commit description accordingly in the next version.

>> -
>> -     /* Wait for PLL loop stabilization */
>> -     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, delay for 20us
>>         * 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);
>> +             udelay(20);
>>        }
>>
>> -     if (MESON_PARM_APPLICABLE(&pll->l_detect)) {
>> -             meson_parm_write(clk->map, &pll->l_detect, 1);
>> +     /* Take the pll out reset */
>> +     if (MESON_PARM_APPLICABLE(&pll->rst))
>> +             meson_parm_write(clk->map, &pll->rst, 0);
>> +
>> +     /* Wait for PLL loop stabilization */
>> +     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_clk_pll_wait_lock(hw)) {
>>                /* disable PLL when PLL lock failed. */
> 
> --
> Jerome



From chuan.liu at amlogic.com  Thu Oct 30 02:27:32 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Thu, 30 Oct 2025 17:27:32 +0800
Subject: [PATCH v2 5/5] clk: amlogic: Change the active level of l_detect
In-Reply-To: <1j4irgzss4.fsf@starbuckisacylon.baylibre.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
 <20251030-optimize_pll_driver-v2-5-37273f5b25ab@amlogic.com>
 <1j4irgzss4.fsf@starbuckisacylon.baylibre.com>
Message-ID: <7e95df48-8f27-47ab-a5e8-5bc0777d41b9@amlogic.com>

Hi Jerome,

On 10/30/2025 4:40 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
> 
>> From: Chuan Liu <chuan.liu at amlogic.com>
>>
>> l_detect controls the enable/disable of the PLL lock-detect module.
>>
>> The enable signal is normally active-high. This design ensures that
>> the module remains disabled during the power-on process, preventing
>> power fluctuations from affecting its operating state.
>>
>> For A1, the l_detect signal is active-low:
>> 0 -> Enable lock-detect module;
>> 1 -> Disable lock-detect module.
>>
>> Here, a flag CLK_MESON_PLL_L_DETECT_N is added to handle cases like
>> A1, where the signal is active-low.
> 
> Given that A1 is the only ship supporting l_detect, this change is not
> necessary.
> 
> Not now at least.
> 

The SoCs queued for upstreaming later will depend on this patch, so I
included it in this patchset.

If that?s not appropriate, would it be acceptable for me to include
it in the A4 submission instead?

>>
>> Signed-off-by: Chuan Liu <chuan.liu at 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 c6eebde1f516..d729e933aa1c 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;
> 
> --
> Jerome



From jian.hu at amlogic.com  Thu Oct 30 02:43:40 2025
From: jian.hu at amlogic.com (Jian Hu)
Date: Thu, 30 Oct 2025 17:43:40 +0800
Subject: [PATCH v4 0/5] add support for T7 family clock controller
Message-ID: <20251030094345.2571222-1-jian.hu@amlogic.com>

It introduces three clock controllers:
- SCMI clock controller: these clocks are managed by the SCP and handled through SCMI.
- PLL clock controller.
- peripheral clock controller.

Changes v4 since v4 at [2]:
- drop amlogic_t7_pll_probe, use meson_clkc_mmio_probe instead
- add CLK_DIVIDER_MAX_AT_ZERO for pcie_pll_od clk
- add frac for hifi_dco_pll_dco
- add l_detect for mclk_pll_dco
- drop v3 5/6 patch, and use MESON_PCLK
- drop SPI_PWM_CLK_XX macro and use MESON_COMP_XX
- drop the register's prefix

Changes v3 since v2 at [2]:
- update T7 PLL YAML
- add 't7_' prefix for t7 clock name and variable in t7-pll.c and t7-peripherals.c
- correct v1 patch link
- add new macro MESON_PCLK_V2
- update the driver,header,yaml file license

Changes v2 since v1 at [1]:
- add CLK_MESON import
- add const for clkc_regmap_config in PLL driver
- fix eth_rmii_sel parent
- update T7 PLL YAML file

[1]: https://lore.kernel.org/all/20241231060047.2298871-1-jian.hu at amlogic.com
[2]: https://lore.kernel.org/all/20250108094025.2664201-1-jian.hu at amlogic.com
[3]: https://lore.kernel.org/all/20250509074825.1933254-1-jian.hu at amlogic.com

Jian Hu (5):
  dt-bindings: clock: add Amlogic T7 PLL clock controller
  dt-bindings: clock: add Amlogic T7 SCMI clock controller
  dt-bindings: clock: add Amlogic T7 peripherals clock controller
  clk: meson: t7: add support for the T7 SoC PLL clock
  clk: meson: t7: add t7 clock peripherals controller driver

 .../clock/amlogic,t7-peripherals-clkc.yaml    |  112 ++
 .../bindings/clock/amlogic,t7-pll-clkc.yaml   |  114 ++
 drivers/clk/meson/Kconfig                     |   27 +
 drivers/clk/meson/Makefile                    |    2 +
 drivers/clk/meson/t7-peripherals.c            | 1734 +++++++++++++++++
 drivers/clk/meson/t7-pll.c                    | 1068 ++++++++++
 .../clock/amlogic,t7-peripherals-clkc.h       |  230 +++
 .../dt-bindings/clock/amlogic,t7-pll-clkc.h   |   56 +
 include/dt-bindings/clock/amlogic,t7-scmi.h   |   47 +
 9 files changed, 3390 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,t7-peripherals-clkc.yaml
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,t7-pll-clkc.yaml
 create mode 100644 drivers/clk/meson/t7-peripherals.c
 create mode 100644 drivers/clk/meson/t7-pll.c
 create mode 100644 include/dt-bindings/clock/amlogic,t7-peripherals-clkc.h
 create mode 100644 include/dt-bindings/clock/amlogic,t7-pll-clkc.h
 create mode 100644 include/dt-bindings/clock/amlogic,t7-scmi.h

-- 
2.47.1



From jian.hu at amlogic.com  Thu Oct 30 02:43:41 2025
From: jian.hu at amlogic.com (Jian Hu)
Date: Thu, 30 Oct 2025 17:43:41 +0800
Subject: [PATCH v4 1/5] dt-bindings: clock: add Amlogic T7 PLL clock controller
In-Reply-To: <20251030094345.2571222-1-jian.hu@amlogic.com>
References: <20251030094345.2571222-1-jian.hu@amlogic.com>
Message-ID: <20251030094345.2571222-2-jian.hu@amlogic.com>

Add DT bindings for the PLL clock controller of the Amlogic T7 SoC family.

Signed-off-by: Jian Hu <jian.hu at amlogic.com>
Reviewed-by: Conor Dooley <conor.dooley at microchip.com>
---
 .../bindings/clock/amlogic,t7-pll-clkc.yaml   | 114 ++++++++++++++++++
 .../dt-bindings/clock/amlogic,t7-pll-clkc.h   |  56 +++++++++
 2 files changed, 170 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,t7-pll-clkc.yaml
 create mode 100644 include/dt-bindings/clock/amlogic,t7-pll-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,t7-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,t7-pll-clkc.yaml
new file mode 100644
index 000000000000..49c61f65deff
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,t7-pll-clkc.yaml
@@ -0,0 +1,114 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,t7-pll-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic T7 PLL Clock Control Controller
+
+maintainers:
+  - Neil Armstrong <neil.armstrong at linaro.org>
+  - Jerome Brunet <jbrunet at baylibre.com>
+  - Jian Hu <jian.hu at amlogic.com>
+  - Xianwei Zhao <xianwei.zhao at amlogic.com>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,t7-gp0-pll
+      - amlogic,t7-gp1-pll
+      - amlogic,t7-hifi-pll
+      - amlogic,t7-pcie-pll
+      - amlogic,t7-mpll
+      - amlogic,t7-hdmi-pll
+      - amlogic,t7-mclk-pll
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+
+  clocks:
+    items:
+      - description: mclk pll input oscillator gate
+      - description: oscillator input clock source for mclk_sel_0
+      - description: fixed input clock source for mclk_sel_0
+    minItems: 1
+
+  clock-names:
+    items:
+      - const: in0
+      - const: in1
+      - const: in2
+    minItems: 1
+
+required:
+  - compatible
+  - '#clock-cells'
+  - reg
+  - clocks
+  - clock-names
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: amlogic,t7-mclk-pll
+
+    then:
+      properties:
+        clocks:
+          minItems: 3
+
+        clock-names:
+          minItems: 3
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amlogic,t7-gp0-pll
+              - amlogic,t7-gp1--pll
+              - amlogic,t7-hifi-pll
+              - amlogic,t7-pcie-pll
+              - amlogic,t7-mpll
+              - amlogic,t7-hdmi-pll
+
+    then:
+      properties:
+        clocks:
+          maxItems: 1
+
+        clock-names:
+          maxItems: 1
+
+additionalProperties: false
+
+examples:
+  - |
+    apb {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        clock-controller at 8080 {
+            compatible = "amlogic,t7-gp0-pll";
+            reg = <0 0x8080 0 0x20>;
+            clocks = <&scmi_clk 2>;
+            clock-names = "in0";
+            #clock-cells = <1>;
+        };
+
+        clock-controller at 8300 {
+            compatible = "amlogic,t7-mclk-pll";
+            reg = <0 0x8300 0 0x18>;
+            clocks = <&scmi_clk 2>,
+                     <&xtal>,
+                     <&scmi_clk 31>;
+            clock-names = "in0", "in1", "in2";
+            #clock-cells = <1>;
+        };
+    };
diff --git a/include/dt-bindings/clock/amlogic,t7-pll-clkc.h b/include/dt-bindings/clock/amlogic,t7-pll-clkc.h
new file mode 100644
index 000000000000..e2481f2f1163
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,t7-pll-clkc.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef __T7_PLL_CLKC_H
+#define __T7_PLL_CLKC_H
+
+/* GP0 */
+#define CLKID_GP0_PLL_DCO	0
+#define CLKID_GP0_PLL		1
+
+/* GP1 */
+#define CLKID_GP1_PLL_DCO	0
+#define CLKID_GP1_PLL		1
+
+/* HIFI */
+#define CLKID_HIFI_PLL_DCO	0
+#define CLKID_HIFI_PLL		1
+
+/* PCIE */
+#define CLKID_PCIE_PLL_DCO	0
+#define CLKID_PCIE_PLL_DCO_DIV2	1
+#define CLKID_PCIE_PLL_OD	2
+#define CLKID_PCIE_PLL		3
+
+/* MPLL */
+#define CLKID_MPLL_PREDIV	0
+#define CLKID_MPLL0_DIV		1
+#define CLKID_MPLL0		2
+#define CLKID_MPLL1_DIV		3
+#define CLKID_MPLL1		4
+#define CLKID_MPLL2_DIV		5
+#define CLKID_MPLL2		6
+#define CLKID_MPLL3_DIV		7
+#define CLKID_MPLL3		8
+
+/* HDMI */
+#define CLKID_HDMI_PLL_DCO	0
+#define CLKID_HDMI_PLL_OD	1
+#define CLKID_HDMI_PLL		2
+
+/* MCLK */
+#define CLKID_MCLK_PLL_DCO	0
+#define CLKID_MCLK_PRE		1
+#define CLKID_MCLK_PLL		2
+#define CLKID_MCLK_0_SEL	3
+#define CLKID_MCLK_0_DIV2	4
+#define CLKID_MCLK_0_PRE	5
+#define CLKID_MCLK_0		6
+#define CLKID_MCLK_1_SEL	7
+#define CLKID_MCLK_1_DIV2	8
+#define CLKID_MCLK_1_PRE	9
+#define CLKID_MCLK_1		10
+
+#endif /* __T7_PLL_CLKC_H */
-- 
2.47.1



From jian.hu at amlogic.com  Thu Oct 30 02:43:42 2025
From: jian.hu at amlogic.com (Jian Hu)
Date: Thu, 30 Oct 2025 17:43:42 +0800
Subject: [PATCH v4 2/5] dt-bindings: clock: add Amlogic T7 SCMI clock controller
In-Reply-To: <20251030094345.2571222-1-jian.hu@amlogic.com>
References: <20251030094345.2571222-1-jian.hu@amlogic.com>
Message-ID: <20251030094345.2571222-3-jian.hu@amlogic.com>

Add DT bindings for the SCMI clock controller of the Amlogic T7 SoC family.

Signed-off-by: Jian Hu <jian.hu at amlogic.com>
Acked-by: Rob Herring (Arm) <robh at kernel.org>
---
 include/dt-bindings/clock/amlogic,t7-scmi.h | 47 +++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 include/dt-bindings/clock/amlogic,t7-scmi.h

diff --git a/include/dt-bindings/clock/amlogic,t7-scmi.h b/include/dt-bindings/clock/amlogic,t7-scmi.h
new file mode 100644
index 000000000000..27bd257bd4ea
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,t7-scmi.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef __T7_SCMI_CLKC_H
+#define __T7_SCMI_CLKC_H
+
+#define CLKID_DDR_PLL_OSC			0
+#define CLKID_AUD_PLL_OSC			1
+#define CLKID_TOP_PLL_OSC			2
+#define CLKID_TCON_PLL_OSC			3
+#define CLKID_USB_PLL0_OSC			4
+#define CLKID_USB_PLL1_OSC			5
+#define CLKID_MCLK_PLL_OSC			6
+#define CLKID_PCIE_OSC				7
+#define CLKID_ETH_PLL_OSC			8
+#define CLKID_PCIE_REFCLK_PLL_OSC		9
+#define CLKID_EARC_OSC				10
+#define CLKID_SYS1_PLL_OSC			11
+#define CLKID_HDMI_PLL_OSC			12
+#define CLKID_SYS_CLK				13
+#define CLKID_AXI_CLK				14
+#define CLKID_FIXED_PLL_DCO			15
+#define CLKID_FIXED_PLL				16
+#define CLKID_FCLK_DIV2_DIV			17
+#define CLKID_FCLK_DIV2				18
+#define CLKID_FCLK_DIV2P5_DIV			19
+#define CLKID_FCLK_DIV2P5			20
+#define CLKID_FCLK_DIV3_DIV			21
+#define CLKID_FCLK_DIV3				22
+#define CLKID_FCLK_DIV4_DIV			23
+#define CLKID_FCLK_DIV4				24
+#define CLKID_FCLK_DIV5_DIV			25
+#define CLKID_FCLK_DIV5				26
+#define CLKID_FCLK_DIV7_DIV			27
+#define CLKID_FCLK_DIV7				28
+#define CLKID_FCLK_50M_DIV			29
+#define CLKID_FCLK_50M				30
+#define CLKID_CPU_CLK				31
+#define CLKID_A73_CLK				32
+#define CLKID_CPU_CLK_DIV16_DIV			33
+#define CLKID_CPU_CLK_DIV16			34
+#define CLKID_A73_CLK_DIV16_DIV			35
+#define CLKID_A73_CLK_DIV16			36
+
+#endif /* __T7_SCMI_CLKC_H */
-- 
2.47.1



From jian.hu at amlogic.com  Thu Oct 30 02:43:43 2025
From: jian.hu at amlogic.com (Jian Hu)
Date: Thu, 30 Oct 2025 17:43:43 +0800
Subject: [PATCH v4 3/5] dt-bindings: clock: add Amlogic T7 peripherals clock controller
In-Reply-To: <20251030094345.2571222-1-jian.hu@amlogic.com>
References: <20251030094345.2571222-1-jian.hu@amlogic.com>
Message-ID: <20251030094345.2571222-4-jian.hu@amlogic.com>

Add DT bindings for the peripheral clock controller of the Amlogic T7
SoC family.

Signed-off-by: Jian Hu <jian.hu at amlogic.com>
Reviewed-by: Rob Herring (Arm) <robh at kernel.org>
---
 .../clock/amlogic,t7-peripherals-clkc.yaml    | 112 +++++++++
 .../clock/amlogic,t7-peripherals-clkc.h       | 230 ++++++++++++++++++
 2 files changed, 342 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/amlogic,t7-peripherals-clkc.yaml
 create mode 100644 include/dt-bindings/clock/amlogic,t7-peripherals-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,t7-peripherals-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,t7-peripherals-clkc.yaml
new file mode 100644
index 000000000000..bced13c0ff50
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,t7-peripherals-clkc.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,t7-peripherals-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic T7 Peripherals Clock Controller
+
+maintainers:
+  - Neil Armstrong <neil.armstrong at linaro.org>
+  - Jerome Brunet <jbrunet at baylibre.com>
+  - Xianwei Zhao <xianwei.zhao at amlogic.com>
+  - Jian Hu <jian.hu at amlogic.com>
+
+properties:
+  compatible:
+    const: amlogic,t7-peripherals-clkc
+
+  reg:
+    maxItems: 1
+
+  '#clock-cells':
+    const: 1
+
+  clocks:
+    minItems: 13
+    items:
+      - description: input oscillator
+      - description: input sys clk
+      - description: input fclk div 2
+      - description: input fclk div 2p5
+      - description: input fclk div 3
+      - description: input fclk div 4
+      - description: input fclk div 5
+      - description: input fclk div 7
+      - description: input hifi pll
+      - description: input gp0 pll
+      - description: input gp1 pll
+      - description: input mpll1
+      - description: input mpll2
+      - description: external input rmii oscillator (optional)
+      - description: input video pll0 (optional)
+      - description: external pad input for rtc (optional)
+
+  clock-names:
+    minItems: 13
+    items:
+      - const: xtal
+      - const: sys
+      - const: fdiv2
+      - const: fdiv2p5
+      - const: fdiv3
+      - const: fdiv4
+      - const: fdiv5
+      - const: fdiv7
+      - const: hifi
+      - const: gp0
+      - const: gp1
+      - const: mpll1
+      - const: mpll2
+      - const: ext_rmii
+      - const: vid_pll0
+      - const: ext_rtc
+
+required:
+  - compatible
+  - '#clock-cells'
+  - reg
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    apb {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        clkc_periphs:clock-controller at 0 {
+            compatible = "amlogic,t7-peripherals-clkc";
+            reg = <0 0x0 0 0x1c8>;
+            #clock-cells = <1>;
+            clocks = <&xtal>,
+                     <&scmi_clk 13>,
+                     <&scmi_clk 18>,
+                     <&scmi_clk 20>,
+                     <&scmi_clk 22>,
+                     <&scmi_clk 24>,
+                     <&scmi_clk 26>,
+                     <&scmi_clk 28>,
+                     <&hifi 1>,
+                     <&gp0 1>,
+                     <&gp1 1>,
+                     <&mpll 4>,
+                     <&mpll 6>;
+            clock-names = "xtal",
+                          "sys",
+                          "fdiv2",
+                          "fdiv2p5",
+                          "fdiv3",
+                          "fdiv4",
+                          "fdiv5",
+                          "fdiv7",
+                          "hifi",
+                          "gp0",
+                          "gp1",
+                          "mpll1",
+                          "mpll2";
+        };
+    };
diff --git a/include/dt-bindings/clock/amlogic,t7-peripherals-clkc.h b/include/dt-bindings/clock/amlogic,t7-peripherals-clkc.h
new file mode 100644
index 000000000000..7b93f5027876
--- /dev/null
+++ b/include/dt-bindings/clock/amlogic,t7-peripherals-clkc.h
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
+/*
+ * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved
+ */
+
+#ifndef __T7_PERIPHERALS_CLKC_H
+#define __T7_PERIPHERALS_CLKC_H
+
+#define CLKID_RTC_32K_IN		0
+#define CLKID_RTC_32K_DIV		1
+#define CLKID_RTC_32K_FORCE_SEL		2
+#define CLKID_RTC_32K_OUT		3
+#define CLKID_RTC_32K_MUX0_0		4
+#define CLKID_RTC_32K_MUX0_1		5
+#define CLKID_RTC			6
+#define CLKID_CECB_32K_IN		7
+#define CLKID_CECB_32K_DIV		8
+#define CLKID_CECB_32K_SEL_PRE		9
+#define CLKID_CECB_32K_SEL		10
+#define CLKID_CECA_32K_IN		11
+#define CLKID_CECA_32K_DIV		12
+#define CLKID_CECA_32K_SEL_PRE		13
+#define CLKID_CECA_32K_SEL		14
+#define CLKID_CECA_32K			15
+#define CLKID_CECB_32K			16
+#define CLKID_SC_SEL			17
+#define CLKID_SC_DIV			18
+#define CLKID_SC			19
+#define CLKID_DSPA_A_SEL		20
+#define CLKID_DSPA_A_DIV		21
+#define CLKID_DSPA_A			22
+#define CLKID_DSPA_B_SEL		23
+#define CLKID_DSPA_B_DIV		24
+#define CLKID_DSPA_B			25
+#define CLKID_DSPA			26
+#define CLKID_DSPB_A_SEL		27
+#define CLKID_DSPB_A_DIV		28
+#define CLKID_DSPB_A			29
+#define CLKID_DSPB_B_SEL		30
+#define CLKID_DSPB_B_DIV		31
+#define CLKID_DSPB_B			32
+#define CLKID_DSPB			33
+#define CLKID_CLK_24M			34
+#define CLKID_CLK_24M_DIV2		35
+#define CLKID_CLK_12M			36
+#define CLKID_ANAKIN_0_SEL		37
+#define CLKID_ANAKIN_0_DIV		38
+#define CLKID_ANAKIN_0			39
+#define CLKID_ANAKIN_1_SEL		40
+#define CLKID_ANAKIN_1_DIV		41
+#define CLKID_ANAKIN_1			42
+#define CLKID_ANAKIN			43
+#define CLKID_ANAKIN_CLK		44
+#define CLKID_FCLK_DIV2_DIVN_PRE	45
+#define CLKID_FCLK_DIV2_DIVN		46
+#define CLKID_TS_DIV			47
+#define CLKID_TS			48
+#define CLKID_MIPI_CSI_PHY_0_SEL	49
+#define CLKID_MIPI_CSI_PHY_0_DIV	50
+#define CLKID_MIPI_CSI_PHY_0		51
+#define CLKID_MIPI_CSI_PHY_1_SEL	52
+#define CLKID_MIPI_CSI_PHY_1_DIV	53
+#define CLKID_MIPI_CSI_PHY_1		54
+#define CLKID_MIPI_CSI_PHY		55
+#define CLKID_MIPI_ISP_SEL		56
+#define CLKID_MIPI_ISP_DIV		57
+#define CLKID_MIPI_ISP			58
+#define CLKID_MALI_0_SEL		59
+#define CLKID_MALI_0_DIV		60
+#define CLKID_MALI_0			61
+#define CLKID_MALI_1_SEL		62
+#define CLKID_MALI_1_DIV		63
+#define CLKID_MALI_1			64
+#define CLKID_MALI			65
+#define CLKID_ETH_RMII_SEL		66
+#define CLKID_ETH_RMII_DIV		67
+#define CLKID_ETH_RMII			68
+#define CLKID_FCLK_DIV2_DIV8		69
+#define CLKID_ETH_125M			70
+#define CLKID_SD_EMMC_C_SEL		71
+#define CLKID_SD_EMMC_C_DIV		72
+#define CLKID_SD_EMMC_C			73
+#define CLKID_SD_EMMC_A_SEL		74
+#define CLKID_SD_EMMC_A_DIV		75
+#define CLKID_SD_EMMC_A			76
+#define CLKID_SD_EMMC_B_SEL		77
+#define CLKID_SD_EMMC_B_DIV		78
+#define CLKID_SD_EMMC_B			79
+#define CLKID_SPICC0_SEL		80
+#define CLKID_SPICC0_DIV		81
+#define CLKID_SPICC0			82
+#define CLKID_SPICC1_SEL		83
+#define CLKID_SPICC1_DIV		84
+#define CLKID_SPICC1			85
+#define CLKID_SPICC2_SEL		86
+#define CLKID_SPICC2_DIV		87
+#define CLKID_SPICC2			88
+#define CLKID_SPICC3_SEL		89
+#define CLKID_SPICC3_DIV		90
+#define CLKID_SPICC3			91
+#define CLKID_SPICC4_SEL		92
+#define CLKID_SPICC4_DIV		93
+#define CLKID_SPICC4			94
+#define CLKID_SPICC5_SEL		95
+#define CLKID_SPICC5_DIV		96
+#define CLKID_SPICC5			97
+#define CLKID_SARADC_SEL		98
+#define CLKID_SARADC_DIV		99
+#define CLKID_SARADC			100
+#define CLKID_PWM_A_SEL			101
+#define CLKID_PWM_A_DIV			102
+#define CLKID_PWM_A			103
+#define CLKID_PWM_B_SEL			104
+#define CLKID_PWM_B_DIV			105
+#define CLKID_PWM_B			106
+#define CLKID_PWM_C_SEL			107
+#define CLKID_PWM_C_DIV			108
+#define CLKID_PWM_C			109
+#define CLKID_PWM_D_SEL			110
+#define CLKID_PWM_D_DIV			111
+#define CLKID_PWM_D			112
+#define CLKID_PWM_E_SEL			113
+#define CLKID_PWM_E_DIV			114
+#define CLKID_PWM_E			115
+#define CLKID_PWM_F_SEL			116
+#define CLKID_PWM_F_DIV			117
+#define CLKID_PWM_F			118
+#define CLKID_PWM_AO_A_SEL		119
+#define CLKID_PWM_AO_A_DIV		120
+#define CLKID_PWM_AO_A			121
+#define CLKID_PWM_AO_B_SEL		122
+#define CLKID_PWM_AO_B_DIV		123
+#define CLKID_PWM_AO_B			124
+#define CLKID_PWM_AO_C_SEL		125
+#define CLKID_PWM_AO_C_DIV		126
+#define CLKID_PWM_AO_C			127
+#define CLKID_PWM_AO_D_SEL		128
+#define CLKID_PWM_AO_D_DIV		129
+#define CLKID_PWM_AO_D			130
+#define CLKID_PWM_AO_E_SEL		131
+#define CLKID_PWM_AO_E_DIV		132
+#define CLKID_PWM_AO_E			133
+#define CLKID_PWM_AO_F_SEL		134
+#define CLKID_PWM_AO_F_DIV		135
+#define CLKID_PWM_AO_F			136
+#define CLKID_PWM_AO_G_SEL		137
+#define CLKID_PWM_AO_G_DIV		138
+#define CLKID_PWM_AO_G			139
+#define CLKID_PWM_AO_H_SEL		140
+#define CLKID_PWM_AO_H_DIV		141
+#define CLKID_PWM_AO_H			142
+#define CLKID_SYS_DDR			143
+#define CLKID_SYS_DOS			144
+#define CLKID_SYS_MIPI_DSI_A		145
+#define CLKID_SYS_MIPI_DSI_B		146
+#define CLKID_SYS_ETHPHY		147
+#define CLKID_SYS_MALI			148
+#define CLKID_SYS_AOCPU			149
+#define CLKID_SYS_AUCPU			150
+#define CLKID_SYS_CEC			151
+#define CLKID_SYS_GDC			152
+#define CLKID_SYS_DESWARP		153
+#define CLKID_SYS_AMPIPE_NAND		154
+#define CLKID_SYS_AMPIPE_ETH		155
+#define CLKID_SYS_AM2AXI0		156
+#define CLKID_SYS_AM2AXI1		157
+#define CLKID_SYS_AM2AXI2		158
+#define CLKID_SYS_SD_EMMC_A		159
+#define CLKID_SYS_SD_EMMC_B		160
+#define CLKID_SYS_SD_EMMC_C		161
+#define CLKID_SYS_SMARTCARD		162
+#define CLKID_SYS_ACODEC		163
+#define CLKID_SYS_SPIFC			164
+#define CLKID_SYS_MSR_CLK		165
+#define CLKID_SYS_IR_CTRL		166
+#define CLKID_SYS_AUDIO			167
+#define CLKID_SYS_ETH			168
+#define CLKID_SYS_UART_A		169
+#define CLKID_SYS_UART_B		170
+#define CLKID_SYS_UART_C		171
+#define CLKID_SYS_UART_D		172
+#define CLKID_SYS_UART_E		173
+#define CLKID_SYS_UART_F		174
+#define CLKID_SYS_AIFIFO		175
+#define CLKID_SYS_SPICC2		176
+#define CLKID_SYS_SPICC3		177
+#define CLKID_SYS_SPICC4		178
+#define CLKID_SYS_TS_A73		179
+#define CLKID_SYS_TS_A53		180
+#define CLKID_SYS_SPICC5		181
+#define CLKID_SYS_G2D			182
+#define CLKID_SYS_SPICC0		183
+#define CLKID_SYS_SPICC1		184
+#define CLKID_SYS_PCIE			185
+#define CLKID_SYS_USB			186
+#define CLKID_SYS_PCIE_PHY		187
+#define CLKID_SYS_I2C_AO_A		188
+#define CLKID_SYS_I2C_AO_B		189
+#define CLKID_SYS_I2C_M_A		190
+#define CLKID_SYS_I2C_M_B		191
+#define CLKID_SYS_I2C_M_C		192
+#define CLKID_SYS_I2C_M_D		193
+#define CLKID_SYS_I2C_M_E		194
+#define CLKID_SYS_I2C_M_F		195
+#define CLKID_SYS_HDMITX_APB		196
+#define CLKID_SYS_I2C_S_A		197
+#define CLKID_SYS_HDMIRX_PCLK		198
+#define CLKID_SYS_MMC_APB		199
+#define CLKID_SYS_MIPI_ISP_PCLK		200
+#define CLKID_SYS_RSA			201
+#define CLKID_SYS_PCLK_SYS_APB		202
+#define CLKID_SYS_A73PCLK_APB		203
+#define CLKID_SYS_DSPA			204
+#define CLKID_SYS_DSPB			205
+#define CLKID_SYS_VPU_INTR		206
+#define CLKID_SYS_SAR_ADC		207
+#define CLKID_SYS_GIC			208
+#define CLKID_SYS_TS_GPU		209
+#define CLKID_SYS_TS_NNA		210
+#define CLKID_SYS_TS_VPU		211
+#define CLKID_SYS_TS_HEVC		212
+#define CLKID_SYS_PWM_AB		213
+#define CLKID_SYS_PWM_CD		214
+#define CLKID_SYS_PWM_EF		215
+#define CLKID_SYS_PWM_AO_AB		216
+#define CLKID_SYS_PWM_AO_CD		217
+#define CLKID_SYS_PWM_AO_EF		218
+#define CLKID_SYS_PWM_AO_GH		219
+
+#endif /* __T7_PERIPHERALS_CLKC_H */
-- 
2.47.1



From jian.hu at amlogic.com  Thu Oct 30 02:43:44 2025
From: jian.hu at amlogic.com (Jian Hu)
Date: Thu, 30 Oct 2025 17:43:44 +0800
Subject: [PATCH v4 4/5] clk: meson: t7: add support for the T7 SoC PLL clock
In-Reply-To: <20251030094345.2571222-1-jian.hu@amlogic.com>
References: <20251030094345.2571222-1-jian.hu@amlogic.com>
Message-ID: <20251030094345.2571222-5-jian.hu@amlogic.com>

Add PLL clock controller driver for the Amlogic T7 SoC family.

Signed-off-by: Jian Hu <jian.hu at amlogic.com>
---
 drivers/clk/meson/Kconfig  |   14 +
 drivers/clk/meson/Makefile |    1 +
 drivers/clk/meson/t7-pll.c | 1068 ++++++++++++++++++++++++++++++++++++
 3 files changed, 1083 insertions(+)
 create mode 100644 drivers/clk/meson/t7-pll.c

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 71481607a6d5..6cdc6a96e105 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -201,4 +201,18 @@ config COMMON_CLK_S4_PERIPHERALS
 	help
 	  Support for the peripherals clock controller on Amlogic S805X2 and S905Y4
 	  devices, AKA S4. Say Y if you want S4 peripherals clock controller to work.
+
+config COMMON_CLK_T7_PLL
+	tristate "Amlogic T7 SoC PLL controller support"
+	depends on ARM64
+	default ARCH_MESON
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_CLKC_UTILS
+	select COMMON_CLK_MESON_PLL
+	imply COMMON_CLK_SCMI
+	help
+	  Support for the PLL clock controller on Amlogic A311D2 based
+	  device, AKA T7. PLLs are required by most peripheral to operate
+	  Say Y if you are a T7 based device.
+
 endmenu
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index c6998e752c68..8e3f7f94c639 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
 obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o
 obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o
+obj-$(CONFIG_COMMON_CLK_T7_PLL) += t7-pll.o
diff --git a/drivers/clk/meson/t7-pll.c b/drivers/clk/meson/t7-pll.c
new file mode 100644
index 000000000000..1730237f7e14
--- /dev/null
+++ b/drivers/clk/meson/t7-pll.c
@@ -0,0 +1,1068 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu at amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-mpll.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,t7-pll-clkc.h>
+
+#define GP0PLL_CTRL0		0x00
+#define GP0PLL_CTRL1		0x04
+#define GP0PLL_CTRL2		0x08
+#define GP0PLL_CTRL3		0x0c
+#define GP0PLL_CTRL4		0x10
+#define GP0PLL_CTRL5		0x14
+#define GP0PLL_CTRL6		0x18
+#define GP0PLL_STS		0x1c
+#define GP1PLL_CTRL0		0x00
+#define GP1PLL_CTRL1		0x04
+#define GP1PLL_CTRL2		0x08
+#define GP1PLL_CTRL3		0x0c
+#define GP1PLL_STS		0x1c
+#define HIFIPLL_CTRL0		0x00
+#define HIFIPLL_CTRL1		0x04
+#define HIFIPLL_CTRL2		0x08
+#define HIFIPLL_CTRL3		0x0c
+#define HIFIPLL_CTRL4		0x10
+#define HIFIPLL_CTRL5		0x14
+#define HIFIPLL_CTRL6		0x18
+#define HIFIPLL_STS		0x1c
+#define PCIEPLL_CTRL0		0x00
+#define PCIEPLL_CTRL1		0x04
+#define PCIEPLL_CTRL2		0x08
+#define PCIEPLL_CTRL3		0x0c
+#define PCIEPLL_CTRL4		0x10
+#define PCIEPLL_CTRL5		0x14
+#define PCIEPLL_STS		0x18
+#define MPLL_CTRL0		0x00
+#define MPLL_CTRL1		0x04
+#define MPLL_CTRL2		0x08
+#define MPLL_CTRL3		0x0c
+#define MPLL_CTRL4		0x10
+#define MPLL_CTRL5		0x14
+#define MPLL_CTRL6		0x18
+#define MPLL_CTRL7		0x1c
+#define MPLL_CTRL8		0x20
+#define MPLL_STS		0x24
+#define HDMIPLL_CTRL0		0x00
+#define HDMIPLL_CTRL1		0x04
+#define HDMIPLL_CTRL2		0x08
+#define HDMIPLL_CTRL3		0x0c
+#define HDMIPLL_CTRL4		0x10
+#define HDMIPLL_CTRL5		0x14
+#define HDMIPLL_CTRL6		0x18
+#define HDMIPLL_STS		0x1c
+#define MCLK_PLL_CNTL0		0x00
+#define MCLK_PLL_CNTL1		0x04
+#define MCLK_PLL_CNTL2		0x08
+#define MCLK_PLL_CNTL3		0x0c
+#define MCLK_PLL_CNTL4		0x10
+#define MCLK_PLL_STS		0x14
+
+static const struct pll_mult_range t7_media_pll_mult_range = {
+	.min = 125,
+	.max = 250,
+};
+
+static const struct reg_sequence t7_gp0_init_regs[] = {
+	{ .reg = GP0PLL_CTRL1,  .def = 0x00000000 },
+	{ .reg = GP0PLL_CTRL2,  .def = 0x00000000 },
+	{ .reg = GP0PLL_CTRL3,  .def = 0x48681c00 },
+	{ .reg = GP0PLL_CTRL4,  .def = 0x88770290 },
+	{ .reg = GP0PLL_CTRL5,  .def = 0x3927200a },
+	{ .reg = GP0PLL_CTRL6,  .def = 0x56540000 },
+};
+
+static struct clk_regmap t7_gp0_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = GP0PLL_STS,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = GP0PLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.range = &t7_media_pll_mult_range,
+		.init_regs = t7_gp0_init_regs,
+		.init_count = ARRAY_SIZE(t7_gp0_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "gp0_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "in0",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_gp0_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = GP0PLL_CTRL0,
+		.shift = 16,
+		.width = 3,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gp0_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_gp0_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/*
+ * The gp1 pll IP is different with gp0 pll, the PLL DCO range is
+ * 1.6GHZ - 3.2GHZ, and the reg_sequence is short
+ */
+static const struct pll_mult_range t7_gp1_pll_mult_range = {
+	.min = 67,
+	.max = 133,
+};
+
+static const struct reg_sequence t7_gp1_init_regs[] = {
+	{ .reg = GP1PLL_CTRL1,  .def = 0x1420500f },
+	{ .reg = GP1PLL_CTRL2,  .def = 0x00023001 },
+	{ .reg = GP1PLL_CTRL3,  .def = 0x00000000 },
+};
+
+static struct clk_regmap t7_gp1_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = GP1PLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = GP1PLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = GP1PLL_CTRL0,
+			.shift   = 16,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = GP1PLL_STS,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = GP1PLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.range = &t7_gp1_pll_mult_range,
+		.init_regs = t7_gp1_init_regs,
+		.init_count = ARRAY_SIZE(t7_gp1_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "gp1_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "in0",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_gp1_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = GP1PLL_CTRL0,
+		.shift = 12,
+		.width = 3,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "gp1_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_gp1_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence t7_hifi_init_regs[] = {
+	{ .reg = HIFIPLL_CTRL1, .def = 0x00000000 },
+	{ .reg = HIFIPLL_CTRL2, .def = 0x00000000 },
+	{ .reg = HIFIPLL_CTRL3, .def = 0x6a285c00 },
+	{ .reg = HIFIPLL_CTRL4, .def = 0x65771290 },
+	{ .reg = HIFIPLL_CTRL5, .def = 0x3927200a },
+	{ .reg = HIFIPLL_CTRL6, .def = 0x56540000 }
+};
+
+static struct clk_regmap t7_hifi_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.frac = {
+			.reg_off = HIFIPLL_CTRL1,
+			.shift   = 0,
+			.width   = 17,
+		},
+		.l = {
+			.reg_off = HIFIPLL_STS,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = HIFIPLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.range = &t7_media_pll_mult_range,
+		.init_regs = t7_hifi_init_regs,
+		.init_count = ARRAY_SIZE(t7_hifi_init_regs),
+		.frac_max = 100000,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hifi_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "in0",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_hifi_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HIFIPLL_CTRL0,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "hifi_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_hifi_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/*
+ * The T7 PCIE PLL is fined tuned to deliver a very precise
+ * 100MHz reference clock for the PCIe Analog PHY, and thus requires
+ * a strict register sequence to enable the PLL.
+ */
+static const struct reg_sequence t7_pcie_pll_init_regs[] = {
+	{ .reg = PCIEPLL_CTRL0,	.def = 0x200c04c8 },
+	{ .reg = PCIEPLL_CTRL0,	.def = 0x300c04c8 },
+	{ .reg = PCIEPLL_CTRL1,	.def = 0x30000000 },
+	{ .reg = PCIEPLL_CTRL2,	.def = 0x00001100 },
+	{ .reg = PCIEPLL_CTRL3,	.def = 0x10058e00 },
+	{ .reg = PCIEPLL_CTRL4,	.def = 0x000100c0 },
+	{ .reg = PCIEPLL_CTRL5,	.def = 0x68000048 },
+	{ .reg = PCIEPLL_CTRL5,	.def = 0x68000068, .delay_us = 20 },
+	{ .reg = PCIEPLL_CTRL4,	.def = 0x008100c0, .delay_us = 20 },
+	{ .reg = PCIEPLL_CTRL0,	.def = 0x340c04c8 },
+	{ .reg = PCIEPLL_CTRL0,	.def = 0x140c04c8, .delay_us = 20 },
+	{ .reg = PCIEPLL_CTRL2,	.def = 0x00001000 }
+};
+
+static struct clk_regmap t7_pcie_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = PCIEPLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = PCIEPLL_CTRL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = PCIEPLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = PCIEPLL_CTRL0,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = PCIEPLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.init_regs = t7_pcie_pll_init_regs,
+		.init_count = ARRAY_SIZE(t7_pcie_pll_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pcie_pll_dco",
+		.ops = &meson_clk_pcie_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "in0",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_fixed_factor t7_pcie_pll_dco_div2 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "pcie_pll_dco_div2",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_pcie_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_pcie_pll_od = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = PCIEPLL_CTRL0,
+		.shift = 16,
+		.width = 5,
+		/* the divisor is 32 when [16:21] = 0 */
+		.flags = CLK_DIVIDER_MAX_AT_ZERO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pcie_pll_od",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_pcie_pll_dco_div2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_fixed_factor t7_pcie_pll = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "pcie_pll",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_pcie_pll_od.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_fixed_factor t7_mpll_prediv = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll_prediv",
+		.ops = &clk_fixed_factor_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "in0",
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct reg_sequence t7_mpll0_init_regs[] = {
+	{ .reg = MPLL_CTRL2, .def = 0x40000033 }
+};
+
+static struct clk_regmap t7_mpll0_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL1,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = t7_mpll0_init_regs,
+		.init_count = ARRAY_SIZE(t7_mpll0_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_mpll0 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL1,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_mpll0_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence t7_mpll1_init_regs[] = {
+	{ .reg = MPLL_CTRL4,	.def = 0x40000033 }
+};
+
+static struct clk_regmap t7_mpll1_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL3,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = t7_mpll1_init_regs,
+		.init_count = ARRAY_SIZE(t7_mpll1_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll1_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_mpll1 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL3,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_mpll1_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence t7_mpll2_init_regs[] = {
+	{ .reg = MPLL_CTRL6, .def = 0x40000033 }
+};
+
+static struct clk_regmap t7_mpll2_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL5,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = t7_mpll2_init_regs,
+		.init_count = ARRAY_SIZE(t7_mpll2_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll2_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_mpll2 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL5,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll2",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_mpll2_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence t7_mpll3_init_regs[] = {
+	{ .reg = MPLL_CTRL8, .def = 0x40000033 }
+};
+
+static struct clk_regmap t7_mpll3_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 30,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 20,
+			.width   = 9,
+		},
+		.ssen = {
+			.reg_off = MPLL_CTRL7,
+			.shift   = 29,
+			.width	 = 1,
+		},
+		.init_regs = t7_mpll3_init_regs,
+		.init_count = ARRAY_SIZE(t7_mpll3_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll3_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_mpll3 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MPLL_CTRL7,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll3",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_mpll3_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct reg_sequence t7_hdmi_init_regs[] = {
+	{ .reg = HDMIPLL_CTRL1, .def = 0x00000000 },
+	{ .reg = HDMIPLL_CTRL2, .def = 0x00000000 },
+	{ .reg = HDMIPLL_CTRL3, .def = 0x6a28dc00 },
+	{ .reg = HDMIPLL_CTRL4, .def = 0x65771290 },
+	{ .reg = HDMIPLL_CTRL5, .def = 0x39272000 },
+	{ .reg = HDMIPLL_CTRL6, .def = 0x56540000 }
+};
+
+static struct clk_regmap t7_hdmi_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HDMIPLL_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = HDMIPLL_CTRL0,
+			.shift   = 0,
+			.width   = 9,
+		},
+		.n = {
+			.reg_off = HDMIPLL_CTRL0,
+			.shift   = 10,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = HDMIPLL_CTRL0,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = HDMIPLL_CTRL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.range = &t7_media_pll_mult_range,
+		.init_regs = t7_hdmi_init_regs,
+		.init_count = ARRAY_SIZE(t7_hdmi_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .fw_name = "in0", }
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_hdmi_pll_od = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HDMIPLL_CTRL0,
+		.shift = 16,
+		.width = 4,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll_od",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_hdmi_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_hdmi_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HDMIPLL_CTRL0,
+		.shift = 20,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_hdmi_pll_od.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct pll_mult_range t7_mclk_pll_mult_range = {
+	.min = 67,
+	.max = 133,
+};
+
+static const struct reg_sequence t7_mclk_init_regs[] = {
+	{ .reg = MCLK_PLL_CNTL1, .def = 0x1470500f },
+	{ .reg = MCLK_PLL_CNTL2, .def = 0x00023001 },
+	{ .reg = MCLK_PLL_CNTL3, .def = 0x18180000 },
+	{ .reg = MCLK_PLL_CNTL4, .def = 0x00180303 },
+};
+
+static struct clk_regmap t7_mclk_pll_dco = {
+	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = MCLK_PLL_CNTL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.m = {
+			.reg_off = MCLK_PLL_CNTL0,
+			.shift   = 0,
+			.width   = 8,
+		},
+		.n = {
+			.reg_off = MCLK_PLL_CNTL0,
+			.shift   = 16,
+			.width   = 5,
+		},
+		.l = {
+			.reg_off = MCLK_PLL_CNTL0,
+			.shift   = 31,
+			.width   = 1,
+		},
+		.rst = {
+			.reg_off = MCLK_PLL_CNTL0,
+			.shift   = 29,
+			.width   = 1,
+		},
+		.l_detect = {
+			.reg_off = MCLK_PLL_CNTL2,
+			.shift   = 6,
+			.width   = 1,
+		},
+		.range = &t7_mclk_pll_mult_range,
+		.init_regs = t7_mclk_init_regs,
+		.init_count = ARRAY_SIZE(t7_mclk_init_regs),
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_pll_dco",
+		.ops = &meson_clk_pll_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "in0",
+		},
+		.num_parents = 1,
+	},
+};
+
+/* max div is 16 */
+static const struct clk_div_table t7_mclk_div[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 8 },
+	{ .val = 4, .div = 16 },
+	{ /* sentinel */ }
+};
+
+static struct clk_regmap t7_mclk_pre_od = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = MCLK_PLL_CNTL0,
+		.shift = 12,
+		.width = 3,
+		.table = t7_mclk_div,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_pre_od",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mclk_pll_dco.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = MCLK_PLL_CNTL4,
+		.shift = 16,
+		.width = 5,
+		.flags = CLK_DIVIDER_ONE_BASED,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mclk_pre_od.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_0_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MCLK_PLL_CNTL4,
+		.mask = 0x3,
+		.shift = 4,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_0_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &t7_mclk_pll.hw },
+			{ .fw_name = "in1", },
+			{ .fw_name = "in2", },
+		},
+		.num_parents = 3,
+	},
+};
+
+static struct clk_fixed_factor t7_mclk_0_div2 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_0_div2",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_mclk_0_sel.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_0_pre = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MCLK_PLL_CNTL4,
+		.bit_idx = 2,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "mclk_0_pre",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mclk_0_div2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_0 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MCLK_PLL_CNTL4,
+		.bit_idx = 0,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "mclk_0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mclk_0_pre.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_1_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MCLK_PLL_CNTL4,
+		.mask = 0x3,
+		.shift = 12,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_1_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .hw = &t7_mclk_pll.hw },
+			{ .fw_name = "in1", },
+			{ .fw_name = "in2", },
+		},
+		.num_parents = 3,
+	},
+};
+
+static struct clk_fixed_factor t7_mclk_1_div2 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk_1_div2",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_mclk_1_sel.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_1_pre = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MCLK_PLL_CNTL4,
+		.bit_idx = 10,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "mclk_1_pre",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mclk_1_div2.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mclk_1 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MCLK_PLL_CNTL4,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "mclk_1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mclk_1_pre.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_hw *t7_gp0_hw_clks[] = {
+	[CLKID_GP0_PLL_DCO]		= &t7_gp0_pll_dco.hw,
+	[CLKID_GP0_PLL]			= &t7_gp0_pll.hw,
+};
+
+static struct clk_hw *t7_gp1_hw_clks[] = {
+	[CLKID_GP1_PLL_DCO]		= &t7_gp1_pll_dco.hw,
+	[CLKID_GP1_PLL]			= &t7_gp1_pll.hw,
+};
+
+static struct clk_hw *t7_hifi_hw_clks[] = {
+	[CLKID_HIFI_PLL_DCO]		= &t7_hifi_pll_dco.hw,
+	[CLKID_HIFI_PLL]		= &t7_hifi_pll.hw,
+};
+
+static struct clk_hw *t7_pcie_hw_clks[] = {
+	[CLKID_PCIE_PLL_DCO]		= &t7_pcie_pll_dco.hw,
+	[CLKID_PCIE_PLL_DCO_DIV2]	= &t7_pcie_pll_dco_div2.hw,
+	[CLKID_PCIE_PLL_OD]		= &t7_pcie_pll_od.hw,
+	[CLKID_PCIE_PLL]		= &t7_pcie_pll.hw,
+};
+
+static struct clk_hw *t7_mpll_hw_clks[] = {
+	[CLKID_MPLL_PREDIV]		= &t7_mpll_prediv.hw,
+	[CLKID_MPLL0_DIV]		= &t7_mpll0_div.hw,
+	[CLKID_MPLL0]			= &t7_mpll0.hw,
+	[CLKID_MPLL1_DIV]		= &t7_mpll1_div.hw,
+	[CLKID_MPLL1]			= &t7_mpll1.hw,
+	[CLKID_MPLL2_DIV]		= &t7_mpll2_div.hw,
+	[CLKID_MPLL2]			= &t7_mpll2.hw,
+	[CLKID_MPLL3_DIV]		= &t7_mpll3_div.hw,
+	[CLKID_MPLL3]			= &t7_mpll3.hw,
+};
+
+static struct clk_hw *t7_hdmi_hw_clks[] = {
+	[CLKID_HDMI_PLL_DCO]		= &t7_hdmi_pll_dco.hw,
+	[CLKID_HDMI_PLL_OD]		= &t7_hdmi_pll_od.hw,
+	[CLKID_HDMI_PLL]		= &t7_hdmi_pll.hw,
+};
+
+static struct clk_hw *t7_mclk_hw_clks[] = {
+	[CLKID_MCLK_PLL_DCO]		= &t7_mclk_pll_dco.hw,
+	[CLKID_MCLK_PRE]		= &t7_mclk_pre_od.hw,
+	[CLKID_MCLK_PLL]		= &t7_mclk_pll.hw,
+	[CLKID_MCLK_0_SEL]		= &t7_mclk_0_sel.hw,
+	[CLKID_MCLK_0_DIV2]		= &t7_mclk_0_div2.hw,
+	[CLKID_MCLK_0_PRE]		= &t7_mclk_0_pre.hw,
+	[CLKID_MCLK_0]			= &t7_mclk_0.hw,
+	[CLKID_MCLK_1_SEL]		= &t7_mclk_1_sel.hw,
+	[CLKID_MCLK_1_DIV2]		= &t7_mclk_1_div2.hw,
+	[CLKID_MCLK_1_PRE]		= &t7_mclk_1_pre.hw,
+	[CLKID_MCLK_1]			= &t7_mclk_1.hw,
+};
+
+static const struct meson_clkc_data t7_gp0_data = {
+	.hw_clks = {
+		.hws = t7_gp0_hw_clks,
+		.num = ARRAY_SIZE(t7_gp0_hw_clks),
+	},
+};
+
+static const struct meson_clkc_data t7_gp1_data = {
+	.hw_clks = {
+		.hws = t7_gp1_hw_clks,
+		.num = ARRAY_SIZE(t7_gp1_hw_clks),
+	},
+};
+
+static const struct meson_clkc_data t7_hifi_data = {
+	.hw_clks = {
+		.hws = t7_hifi_hw_clks,
+		.num = ARRAY_SIZE(t7_hifi_hw_clks),
+	},
+};
+
+static const struct meson_clkc_data t7_pcie_data = {
+	.hw_clks = {
+		.hws = t7_pcie_hw_clks,
+		.num = ARRAY_SIZE(t7_pcie_hw_clks),
+	},
+};
+
+static const struct reg_sequence t7_mpll_init_regs[] = {
+	{ .reg = MPLL_CTRL0, .def = 0x00000543 }
+};
+
+static const struct meson_clkc_data t7_mpll_data = {
+	.hw_clks = {
+		.hws = t7_mpll_hw_clks,
+		.num = ARRAY_SIZE(t7_mpll_hw_clks),
+	},
+	.init_regs = t7_mpll_init_regs,
+	.init_count = ARRAY_SIZE(t7_mpll_init_regs),
+};
+
+static const struct meson_clkc_data t7_hdmi_data = {
+	.hw_clks = {
+		.hws = t7_hdmi_hw_clks,
+		.num = ARRAY_SIZE(t7_hdmi_hw_clks),
+	},
+};
+
+static const struct meson_clkc_data t7_mclk_data = {
+	.hw_clks = {
+		.hws = t7_mclk_hw_clks,
+		.num = ARRAY_SIZE(t7_mclk_hw_clks),
+	},
+};
+
+static const struct of_device_id t7_pll_clkc_match_table[] = {
+	{ .compatible = "amlogic,t7-gp0-pll",	.data = &t7_gp0_data, },
+	{ .compatible = "amlogic,t7-gp1-pll",	.data = &t7_gp1_data, },
+	{ .compatible = "amlogic,t7-hifi-pll",	.data = &t7_hifi_data, },
+	{ .compatible = "amlogic,t7-pcie-pll",	.data = &t7_pcie_data, },
+	{ .compatible = "amlogic,t7-mpll",	.data = &t7_mpll_data, },
+	{ .compatible = "amlogic,t7-hdmi-pll",	.data = &t7_hdmi_data, },
+	{ .compatible = "amlogic,t7-mclk-pll",	.data = &t7_mclk_data, },
+	{}
+};
+MODULE_DEVICE_TABLE(of, t7_pll_clkc_match_table);
+
+static struct platform_driver t7_pll_clkc_driver = {
+	.probe = meson_clkc_mmio_probe,
+	.driver = {
+		.name = "t7-pll-clkc",
+		.of_match_table = t7_pll_clkc_match_table,
+	},
+};
+
+MODULE_DESCRIPTION("Amlogic T7 PLL Clock Controller driver");
+module_platform_driver(t7_pll_clkc_driver);
+MODULE_AUTHOR("Jian Hu <jian.hu at amlogic.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_MESON");
-- 
2.47.1



From jian.hu at amlogic.com  Thu Oct 30 02:43:45 2025
From: jian.hu at amlogic.com (Jian Hu)
Date: Thu, 30 Oct 2025 17:43:45 +0800
Subject: [PATCH v4 5/5] clk: meson: t7: add t7 clock peripherals controller driver
In-Reply-To: <20251030094345.2571222-1-jian.hu@amlogic.com>
References: <20251030094345.2571222-1-jian.hu@amlogic.com>
Message-ID: <20251030094345.2571222-6-jian.hu@amlogic.com>

Add Peripheral clock controller driver for the Amlogic T7 SoC family.

Signed-off-by: Jian Hu <jian.hu at amlogic.com>
---
 drivers/clk/meson/Kconfig          |   13 +
 drivers/clk/meson/Makefile         |    1 +
 drivers/clk/meson/t7-peripherals.c | 1734 ++++++++++++++++++++++++++++
 3 files changed, 1748 insertions(+)
 create mode 100644 drivers/clk/meson/t7-peripherals.c

diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index 6cdc6a96e105..d2442ae0f5be 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -215,4 +215,17 @@ config COMMON_CLK_T7_PLL
 	  device, AKA T7. PLLs are required by most peripheral to operate
 	  Say Y if you are a T7 based device.
 
+config COMMON_CLK_T7_PERIPHERALS
+	tristate "Amlogic T7 SoC peripherals clock controller support"
+	depends on ARM64
+	default ARCH_MESON
+	select COMMON_CLK_MESON_REGMAP
+	select COMMON_CLK_MESON_CLKC_UTILS
+	select COMMON_CLK_MESON_DUALDIV
+	imply COMMON_CLK_SCMI
+	imply COMMON_CLK_T7_PLL
+	help
+	  Support for the Peripherals clock controller on Amlogic A311D2 based
+	  device, AKA T7. Peripherals are required by most peripheral to operate
+	  Say Y if you are a T7 based device.
 endmenu
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 8e3f7f94c639..c6719694a242 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -27,3 +27,4 @@ obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
 obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o
 obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o
 obj-$(CONFIG_COMMON_CLK_T7_PLL) += t7-pll.o
+obj-$(CONFIG_COMMON_CLK_T7_PERIPHERALS) += t7-peripherals.o
diff --git a/drivers/clk/meson/t7-peripherals.c b/drivers/clk/meson/t7-peripherals.c
new file mode 100644
index 000000000000..e2ee0ba2bb8a
--- /dev/null
+++ b/drivers/clk/meson/t7-peripherals.c
@@ -0,0 +1,1734 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved.
+ * Author: Jian Hu <jian.hu at amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include "clk-dualdiv.h"
+#include "clk-regmap.h"
+#include "meson-clkc-utils.h"
+#include <dt-bindings/clock/amlogic,t7-peripherals-clkc.h>
+
+#define RTC_BY_OSCIN_CTRL0	0x8
+#define RTC_BY_OSCIN_CTRL1	0xc
+#define RTC_CTRL		0x10
+#define SYS_CLK_CTRL0		0x40
+#define SYS_CLK_EN0_REG0	0x44
+#define SYS_CLK_EN0_REG1	0x48
+#define SYS_CLK_EN0_REG2	0x4c
+#define SYS_CLK_EN0_REG3	0x50
+#define CECA_CTRL0		0x88
+#define CECA_CTRL1		0x8c
+#define CECB_CTRL0		0x90
+#define CECB_CTRL1		0x94
+#define SC_CLK_CTRL		0x98
+#define DSPA_CLK_CTRL0		0x9c
+#define DSPB_CLK_CTRL0		0xa0
+#define CLK12_24_CTRL		0xa8
+#define ANAKIN_CLK_CTRL		0xac
+#define MIPI_CSI_PHY_CLK_CTRL	0x10c
+#define MIPI_ISP_CLK_CTRL	0x110
+#define TS_CLK_CTRL		0x158
+#define MALI_CLK_CTRL		0x15c
+#define ETH_CLK_CTRL		0x164
+#define NAND_CLK_CTRL		0x168
+#define SD_EMMC_CLK_CTRL	0x16c
+#define SPICC_CLK_CTRL		0x174
+#define SAR_CLK_CTRL0		0x17c
+#define PWM_CLK_AB_CTRL		0x180
+#define PWM_CLK_CD_CTRL		0x184
+#define PWM_CLK_EF_CTRL		0x188
+#define PWM_CLK_AO_AB_CTRL	0x1a0
+#define PWM_CLK_AO_CD_CTRL	0x1a4
+#define PWM_CLK_AO_EF_CTRL	0x1a8
+#define PWM_CLK_AO_GH_CTRL	0x1ac
+#define SPICC_CLK_CTRL1		0x1c0
+#define SPICC_CLK_CTRL2		0x1c4
+
+#define T7_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
+	MESON_COMP_SEL(t7_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
+
+#define T7_COMP_DIV(_name, _reg, _shift, _width) \
+	MESON_COMP_DIV(t7_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
+
+#define T7_COMP_GATE(_name, _reg, _bit) \
+	MESON_COMP_GATE(t7_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
+
+static struct clk_regmap t7_rtc_32k_in = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = RTC_BY_OSCIN_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_32k_in",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct meson_clk_dualdiv_param t7_clk_32k_div_table[] = {
+	{
+		.n1	= 733, .m1	= 8,
+		.n2	= 732, .m2	= 11,
+		.dual	= 1,
+	},
+	{}
+};
+
+static struct clk_regmap t7_rtc_32k_div = {
+	.data = &(struct meson_clk_dualdiv_data){
+		.n1 = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = RTC_BY_OSCIN_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = RTC_BY_OSCIN_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = RTC_BY_OSCIN_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = t7_clk_32k_div_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_32k_div",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_rtc_32k_in.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_rtc_32k_force_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_BY_OSCIN_CTRL1,
+		.mask = 0x1,
+		.shift = 24,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_32k_force_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_rtc_32k_div.hw,
+			&t7_rtc_32k_in.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_rtc_32k_out = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = RTC_BY_OSCIN_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "rtc_32k_out",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_rtc_32k_force_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_rtc_32k_mux0_0 = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_CTRL,
+		.mask = 0x1,
+		.shift = 0,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_32k_mux0_0",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .fw_name = "xtal", },
+			{ .hw = &t7_rtc_32k_out.hw },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_rtc_32k_mux0_1 = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_CTRL,
+		.mask = 0x1,
+		.shift = 0,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc_32k_mux0_1",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .fw_name = "pad", },
+			{ .fw_name = "xtal", },
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_rtc = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = RTC_CTRL,
+		.mask = 0x1,
+		.shift = 1,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "rtc",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_rtc_32k_mux0_0.hw,
+			&t7_rtc_32k_mux0_1.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_ceca_32k_in = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECA_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "ceca_32k_in",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_ceca_32k_div = {
+	.data = &(struct meson_clk_dualdiv_data){
+		.n1 = {
+			.reg_off = CECA_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = CECA_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = CECA_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = CECA_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = CECA_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = t7_clk_32k_div_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_div",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_ceca_32k_in.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_ceca_32k_sel_pre = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECA_CTRL1,
+		.mask = 0x1,
+		.shift = 24,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_sel_pre",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_ceca_32k_div.hw,
+			&t7_ceca_32k_in.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_ceca_32k_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECA_CTRL1,
+		.mask = 0x1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_ceca_32k_sel_pre.hw,
+			&t7_rtc.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_ceca_32k_out = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECA_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ceca_32k_out",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_ceca_32k_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_cecb_32k_in = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECB_CTRL0,
+		.bit_idx = 31,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "cecb_32k_in",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_cecb_32k_div = {
+	.data = &(struct meson_clk_dualdiv_data){
+		.n1 = {
+			.reg_off = CECB_CTRL0,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.n2 = {
+			.reg_off = CECB_CTRL0,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.m1 = {
+			.reg_off = CECB_CTRL1,
+			.shift   = 0,
+			.width   = 12,
+		},
+		.m2 = {
+			.reg_off = CECB_CTRL1,
+			.shift   = 12,
+			.width   = 12,
+		},
+		.dual = {
+			.reg_off = CECB_CTRL0,
+			.shift   = 28,
+			.width   = 1,
+		},
+		.table = t7_clk_32k_div_table,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_div",
+		.ops = &meson_clk_dualdiv_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_cecb_32k_in.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_cecb_32k_sel_pre = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECB_CTRL1,
+		.mask = 0x1,
+		.shift = 24,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_sel_pre",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_cecb_32k_div.hw,
+			&t7_cecb_32k_in.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_cecb_32k_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = CECB_CTRL1,
+		.mask = 0x1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_cecb_32k_sel_pre.hw,
+			&t7_rtc.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_cecb_32k_out = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CECB_CTRL0,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "cecb_32k_out",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_cecb_32k_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct clk_parent_data t7_sc_parents[] = {
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "xtal", },
+};
+
+static T7_COMP_SEL(sc, SC_CLK_CTRL, 9, 0x3, t7_sc_parents);
+static T7_COMP_DIV(sc, SC_CLK_CTRL, 0, 8);
+static T7_COMP_GATE(sc, SC_CLK_CTRL, 8);
+
+static const struct clk_parent_data t7_dsp_ab_parent_data[] = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "fdiv2p5", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "hifi", },
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv7", },
+	{ .hw = &t7_rtc.hw },
+};
+
+static struct clk_regmap t7_dspa_a_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_a_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_dsp_ab_parent_data,
+		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
+	},
+};
+
+static struct clk_regmap t7_dspa_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPA_CLK_CTRL0,
+		.shift = 0,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspa_a_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspa_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPA_CLK_CTRL0,
+		.bit_idx = 13,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspa_a_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspa_b_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 26,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_b_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_dsp_ab_parent_data,
+		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
+	},
+};
+
+static struct clk_regmap t7_dspa_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPA_CLK_CTRL0,
+		.shift = 16,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspa_b_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspa_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPA_CLK_CTRL0,
+		.bit_idx = 29,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspa_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspa_b_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspa = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPA_CLK_CTRL0,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspa",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspa_a.hw,
+			&t7_dspa_b.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspb_a_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPB_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_a_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_dsp_ab_parent_data,
+		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
+	},
+};
+
+static struct clk_regmap t7_dspb_a_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPB_CLK_CTRL0,
+		.shift = 0,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_a_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspb_a_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspb_a = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPB_CLK_CTRL0,
+		.bit_idx = 13,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspb_a",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspb_a_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspb_b_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPB_CLK_CTRL0,
+		.mask = 0x7,
+		.shift = 26,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_b_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_dsp_ab_parent_data,
+		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
+	},
+};
+
+static struct clk_regmap t7_dspb_b_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = DSPB_CLK_CTRL0,
+		.shift = 16,
+		.width = 10,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb_b_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspb_b_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspb_b = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = DSPB_CLK_CTRL0,
+		.bit_idx = 29,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "dspb_b",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspb_b_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_dspb = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = DSPB_CLK_CTRL0,
+		.mask = 0x1,
+		.shift = 15,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "dspb",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_dspb_a.hw,
+			&t7_dspb_b.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_clk_24m = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 11,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "24m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_fixed_factor t7_clk_24m_div2 = {
+	.mult = 1,
+	.div = 2,
+	.hw.init = &(struct clk_init_data){
+		.name = "24m_div2",
+		.ops = &clk_fixed_factor_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_clk_24m.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_clk_12m = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 10,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "12m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_clk_24m_div2.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_fdiv2_divn_pre = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = CLK12_24_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fdiv2_divn_pre",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "fdiv2",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_fdiv2_divn = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = CLK12_24_CTRL,
+		.bit_idx = 12,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fdiv2_divn",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_fdiv2_divn_pre.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/*
+ * The NNA IP is clocked by two identical clocks (anakin_0 and anakin_1)
+ * muxed by a glitch-free switch.
+ */
+static const struct clk_parent_data t7_anakin_parent_data[] = {
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "fdiv2", },
+	{ .fw_name = "vid_pll0", },
+	{ .fw_name = "mpll1", },
+	{ .fw_name = "mpll2", },
+	{ .fw_name = "fdiv2p5", },
+};
+
+static struct clk_regmap t7_anakin_0_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "anakin_0_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_anakin_parent_data,
+		.num_parents = ARRAY_SIZE(t7_anakin_parent_data),
+	},
+};
+
+static struct clk_regmap t7_anakin_0_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.shift = 0,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "anakin_0_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_anakin_0_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_anakin_0 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "anakin_0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) { &t7_anakin_0_div.hw },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_anakin_1_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 25,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "anakin_1_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_anakin_parent_data,
+		.num_parents = ARRAY_SIZE(t7_anakin_parent_data),
+	},
+};
+
+static struct clk_regmap t7_anakin_1_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.shift = 16,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "anakin_1_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_anakin_1_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_anakin_1 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "anakin_1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_anakin_1_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_anakin = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.mask = 1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "anakin_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_anakin_0.hw,
+			&t7_anakin_1.hw
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT
+	},
+};
+
+static struct clk_regmap t7_anakin_clk = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = ANAKIN_CLK_CTRL,
+		.bit_idx = 30,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "anakin_clk",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_anakin.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT
+	},
+};
+
+static const struct clk_parent_data t7_mipi_csi_parents[] = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "gp1", },
+	{ .fw_name = "mpll1", },
+	{ .fw_name = "mpll2", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "fdiv7", },
+};
+
+static struct clk_regmap t7_mipi_csi_phy0_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mipi_csi_phy0_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_mipi_csi_parents,
+		.num_parents = ARRAY_SIZE(t7_mipi_csi_parents),
+	},
+};
+
+static struct clk_regmap t7_mipi_csi_phy0_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.shift = 0,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mipi_csi_phy0_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mipi_csi_phy0_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mipi_csi_phy0 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "mipi_csi_phy0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mipi_csi_phy0_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mipi_csi_phy1_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 25,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mipi_csi_phy1_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_mipi_csi_parents,
+		.num_parents = ARRAY_SIZE(t7_mipi_csi_parents),
+	},
+};
+
+static struct clk_regmap t7_mipi_csi_phy1_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.shift = 16,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mipi_csi_phy1_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mipi_csi_phy1_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mipi_csi_phy1 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data) {
+		.name = "mipi_csi_phy1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mipi_csi_phy1_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mipi_csi_phy = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MIPI_CSI_PHY_CLK_CTRL,
+		.mask = 0x1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mipi_csi_phy",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mipi_csi_phy0.hw,
+			&t7_mipi_csi_phy1.hw
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static const struct clk_parent_data t7_mipi_isp_parents[] = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "fdiv7", },
+	{ .fw_name = "mpll2", },
+	{ .fw_name = "mpll3", },
+	{ .fw_name = "gp1", },
+};
+
+static T7_COMP_SEL(mipi_isp, MIPI_ISP_CLK_CTRL, 9, 0x7, t7_mipi_isp_parents);
+static T7_COMP_DIV(mipi_isp, MIPI_ISP_CLK_CTRL, 0, 7);
+static T7_COMP_GATE(mipi_isp, MIPI_ISP_CLK_CTRL, 8);
+
+static struct clk_regmap t7_ts_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = TS_CLK_CTRL,
+		.shift = 0,
+		.width = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ts_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "xtal",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_ts = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = TS_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "ts",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_ts_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/*
+ * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
+ * muxed by a glitch-free switch.
+ */
+static const struct clk_parent_data t7_mali_parents[] = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "gp0", },
+	{ .fw_name = "gp1", },
+	{ .fw_name = "fdiv2p5", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "fdiv7", },
+};
+
+static struct clk_regmap t7_mali_0_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MALI_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 9,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali_0_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_mali_parents,
+		.num_parents = ARRAY_SIZE(t7_mali_parents),
+	},
+};
+
+static struct clk_regmap t7_mali_0_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = MALI_CLK_CTRL,
+		.shift = 0,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali_0_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mali_0_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mali_0 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MALI_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali_0",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mali_0_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mali_1_sel = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MALI_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 25,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali_1_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_mali_parents,
+		.num_parents = ARRAY_SIZE(t7_mali_parents),
+	},
+};
+
+static struct clk_regmap t7_mali_1_div = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = MALI_CLK_CTRL,
+		.shift = 16,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali_1_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mali_1_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mali_1 = {
+	.data = &(struct clk_regmap_gate_data){
+		.offset = MALI_CLK_CTRL,
+		.bit_idx = 24,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali_1",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mali_1_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_mali = {
+	.data = &(struct clk_regmap_mux_data){
+		.offset = MALI_CLK_CTRL,
+		.mask = 1,
+		.shift = 31,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mali",
+		.ops = &clk_regmap_mux_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_mali_0.hw,
+			&t7_mali_1.hw,
+		},
+		.num_parents = 2,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+/* parent index 2, 3, 4, 5, 6 not connect any clock signal, they are empty */
+static u32 t7_eth_rmii_table[] = { 0, 1, 7 };
+
+static const struct clk_parent_data t7_eth_rmii_parents[] = {
+	{ .fw_name = "fdiv2", },
+	{ .fw_name = "gp1", },
+	{ .fw_name = "ext_rmii", },
+};
+
+static struct clk_regmap t7_eth_rmii_sel = {
+	.data = &(struct clk_regmap_mux_data) {
+		.offset = ETH_CLK_CTRL,
+		.mask = 0x7,
+		.shift = 9,
+		.table = t7_eth_rmii_table
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "eth_rmii_sel",
+		.ops = &clk_regmap_mux_ops,
+		.parent_data = t7_eth_rmii_parents,
+		.num_parents = ARRAY_SIZE(t7_eth_rmii_parents),
+	},
+};
+
+static struct clk_regmap t7_eth_rmii_div = {
+	.data = &(struct clk_regmap_div_data) {
+		.offset = ETH_CLK_CTRL,
+		.shift = 0,
+		.width = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "eth_rmii_div",
+		.ops = &clk_regmap_divider_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_eth_rmii_sel.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap t7_eth_rmii = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = ETH_CLK_CTRL,
+		.bit_idx = 8,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "eth_rmii",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_eth_rmii_div.hw
+		},
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_fixed_factor t7_fdiv2_div8 = {
+	.mult = 1,
+	.div = 8,
+	.hw.init = &(struct clk_init_data){
+		.name = "fdiv2_div8",
+		.ops = &clk_fixed_factor_ops,
+		.parent_data = &(const struct clk_parent_data) {
+			.fw_name = "fdiv2",
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap t7_eth_125m = {
+	.data = &(struct clk_regmap_gate_data) {
+		.offset = ETH_CLK_CTRL,
+		.bit_idx = 7,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "eth_125m",
+		.ops = &clk_regmap_gate_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&t7_fdiv2_div8.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static const struct clk_parent_data t7_sd_emmc_parents[] = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "fdiv2", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "hifi", },
+	{ .fw_name = "fdiv2p5", },
+	{ .fw_name = "mpll2", },
+	{ .fw_name = "mpll3", },
+	{ .fw_name = "gp0", },
+};
+
+static T7_COMP_SEL(sd_emmc_c, NAND_CLK_CTRL, 9, 0x7, t7_sd_emmc_parents);
+static T7_COMP_DIV(sd_emmc_c, NAND_CLK_CTRL, 0, 7);
+static T7_COMP_GATE(sd_emmc_c, NAND_CLK_CTRL, 7);
+
+static T7_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL, 9, 0x7, t7_sd_emmc_parents);
+static T7_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL, 0, 7);
+static T7_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL, 7);
+
+static T7_COMP_SEL(sd_emmc_b, SD_EMMC_CLK_CTRL, 25, 0x7, t7_sd_emmc_parents);
+static T7_COMP_DIV(sd_emmc_b, SD_EMMC_CLK_CTRL, 16, 7);
+static T7_COMP_GATE(sd_emmc_b, SD_EMMC_CLK_CTRL, 23);
+
+static const struct clk_parent_data t7_spicc_parents[] = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "sys", },
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv3", },
+	{ .fw_name = "fdiv2", },
+	{ .fw_name = "fdiv5", },
+	{ .fw_name = "fdiv7", },
+	{ .fw_name = "gp1", },
+};
+
+static T7_COMP_SEL(spicc0, SPICC_CLK_CTRL, 7, 0x7, t7_spicc_parents);
+static T7_COMP_DIV(spicc0, SPICC_CLK_CTRL, 0, 6);
+static T7_COMP_GATE(spicc0, SPICC_CLK_CTRL, 6);
+
+static T7_COMP_SEL(spicc1, SPICC_CLK_CTRL, 23, 0x7, t7_spicc_parents);
+static T7_COMP_DIV(spicc1, SPICC_CLK_CTRL, 16, 6);
+static T7_COMP_GATE(spicc1, SPICC_CLK_CTRL, 22);
+
+static T7_COMP_SEL(spicc2, SPICC_CLK_CTRL1, 7, 0x7, t7_spicc_parents);
+static T7_COMP_DIV(spicc2, SPICC_CLK_CTRL1, 0, 6);
+static T7_COMP_GATE(spicc2, SPICC_CLK_CTRL1, 6);
+
+static T7_COMP_SEL(spicc3, SPICC_CLK_CTRL1, 23, 0x7, t7_spicc_parents);
+static T7_COMP_DIV(spicc3, SPICC_CLK_CTRL1, 16, 6);
+static T7_COMP_GATE(spicc3, SPICC_CLK_CTRL1, 22);
+
+static T7_COMP_SEL(spicc4, SPICC_CLK_CTRL2, 7, 0x7, t7_spicc_parents);
+static T7_COMP_DIV(spicc4, SPICC_CLK_CTRL2, 0, 6);
+static T7_COMP_GATE(spicc4, SPICC_CLK_CTRL2, 6);
+
+static T7_COMP_SEL(spicc5, SPICC_CLK_CTRL2, 23, 0x7, t7_spicc_parents);
+static T7_COMP_DIV(spicc5, SPICC_CLK_CTRL2, 16, 6);
+static T7_COMP_GATE(spicc5, SPICC_CLK_CTRL2, 22);
+
+static const struct clk_parent_data t7_saradc_parents[] = {
+	{ .fw_name = "xtal" },
+	{ .fw_name = "sys" },
+};
+
+static T7_COMP_SEL(saradc, SAR_CLK_CTRL0, 9, 0x1, t7_saradc_parents);
+static T7_COMP_DIV(saradc, SAR_CLK_CTRL0, 0, 8);
+static T7_COMP_GATE(saradc, SAR_CLK_CTRL0, 8);
+
+static const struct clk_parent_data t7_pwm_parents[]  = {
+	{ .fw_name = "xtal", },
+	{ .fw_name = "vid_pll0", },
+	{ .fw_name = "fdiv4", },
+	{ .fw_name = "fdiv3", },
+};
+
+static T7_COMP_SEL(pwm_a, PWM_CLK_AB_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_a, PWM_CLK_AB_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_a, PWM_CLK_AB_CTRL, 8);
+
+static T7_COMP_SEL(pwm_b, PWM_CLK_AB_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_b, PWM_CLK_AB_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_b, PWM_CLK_AB_CTRL, 24);
+
+static T7_COMP_SEL(pwm_c, PWM_CLK_CD_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_c, PWM_CLK_CD_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_c, PWM_CLK_CD_CTRL, 8);
+
+static T7_COMP_SEL(pwm_d, PWM_CLK_CD_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_d, PWM_CLK_CD_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_d, PWM_CLK_CD_CTRL, 24);
+
+static T7_COMP_SEL(pwm_e, PWM_CLK_EF_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_e, PWM_CLK_EF_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_e, PWM_CLK_EF_CTRL, 8);
+
+static T7_COMP_SEL(pwm_f, PWM_CLK_EF_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_f, PWM_CLK_EF_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_f, PWM_CLK_EF_CTRL, 24);
+
+static T7_COMP_SEL(pwm_ao_a, PWM_CLK_AO_AB_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_a, PWM_CLK_AO_AB_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_ao_a, PWM_CLK_AO_AB_CTRL, 8);
+
+static T7_COMP_SEL(pwm_ao_b, PWM_CLK_AO_AB_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_b, PWM_CLK_AO_AB_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_ao_b, PWM_CLK_AO_AB_CTRL, 24);
+
+static T7_COMP_SEL(pwm_ao_c, PWM_CLK_AO_CD_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_c, PWM_CLK_AO_CD_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_ao_c, PWM_CLK_AO_CD_CTRL, 8);
+
+static T7_COMP_SEL(pwm_ao_d, PWM_CLK_AO_CD_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_d, PWM_CLK_AO_CD_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_ao_d, PWM_CLK_AO_CD_CTRL, 24);
+
+static T7_COMP_SEL(pwm_ao_e, PWM_CLK_AO_EF_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_e, PWM_CLK_AO_EF_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_ao_e, PWM_CLK_AO_EF_CTRL, 8);
+
+static T7_COMP_SEL(pwm_ao_f, PWM_CLK_AO_EF_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_f, PWM_CLK_AO_EF_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_ao_f, PWM_CLK_AO_EF_CTRL, 24);
+
+static T7_COMP_SEL(pwm_ao_g, PWM_CLK_AO_GH_CTRL, 9, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_g, PWM_CLK_AO_GH_CTRL, 0, 8);
+static T7_COMP_GATE(pwm_ao_g, PWM_CLK_AO_GH_CTRL, 8);
+
+static T7_COMP_SEL(pwm_ao_h, PWM_CLK_AO_GH_CTRL, 25, 0x3, t7_pwm_parents);
+static T7_COMP_DIV(pwm_ao_h, PWM_CLK_AO_GH_CTRL, 16, 8);
+static T7_COMP_GATE(pwm_ao_h, PWM_CLK_AO_GH_CTRL, 24);
+
+static const struct clk_parent_data t7_sys_pclk_parents = { .fw_name = "sys" };
+
+#define T7_SYS_PCLK(_name, _reg, _bit, _flags) \
+	MESON_PCLK(t7_##_name, _reg, _bit, &t7_sys_pclk_parents, _flags)
+
+static T7_SYS_PCLK(sys_ddr,		SYS_CLK_EN0_REG0, 0,	0);
+static T7_SYS_PCLK(sys_dos,		SYS_CLK_EN0_REG0, 1,	0);
+static T7_SYS_PCLK(sys_mipi_dsi_a,	SYS_CLK_EN0_REG0, 2,	0);
+static T7_SYS_PCLK(sys_mipi_dsi_b,	SYS_CLK_EN0_REG0, 3,	0);
+static T7_SYS_PCLK(sys_ethphy,		SYS_CLK_EN0_REG0, 4,	0);
+static T7_SYS_PCLK(sys_mali,		SYS_CLK_EN0_REG0, 6,	0);
+static T7_SYS_PCLK(sys_aocpu,		SYS_CLK_EN0_REG0, 13,	0);
+static T7_SYS_PCLK(sys_aucpu,		SYS_CLK_EN0_REG0, 14,	0);
+static T7_SYS_PCLK(sys_cec,		SYS_CLK_EN0_REG0, 16,	0);
+static T7_SYS_PCLK(sys_gdc,		SYS_CLK_EN0_REG0, 17,	0);
+static T7_SYS_PCLK(sys_deswarp,		SYS_CLK_EN0_REG0, 18,	0);
+static T7_SYS_PCLK(sys_ampipe_nand,	SYS_CLK_EN0_REG0, 19,	0);
+static T7_SYS_PCLK(sys_ampipe_eth,	SYS_CLK_EN0_REG0, 20,	0);
+static T7_SYS_PCLK(sys_am2axi0,		SYS_CLK_EN0_REG0, 21,	0);
+static T7_SYS_PCLK(sys_am2axi1,		SYS_CLK_EN0_REG0, 22,	0);
+static T7_SYS_PCLK(sys_am2axi2,		SYS_CLK_EN0_REG0, 23,	0);
+static T7_SYS_PCLK(sys_sdemmca,		SYS_CLK_EN0_REG0, 24,	0);
+static T7_SYS_PCLK(sys_sdemmcb,		SYS_CLK_EN0_REG0, 25,	0);
+static T7_SYS_PCLK(sys_sdemmcc,		SYS_CLK_EN0_REG0, 26,	0);
+static T7_SYS_PCLK(sys_smartcard,	SYS_CLK_EN0_REG0, 27,	0);
+static T7_SYS_PCLK(sys_acodec,		SYS_CLK_EN0_REG0, 28,	0);
+static T7_SYS_PCLK(sys_spifc,		SYS_CLK_EN0_REG0, 29,	0);
+static T7_SYS_PCLK(sys_msr_clk,		SYS_CLK_EN0_REG0, 30,	0);
+static T7_SYS_PCLK(sys_ir_ctrl,		SYS_CLK_EN0_REG0, 31,	0);
+static T7_SYS_PCLK(sys_audio,		SYS_CLK_EN0_REG1, 0,	0);
+static T7_SYS_PCLK(sys_eth,		SYS_CLK_EN0_REG1, 3,	0);
+static T7_SYS_PCLK(sys_uart_a,		SYS_CLK_EN0_REG1, 5,	0);
+static T7_SYS_PCLK(sys_uart_b,		SYS_CLK_EN0_REG1, 6,	0);
+static T7_SYS_PCLK(sys_uart_c,		SYS_CLK_EN0_REG1, 7,	0);
+static T7_SYS_PCLK(sys_uart_d,		SYS_CLK_EN0_REG1, 8,	0);
+static T7_SYS_PCLK(sys_uart_e,		SYS_CLK_EN0_REG1, 9,	0);
+static T7_SYS_PCLK(sys_uart_f,		SYS_CLK_EN0_REG1, 10,	0);
+static T7_SYS_PCLK(sys_aififo,		SYS_CLK_EN0_REG1, 11,	0);
+static T7_SYS_PCLK(sys_spicc2,		SYS_CLK_EN0_REG1, 12,	0);
+static T7_SYS_PCLK(sys_spicc3,		SYS_CLK_EN0_REG1, 13,	0);
+static T7_SYS_PCLK(sys_spicc4,		SYS_CLK_EN0_REG1, 14,	0);
+static T7_SYS_PCLK(sys_ts_a73,		SYS_CLK_EN0_REG1, 15,	0);
+static T7_SYS_PCLK(sys_ts_a53,		SYS_CLK_EN0_REG1, 16,	0);
+static T7_SYS_PCLK(sys_spicc5,		SYS_CLK_EN0_REG1, 17,	0);
+static T7_SYS_PCLK(sys_g2d,		SYS_CLK_EN0_REG1, 20,	0);
+static T7_SYS_PCLK(sys_spicc0,		SYS_CLK_EN0_REG1, 21,	0);
+static T7_SYS_PCLK(sys_spicc1,		SYS_CLK_EN0_REG1, 22,	0);
+static T7_SYS_PCLK(sys_pcie,		SYS_CLK_EN0_REG1, 24,	0);
+static T7_SYS_PCLK(sys_usb,		SYS_CLK_EN0_REG1, 26,	0);
+static T7_SYS_PCLK(sys_pcie_phy,	SYS_CLK_EN0_REG1, 27,	0);
+static T7_SYS_PCLK(sys_i2c_ao_a,	SYS_CLK_EN0_REG1, 28,	0);
+static T7_SYS_PCLK(sys_i2c_ao_b,	SYS_CLK_EN0_REG1, 29,	0);
+static T7_SYS_PCLK(sys_i2c_m_a,		SYS_CLK_EN0_REG1, 30,	0);
+static T7_SYS_PCLK(sys_i2c_m_b,		SYS_CLK_EN0_REG1, 31,	0);
+static T7_SYS_PCLK(sys_i2c_m_c,		SYS_CLK_EN0_REG2, 0,	0);
+static T7_SYS_PCLK(sys_i2c_m_d,		SYS_CLK_EN0_REG2, 1,	0);
+static T7_SYS_PCLK(sys_i2c_m_e,		SYS_CLK_EN0_REG2, 2,	0);
+static T7_SYS_PCLK(sys_i2c_m_f,		SYS_CLK_EN0_REG2, 3,	0);
+static T7_SYS_PCLK(sys_hdmitx_apb,	SYS_CLK_EN0_REG2, 4,	0);
+static T7_SYS_PCLK(sys_i2c_s_a,		SYS_CLK_EN0_REG2, 5,	0);
+static T7_SYS_PCLK(sys_hdmirx_pclk,	SYS_CLK_EN0_REG2, 8,	0);
+static T7_SYS_PCLK(sys_mmc_apb,		SYS_CLK_EN0_REG2, 11,	0);
+static T7_SYS_PCLK(sys_mipi_isp_pclk,	SYS_CLK_EN0_REG2, 17,	0);
+static T7_SYS_PCLK(sys_rsa,		SYS_CLK_EN0_REG2, 18,	0);
+static T7_SYS_PCLK(sys_pclk_sys_apb,	SYS_CLK_EN0_REG2, 19,	0);
+static T7_SYS_PCLK(sys_a73pclk_apb,	SYS_CLK_EN0_REG2, 20,	0);
+static T7_SYS_PCLK(sys_dspa,		SYS_CLK_EN0_REG2, 21,	0);
+static T7_SYS_PCLK(sys_dspb,		SYS_CLK_EN0_REG2, 22,	0);
+static T7_SYS_PCLK(sys_vpu_intr,	SYS_CLK_EN0_REG2, 25,	0);
+static T7_SYS_PCLK(sys_sar_adc,		SYS_CLK_EN0_REG2, 28,	0);
+/*
+ * sys_gic provides the clock for GIC(Generic Interrupt Controller).
+ * After clock is disabled, The GIC cannot work properly. At present, the driver
+ * used by our GIC is the public driver in kernel, and there is no management
+ * clock in the driver.
+ */
+static T7_SYS_PCLK(sys_gic,		SYS_CLK_EN0_REG2, 30,	CLK_IS_CRITICAL);
+static T7_SYS_PCLK(sys_ts_gpu,		SYS_CLK_EN0_REG2, 31,	0);
+static T7_SYS_PCLK(sys_ts_nna,		SYS_CLK_EN0_REG3, 0,	0);
+static T7_SYS_PCLK(sys_ts_vpu,		SYS_CLK_EN0_REG3, 1,	0);
+static T7_SYS_PCLK(sys_ts_hevc,		SYS_CLK_EN0_REG3, 2,	0);
+static T7_SYS_PCLK(sys_pwm_ao_ab,	SYS_CLK_EN0_REG3, 3,	0);
+static T7_SYS_PCLK(sys_pwm_ao_cd,	SYS_CLK_EN0_REG3, 4,	0);
+static T7_SYS_PCLK(sys_pwm_ao_ef,	SYS_CLK_EN0_REG3, 5,	0);
+static T7_SYS_PCLK(sys_pwm_ao_gh,	SYS_CLK_EN0_REG3, 6,	0);
+static T7_SYS_PCLK(sys_pwm_ab,		SYS_CLK_EN0_REG3, 7,	0);
+static T7_SYS_PCLK(sys_pwm_cd,		SYS_CLK_EN0_REG3, 8,	0);
+static T7_SYS_PCLK(sys_pwm_ef,		SYS_CLK_EN0_REG3, 9,	0);
+
+/* Array of all clocks registered by this provider */
+static struct clk_hw *t7_peripherals_hw_clks[] = {
+	[CLKID_RTC_32K_IN]		= &t7_rtc_32k_in.hw,
+	[CLKID_RTC_32K_DIV]		= &t7_rtc_32k_div.hw,
+	[CLKID_RTC_32K_FORCE_SEL]	= &t7_rtc_32k_force_sel.hw,
+	[CLKID_RTC_32K_OUT]		= &t7_rtc_32k_out.hw,
+	[CLKID_RTC_32K_MUX0_0]		= &t7_rtc_32k_mux0_0.hw,
+	[CLKID_RTC_32K_MUX0_1]		= &t7_rtc_32k_mux0_1.hw,
+	[CLKID_RTC]			= &t7_rtc.hw,
+	[CLKID_CECB_32K_IN]		= &t7_cecb_32k_in.hw,
+	[CLKID_CECB_32K_DIV]		= &t7_cecb_32k_div.hw,
+	[CLKID_CECB_32K_SEL_PRE]	= &t7_cecb_32k_sel_pre.hw,
+	[CLKID_CECB_32K_SEL]		= &t7_cecb_32k_sel.hw,
+	[CLKID_CECA_32K_IN]		= &t7_ceca_32k_in.hw,
+	[CLKID_CECA_32K_DIV]		= &t7_ceca_32k_div.hw,
+	[CLKID_CECA_32K_SEL_PRE]	= &t7_ceca_32k_sel_pre.hw,
+	[CLKID_CECA_32K_SEL]		= &t7_ceca_32k_sel.hw,
+	[CLKID_CECA_32K]		= &t7_ceca_32k_out.hw,
+	[CLKID_CECB_32K]		= &t7_cecb_32k_out.hw,
+	[CLKID_SC_SEL]			= &t7_sc_sel.hw,
+	[CLKID_SC_DIV]			= &t7_sc_div.hw,
+	[CLKID_SC]			= &t7_sc.hw,
+	[CLKID_DSPA_A_SEL]		= &t7_dspa_a_sel.hw,
+	[CLKID_DSPA_A_DIV]		= &t7_dspa_a_div.hw,
+	[CLKID_DSPA_A]			= &t7_dspa_a.hw,
+	[CLKID_DSPA_B_SEL]		= &t7_dspa_b_sel.hw,
+	[CLKID_DSPA_B_DIV]		= &t7_dspa_b_div.hw,
+	[CLKID_DSPA_B]			= &t7_dspa_b.hw,
+	[CLKID_DSPA]			= &t7_dspa.hw,
+	[CLKID_DSPB_A_SEL]		= &t7_dspb_a_sel.hw,
+	[CLKID_DSPB_A_DIV]		= &t7_dspb_a_div.hw,
+	[CLKID_DSPB_A]			= &t7_dspb_a.hw,
+	[CLKID_DSPB_B_SEL]		= &t7_dspb_b_sel.hw,
+	[CLKID_DSPB_B_DIV]		= &t7_dspb_b_div.hw,
+	[CLKID_DSPB_B]			= &t7_dspb_b.hw,
+	[CLKID_DSPB]			= &t7_dspb.hw,
+	[CLKID_CLK_24M]			= &t7_clk_24m.hw,
+	[CLKID_CLK_24M_DIV2]		= &t7_clk_24m_div2.hw,
+	[CLKID_CLK_12M]			= &t7_clk_12m.hw,
+	[CLKID_ANAKIN_0_SEL]		= &t7_anakin_0_sel.hw,
+	[CLKID_ANAKIN_0_DIV]		= &t7_anakin_0_div.hw,
+	[CLKID_ANAKIN_0]		= &t7_anakin_0.hw,
+	[CLKID_ANAKIN_1_SEL]		= &t7_anakin_1_sel.hw,
+	[CLKID_ANAKIN_1_DIV]		= &t7_anakin_1_div.hw,
+	[CLKID_ANAKIN_1]		= &t7_anakin_1.hw,
+	[CLKID_ANAKIN]			= &t7_anakin.hw,
+	[CLKID_ANAKIN_CLK]		= &t7_anakin_clk.hw,
+	[CLKID_FCLK_DIV2_DIVN_PRE]	= &t7_fdiv2_divn_pre.hw,
+	[CLKID_FCLK_DIV2_DIVN]		= &t7_fdiv2_divn.hw,
+	[CLKID_MIPI_CSI_PHY_0_SEL]	= &t7_mipi_csi_phy0_sel.hw,
+	[CLKID_MIPI_CSI_PHY_0_DIV]	= &t7_mipi_csi_phy0_div.hw,
+	[CLKID_MIPI_CSI_PHY_0]		= &t7_mipi_csi_phy0.hw,
+	[CLKID_MIPI_CSI_PHY_1_SEL]	= &t7_mipi_csi_phy1_sel.hw,
+	[CLKID_MIPI_CSI_PHY_1_DIV]	= &t7_mipi_csi_phy1_div.hw,
+	[CLKID_MIPI_CSI_PHY_1]		= &t7_mipi_csi_phy1.hw,
+	[CLKID_MIPI_CSI_PHY]		= &t7_mipi_csi_phy.hw,
+	[CLKID_MIPI_ISP_SEL]		= &t7_mipi_isp_sel.hw,
+	[CLKID_MIPI_ISP_DIV]		= &t7_mipi_isp_div.hw,
+	[CLKID_MIPI_ISP]		= &t7_mipi_isp.hw,
+	[CLKID_TS_DIV]			= &t7_ts_div.hw,
+	[CLKID_TS]			= &t7_ts.hw,
+	[CLKID_MALI_0_SEL]		= &t7_mali_0_sel.hw,
+	[CLKID_MALI_0_DIV]		= &t7_mali_0_div.hw,
+	[CLKID_MALI_0]			= &t7_mali_0.hw,
+	[CLKID_MALI_1_SEL]		= &t7_mali_1_sel.hw,
+	[CLKID_MALI_1_DIV]		= &t7_mali_1_div.hw,
+	[CLKID_MALI_1]			= &t7_mali_1.hw,
+	[CLKID_MALI]			= &t7_mali.hw,
+	[CLKID_ETH_RMII_SEL]		= &t7_eth_rmii_sel.hw,
+	[CLKID_ETH_RMII_DIV]		= &t7_eth_rmii_div.hw,
+	[CLKID_ETH_RMII]		= &t7_eth_rmii.hw,
+	[CLKID_FCLK_DIV2_DIV8]		= &t7_fdiv2_div8.hw,
+	[CLKID_ETH_125M]		= &t7_eth_125m.hw,
+	[CLKID_SD_EMMC_C_SEL]		= &t7_sd_emmc_c_sel.hw,
+	[CLKID_SD_EMMC_C_DIV]		= &t7_sd_emmc_c_div.hw,
+	[CLKID_SD_EMMC_C]		= &t7_sd_emmc_c.hw,
+	[CLKID_SD_EMMC_A_SEL]		= &t7_sd_emmc_a_sel.hw,
+	[CLKID_SD_EMMC_A_DIV]		= &t7_sd_emmc_a_div.hw,
+	[CLKID_SD_EMMC_A]		= &t7_sd_emmc_a.hw,
+	[CLKID_SD_EMMC_B_SEL]		= &t7_sd_emmc_b_sel.hw,
+	[CLKID_SD_EMMC_B_DIV]		= &t7_sd_emmc_b_div.hw,
+	[CLKID_SD_EMMC_B]		= &t7_sd_emmc_b.hw,
+	[CLKID_SPICC0_SEL]		= &t7_spicc0_sel.hw,
+	[CLKID_SPICC0_DIV]		= &t7_spicc0_div.hw,
+	[CLKID_SPICC0]			= &t7_spicc0.hw,
+	[CLKID_SPICC1_SEL]		= &t7_spicc1_sel.hw,
+	[CLKID_SPICC1_DIV]		= &t7_spicc1_div.hw,
+	[CLKID_SPICC1]			= &t7_spicc1.hw,
+	[CLKID_SPICC2_SEL]		= &t7_spicc2_sel.hw,
+	[CLKID_SPICC2_DIV]		= &t7_spicc2_div.hw,
+	[CLKID_SPICC2]			= &t7_spicc2.hw,
+	[CLKID_SPICC3_SEL]		= &t7_spicc3_sel.hw,
+	[CLKID_SPICC3_DIV]		= &t7_spicc3_div.hw,
+	[CLKID_SPICC3]			= &t7_spicc3.hw,
+	[CLKID_SPICC4_SEL]		= &t7_spicc4_sel.hw,
+	[CLKID_SPICC4_DIV]		= &t7_spicc4_div.hw,
+	[CLKID_SPICC4]			= &t7_spicc4.hw,
+	[CLKID_SPICC5_SEL]		= &t7_spicc5_sel.hw,
+	[CLKID_SPICC5_DIV]		= &t7_spicc5_div.hw,
+	[CLKID_SPICC5]			= &t7_spicc5.hw,
+	[CLKID_SARADC_SEL]		= &t7_saradc_sel.hw,
+	[CLKID_SARADC_DIV]		= &t7_saradc_div.hw,
+	[CLKID_SARADC]			= &t7_saradc.hw,
+	[CLKID_PWM_A_SEL]		= &t7_pwm_a_sel.hw,
+	[CLKID_PWM_A_DIV]		= &t7_pwm_a_div.hw,
+	[CLKID_PWM_A]			= &t7_pwm_a.hw,
+	[CLKID_PWM_B_SEL]		= &t7_pwm_b_sel.hw,
+	[CLKID_PWM_B_DIV]		= &t7_pwm_b_div.hw,
+	[CLKID_PWM_B]			= &t7_pwm_b.hw,
+	[CLKID_PWM_C_SEL]		= &t7_pwm_c_sel.hw,
+	[CLKID_PWM_C_DIV]		= &t7_pwm_c_div.hw,
+	[CLKID_PWM_C]			= &t7_pwm_c.hw,
+	[CLKID_PWM_D_SEL]		= &t7_pwm_d_sel.hw,
+	[CLKID_PWM_D_DIV]		= &t7_pwm_d_div.hw,
+	[CLKID_PWM_D]			= &t7_pwm_d.hw,
+	[CLKID_PWM_E_SEL]		= &t7_pwm_e_sel.hw,
+	[CLKID_PWM_E_DIV]		= &t7_pwm_e_div.hw,
+	[CLKID_PWM_E]			= &t7_pwm_e.hw,
+	[CLKID_PWM_F_SEL]		= &t7_pwm_f_sel.hw,
+	[CLKID_PWM_F_DIV]		= &t7_pwm_f_div.hw,
+	[CLKID_PWM_F]			= &t7_pwm_f.hw,
+	[CLKID_PWM_AO_A_SEL]		= &t7_pwm_ao_a_sel.hw,
+	[CLKID_PWM_AO_A_DIV]		= &t7_pwm_ao_a_div.hw,
+	[CLKID_PWM_AO_A]		= &t7_pwm_ao_a.hw,
+	[CLKID_PWM_AO_B_SEL]		= &t7_pwm_ao_b_sel.hw,
+	[CLKID_PWM_AO_B_DIV]		= &t7_pwm_ao_b_div.hw,
+	[CLKID_PWM_AO_B]		= &t7_pwm_ao_b.hw,
+	[CLKID_PWM_AO_C_SEL]		= &t7_pwm_ao_c_sel.hw,
+	[CLKID_PWM_AO_C_DIV]		= &t7_pwm_ao_c_div.hw,
+	[CLKID_PWM_AO_C]		= &t7_pwm_ao_c.hw,
+	[CLKID_PWM_AO_D_SEL]		= &t7_pwm_ao_d_sel.hw,
+	[CLKID_PWM_AO_D_DIV]		= &t7_pwm_ao_d_div.hw,
+	[CLKID_PWM_AO_D]		= &t7_pwm_ao_d.hw,
+	[CLKID_PWM_AO_E_SEL]		= &t7_pwm_ao_e_sel.hw,
+	[CLKID_PWM_AO_E_DIV]		= &t7_pwm_ao_e_div.hw,
+	[CLKID_PWM_AO_E]		= &t7_pwm_ao_e.hw,
+	[CLKID_PWM_AO_F_SEL]		= &t7_pwm_ao_f_sel.hw,
+	[CLKID_PWM_AO_F_DIV]		= &t7_pwm_ao_f_div.hw,
+	[CLKID_PWM_AO_F]		= &t7_pwm_ao_f.hw,
+	[CLKID_PWM_AO_G_SEL]		= &t7_pwm_ao_g_sel.hw,
+	[CLKID_PWM_AO_G_DIV]		= &t7_pwm_ao_g_div.hw,
+	[CLKID_PWM_AO_G]		= &t7_pwm_ao_g.hw,
+	[CLKID_PWM_AO_H_SEL]		= &t7_pwm_ao_h_sel.hw,
+	[CLKID_PWM_AO_H_DIV]		= &t7_pwm_ao_h_div.hw,
+	[CLKID_PWM_AO_H]		= &t7_pwm_ao_h.hw,
+	[CLKID_SYS_DDR]			= &t7_sys_ddr.hw,
+	[CLKID_SYS_DOS]			= &t7_sys_dos.hw,
+	[CLKID_SYS_MIPI_DSI_A]		= &t7_sys_mipi_dsi_a.hw,
+	[CLKID_SYS_MIPI_DSI_B]		= &t7_sys_mipi_dsi_b.hw,
+	[CLKID_SYS_ETHPHY]		= &t7_sys_ethphy.hw,
+	[CLKID_SYS_MALI]		= &t7_sys_mali.hw,
+	[CLKID_SYS_AOCPU]		= &t7_sys_aocpu.hw,
+	[CLKID_SYS_AUCPU]		= &t7_sys_aucpu.hw,
+	[CLKID_SYS_CEC]			= &t7_sys_cec.hw,
+	[CLKID_SYS_GDC]			= &t7_sys_gdc.hw,
+	[CLKID_SYS_DESWARP]		= &t7_sys_deswarp.hw,
+	[CLKID_SYS_AMPIPE_NAND]		= &t7_sys_ampipe_nand.hw,
+	[CLKID_SYS_AMPIPE_ETH]		= &t7_sys_ampipe_eth.hw,
+	[CLKID_SYS_AM2AXI0]		= &t7_sys_am2axi0.hw,
+	[CLKID_SYS_AM2AXI1]		= &t7_sys_am2axi1.hw,
+	[CLKID_SYS_AM2AXI2]		= &t7_sys_am2axi2.hw,
+	[CLKID_SYS_SD_EMMC_A]		= &t7_sys_sdemmca.hw,
+	[CLKID_SYS_SD_EMMC_B]		= &t7_sys_sdemmcb.hw,
+	[CLKID_SYS_SD_EMMC_C]		= &t7_sys_sdemmcc.hw,
+	[CLKID_SYS_SMARTCARD]		= &t7_sys_smartcard.hw,
+	[CLKID_SYS_ACODEC]		= &t7_sys_acodec.hw,
+	[CLKID_SYS_SPIFC]		= &t7_sys_spifc.hw,
+	[CLKID_SYS_MSR_CLK]		= &t7_sys_msr_clk.hw,
+	[CLKID_SYS_IR_CTRL]		= &t7_sys_ir_ctrl.hw,
+	[CLKID_SYS_AUDIO]		= &t7_sys_audio.hw,
+	[CLKID_SYS_ETH]			= &t7_sys_eth.hw,
+	[CLKID_SYS_UART_A]		= &t7_sys_uart_a.hw,
+	[CLKID_SYS_UART_B]		= &t7_sys_uart_b.hw,
+	[CLKID_SYS_UART_C]		= &t7_sys_uart_c.hw,
+	[CLKID_SYS_UART_D]		= &t7_sys_uart_d.hw,
+	[CLKID_SYS_UART_E]		= &t7_sys_uart_e.hw,
+	[CLKID_SYS_UART_F]		= &t7_sys_uart_f.hw,
+	[CLKID_SYS_AIFIFO]		= &t7_sys_aififo.hw,
+	[CLKID_SYS_SPICC2]		= &t7_sys_spicc2.hw,
+	[CLKID_SYS_SPICC3]		= &t7_sys_spicc3.hw,
+	[CLKID_SYS_SPICC4]		= &t7_sys_spicc4.hw,
+	[CLKID_SYS_TS_A73]		= &t7_sys_ts_a73.hw,
+	[CLKID_SYS_TS_A53]		= &t7_sys_ts_a53.hw,
+	[CLKID_SYS_SPICC5]		= &t7_sys_spicc5.hw,
+	[CLKID_SYS_G2D]			= &t7_sys_g2d.hw,
+	[CLKID_SYS_SPICC0]		= &t7_sys_spicc0.hw,
+	[CLKID_SYS_SPICC1]		= &t7_sys_spicc1.hw,
+	[CLKID_SYS_PCIE]		= &t7_sys_pcie.hw,
+	[CLKID_SYS_USB]			= &t7_sys_usb.hw,
+	[CLKID_SYS_PCIE_PHY]		= &t7_sys_pcie_phy.hw,
+	[CLKID_SYS_I2C_AO_A]		= &t7_sys_i2c_ao_a.hw,
+	[CLKID_SYS_I2C_AO_B]		= &t7_sys_i2c_ao_b.hw,
+	[CLKID_SYS_I2C_M_A]		= &t7_sys_i2c_m_a.hw,
+	[CLKID_SYS_I2C_M_B]		= &t7_sys_i2c_m_b.hw,
+	[CLKID_SYS_I2C_M_C]		= &t7_sys_i2c_m_c.hw,
+	[CLKID_SYS_I2C_M_D]		= &t7_sys_i2c_m_d.hw,
+	[CLKID_SYS_I2C_M_E]		= &t7_sys_i2c_m_e.hw,
+	[CLKID_SYS_I2C_M_F]		= &t7_sys_i2c_m_f.hw,
+	[CLKID_SYS_HDMITX_APB]		= &t7_sys_hdmitx_apb.hw,
+	[CLKID_SYS_I2C_S_A]		= &t7_sys_i2c_s_a.hw,
+	[CLKID_SYS_HDMIRX_PCLK]		= &t7_sys_hdmirx_pclk.hw,
+	[CLKID_SYS_MMC_APB]		= &t7_sys_mmc_apb.hw,
+	[CLKID_SYS_MIPI_ISP_PCLK]	= &t7_sys_mipi_isp_pclk.hw,
+	[CLKID_SYS_RSA]			= &t7_sys_rsa.hw,
+	[CLKID_SYS_PCLK_SYS_APB]	= &t7_sys_pclk_sys_apb.hw,
+	[CLKID_SYS_A73PCLK_APB]		= &t7_sys_a73pclk_apb.hw,
+	[CLKID_SYS_DSPA]		= &t7_sys_dspa.hw,
+	[CLKID_SYS_DSPB]		= &t7_sys_dspb.hw,
+	[CLKID_SYS_VPU_INTR]		= &t7_sys_vpu_intr.hw,
+	[CLKID_SYS_SAR_ADC]		= &t7_sys_sar_adc.hw,
+	[CLKID_SYS_GIC]			= &t7_sys_gic.hw,
+	[CLKID_SYS_TS_GPU]		= &t7_sys_ts_gpu.hw,
+	[CLKID_SYS_TS_NNA]		= &t7_sys_ts_nna.hw,
+	[CLKID_SYS_TS_VPU]		= &t7_sys_ts_vpu.hw,
+	[CLKID_SYS_TS_HEVC]		= &t7_sys_ts_hevc.hw,
+	[CLKID_SYS_PWM_AO_AB]		= &t7_sys_pwm_ao_ab.hw,
+	[CLKID_SYS_PWM_AO_CD]		= &t7_sys_pwm_ao_cd.hw,
+	[CLKID_SYS_PWM_AO_EF]		= &t7_sys_pwm_ao_ef.hw,
+	[CLKID_SYS_PWM_AO_GH]		= &t7_sys_pwm_ao_gh.hw,
+	[CLKID_SYS_PWM_AB]		= &t7_sys_pwm_ab.hw,
+	[CLKID_SYS_PWM_CD]		= &t7_sys_pwm_cd.hw,
+	[CLKID_SYS_PWM_EF]		= &t7_sys_pwm_ef.hw,
+};
+
+static const struct meson_clkc_data t7_peripherals_data = {
+	.hw_clks = {
+		.hws = t7_peripherals_hw_clks,
+		.num = ARRAY_SIZE(t7_peripherals_hw_clks),
+	},
+};
+
+static const struct of_device_id t7_peripherals_clkc_match_table[] = {
+	{ .compatible = "amlogic,t7-peripherals-clkc", .data = &t7_peripherals_data },
+	{}
+};
+MODULE_DEVICE_TABLE(of, t7_peripherals_clkc_match_table);
+
+static struct platform_driver t7_peripherals_clkc_driver = {
+	.probe = meson_clkc_mmio_probe,
+	.driver = {
+		.name = "t7-peripherals-clkc",
+		.of_match_table = t7_peripherals_clkc_match_table,
+	},
+};
+
+MODULE_DESCRIPTION("Amlogic T7 Peripherals Clock Controller driver");
+module_platform_driver(t7_peripherals_clkc_driver);
+MODULE_AUTHOR("Jian Hu <jian.hu at amlogic.com>");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("CLK_MESON");
-- 
2.47.1



From funderscore at postmarketos.org  Thu Oct 30 03:50:26 2025
From: funderscore at postmarketos.org (Ferass El Hafidi)
Date: Thu, 30 Oct 2025 10:50:26 +0000
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
In-Reply-To: <9a8e0391-c73f-4913-88e1-0a278d99f90d@amlogic.com>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com> <B9A578FB-BF95-47E1-B202-B59897C2C898@gmail.com> <9a8e0391-c73f-4913-88e1-0a278d99f90d@amlogic.com>
Message-ID: <t4xy6q.vhi5j58gpfcw@postmarketos.org>

On Tue, 28 Oct 2025 11:08, Zhentao Guo <zhentao.guo at amlogic.com> wrote:
>
>? 2025/10/27 20:57, Christian Hewitt ??:
>> [christianshewitt at gmail.com appears similar to someone who previously sent you email, but may not be that person. Learn why this could be a risk at https://aka.ms/LearnAboutSenderIdentification ]
>>
>> [ EXTERNAL EMAIL ]
>>
>>> On 27 Oct 2025, at 9:42?am, Zhentao Guo via B4 Relay <devnull+zhentao.guo.amlogic.com at kernel.org> wrote:
>>>
>>> Introduce initial driver support for Amlogic's new video acceleration
>>> hardware architecture, designed for video stream decoding.
>>>
>>> Compared to the current Amlogic video decoder hardware architecture,
>>> this new implementation eliminates the Esparser hardware component,
>>> enabling direct vb2 buffer input. The driver is designed to support
>>> the V4L2 M2M stateless decoder API. The initial phase includes support
>>> for H.264 decoding on Amlogic S805X2 platform.
>> It would be nice if you can outline the additional hardware the driver
>> plans to support so reviewers have perspective on where we are now, and
>> what more be coming? - the community would also like to understand if
>> this driver will supersede the stalled driver attempt in staging.
>Yes, we will follow Amlogic's overall upstream progress to support more 
>hardware
>platforms in the future. The next step will be adding support for 
>A311D2(T7) platform.
>We also plan to replace the stalled driver with the new stateless 
>decoder driver.
>The new stateless driver is fully compatible with the old G12/SM1 
>platforms, making
>this transition feasible.

That's awesome news! But how about the older platforms such as GXBB
(S905), GXL (S905X) and AXG (A113D)? Will support for them also be added
or not?

I and probably many other people still have interest on these older
SoCs.. they otherwise run Mainline linux mostly fine, so if a working
vdec driver comes along for these, that would be great!

Best regards,
Ferass


From chuan.liu at amlogic.com  Thu Oct 30 04:48:58 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Thu, 30 Oct 2025 19:48:58 +0800
Subject: [PATCH v2 3/5] clk: amlogic: Add handling for PLL lock failure
In-Reply-To: <4f245c6a-5a03-4321-bbf8-61249a7a550f@amlogic.com>
References: <20251030-optimize_pll_driver-v2-0-37273f5b25ab@amlogic.com>
 <20251030-optimize_pll_driver-v2-3-37273f5b25ab@amlogic.com>
 <1jikfwzt5x.fsf@starbuckisacylon.baylibre.com>
 <4f245c6a-5a03-4321-bbf8-61249a7a550f@amlogic.com>
Message-ID: <1dea766d-d9c5-4951-889d-9a4f126c7924@amlogic.com>

Hi Jerome,

On 10/30/2025 5:15 PM, Chuan Liu wrote:
> Hi Jerome,
> 
> On 10/30/2025 4:32 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>> On Thu 30 Oct 2025 at 13:24, Chuan Liu via B4 Relay 
>> <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>>
>>> From: Chuan Liu <chuan.liu at amlogic.com>
>>>
>>> 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 at amlogic.com>
>>> ---
>>> ? drivers/clk/meson/clk-pll.c | 41 ++++++++++++++++++++++ 
>>> +------------------
>>> ? 1 file changed, 23 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
>>> index f81ebf6cc981..6c794adb8ccd 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);
>>> @@ -397,29 +414,17 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
>>> ?????????????? meson_parm_write(clk->map, &pll->l_detect, 0);
>>> ?????? }
>>>
>>> -???? if (meson_clk_pll_wait_lock(hw))
>>> +???? 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));
>>> +
>>
>> This is something that's likely to spam, so pr_warn_once() (if you 
>> must warn)

Different PLLs or different timing conditions may trigger PLL lock
failures repeatedly, so using pr_warn_once() might not achieve the
intended effect.

Do you mind keeping pr_warn() here?

>> and I don't think 3 "!" are necessary to convey the message.
>>
> 
> In the next version, I'll remove the "!", and replace pr_warn to
> pr_warn_once.
> 
> Some drivers that reference the clock may not check the function?s
> return value (even though that's not ideal), so adding this warning
> makes the issue more noticeable.
> 
>>> ?????????????? return -EIO;
>>> +???? }
>>>
>>> ?????? return 0;
>>> ? }
>>>
>>> -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_set_rate(struct clk_hw *hw, unsigned long 
>>> rate,
>>> ???????????????????????????????? unsigned long parent_rate)
>>> ? {
>>
>> -- 
>> Jerome
> 



From helgaas at kernel.org  Thu Oct 30 15:34:36 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Thu, 30 Oct 2025 17:34:36 -0500
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <20251023164205.GA1299816@bhelgaas>
Message-ID: <20251030223436.GA1657470@bhelgaas>

On Thu, Oct 23, 2025 at 11:42:05AM -0500, Bjorn Helgaas wrote:
> #regzbot ^introduced: v6.18-rc1

#regzbot report: https://lore.kernel.org/r/DM4PR05MB102707B8CDF84D776C39F22F2C7F0A at DM4PR05MB10270.namprd05.prod.outlook.com
#regzbot introduced: f3ac2ff14834

f3ac2ff14834 ("PCI/ASPM: Enable all ClockPM and ASPM states for devicetree platforms")


From zhentao.guo at amlogic.com  Thu Oct 30 19:32:34 2025
From: zhentao.guo at amlogic.com (Zhentao Guo)
Date: Fri, 31 Oct 2025 10:32:34 +0800
Subject: [PATCH 0/3] Add Amlogic stateless H.264 video decoder for S4
In-Reply-To: <t4xy6q.vhi5j58gpfcw@postmarketos.org>
References: <20251027-b4-s4-vdec-upstream-v1-0-620401813b5d@amlogic.com>
 <B9A578FB-BF95-47E1-B202-B59897C2C898@gmail.com>
 <9a8e0391-c73f-4913-88e1-0a278d99f90d@amlogic.com>
 <t4xy6q.vhi5j58gpfcw@postmarketos.org>
Message-ID: <731eb8c3-00db-460b-9b28-11472e8b639f@amlogic.com>

Hi,

? 2025/10/30 18:50, Ferass El Hafidi ??:
> [You don't often get email from funderscore at postmarketos.org. Learn 
> why this is important at https://aka.ms/LearnAboutSenderIdentification ]
>
> [ EXTERNAL EMAIL ]
>
> On Tue, 28 Oct 2025 11:08, Zhentao Guo <zhentao.guo at amlogic.com> wrote:
>>
>> ? 2025/10/27 20:57, Christian Hewitt ??:
>>> [christianshewitt at gmail.com appears similar to someone who 
>>> previously sent you email, but may not be that person. Learn why 
>>> this could be a risk at https://aka.ms/LearnAboutSenderIdentification ]
>>>
>>> [ EXTERNAL EMAIL ]
>>>
>>>> On 27 Oct 2025, at 9:42?am, Zhentao Guo via B4 Relay 
>>>> <devnull+zhentao.guo.amlogic.com at kernel.org> wrote:
>>>>
>>>> Introduce initial driver support for Amlogic's new video acceleration
>>>> hardware architecture, designed for video stream decoding.
>>>>
>>>> Compared to the current Amlogic video decoder hardware architecture,
>>>> this new implementation eliminates the Esparser hardware component,
>>>> enabling direct vb2 buffer input. The driver is designed to support
>>>> the V4L2 M2M stateless decoder API. The initial phase includes support
>>>> for H.264 decoding on Amlogic S805X2 platform.
>>> It would be nice if you can outline the additional hardware the driver
>>> plans to support so reviewers have perspective on where we are now, and
>>> what more be coming? - the community would also like to understand if
>>> this driver will supersede the stalled driver attempt in staging.
>> Yes, we will follow Amlogic's overall upstream progress to support more
>> hardware
>> platforms in the future. The next step will be adding support for
>> A311D2(T7) platform.
>> We also plan to replace the stalled driver with the new stateless
>> decoder driver.
>> The new stateless driver is fully compatible with the old G12/SM1
>> platforms, making
>> this transition feasible.
>
> That's awesome news! But how about the older platforms such as GXBB
> (S905), GXL (S905X) and AXG (A113D)? Will support for them also be added
> or not?
>
> I and probably many other people still have interest on these older
> SoCs.. they otherwise run Mainline linux mostly fine, so if a working
> vdec driver comes along for these, that would be great!

That's great to hear! Theoretically, the new driver should be compatible 
with these older SOCs.

We'll evaluate the feasibility of supporting the new stateless driver on 
these legacy platforms and will provide a follow-up plan for future support.

>
> Best regards,
> Ferass

Thank you

Zhentao



From linnaea-von-lavia at live.com  Thu Oct 30 22:34:41 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Fri, 31 Oct 2025 13:34:41 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <20251029171542.GA1566240@bhelgaas>
References: <20251029171542.GA1566240@bhelgaas>
Message-ID: <DM4PR05MB10270506AAC1FCE53C4915CC2C7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>

On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
> On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
>> On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
> 
>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>> index 214ed060ca1b..9cd12924b5cb 100644
>>> --- a/drivers/pci/quirks.c
>>> +++ b/drivers/pci/quirks.c
>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>     * disable both L0s and L1 for now to be safe.
>>>     */
>>>    DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>    /*
>>>     * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
>>
>> I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
> 
> Sorry, my fault, I should have made that fixup run earlier, so the
> patch should be this instead:
> 
> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> index 214ed060ca1b..4fc04015ca0c 100644
> --- a/drivers/pci/quirks.c
> +++ b/drivers/pci/quirks.c
> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>    * disable both L0s and L1 for now to be safe.
>    */
>   DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);

L1 still got enabled

# dmesg | grep -i -e pci -e iwlwifi -e aspm
[    0.130298] [      T1] PCI: CLS 0 bytes, default 64
[    5.243878] [     T48] dw-pcie fc000000.pcie: error -ENXIO: IRQ index 1 not found
[    5.294697] [     T48] meson-pcie fc000000.pcie: host bridge /soc/pcie at fc000000 ranges:
[    5.298580] [     T48] meson-pcie fc000000.pcie:       IO 0x00fc600000..0x00fc6fffff -> 0x0000000000
[    5.307484] [     T48] meson-pcie fc000000.pcie:      MEM 0x00fc700000..0x00fdffffff -> 0x00fc700000
[    5.324258] [     T48] meson-pcie fc000000.pcie: iATU: unroll T, 4 ob, 4 ib, align 64K, limit 4G
[    5.366020] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.371376] [     T48] meson-pcie fc000000.pcie: PCIe Gen.2 x1 link up
[    5.375932] [     T48] meson-pcie fc000000.pcie: PCI host bridge to bus 0000:00
[    5.381390] [     T48] pci_bus 0000:00: root bus resource [bus 00-ff]
[    5.388280] [     T48] pci_bus 0000:00: root bus resource [io  0x0000-0xfffff]
[    5.395226] [     T48] pci_bus 0000:00: root bus resource [mem 0xfc700000-0xfdffffff]
[    5.402942] [     T48] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400 PCIe Root Port
[    5.410068] [     T48] pci 0000:00:00.0: ROM [mem 0x00000000-0x0000ffff pref]
[    5.416900] [     T48] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.422838] [     T48] pci 0000:00:00.0:   bridge window [io  0x0000-0x0fff]
[    5.429605] [     T48] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff]
[    5.437147] [     T48] pci 0000:00:00.0:   bridge window [mem 0x00000000-0x000fffff pref]
[    5.445853] [     T48] pci 0000:00:00.0: Disabling ASPM L0s/L1
[    5.451334] [     T48] pci 0000:00:00.0: supports D1
[    5.455104] [     T48] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[    5.480231] [     T48] pci 0000:01:00.0: [8086:2725] type 00 class 0x028000 PCIe Endpoint
[    5.490539] [     T48] pci 0000:01:00.0: BAR 0 [mem 0x00000000-0x00003fff 64bit]
[    5.503464] [     T48] pci 0000:01:00.0: Upstream bridge's Max Payload Size set to 128 (was 256, max 256)
[    5.525959] [     T48] pci 0000:01:00.0: Max Payload Size set to 128 (was 128, max 128)
[    5.534845] [     T48] pci 0000:01:00.0: PME# supported from D0 D3hot D3cold
[    5.560448] [     T48] pci 0000:01:00.0: ASPM: default states L1
[    5.603416] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.606141] [     T48] pci 0000:00:00.0: bridge window [mem 0xfc700000-0xfc7fffff]: assigned
[    5.636768] [     T48] pci 0000:00:00.0: ROM [mem 0xfc800000-0xfc80ffff pref]: assigned
[    5.636812] [     T48] pci 0000:01:00.0: BAR 0 [mem 0xfc700000-0xfc703fff 64bit]: assigned
[    5.693932] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.735461] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.778011] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.820548] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.821633] [     T48] pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
[    5.870950] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.913471] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.914547] [     T48] pci 0000:01:00.0: BAR 0: error updating (high 0x00000000 != 0xffffffff)
[    5.964337] [     T48] meson-pcie fc000000.pcie: error: wait linkup timeout
[    5.975124] [     T48] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[    5.988201] [     T48] pci 0000:00:00.0:   bridge window [mem 0xfc700000-0xfc7fffff]
[    6.004583] [     T48] pci_bus 0000:00: resource 4 [io  0x0000-0xfffff]
[    6.018790] [     T48] pci_bus 0000:00: resource 5 [mem 0xfc700000-0xfdffffff]
[    6.032400] [     T48] pci_bus 0000:01: resource 1 [mem 0xfc700000-0xfc7fffff]
[    6.033164] [     T48] pcieport 0000:00:00.0: PME: Signaling with IRQ 24
[    6.045204] [     T48] pcieport 0000:00:00.0: AER: enabled with IRQ 24

# lspci -vv
00:00.0 PCI bridge: Synopsys, Inc. DWC_usb3 / PCIe bridge (rev 01) (prog-if 00 [Normal decode])
         Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx+
         Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
         Latency: 0
         Interrupt: pin A routed to IRQ 24
         Bus: primary=00, secondary=01, subordinate=ff, sec-latency=0
         I/O behind bridge: [disabled] [16-bit]
         Memory behind bridge: fc700000-fc7fffff [size=1M] [32-bit]
         Prefetchable memory behind bridge: [disabled] [32-bit]
         Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort+ <SERR- <PERR-
         Expansion ROM at fc800000 [virtual] [disabled] [size=64K]
         BridgeCtl: Parity- SERR+ NoISA- VGA- VGA16- MAbort- >Reset- FastB2B-
                 PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-
         Capabilities: [40] Power Management version 3
                 Flags: PMEClk- DSI- D1+ D2- AuxCurrent=375mA PME(D0+,D1+,D2-,D3hot+,D3cold+)
                 Status: D0 NoSoftRst+ PME-Enable- DSel=0 DScale=0 PME-
         Capabilities: [50] MSI: Enable+ Count=1/1 Maskable- 64bit+
                 Address: 000000000935f000  Data: 0000
         Capabilities: [70] Express (v2) Root Port (Slot-), IntMsgNum 0
                 DevCap: MaxPayload 256 bytes, PhantFunc 0
                         ExtTag- RBE+ TEE-IO-
                 DevCtl: CorrErr+ NonFatalErr+ FatalErr+ UnsupReq+
                         RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop-
                         MaxPayload 128 bytes, MaxReadReq 256 bytes
                 DevSta: CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr+ TransPend-
                 LnkCap: Port #0, Speed 5GT/s, Width x1, ASPM L0s L1, Exit Latency L0s <1us, L1 <2us
                         ClockPM- Surprise- LLActRep+ BwNot+ ASPMOptComp+
                 LnkCtl: ASPM L1 Enabled; RCB 64 bytes, LnkDisable- CommClk+
                         ExtSynch- ClockPM- AutWidDis- BWInt+ AutBWInt+
                 LnkSta: Speed 5GT/s, Width x1
                         TrErr- Train- SlotClk+ DLActive+ BWMgmt- ABWMgmt-
                 RootCap: CRSVisible+
                 RootCtl: ErrCorrectable- ErrNon-Fatal- ErrFatal- PMEIntEna+ CRSVisible+
                 RootSta: PME ReqID 0000, PMEStatus- PMEPending-
                 DevCap2: Completion Timeout: Range ABCD, TimeoutDis+ NROPrPrP+ LTR-
                          10BitTagComp- 10BitTagReq- OBFF Not Supported, ExtFmt- EETLPPrefix-
                          EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-
                          FRS- LN System CLS Not Supported, TPHComp- ExtTPHComp- ARIFwd-
                          AtomicOpsCap: Routing- 32bit- 64bit- 128bitCAS-
                 DevCtl2: Completion Timeout: 50us to 50ms, TimeoutDis- ARIFwd-
                          AtomicOpsCtl: ReqEn- EgressBlck-
                          IDOReq- IDOCompl- LTR- EmergencyPowerReductionReq-
                          10BitTagReq- OBFF Disabled, EETLPPrefixBlk-
                 LnkCap2: Supported Link Speeds: 2.5-5GT/s, Crosslink- Retimer- 2Retimers- DRS-
                 LnkCtl2: Target Link Speed: 5GT/s, EnterCompliance- SpeedDis-
                          Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
                          Compliance Preset/De-emphasis: -6dB de-emphasis, 0dB preshoot
                 LnkSta2: Current De-emphasis Level: -6dB, EqualizationComplete- EqualizationPhase1-
                          EqualizationPhase2- EqualizationPhase3- LinkEqualizationRequest-
                          Retimer- 2Retimers- CrosslinkRes: unsupported
         Capabilities: [100 v2] Advanced Error Reporting
                 UESta:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UEMsk:  DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
                         ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
                         PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
                 CESta:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr- CorrIntErr- HeaderOF-
                 CEMsk:  RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr+ HeaderOF+
                 AERCap: First Error Pointer: 00, ECRCGenCap+ ECRCGenEn- ECRCChkCap+ ECRCChkEn-
                         MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
                 HeaderLog: 00000000 00000000 00000000 00000000
                 RootCmd: CERptEn+ NFERptEn+ FERptEn+
                 RootSta: CERcvd- MultCERcvd- UERcvd- MultUERcvd-
                          FirstFatal- NonFatalMsg- FatalMsg- IntMsgNum 0
                 ErrorSrc: ERR_COR: 0000 ERR_FATAL/NONFATAL: 0000
         Capabilities: [148 v1] L1 PM Substates
                 L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2- ASPM_L1.1+ L1_PM_Substates+
                           PortCommonModeRestoreTime=55us PortTPowerOnTime=12us
                 L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2- ASPM_L1.1-
                            T_CommonMode=55us
                 L1SubCtl2: T_PwrOn=18us
         Kernel driver in use: pcieport
         Kernel modules: shpchp

01:00.0 Network controller: Intel Corporation Wi-Fi 6E(802.11ax) AX210/AX1675* 2x2 [Typhoon Peak] (rev 1a)
         Subsystem: Intel Corporation Wi-Fi 6 AX210 160MHz
         !!! Unknown header type 7f
         Region 0: Memory at fc700000 (64-bit, non-prefetchable) [size=16K]
         Kernel modules: iwlwifi

Something else I tried was to boot with pcie_aspm.policy=performance so the link and device can be initialized, then

# echo default > /sys/module/pcie_aspm/parameters/policy

# while true; do cat /sys/kernel/debug/dwc_pcie_fc000000.pcie/ltssm_status; done | uniq
L1_IDLE (0x14)
RCVRY_LOCK (0x0d)
L1_IDLE (0x14)
RCVRY_IDLE (0x10)
L1_IDLE (0x14)
RCVRY_LOCK (0x0d)
L1_IDLE (0x14)
RCVRY_LOCK (0x0d)
L1_IDLE (0x14)
L0 (0x11)
L1_IDLE (0x14)
RCVRY_LOCK (0x0d)
L1_IDLE (0x14)
L0 (0x11)
L1_IDLE (0x14)
RCVRY_LOCK (0x0d)
L1_IDLE (0x14)
RCVRY_LOCK (0x0d)
L1_IDLE (0x14)
L0 (0x11)
L1_IDLE (0x14)
L0 (0x11)
L1_IDLE (0x14)
L0 (0x11)
L1_IDLE (0x14)
L0 (0x11)
L1_IDLE (0x14)
L123_SEND_EIDLE (0x13)
L1_IDLE (0x14)

The card works just fine. I'm thinking the ASPM issue is probably from the glue driver reporting the link to be down when it's really just in low power state.


From devnull+chuan.liu.amlogic.com at kernel.org  Fri Oct 31 01:10:11 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Fri, 31 Oct 2025 16:10:11 +0800
Subject: [PATCH v3 4/4] clk: amlogic: Optimize PLL enable timing
In-Reply-To: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
Message-ID: <20251031-optimize_pll_driver-v3-4-92f3b2f36a83@amlogic.com>

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

l_detect controls the enablement of the PLL lock detection module.
It should remain disabled while the internal PLL circuits are
reaching a steady state; otherwise, the lock signal may be falsely
triggered high.

A 20 us delay has been added before enabling the PLL, so there?s no
need for an additional 10 us delay before enabling current_en.

Currently, only A1 supports both l_detect and current_en, so this
patch will only affect A1.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
 drivers/clk/meson/clk-pll.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index cdb39a723bd0..c9b941adf688 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -383,6 +383,10 @@ 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);
 
@@ -401,20 +405,18 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 	 * 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, delay for 20us
 	 * 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);
+	/* Enable the lock-detect module */
+	if (MESON_PARM_APPLICABLE(&pll->l_detect))
 		meson_parm_write(clk->map, &pll->l_detect, 0);
-	}
 
 	if (meson_clk_pll_wait_lock(hw)) {
 		/* disable PLL when PLL lock failed. */

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Fri Oct 31 01:10:08 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Fri, 31 Oct 2025 16:10:08 +0800
Subject: [PATCH v3 1/4] clk: amlogic: Fix out-of-range PLL frequency
 setting
In-Reply-To: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
Message-ID: <20251031-optimize_pll_driver-v3-1-92f3b2f36a83@amlogic.com>

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

If the calculated 'm' falls into the range:

    pll->range->max < m < (1 << pll->m.width)

Here an incorrect 'm' value could be obtained, so an additional
condition is added to ensure that the calculated 'm' stays within a
valid range.

Fixes: 8eed1db1adec6 ("clk: meson: pll: update driver for the g12a")
Signed-off-by: Chuan Liu <chuan.liu at 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..629f6af18ea1 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 || *m >= (1 << pll->m.width))
 		return -EINVAL;
 
 	return 0;

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Fri Oct 31 01:10:09 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Fri, 31 Oct 2025 16:10:09 +0800
Subject: [PATCH v3 2/4] clk: amlogic: Improve the issue of PLL lock
 failures
In-Reply-To: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
Message-ID: <20251031-optimize_pll_driver-v3-2-92f3b2f36a83@amlogic.com>

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

Due to factors such as temperature and process variations, the
internal circuits of the PLL may require a longer time to reach a
steady state, which can result in occasional lock failures on some
SoCs under low-temperature conditions.

After enabling the PLL and releasing its reset, a 20 us delay is
added at each step to provide enough time for the internal PLL
circuit to stabilize, thus reducing the probability of PLL lock
failure.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
 drivers/clk/meson/clk-pll.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 629f6af18ea1..70c8c7078046 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -369,10 +369,17 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 	/* Enable the pll */
 	meson_parm_write(clk->map, &pll->en, 1);
 
+	/* Wait for Bandgap and LDO to power up and stabilize */
+	udelay(20);
+
 	/* Take the pll out reset */
-	if (MESON_PARM_APPLICABLE(&pll->rst))
+	if (MESON_PARM_APPLICABLE(&pll->rst)) {
 		meson_parm_write(clk->map, &pll->rst, 0);
 
+		/* Wait for PLL loop stabilization */
+		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

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Fri Oct 31 01:10:10 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Fri, 31 Oct 2025 16:10:10 +0800
Subject: [PATCH v3 3/4] clk: amlogic: Add handling for PLL lock failure
In-Reply-To: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
Message-ID: <20251031-optimize_pll_driver-v3-3-92f3b2f36a83@amlogic.com>

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

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 at amlogic.com>
---
 drivers/clk/meson/clk-pll.c | 41 +++++++++++++++++++++++------------------
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 70c8c7078046..cdb39a723bd0 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);
@@ -399,29 +416,17 @@ static int meson_clk_pll_enable(struct clk_hw *hw)
 		meson_parm_write(clk->map, &pll->l_detect, 0);
 	}
 
-	if (meson_clk_pll_wait_lock(hw))
+	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));
+
 		return -EIO;
+	}
 
 	return 0;
 }
 
-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_set_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long parent_rate)
 {

-- 
2.42.0




From devnull+chuan.liu.amlogic.com at kernel.org  Fri Oct 31 01:10:07 2025
From: devnull+chuan.liu.amlogic.com at kernel.org (Chuan Liu via B4 Relay)
Date: Fri, 31 Oct 2025 16:10:07 +0800
Subject: [PATCH v3 0/4] clk: amlogic: optimize the PLL driver
Message-ID: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>

This patch series consists of four topics involving the amlogic PLL
driver:
- Fix out-of-range PLL frequency setting.
- Improve the issue of PLL lock failures.
- Add handling for PLL lock failure.
- Optimize PLL enable timing.

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

The PLL timing optimization changes were merged into our internal
repository quite some time ago and have been verified on a large
number of SoCs:
- Already supported upstream: G12A, G12B, SM1, S4, A1, C3.
- Planned for upstream support: T7, A5, A4, S7, S7D, S6, etc.

Based on the upstream code base, I have performed functional testing
on G12A, A1, A5, A4, T7, S7, S7D, and S6, all of which passed.

Additionally, stress testing using scripts was conducted on A5 and
A1, with over 40,000 and 50,000 iterations respectively, and no
abnormalities were observed. Below is a portion of the stress test
log (CLOCK_ALLOW_WRITE_DEBUGFS has been manually enabled):

- For A5:
  # echo 491520000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
  # cnt=0
  # while true; do
  >     echo "------------ cnt=$cnt -----------"
  >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
  >     if [ "$en" != "1" ]; then
  >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
  >         break
  >     fi
  > 
  >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     cnt=$((cnt + 1))
  >     echo -e "sleep time: 1 s."
  >     sleep 1
  > done &
  # ------------ cnt=0 -----------
  sleep time: 1 s.
  ------------ cnt=1 -----------
  sleep time: 1 s.
  ------------ cnt=2 -----------
  sleep time: 1 s.
  ...
  ------------ cnt=42076 -----------
  sleep time: 1 s.

- For A1:
  # echo 983040000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
  # cnt=0
  # while true; do
  >     echo "------------ cnt=$cnt -----------"
  >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
  >     if [ "$en" != "1" ]; then
  >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
  >         break
  >     fi
  > 
  >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
  >     cnt=$((cnt + 1))
  >     echo -e "sleep time: 1 s."
  >     sleep 1
  > done &
  # ------------ cnt=0 -----------
  sleep time: 1 s.
  ------------ cnt=1 -----------
  sleep time: 1 s.
  ------------ cnt=2 -----------
  sleep time: 1 s.
  ...
  ------------ cnt=55051 -----------
  sleep time: 1 s.

Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
---
Changes in v3:
- Fix some formatting issues.
- Move the 20 us delay after reset into the corresponding if
condition (no delay is needed if there is no reset).
- Move the code that releases rst back to execute before current_en.
- Remove the patch that changes the active level of l_detect.
- Link to v2: https://lore.kernel.org/r/20251030-optimize_pll_driver-v2-0-37273f5b25ab at amlogic.com

Changes in v2:
- Modify the judgment condition of 'm' out of range.
- Split the PLL timing optimization patch to make it easier to review.
- Link to v1: https://lore.kernel.org/r/20251022-optimize_pll_driver-v1-0-a275722fb6f4 at amlogic.com

---
Chuan Liu (4):
      clk: amlogic: Fix out-of-range PLL frequency setting
      clk: amlogic: Improve the issue of PLL lock failures
      clk: amlogic: Add handling for PLL lock failure
      clk: amlogic: Optimize PLL enable timing

 drivers/clk/meson/clk-pll.c | 64 +++++++++++++++++++++++++++------------------
 1 file changed, 39 insertions(+), 25 deletions(-)
---
base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
change-id: 20251020-optimize_pll_driver-7bef91876c41

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




From neil.armstrong at linaro.org  Fri Oct 31 01:50:59 2025
From: neil.armstrong at linaro.org (Neil Armstrong)
Date: Fri, 31 Oct 2025 09:50:59 +0100
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <DM4PR05MB10270506AAC1FCE53C4915CC2C7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>
References: <20251029171542.GA1566240@bhelgaas>
 <DM4PR05MB10270506AAC1FCE53C4915CC2C7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>
Message-ID: <59baecc0-bc28-4411-bf83-37ff9e7dd193@linaro.org>

On 10/31/25 06:34, Linnaea Lavia wrote:
> On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
>> On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
>>> On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
>>
>>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>>> index 214ed060ca1b..9cd12924b5cb 100644
>>>> --- a/drivers/pci/quirks.c
>>>> +++ b/drivers/pci/quirks.c
>>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>> ??? * disable both L0s and L1 for now to be safe.
>>>> ??? */
>>>> ?? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>> ?? /*
>>>> ??? * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
>>>
>>> I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
>>
>> Sorry, my fault, I should have made that fixup run earlier, so the
>> patch should be this instead:
>>
>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>> index 214ed060ca1b..4fc04015ca0c 100644
>> --- a/drivers/pci/quirks.c
>> +++ b/drivers/pci/quirks.c
>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>> ?? * disable both L0s and L1 for now to be safe.
>> ?? */
>> ? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
> 
> L1 still got enabled

<snip>

> 
> The card works just fine. I'm thinking the ASPM issue is probably from the glue driver reporting the link to be down when it's really just in low power state.

You're probbaly right, the meson_pcie_link_up() not only checks the LTSSM but also the speed, which is probably wrong.

Can you try removing the test for speed ?

-                 if (smlh_up && rdlh_up && ltssm_up && speed_okay)
+                 if (smlh_up && rdlh_up && ltssm_up)

The other drivers just checks the link, and some only the smlh_up && rdlh_up. So you can also probably drop ltssm_up aswell.

Neil




From jbrunet at baylibre.com  Fri Oct 31 02:04:42 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 31 Oct 2025 10:04:42 +0100
Subject: [PATCH v3 0/4] clk: amlogic: optimize the PLL driver
In-Reply-To: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
	(Chuan Liu via's message of "Fri, 31 Oct 2025 16:10:07 +0800")
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
Message-ID: <1jms57xx05.fsf@starbuckisacylon.baylibre.com>

On Fri 31 Oct 2025 at 16:10, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:

> This patch series consists of four topics involving the amlogic PLL
> driver:
> - Fix out-of-range PLL frequency setting.
> - Improve the issue of PLL lock failures.
> - Add handling for PLL lock failure.
> - Optimize PLL enable timing.
>
> For easier review and management, these are submitted as a single
> patch series.
>
> The PLL timing optimization changes were merged into our internal
> repository quite some time ago and have been verified on a large
> number of SoCs:
> - Already supported upstream: G12A, G12B, SM1, S4, A1, C3.
> - Planned for upstream support: T7, A5, A4, S7, S7D, S6, etc.
>
> Based on the upstream code base, I have performed functional testing
> on G12A, A1, A5, A4, T7, S7, S7D, and S6, all of which passed.
>
> Additionally, stress testing using scripts was conducted on A5 and
> A1, with over 40,000 and 50,000 iterations respectively, and no
> abnormalities were observed. Below is a portion of the stress test
> log (CLOCK_ALLOW_WRITE_DEBUGFS has been manually enabled):

Okay, this little game has been going on long enough.

You've posted v2 24h hours ago
You've got feedback within hours
There was still a 1 question pending
The rest of community had no chance to review.

and yet, here the v3 already ! still with bearing pr_warn().

Chuan, the community is not dedicated to reviewing your submission.
Time and time again you ignore the feedback provided in reviews and the
documentation. I've had enough of your sloppy submission.

I will not review or apply anything from you in this cycle.

You have been warned multiple times. Every time you ignore a review,
you'll get ignored in return. This is how it will be from now on.

>
> - For A5:
>   # echo 491520000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
>   # cnt=0
>   # while true; do
>   >     echo "------------ cnt=$cnt -----------"
>   >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>   >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
>   >     if [ "$en" != "1" ]; then
>   >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
>   >         break
>   >     fi
>   > 
>   >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>   >     cnt=$((cnt + 1))
>   >     echo -e "sleep time: 1 s."
>   >     sleep 1
>   > done &
>   # ------------ cnt=0 -----------
>   sleep time: 1 s.
>   ------------ cnt=1 -----------
>   sleep time: 1 s.
>   ------------ cnt=2 -----------
>   sleep time: 1 s.
>   ...
>   ------------ cnt=42076 -----------
>   sleep time: 1 s.
>
> - For A1:
>   # echo 983040000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
>   # cnt=0
>   # while true; do
>   >     echo "------------ cnt=$cnt -----------"
>   >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>   >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
>   >     if [ "$en" != "1" ]; then
>   >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
>   >         break
>   >     fi
>   > 
>   >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>   >     cnt=$((cnt + 1))
>   >     echo -e "sleep time: 1 s."
>   >     sleep 1
>   > done &
>   # ------------ cnt=0 -----------
>   sleep time: 1 s.
>   ------------ cnt=1 -----------
>   sleep time: 1 s.
>   ------------ cnt=2 -----------
>   sleep time: 1 s.
>   ...
>   ------------ cnt=55051 -----------
>   sleep time: 1 s.
>
> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
> ---
> Changes in v3:
> - Fix some formatting issues.
> - Move the 20 us delay after reset into the corresponding if
> condition (no delay is needed if there is no reset).
> - Move the code that releases rst back to execute before current_en.
> - Remove the patch that changes the active level of l_detect.
> - Link to v2: https://lore.kernel.org/r/20251030-optimize_pll_driver-v2-0-37273f5b25ab at amlogic.com
>
> Changes in v2:
> - Modify the judgment condition of 'm' out of range.
> - Split the PLL timing optimization patch to make it easier to review.
> - Link to v1: https://lore.kernel.org/r/20251022-optimize_pll_driver-v1-0-a275722fb6f4 at amlogic.com
>
> ---
> Chuan Liu (4):
>       clk: amlogic: Fix out-of-range PLL frequency setting
>       clk: amlogic: Improve the issue of PLL lock failures
>       clk: amlogic: Add handling for PLL lock failure
>       clk: amlogic: Optimize PLL enable timing
>
>  drivers/clk/meson/clk-pll.c | 64 +++++++++++++++++++++++++++------------------
>  1 file changed, 39 insertions(+), 25 deletions(-)
> ---
> base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
> change-id: 20251020-optimize_pll_driver-7bef91876c41
>
> Best regards,

-- 
Jerome


From jbrunet at baylibre.com  Fri Oct 31 02:51:19 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 31 Oct 2025 10:51:19 +0100
Subject: [PATCH v4 5/5] clk: meson: t7: add t7 clock peripherals
 controller driver
In-Reply-To: <20251030094345.2571222-6-jian.hu@amlogic.com> (Jian Hu's message
	of "Thu, 30 Oct 2025 17:43:45 +0800")
References: <20251030094345.2571222-1-jian.hu@amlogic.com>
	<20251030094345.2571222-6-jian.hu@amlogic.com>
Message-ID: <1jbjlnxuug.fsf@starbuckisacylon.baylibre.com>

On Thu 30 Oct 2025 at 17:43, Jian Hu <jian.hu at amlogic.com> wrote:

> Add Peripheral clock controller driver for the Amlogic T7 SoC family.
>
> Signed-off-by: Jian Hu <jian.hu at amlogic.com>
> ---
>  drivers/clk/meson/Kconfig          |   13 +
>  drivers/clk/meson/Makefile         |    1 +
>  drivers/clk/meson/t7-peripherals.c | 1734 ++++++++++++++++++++++++++++
>  3 files changed, 1748 insertions(+)
>  create mode 100644 drivers/clk/meson/t7-peripherals.c
>
> diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
> index 6cdc6a96e105..d2442ae0f5be 100644
> --- a/drivers/clk/meson/Kconfig
> +++ b/drivers/clk/meson/Kconfig
> @@ -215,4 +215,17 @@ config COMMON_CLK_T7_PLL
>  	  device, AKA T7. PLLs are required by most peripheral to operate
>  	  Say Y if you are a T7 based device.
>  
> +config COMMON_CLK_T7_PERIPHERALS
> +	tristate "Amlogic T7 SoC peripherals clock controller support"
> +	depends on ARM64
> +	default ARCH_MESON
> +	select COMMON_CLK_MESON_REGMAP
> +	select COMMON_CLK_MESON_CLKC_UTILS
> +	select COMMON_CLK_MESON_DUALDIV
> +	imply COMMON_CLK_SCMI
> +	imply COMMON_CLK_T7_PLL
> +	help
> +	  Support for the Peripherals clock controller on Amlogic A311D2 based
> +	  device, AKA T7. Peripherals are required by most peripheral to operate
> +	  Say Y if you are a T7 based device.
>  endmenu
> diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
> index 8e3f7f94c639..c6719694a242 100644
> --- a/drivers/clk/meson/Makefile
> +++ b/drivers/clk/meson/Makefile
> @@ -27,3 +27,4 @@ obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
>  obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o
>  obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o
>  obj-$(CONFIG_COMMON_CLK_T7_PLL) += t7-pll.o
> +obj-$(CONFIG_COMMON_CLK_T7_PERIPHERALS) += t7-peripherals.o
> diff --git a/drivers/clk/meson/t7-peripherals.c b/drivers/clk/meson/t7-peripherals.c
> new file mode 100644
> index 000000000000..e2ee0ba2bb8a
> --- /dev/null
> +++ b/drivers/clk/meson/t7-peripherals.c
> @@ -0,0 +1,1734 @@
> +// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
> +/*
> + * Copyright (C) 2024-2025 Amlogic, Inc. All rights reserved.
> + * Author: Jian Hu <jian.hu at amlogic.com>
> + */
> +
> +#include <linux/clk-provider.h>
> +#include <linux/platform_device.h>
> +#include "clk-dualdiv.h"
> +#include "clk-regmap.h"
> +#include "meson-clkc-utils.h"
> +#include <dt-bindings/clock/amlogic,t7-peripherals-clkc.h>
> +
> +#define RTC_BY_OSCIN_CTRL0	0x8
> +#define RTC_BY_OSCIN_CTRL1	0xc
> +#define RTC_CTRL		0x10
> +#define SYS_CLK_CTRL0		0x40
> +#define SYS_CLK_EN0_REG0	0x44
> +#define SYS_CLK_EN0_REG1	0x48
> +#define SYS_CLK_EN0_REG2	0x4c
> +#define SYS_CLK_EN0_REG3	0x50
> +#define CECA_CTRL0		0x88
> +#define CECA_CTRL1		0x8c
> +#define CECB_CTRL0		0x90
> +#define CECB_CTRL1		0x94
> +#define SC_CLK_CTRL		0x98
> +#define DSPA_CLK_CTRL0		0x9c
> +#define DSPB_CLK_CTRL0		0xa0
> +#define CLK12_24_CTRL		0xa8
> +#define ANAKIN_CLK_CTRL		0xac
> +#define MIPI_CSI_PHY_CLK_CTRL	0x10c
> +#define MIPI_ISP_CLK_CTRL	0x110
> +#define TS_CLK_CTRL		0x158
> +#define MALI_CLK_CTRL		0x15c
> +#define ETH_CLK_CTRL		0x164
> +#define NAND_CLK_CTRL		0x168
> +#define SD_EMMC_CLK_CTRL	0x16c
> +#define SPICC_CLK_CTRL		0x174
> +#define SAR_CLK_CTRL0		0x17c
> +#define PWM_CLK_AB_CTRL		0x180
> +#define PWM_CLK_CD_CTRL		0x184
> +#define PWM_CLK_EF_CTRL		0x188
> +#define PWM_CLK_AO_AB_CTRL	0x1a0
> +#define PWM_CLK_AO_CD_CTRL	0x1a4
> +#define PWM_CLK_AO_EF_CTRL	0x1a8
> +#define PWM_CLK_AO_GH_CTRL	0x1ac
> +#define SPICC_CLK_CTRL1		0x1c0
> +#define SPICC_CLK_CTRL2		0x1c4
> +
> +#define T7_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
> +	MESON_COMP_SEL(t7_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
> +
> +#define T7_COMP_DIV(_name, _reg, _shift, _width) \
> +	MESON_COMP_DIV(t7_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
> +
> +#define T7_COMP_GATE(_name, _reg, _bit) \
> +	MESON_COMP_GATE(t7_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
> +
> +static struct clk_regmap t7_rtc_32k_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = RTC_BY_OSCIN_CTRL0,
> +		.bit_idx = 31,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "rtc_32k_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static const struct meson_clk_dualdiv_param t7_clk_32k_div_table[] = {
> +	{
> +		.n1	= 733, .m1	= 8,
> +		.n2	= 732, .m2	= 11,
> +		.dual	= 1,
> +	},
> +	{}
> +};
> +
> +static struct clk_regmap t7_rtc_32k_div = {
> +	.data = &(struct meson_clk_dualdiv_data){
> +		.n1 = {
> +			.reg_off = RTC_BY_OSCIN_CTRL0,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.n2 = {
> +			.reg_off = RTC_BY_OSCIN_CTRL0,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.m1 = {
> +			.reg_off = RTC_BY_OSCIN_CTRL1,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.m2 = {
> +			.reg_off = RTC_BY_OSCIN_CTRL1,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.dual = {
> +			.reg_off = RTC_BY_OSCIN_CTRL0,
> +			.shift   = 28,
> +			.width   = 1,
> +		},
> +		.table = t7_clk_32k_div_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "rtc_32k_div",
> +		.ops = &meson_clk_dualdiv_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_rtc_32k_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_rtc_32k_force_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = RTC_BY_OSCIN_CTRL1,
> +		.mask = 0x1,
> +		.shift = 24,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "rtc_32k_force_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_rtc_32k_div.hw,
> +			&t7_rtc_32k_in.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_rtc_32k_out = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = RTC_BY_OSCIN_CTRL0,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "rtc_32k_out",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_rtc_32k_force_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_rtc_32k_mux0_0 = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = RTC_CTRL,
> +		.mask = 0x1,
> +		.shift = 0,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "rtc_32k_mux0_0",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .fw_name = "xtal", },
> +			{ .hw = &t7_rtc_32k_out.hw },
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_rtc_32k_mux0_1 = {

mux0_0 and mux0_1 ? Those are  terrible names to search and grep.
Is this really what your documentation is using ? If not, please come up
with something better

> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = RTC_CTRL,
> +		.mask = 0x1,
> +		.shift = 0,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "rtc_32k_mux0_1",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = (const struct clk_parent_data []) {
> +			{ .fw_name = "pad", },
> +			{ .fw_name = "xtal", },
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,

You probably want CLK_SET_RATE_NO_REPARENT for clock with a pad source
like this.

> +	},
> +};
> +
> +static struct clk_regmap t7_rtc = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = RTC_CTRL,
> +		.mask = 0x1,
> +		.shift = 1,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "rtc",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_rtc_32k_mux0_0.hw,
> +			&t7_rtc_32k_mux0_1.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_ceca_32k_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CECA_CTRL0,
> +		.bit_idx = 31,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "ceca_32k_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_ceca_32k_div = {
> +	.data = &(struct meson_clk_dualdiv_data){
> +		.n1 = {
> +			.reg_off = CECA_CTRL0,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.n2 = {
> +			.reg_off = CECA_CTRL0,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.m1 = {
> +			.reg_off = CECA_CTRL1,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.m2 = {
> +			.reg_off = CECA_CTRL1,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.dual = {
> +			.reg_off = CECA_CTRL0,
> +			.shift   = 28,
> +			.width   = 1,
> +		},
> +		.table = t7_clk_32k_div_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ceca_32k_div",
> +		.ops = &meson_clk_dualdiv_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_ceca_32k_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_ceca_32k_sel_pre = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = CECA_CTRL1,
> +		.mask = 0x1,
> +		.shift = 24,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ceca_32k_sel_pre",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_ceca_32k_div.hw,
> +			&t7_ceca_32k_in.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_ceca_32k_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = CECA_CTRL1,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ceca_32k_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_ceca_32k_sel_pre.hw,
> +			&t7_rtc.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_ceca_32k_out = {

Is the "_out" really necessary ? usually the last element just the base
clock name. Same for the other occurence.

> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CECA_CTRL0,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ceca_32k_out",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_ceca_32k_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_cecb_32k_in = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CECB_CTRL0,
> +		.bit_idx = 31,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "cecb_32k_in",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_cecb_32k_div = {
> +	.data = &(struct meson_clk_dualdiv_data){
> +		.n1 = {
> +			.reg_off = CECB_CTRL0,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.n2 = {
> +			.reg_off = CECB_CTRL0,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.m1 = {
> +			.reg_off = CECB_CTRL1,
> +			.shift   = 0,
> +			.width   = 12,
> +		},
> +		.m2 = {
> +			.reg_off = CECB_CTRL1,
> +			.shift   = 12,
> +			.width   = 12,
> +		},
> +		.dual = {
> +			.reg_off = CECB_CTRL0,
> +			.shift   = 28,
> +			.width   = 1,
> +		},
> +		.table = t7_clk_32k_div_table,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "cecb_32k_div",
> +		.ops = &meson_clk_dualdiv_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_cecb_32k_in.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_cecb_32k_sel_pre = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = CECB_CTRL1,
> +		.mask = 0x1,
> +		.shift = 24,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "cecb_32k_sel_pre",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_cecb_32k_div.hw,
> +			&t7_cecb_32k_in.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_cecb_32k_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = CECB_CTRL1,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "cecb_32k_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_cecb_32k_sel_pre.hw,
> +			&t7_rtc.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_cecb_32k_out = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CECB_CTRL0,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "cecb_32k_out",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_cecb_32k_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data t7_sc_parents[] = {
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "xtal", },
> +};
> +
> +static T7_COMP_SEL(sc, SC_CLK_CTRL, 9, 0x3, t7_sc_parents);
> +static T7_COMP_DIV(sc, SC_CLK_CTRL, 0, 8);
> +static T7_COMP_GATE(sc, SC_CLK_CTRL, 8);
> +
> +static const struct clk_parent_data t7_dsp_ab_parent_data[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "hifi", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv7", },
> +	{ .hw = &t7_rtc.hw },
> +};
> +
> +static struct clk_regmap t7_dspa_a_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.mask = 0x7,
> +		.shift = 10,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspa_a_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_dsp_ab_parent_data,
> +		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
> +	},
> +};
> +
> +static struct clk_regmap t7_dspa_a_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.shift = 0,
> +		.width = 10,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspa_a_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspa_a_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspa_a = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.bit_idx = 13,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "dspa_a",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspa_a_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspa_b_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.mask = 0x7,
> +		.shift = 26,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspa_b_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_dsp_ab_parent_data,
> +		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
> +	},
> +};
> +
> +static struct clk_regmap t7_dspa_b_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.shift = 16,
> +		.width = 10,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspa_b_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspa_b_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspa_b = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.bit_idx = 29,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "dspa_b",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspa_b_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};

You have several instances of these glitch free mux (dsp here, anakin
below, etc ...). That's quite verbose.

I suggest defining T7_COMP_GATE() such that flags is a parameter
Then use it for the sel, div and gate of element.

You'll just have to fully define the final mux element, like you have
below.

> +
> +static struct clk_regmap t7_dspa = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPA_CLK_CTRL0,
> +		.mask = 0x1,
> +		.shift = 15,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspa",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspa_a.hw,
> +			&t7_dspa_b.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb_a_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.mask = 0x7,
> +		.shift = 10,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspb_a_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_dsp_ab_parent_data,
> +		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb_a_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.shift = 0,
> +		.width = 10,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspb_a_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspb_a_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb_a = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.bit_idx = 13,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "dspb_a",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspb_a_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb_b_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.mask = 0x7,
> +		.shift = 26,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspb_b_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_dsp_ab_parent_data,
> +		.num_parents = ARRAY_SIZE(t7_dsp_ab_parent_data),
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb_b_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.shift = 16,
> +		.width = 10,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspb_b_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspb_b_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb_b = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.bit_idx = 29,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "dspb_b",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspb_b_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_dspb = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = DSPB_CLK_CTRL0,
> +		.mask = 0x1,
> +		.shift = 15,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "dspb",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_dspb_a.hw,
> +			&t7_dspb_b.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_clk_24m = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CLK12_24_CTRL,
> +		.bit_idx = 11,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "24m",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_fixed_factor t7_clk_24m_div2 = {
> +	.mult = 1,
> +	.div = 2,
> +	.hw.init = &(struct clk_init_data){
> +		.name = "24m_div2",
> +		.ops = &clk_fixed_factor_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_clk_24m.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_clk_12m = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CLK12_24_CTRL,
> +		.bit_idx = 10,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "12m",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_clk_24m_div2.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_fdiv2_divn_pre = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = CLK12_24_CTRL,
> +		.shift = 0,
> +		.width = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "fdiv2_divn_pre",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "fdiv2",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_fdiv2_divn = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = CLK12_24_CTRL,
> +		.bit_idx = 12,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "fdiv2_divn",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_fdiv2_divn_pre.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/*
> + * The NNA IP is clocked by two identical clocks (anakin_0 and anakin_1)
> + * muxed by a glitch-free switch.
> + */
> +static const struct clk_parent_data t7_anakin_parent_data[] = {
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "vid_pll0", },
> +	{ .fw_name = "mpll1", },
> +	{ .fw_name = "mpll2", },
> +	{ .fw_name = "fdiv2p5", },
> +};
> +
> +static struct clk_regmap t7_anakin_0_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 9,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "anakin_0_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_anakin_parent_data,
> +		.num_parents = ARRAY_SIZE(t7_anakin_parent_data),
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin_0_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.shift = 0,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "anakin_0_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_anakin_0_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin_0 = {

Nitpick: for the DSP it was a/b, here it is 0/1
Could you pick one way or the other and stick to it ?

> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "anakin_0",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) { &t7_anakin_0_div.hw },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin_1_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 25,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "anakin_1_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_anakin_parent_data,
> +		.num_parents = ARRAY_SIZE(t7_anakin_parent_data),
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin_1_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.shift = 16,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "anakin_1_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_anakin_1_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin_1 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.bit_idx = 24,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "anakin_1",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_anakin_1_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.mask = 1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "anakin_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_anakin_0.hw,
> +			&t7_anakin_1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT
> +	},
> +};
> +
> +static struct clk_regmap t7_anakin_clk = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = ANAKIN_CLK_CTRL,
> +		.bit_idx = 30,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "anakin_clk",

Again, not a great name, especially considering the one above.
Is this really really how the doc refers to these 2 clocks ?

> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_anakin.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT
> +	},
> +};
> +
> +static const struct clk_parent_data t7_mipi_csi_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "mpll1", },
> +	{ .fw_name = "mpll2", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy0_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 9,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mipi_csi_phy0_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_mipi_csi_parents,
> +		.num_parents = ARRAY_SIZE(t7_mipi_csi_parents),
> +	},
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy0_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.shift = 0,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mipi_csi_phy0_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mipi_csi_phy0_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy0 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "mipi_csi_phy0",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mipi_csi_phy0_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy1_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 25,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mipi_csi_phy1_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_mipi_csi_parents,
> +		.num_parents = ARRAY_SIZE(t7_mipi_csi_parents),
> +	},
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy1_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.shift = 16,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mipi_csi_phy1_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mipi_csi_phy1_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy1 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.bit_idx = 24,
> +	},
> +	.hw.init = &(struct clk_init_data) {
> +		.name = "mipi_csi_phy1",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mipi_csi_phy1_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mipi_csi_phy = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MIPI_CSI_PHY_CLK_CTRL,
> +		.mask = 0x1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mipi_csi_phy",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mipi_csi_phy0.hw,
> +			&t7_mipi_csi_phy1.hw
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static const struct clk_parent_data t7_mipi_isp_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "mpll2", },
> +	{ .fw_name = "mpll3", },
> +	{ .fw_name = "gp1", },
> +};
> +
> +static T7_COMP_SEL(mipi_isp, MIPI_ISP_CLK_CTRL, 9, 0x7, t7_mipi_isp_parents);
> +static T7_COMP_DIV(mipi_isp, MIPI_ISP_CLK_CTRL, 0, 7);
> +static T7_COMP_GATE(mipi_isp, MIPI_ISP_CLK_CTRL, 8);
> +
> +static struct clk_regmap t7_ts_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = TS_CLK_CTRL,
> +		.shift = 0,
> +		.width = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ts_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "xtal",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_ts = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = TS_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "ts",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_ts_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/*
> + * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
> + * muxed by a glitch-free switch.
> + */
> +static const struct clk_parent_data t7_mali_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "gp0", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +};
> +
> +static struct clk_regmap t7_mali_0_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MALI_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 9,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_0_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_mali_parents,
> +		.num_parents = ARRAY_SIZE(t7_mali_parents),
> +	},
> +};
> +
> +static struct clk_regmap t7_mali_0_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = MALI_CLK_CTRL,
> +		.shift = 0,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_0_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mali_0_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mali_0 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = MALI_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_0",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mali_0_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mali_1_sel = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MALI_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 25,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_1_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_mali_parents,
> +		.num_parents = ARRAY_SIZE(t7_mali_parents),
> +	},
> +};
> +
> +static struct clk_regmap t7_mali_1_div = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = MALI_CLK_CTRL,
> +		.shift = 16,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_1_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mali_1_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mali_1 = {
> +	.data = &(struct clk_regmap_gate_data){
> +		.offset = MALI_CLK_CTRL,
> +		.bit_idx = 24,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali_1",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mali_1_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_mali = {
> +	.data = &(struct clk_regmap_mux_data){
> +		.offset = MALI_CLK_CTRL,
> +		.mask = 1,
> +		.shift = 31,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "mali",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_mali_0.hw,
> +			&t7_mali_1.hw,
> +		},
> +		.num_parents = 2,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +/* parent index 2, 3, 4, 5, 6 not connect any clock signal, they are empty */

Remove "they are empty" ... the rest is fine

> +static u32 t7_eth_rmii_table[] = { 0, 1, 7 };

t7_eth_rmii_parents_val_table[] ... consistency (please check for other occurences)

> +
> +static const struct clk_parent_data t7_eth_rmii_parents[] = {
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "gp1", },
> +	{ .fw_name = "ext_rmii", },
> +};
> +
> +static struct clk_regmap t7_eth_rmii_sel = {
> +	.data = &(struct clk_regmap_mux_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.mask = 0x7,
> +		.shift = 9,
> +		.table = t7_eth_rmii_table
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_rmii_sel",
> +		.ops = &clk_regmap_mux_ops,
> +		.parent_data = t7_eth_rmii_parents,
> +		.num_parents = ARRAY_SIZE(t7_eth_rmii_parents),
> +	},
> +};
> +
> +static struct clk_regmap t7_eth_rmii_div = {
> +	.data = &(struct clk_regmap_div_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.shift = 0,
> +		.width = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_rmii_div",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_eth_rmii_sel.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap t7_eth_rmii = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.bit_idx = 8,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_rmii",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_eth_rmii_div.hw
> +		},
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_fixed_factor t7_fdiv2_div8 = {
> +	.mult = 1,
> +	.div = 8,
> +	.hw.init = &(struct clk_init_data){
> +		.name = "fdiv2_div8",
> +		.ops = &clk_fixed_factor_ops,
> +		.parent_data = &(const struct clk_parent_data) {
> +			.fw_name = "fdiv2",
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap t7_eth_125m = {
> +	.data = &(struct clk_regmap_gate_data) {
> +		.offset = ETH_CLK_CTRL,
> +		.bit_idx = 7,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "eth_125m",
> +		.ops = &clk_regmap_gate_ops,
> +		.parent_hws = (const struct clk_hw *[]) {
> +			&t7_fdiv2_div8.hw
> +		},
> +		.num_parents = 1,
> +	},
> +};
> +
> +static const struct clk_parent_data t7_sd_emmc_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "hifi", },
> +	{ .fw_name = "fdiv2p5", },
> +	{ .fw_name = "mpll2", },
> +	{ .fw_name = "mpll3", },
> +	{ .fw_name = "gp0", },
> +};
> +
> +static T7_COMP_SEL(sd_emmc_c, NAND_CLK_CTRL, 9, 0x7, t7_sd_emmc_parents);
> +static T7_COMP_DIV(sd_emmc_c, NAND_CLK_CTRL, 0, 7);
> +static T7_COMP_GATE(sd_emmc_c, NAND_CLK_CTRL, 7);
> +
> +static T7_COMP_SEL(sd_emmc_a, SD_EMMC_CLK_CTRL, 9, 0x7, t7_sd_emmc_parents);
> +static T7_COMP_DIV(sd_emmc_a, SD_EMMC_CLK_CTRL, 0, 7);
> +static T7_COMP_GATE(sd_emmc_a, SD_EMMC_CLK_CTRL, 7);
> +
> +static T7_COMP_SEL(sd_emmc_b, SD_EMMC_CLK_CTRL, 25, 0x7, t7_sd_emmc_parents);
> +static T7_COMP_DIV(sd_emmc_b, SD_EMMC_CLK_CTRL, 16, 7);
> +static T7_COMP_GATE(sd_emmc_b, SD_EMMC_CLK_CTRL, 23);
> +
> +static const struct clk_parent_data t7_spicc_parents[] = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "sys", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +	{ .fw_name = "fdiv2", },
> +	{ .fw_name = "fdiv5", },
> +	{ .fw_name = "fdiv7", },
> +	{ .fw_name = "gp1", },
> +};
> +
> +static T7_COMP_SEL(spicc0, SPICC_CLK_CTRL, 7, 0x7, t7_spicc_parents);
> +static T7_COMP_DIV(spicc0, SPICC_CLK_CTRL, 0, 6);
> +static T7_COMP_GATE(spicc0, SPICC_CLK_CTRL, 6);
> +
> +static T7_COMP_SEL(spicc1, SPICC_CLK_CTRL, 23, 0x7, t7_spicc_parents);
> +static T7_COMP_DIV(spicc1, SPICC_CLK_CTRL, 16, 6);
> +static T7_COMP_GATE(spicc1, SPICC_CLK_CTRL, 22);
> +
> +static T7_COMP_SEL(spicc2, SPICC_CLK_CTRL1, 7, 0x7, t7_spicc_parents);
> +static T7_COMP_DIV(spicc2, SPICC_CLK_CTRL1, 0, 6);
> +static T7_COMP_GATE(spicc2, SPICC_CLK_CTRL1, 6);
> +
> +static T7_COMP_SEL(spicc3, SPICC_CLK_CTRL1, 23, 0x7, t7_spicc_parents);
> +static T7_COMP_DIV(spicc3, SPICC_CLK_CTRL1, 16, 6);
> +static T7_COMP_GATE(spicc3, SPICC_CLK_CTRL1, 22);
> +
> +static T7_COMP_SEL(spicc4, SPICC_CLK_CTRL2, 7, 0x7, t7_spicc_parents);
> +static T7_COMP_DIV(spicc4, SPICC_CLK_CTRL2, 0, 6);
> +static T7_COMP_GATE(spicc4, SPICC_CLK_CTRL2, 6);
> +
> +static T7_COMP_SEL(spicc5, SPICC_CLK_CTRL2, 23, 0x7, t7_spicc_parents);
> +static T7_COMP_DIV(spicc5, SPICC_CLK_CTRL2, 16, 6);
> +static T7_COMP_GATE(spicc5, SPICC_CLK_CTRL2, 22);
> +
> +static const struct clk_parent_data t7_saradc_parents[] = {
> +	{ .fw_name = "xtal" },
> +	{ .fw_name = "sys" },
> +};
> +
> +static T7_COMP_SEL(saradc, SAR_CLK_CTRL0, 9, 0x1, t7_saradc_parents);
> +static T7_COMP_DIV(saradc, SAR_CLK_CTRL0, 0, 8);
> +static T7_COMP_GATE(saradc, SAR_CLK_CTRL0, 8);
> +
> +static const struct clk_parent_data t7_pwm_parents[]  = {
> +	{ .fw_name = "xtal", },
> +	{ .fw_name = "vid_pll0", },
> +	{ .fw_name = "fdiv4", },
> +	{ .fw_name = "fdiv3", },
> +};
> +
> +static T7_COMP_SEL(pwm_a, PWM_CLK_AB_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_a, PWM_CLK_AB_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_a, PWM_CLK_AB_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_b, PWM_CLK_AB_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_b, PWM_CLK_AB_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_b, PWM_CLK_AB_CTRL, 24);
> +
> +static T7_COMP_SEL(pwm_c, PWM_CLK_CD_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_c, PWM_CLK_CD_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_c, PWM_CLK_CD_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_d, PWM_CLK_CD_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_d, PWM_CLK_CD_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_d, PWM_CLK_CD_CTRL, 24);
> +
> +static T7_COMP_SEL(pwm_e, PWM_CLK_EF_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_e, PWM_CLK_EF_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_e, PWM_CLK_EF_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_f, PWM_CLK_EF_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_f, PWM_CLK_EF_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_f, PWM_CLK_EF_CTRL, 24);
> +
> +static T7_COMP_SEL(pwm_ao_a, PWM_CLK_AO_AB_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_a, PWM_CLK_AO_AB_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_ao_a, PWM_CLK_AO_AB_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_ao_b, PWM_CLK_AO_AB_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_b, PWM_CLK_AO_AB_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_ao_b, PWM_CLK_AO_AB_CTRL, 24);
> +
> +static T7_COMP_SEL(pwm_ao_c, PWM_CLK_AO_CD_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_c, PWM_CLK_AO_CD_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_ao_c, PWM_CLK_AO_CD_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_ao_d, PWM_CLK_AO_CD_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_d, PWM_CLK_AO_CD_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_ao_d, PWM_CLK_AO_CD_CTRL, 24);
> +
> +static T7_COMP_SEL(pwm_ao_e, PWM_CLK_AO_EF_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_e, PWM_CLK_AO_EF_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_ao_e, PWM_CLK_AO_EF_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_ao_f, PWM_CLK_AO_EF_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_f, PWM_CLK_AO_EF_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_ao_f, PWM_CLK_AO_EF_CTRL, 24);
> +
> +static T7_COMP_SEL(pwm_ao_g, PWM_CLK_AO_GH_CTRL, 9, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_g, PWM_CLK_AO_GH_CTRL, 0, 8);
> +static T7_COMP_GATE(pwm_ao_g, PWM_CLK_AO_GH_CTRL, 8);
> +
> +static T7_COMP_SEL(pwm_ao_h, PWM_CLK_AO_GH_CTRL, 25, 0x3, t7_pwm_parents);
> +static T7_COMP_DIV(pwm_ao_h, PWM_CLK_AO_GH_CTRL, 16, 8);
> +static T7_COMP_GATE(pwm_ao_h, PWM_CLK_AO_GH_CTRL, 24);
> +
> +static const struct clk_parent_data t7_sys_pclk_parents = { .fw_name = "sys" };
> +
> +#define T7_SYS_PCLK(_name, _reg, _bit, _flags) \
> +	MESON_PCLK(t7_##_name, _reg, _bit, &t7_sys_pclk_parents, _flags)
> +
> +static T7_SYS_PCLK(sys_ddr,		SYS_CLK_EN0_REG0, 0,	0);
> +static T7_SYS_PCLK(sys_dos,		SYS_CLK_EN0_REG0, 1,	0);
> +static T7_SYS_PCLK(sys_mipi_dsi_a,	SYS_CLK_EN0_REG0, 2,	0);
> +static T7_SYS_PCLK(sys_mipi_dsi_b,	SYS_CLK_EN0_REG0, 3,	0);
> +static T7_SYS_PCLK(sys_ethphy,		SYS_CLK_EN0_REG0, 4,	0);
> +static T7_SYS_PCLK(sys_mali,		SYS_CLK_EN0_REG0, 6,	0);
> +static T7_SYS_PCLK(sys_aocpu,		SYS_CLK_EN0_REG0, 13,	0);
> +static T7_SYS_PCLK(sys_aucpu,		SYS_CLK_EN0_REG0, 14,	0);
> +static T7_SYS_PCLK(sys_cec,		SYS_CLK_EN0_REG0, 16,	0);
> +static T7_SYS_PCLK(sys_gdc,		SYS_CLK_EN0_REG0, 17,	0);
> +static T7_SYS_PCLK(sys_deswarp,		SYS_CLK_EN0_REG0, 18,	0);
> +static T7_SYS_PCLK(sys_ampipe_nand,	SYS_CLK_EN0_REG0, 19,	0);
> +static T7_SYS_PCLK(sys_ampipe_eth,	SYS_CLK_EN0_REG0, 20,	0);
> +static T7_SYS_PCLK(sys_am2axi0,		SYS_CLK_EN0_REG0, 21,	0);
> +static T7_SYS_PCLK(sys_am2axi1,		SYS_CLK_EN0_REG0, 22,	0);
> +static T7_SYS_PCLK(sys_am2axi2,		SYS_CLK_EN0_REG0, 23,	0);
> +static T7_SYS_PCLK(sys_sdemmca,		SYS_CLK_EN0_REG0, 24,	0);
> +static T7_SYS_PCLK(sys_sdemmcb,		SYS_CLK_EN0_REG0, 25,	0);
> +static T7_SYS_PCLK(sys_sdemmcc,		SYS_CLK_EN0_REG0, 26,	0);
> +static T7_SYS_PCLK(sys_smartcard,	SYS_CLK_EN0_REG0, 27,	0);
> +static T7_SYS_PCLK(sys_acodec,		SYS_CLK_EN0_REG0, 28,	0);
> +static T7_SYS_PCLK(sys_spifc,		SYS_CLK_EN0_REG0, 29,	0);
> +static T7_SYS_PCLK(sys_msr_clk,		SYS_CLK_EN0_REG0, 30,	0);
> +static T7_SYS_PCLK(sys_ir_ctrl,		SYS_CLK_EN0_REG0, 31,	0);
> +static T7_SYS_PCLK(sys_audio,		SYS_CLK_EN0_REG1, 0,	0);
> +static T7_SYS_PCLK(sys_eth,		SYS_CLK_EN0_REG1, 3,	0);
> +static T7_SYS_PCLK(sys_uart_a,		SYS_CLK_EN0_REG1, 5,	0);
> +static T7_SYS_PCLK(sys_uart_b,		SYS_CLK_EN0_REG1, 6,	0);
> +static T7_SYS_PCLK(sys_uart_c,		SYS_CLK_EN0_REG1, 7,	0);
> +static T7_SYS_PCLK(sys_uart_d,		SYS_CLK_EN0_REG1, 8,	0);
> +static T7_SYS_PCLK(sys_uart_e,		SYS_CLK_EN0_REG1, 9,	0);
> +static T7_SYS_PCLK(sys_uart_f,		SYS_CLK_EN0_REG1, 10,	0);
> +static T7_SYS_PCLK(sys_aififo,		SYS_CLK_EN0_REG1, 11,	0);
> +static T7_SYS_PCLK(sys_spicc2,		SYS_CLK_EN0_REG1, 12,	0);
> +static T7_SYS_PCLK(sys_spicc3,		SYS_CLK_EN0_REG1, 13,	0);
> +static T7_SYS_PCLK(sys_spicc4,		SYS_CLK_EN0_REG1, 14,	0);
> +static T7_SYS_PCLK(sys_ts_a73,		SYS_CLK_EN0_REG1, 15,	0);
> +static T7_SYS_PCLK(sys_ts_a53,		SYS_CLK_EN0_REG1, 16,	0);
> +static T7_SYS_PCLK(sys_spicc5,		SYS_CLK_EN0_REG1, 17,	0);
> +static T7_SYS_PCLK(sys_g2d,		SYS_CLK_EN0_REG1, 20,	0);
> +static T7_SYS_PCLK(sys_spicc0,		SYS_CLK_EN0_REG1, 21,	0);
> +static T7_SYS_PCLK(sys_spicc1,		SYS_CLK_EN0_REG1, 22,	0);
> +static T7_SYS_PCLK(sys_pcie,		SYS_CLK_EN0_REG1, 24,	0);
> +static T7_SYS_PCLK(sys_usb,		SYS_CLK_EN0_REG1, 26,	0);
> +static T7_SYS_PCLK(sys_pcie_phy,	SYS_CLK_EN0_REG1, 27,	0);
> +static T7_SYS_PCLK(sys_i2c_ao_a,	SYS_CLK_EN0_REG1, 28,	0);
> +static T7_SYS_PCLK(sys_i2c_ao_b,	SYS_CLK_EN0_REG1, 29,	0);
> +static T7_SYS_PCLK(sys_i2c_m_a,		SYS_CLK_EN0_REG1, 30,	0);
> +static T7_SYS_PCLK(sys_i2c_m_b,		SYS_CLK_EN0_REG1, 31,	0);
> +static T7_SYS_PCLK(sys_i2c_m_c,		SYS_CLK_EN0_REG2, 0,	0);
> +static T7_SYS_PCLK(sys_i2c_m_d,		SYS_CLK_EN0_REG2, 1,	0);
> +static T7_SYS_PCLK(sys_i2c_m_e,		SYS_CLK_EN0_REG2, 2,	0);
> +static T7_SYS_PCLK(sys_i2c_m_f,		SYS_CLK_EN0_REG2, 3,	0);
> +static T7_SYS_PCLK(sys_hdmitx_apb,	SYS_CLK_EN0_REG2, 4,	0);
> +static T7_SYS_PCLK(sys_i2c_s_a,		SYS_CLK_EN0_REG2, 5,	0);
> +static T7_SYS_PCLK(sys_hdmirx_pclk,	SYS_CLK_EN0_REG2, 8,	0);
> +static T7_SYS_PCLK(sys_mmc_apb,		SYS_CLK_EN0_REG2, 11,	0);
> +static T7_SYS_PCLK(sys_mipi_isp_pclk,	SYS_CLK_EN0_REG2, 17,	0);
> +static T7_SYS_PCLK(sys_rsa,		SYS_CLK_EN0_REG2, 18,	0);
> +static T7_SYS_PCLK(sys_pclk_sys_apb,	SYS_CLK_EN0_REG2, 19,	0);
> +static T7_SYS_PCLK(sys_a73pclk_apb,	SYS_CLK_EN0_REG2, 20,	0);
> +static T7_SYS_PCLK(sys_dspa,		SYS_CLK_EN0_REG2, 21,	0);
> +static T7_SYS_PCLK(sys_dspb,		SYS_CLK_EN0_REG2, 22,	0);
> +static T7_SYS_PCLK(sys_vpu_intr,	SYS_CLK_EN0_REG2, 25,	0);
> +static T7_SYS_PCLK(sys_sar_adc,		SYS_CLK_EN0_REG2, 28,	0);
> +/*
> + * sys_gic provides the clock for GIC(Generic Interrupt Controller).
> + * After clock is disabled, The GIC cannot work properly. At present, the driver
> + * used by our GIC is the public driver in kernel, and there is no management
> + * clock in the driver.
> + */
> +static T7_SYS_PCLK(sys_gic,		SYS_CLK_EN0_REG2, 30,	CLK_IS_CRITICAL);
> +static T7_SYS_PCLK(sys_ts_gpu,		SYS_CLK_EN0_REG2, 31,	0);
> +static T7_SYS_PCLK(sys_ts_nna,		SYS_CLK_EN0_REG3, 0,	0);
> +static T7_SYS_PCLK(sys_ts_vpu,		SYS_CLK_EN0_REG3, 1,	0);
> +static T7_SYS_PCLK(sys_ts_hevc,		SYS_CLK_EN0_REG3, 2,	0);
> +static T7_SYS_PCLK(sys_pwm_ao_ab,	SYS_CLK_EN0_REG3, 3,	0);
> +static T7_SYS_PCLK(sys_pwm_ao_cd,	SYS_CLK_EN0_REG3, 4,	0);
> +static T7_SYS_PCLK(sys_pwm_ao_ef,	SYS_CLK_EN0_REG3, 5,	0);
> +static T7_SYS_PCLK(sys_pwm_ao_gh,	SYS_CLK_EN0_REG3, 6,	0);
> +static T7_SYS_PCLK(sys_pwm_ab,		SYS_CLK_EN0_REG3, 7,	0);
> +static T7_SYS_PCLK(sys_pwm_cd,		SYS_CLK_EN0_REG3, 8,	0);
> +static T7_SYS_PCLK(sys_pwm_ef,		SYS_CLK_EN0_REG3, 9,	0);
> +
> +/* Array of all clocks registered by this provider */
> +static struct clk_hw *t7_peripherals_hw_clks[] = {
> +	[CLKID_RTC_32K_IN]		= &t7_rtc_32k_in.hw,
> +	[CLKID_RTC_32K_DIV]		= &t7_rtc_32k_div.hw,
> +	[CLKID_RTC_32K_FORCE_SEL]	= &t7_rtc_32k_force_sel.hw,
> +	[CLKID_RTC_32K_OUT]		= &t7_rtc_32k_out.hw,
> +	[CLKID_RTC_32K_MUX0_0]		= &t7_rtc_32k_mux0_0.hw,
> +	[CLKID_RTC_32K_MUX0_1]		= &t7_rtc_32k_mux0_1.hw,
> +	[CLKID_RTC]			= &t7_rtc.hw,
> +	[CLKID_CECB_32K_IN]		= &t7_cecb_32k_in.hw,
> +	[CLKID_CECB_32K_DIV]		= &t7_cecb_32k_div.hw,
> +	[CLKID_CECB_32K_SEL_PRE]	= &t7_cecb_32k_sel_pre.hw,
> +	[CLKID_CECB_32K_SEL]		= &t7_cecb_32k_sel.hw,
> +	[CLKID_CECA_32K_IN]		= &t7_ceca_32k_in.hw,
> +	[CLKID_CECA_32K_DIV]		= &t7_ceca_32k_div.hw,
> +	[CLKID_CECA_32K_SEL_PRE]	= &t7_ceca_32k_sel_pre.hw,
> +	[CLKID_CECA_32K_SEL]		= &t7_ceca_32k_sel.hw,
> +	[CLKID_CECA_32K]		= &t7_ceca_32k_out.hw,
> +	[CLKID_CECB_32K]		= &t7_cecb_32k_out.hw,
> +	[CLKID_SC_SEL]			= &t7_sc_sel.hw,
> +	[CLKID_SC_DIV]			= &t7_sc_div.hw,
> +	[CLKID_SC]			= &t7_sc.hw,
> +	[CLKID_DSPA_A_SEL]		= &t7_dspa_a_sel.hw,
> +	[CLKID_DSPA_A_DIV]		= &t7_dspa_a_div.hw,
> +	[CLKID_DSPA_A]			= &t7_dspa_a.hw,
> +	[CLKID_DSPA_B_SEL]		= &t7_dspa_b_sel.hw,
> +	[CLKID_DSPA_B_DIV]		= &t7_dspa_b_div.hw,
> +	[CLKID_DSPA_B]			= &t7_dspa_b.hw,
> +	[CLKID_DSPA]			= &t7_dspa.hw,
> +	[CLKID_DSPB_A_SEL]		= &t7_dspb_a_sel.hw,
> +	[CLKID_DSPB_A_DIV]		= &t7_dspb_a_div.hw,
> +	[CLKID_DSPB_A]			= &t7_dspb_a.hw,
> +	[CLKID_DSPB_B_SEL]		= &t7_dspb_b_sel.hw,
> +	[CLKID_DSPB_B_DIV]		= &t7_dspb_b_div.hw,
> +	[CLKID_DSPB_B]			= &t7_dspb_b.hw,
> +	[CLKID_DSPB]			= &t7_dspb.hw,
> +	[CLKID_CLK_24M]			= &t7_clk_24m.hw,
> +	[CLKID_CLK_24M_DIV2]		= &t7_clk_24m_div2.hw,
> +	[CLKID_CLK_12M]			= &t7_clk_12m.hw,
> +	[CLKID_ANAKIN_0_SEL]		= &t7_anakin_0_sel.hw,
> +	[CLKID_ANAKIN_0_DIV]		= &t7_anakin_0_div.hw,
> +	[CLKID_ANAKIN_0]		= &t7_anakin_0.hw,
> +	[CLKID_ANAKIN_1_SEL]		= &t7_anakin_1_sel.hw,
> +	[CLKID_ANAKIN_1_DIV]		= &t7_anakin_1_div.hw,
> +	[CLKID_ANAKIN_1]		= &t7_anakin_1.hw,
> +	[CLKID_ANAKIN]			= &t7_anakin.hw,
> +	[CLKID_ANAKIN_CLK]		= &t7_anakin_clk.hw,
> +	[CLKID_FCLK_DIV2_DIVN_PRE]	= &t7_fdiv2_divn_pre.hw,
> +	[CLKID_FCLK_DIV2_DIVN]		= &t7_fdiv2_divn.hw,
> +	[CLKID_MIPI_CSI_PHY_0_SEL]	= &t7_mipi_csi_phy0_sel.hw,
> +	[CLKID_MIPI_CSI_PHY_0_DIV]	= &t7_mipi_csi_phy0_div.hw,
> +	[CLKID_MIPI_CSI_PHY_0]		= &t7_mipi_csi_phy0.hw,
> +	[CLKID_MIPI_CSI_PHY_1_SEL]	= &t7_mipi_csi_phy1_sel.hw,
> +	[CLKID_MIPI_CSI_PHY_1_DIV]	= &t7_mipi_csi_phy1_div.hw,
> +	[CLKID_MIPI_CSI_PHY_1]		= &t7_mipi_csi_phy1.hw,
> +	[CLKID_MIPI_CSI_PHY]		= &t7_mipi_csi_phy.hw,
> +	[CLKID_MIPI_ISP_SEL]		= &t7_mipi_isp_sel.hw,
> +	[CLKID_MIPI_ISP_DIV]		= &t7_mipi_isp_div.hw,
> +	[CLKID_MIPI_ISP]		= &t7_mipi_isp.hw,
> +	[CLKID_TS_DIV]			= &t7_ts_div.hw,
> +	[CLKID_TS]			= &t7_ts.hw,
> +	[CLKID_MALI_0_SEL]		= &t7_mali_0_sel.hw,
> +	[CLKID_MALI_0_DIV]		= &t7_mali_0_div.hw,
> +	[CLKID_MALI_0]			= &t7_mali_0.hw,
> +	[CLKID_MALI_1_SEL]		= &t7_mali_1_sel.hw,
> +	[CLKID_MALI_1_DIV]		= &t7_mali_1_div.hw,
> +	[CLKID_MALI_1]			= &t7_mali_1.hw,
> +	[CLKID_MALI]			= &t7_mali.hw,
> +	[CLKID_ETH_RMII_SEL]		= &t7_eth_rmii_sel.hw,
> +	[CLKID_ETH_RMII_DIV]		= &t7_eth_rmii_div.hw,
> +	[CLKID_ETH_RMII]		= &t7_eth_rmii.hw,
> +	[CLKID_FCLK_DIV2_DIV8]		= &t7_fdiv2_div8.hw,
> +	[CLKID_ETH_125M]		= &t7_eth_125m.hw,
> +	[CLKID_SD_EMMC_C_SEL]		= &t7_sd_emmc_c_sel.hw,
> +	[CLKID_SD_EMMC_C_DIV]		= &t7_sd_emmc_c_div.hw,
> +	[CLKID_SD_EMMC_C]		= &t7_sd_emmc_c.hw,
> +	[CLKID_SD_EMMC_A_SEL]		= &t7_sd_emmc_a_sel.hw,
> +	[CLKID_SD_EMMC_A_DIV]		= &t7_sd_emmc_a_div.hw,
> +	[CLKID_SD_EMMC_A]		= &t7_sd_emmc_a.hw,
> +	[CLKID_SD_EMMC_B_SEL]		= &t7_sd_emmc_b_sel.hw,
> +	[CLKID_SD_EMMC_B_DIV]		= &t7_sd_emmc_b_div.hw,
> +	[CLKID_SD_EMMC_B]		= &t7_sd_emmc_b.hw,
> +	[CLKID_SPICC0_SEL]		= &t7_spicc0_sel.hw,
> +	[CLKID_SPICC0_DIV]		= &t7_spicc0_div.hw,
> +	[CLKID_SPICC0]			= &t7_spicc0.hw,
> +	[CLKID_SPICC1_SEL]		= &t7_spicc1_sel.hw,
> +	[CLKID_SPICC1_DIV]		= &t7_spicc1_div.hw,
> +	[CLKID_SPICC1]			= &t7_spicc1.hw,
> +	[CLKID_SPICC2_SEL]		= &t7_spicc2_sel.hw,
> +	[CLKID_SPICC2_DIV]		= &t7_spicc2_div.hw,
> +	[CLKID_SPICC2]			= &t7_spicc2.hw,
> +	[CLKID_SPICC3_SEL]		= &t7_spicc3_sel.hw,
> +	[CLKID_SPICC3_DIV]		= &t7_spicc3_div.hw,
> +	[CLKID_SPICC3]			= &t7_spicc3.hw,
> +	[CLKID_SPICC4_SEL]		= &t7_spicc4_sel.hw,
> +	[CLKID_SPICC4_DIV]		= &t7_spicc4_div.hw,
> +	[CLKID_SPICC4]			= &t7_spicc4.hw,
> +	[CLKID_SPICC5_SEL]		= &t7_spicc5_sel.hw,
> +	[CLKID_SPICC5_DIV]		= &t7_spicc5_div.hw,
> +	[CLKID_SPICC5]			= &t7_spicc5.hw,
> +	[CLKID_SARADC_SEL]		= &t7_saradc_sel.hw,
> +	[CLKID_SARADC_DIV]		= &t7_saradc_div.hw,
> +	[CLKID_SARADC]			= &t7_saradc.hw,
> +	[CLKID_PWM_A_SEL]		= &t7_pwm_a_sel.hw,
> +	[CLKID_PWM_A_DIV]		= &t7_pwm_a_div.hw,
> +	[CLKID_PWM_A]			= &t7_pwm_a.hw,
> +	[CLKID_PWM_B_SEL]		= &t7_pwm_b_sel.hw,
> +	[CLKID_PWM_B_DIV]		= &t7_pwm_b_div.hw,
> +	[CLKID_PWM_B]			= &t7_pwm_b.hw,
> +	[CLKID_PWM_C_SEL]		= &t7_pwm_c_sel.hw,
> +	[CLKID_PWM_C_DIV]		= &t7_pwm_c_div.hw,
> +	[CLKID_PWM_C]			= &t7_pwm_c.hw,
> +	[CLKID_PWM_D_SEL]		= &t7_pwm_d_sel.hw,
> +	[CLKID_PWM_D_DIV]		= &t7_pwm_d_div.hw,
> +	[CLKID_PWM_D]			= &t7_pwm_d.hw,
> +	[CLKID_PWM_E_SEL]		= &t7_pwm_e_sel.hw,
> +	[CLKID_PWM_E_DIV]		= &t7_pwm_e_div.hw,
> +	[CLKID_PWM_E]			= &t7_pwm_e.hw,
> +	[CLKID_PWM_F_SEL]		= &t7_pwm_f_sel.hw,
> +	[CLKID_PWM_F_DIV]		= &t7_pwm_f_div.hw,
> +	[CLKID_PWM_F]			= &t7_pwm_f.hw,
> +	[CLKID_PWM_AO_A_SEL]		= &t7_pwm_ao_a_sel.hw,
> +	[CLKID_PWM_AO_A_DIV]		= &t7_pwm_ao_a_div.hw,
> +	[CLKID_PWM_AO_A]		= &t7_pwm_ao_a.hw,
> +	[CLKID_PWM_AO_B_SEL]		= &t7_pwm_ao_b_sel.hw,
> +	[CLKID_PWM_AO_B_DIV]		= &t7_pwm_ao_b_div.hw,
> +	[CLKID_PWM_AO_B]		= &t7_pwm_ao_b.hw,
> +	[CLKID_PWM_AO_C_SEL]		= &t7_pwm_ao_c_sel.hw,
> +	[CLKID_PWM_AO_C_DIV]		= &t7_pwm_ao_c_div.hw,
> +	[CLKID_PWM_AO_C]		= &t7_pwm_ao_c.hw,
> +	[CLKID_PWM_AO_D_SEL]		= &t7_pwm_ao_d_sel.hw,
> +	[CLKID_PWM_AO_D_DIV]		= &t7_pwm_ao_d_div.hw,
> +	[CLKID_PWM_AO_D]		= &t7_pwm_ao_d.hw,
> +	[CLKID_PWM_AO_E_SEL]		= &t7_pwm_ao_e_sel.hw,
> +	[CLKID_PWM_AO_E_DIV]		= &t7_pwm_ao_e_div.hw,
> +	[CLKID_PWM_AO_E]		= &t7_pwm_ao_e.hw,
> +	[CLKID_PWM_AO_F_SEL]		= &t7_pwm_ao_f_sel.hw,
> +	[CLKID_PWM_AO_F_DIV]		= &t7_pwm_ao_f_div.hw,
> +	[CLKID_PWM_AO_F]		= &t7_pwm_ao_f.hw,
> +	[CLKID_PWM_AO_G_SEL]		= &t7_pwm_ao_g_sel.hw,
> +	[CLKID_PWM_AO_G_DIV]		= &t7_pwm_ao_g_div.hw,
> +	[CLKID_PWM_AO_G]		= &t7_pwm_ao_g.hw,
> +	[CLKID_PWM_AO_H_SEL]		= &t7_pwm_ao_h_sel.hw,
> +	[CLKID_PWM_AO_H_DIV]		= &t7_pwm_ao_h_div.hw,
> +	[CLKID_PWM_AO_H]		= &t7_pwm_ao_h.hw,
> +	[CLKID_SYS_DDR]			= &t7_sys_ddr.hw,
> +	[CLKID_SYS_DOS]			= &t7_sys_dos.hw,
> +	[CLKID_SYS_MIPI_DSI_A]		= &t7_sys_mipi_dsi_a.hw,
> +	[CLKID_SYS_MIPI_DSI_B]		= &t7_sys_mipi_dsi_b.hw,
> +	[CLKID_SYS_ETHPHY]		= &t7_sys_ethphy.hw,
> +	[CLKID_SYS_MALI]		= &t7_sys_mali.hw,
> +	[CLKID_SYS_AOCPU]		= &t7_sys_aocpu.hw,
> +	[CLKID_SYS_AUCPU]		= &t7_sys_aucpu.hw,
> +	[CLKID_SYS_CEC]			= &t7_sys_cec.hw,
> +	[CLKID_SYS_GDC]			= &t7_sys_gdc.hw,
> +	[CLKID_SYS_DESWARP]		= &t7_sys_deswarp.hw,
> +	[CLKID_SYS_AMPIPE_NAND]		= &t7_sys_ampipe_nand.hw,
> +	[CLKID_SYS_AMPIPE_ETH]		= &t7_sys_ampipe_eth.hw,
> +	[CLKID_SYS_AM2AXI0]		= &t7_sys_am2axi0.hw,
> +	[CLKID_SYS_AM2AXI1]		= &t7_sys_am2axi1.hw,
> +	[CLKID_SYS_AM2AXI2]		= &t7_sys_am2axi2.hw,
> +	[CLKID_SYS_SD_EMMC_A]		= &t7_sys_sdemmca.hw,
> +	[CLKID_SYS_SD_EMMC_B]		= &t7_sys_sdemmcb.hw,
> +	[CLKID_SYS_SD_EMMC_C]		= &t7_sys_sdemmcc.hw,
> +	[CLKID_SYS_SMARTCARD]		= &t7_sys_smartcard.hw,
> +	[CLKID_SYS_ACODEC]		= &t7_sys_acodec.hw,
> +	[CLKID_SYS_SPIFC]		= &t7_sys_spifc.hw,
> +	[CLKID_SYS_MSR_CLK]		= &t7_sys_msr_clk.hw,
> +	[CLKID_SYS_IR_CTRL]		= &t7_sys_ir_ctrl.hw,
> +	[CLKID_SYS_AUDIO]		= &t7_sys_audio.hw,
> +	[CLKID_SYS_ETH]			= &t7_sys_eth.hw,
> +	[CLKID_SYS_UART_A]		= &t7_sys_uart_a.hw,
> +	[CLKID_SYS_UART_B]		= &t7_sys_uart_b.hw,
> +	[CLKID_SYS_UART_C]		= &t7_sys_uart_c.hw,
> +	[CLKID_SYS_UART_D]		= &t7_sys_uart_d.hw,
> +	[CLKID_SYS_UART_E]		= &t7_sys_uart_e.hw,
> +	[CLKID_SYS_UART_F]		= &t7_sys_uart_f.hw,
> +	[CLKID_SYS_AIFIFO]		= &t7_sys_aififo.hw,
> +	[CLKID_SYS_SPICC2]		= &t7_sys_spicc2.hw,
> +	[CLKID_SYS_SPICC3]		= &t7_sys_spicc3.hw,
> +	[CLKID_SYS_SPICC4]		= &t7_sys_spicc4.hw,
> +	[CLKID_SYS_TS_A73]		= &t7_sys_ts_a73.hw,
> +	[CLKID_SYS_TS_A53]		= &t7_sys_ts_a53.hw,
> +	[CLKID_SYS_SPICC5]		= &t7_sys_spicc5.hw,
> +	[CLKID_SYS_G2D]			= &t7_sys_g2d.hw,
> +	[CLKID_SYS_SPICC0]		= &t7_sys_spicc0.hw,
> +	[CLKID_SYS_SPICC1]		= &t7_sys_spicc1.hw,
> +	[CLKID_SYS_PCIE]		= &t7_sys_pcie.hw,
> +	[CLKID_SYS_USB]			= &t7_sys_usb.hw,
> +	[CLKID_SYS_PCIE_PHY]		= &t7_sys_pcie_phy.hw,
> +	[CLKID_SYS_I2C_AO_A]		= &t7_sys_i2c_ao_a.hw,
> +	[CLKID_SYS_I2C_AO_B]		= &t7_sys_i2c_ao_b.hw,
> +	[CLKID_SYS_I2C_M_A]		= &t7_sys_i2c_m_a.hw,
> +	[CLKID_SYS_I2C_M_B]		= &t7_sys_i2c_m_b.hw,
> +	[CLKID_SYS_I2C_M_C]		= &t7_sys_i2c_m_c.hw,
> +	[CLKID_SYS_I2C_M_D]		= &t7_sys_i2c_m_d.hw,
> +	[CLKID_SYS_I2C_M_E]		= &t7_sys_i2c_m_e.hw,
> +	[CLKID_SYS_I2C_M_F]		= &t7_sys_i2c_m_f.hw,
> +	[CLKID_SYS_HDMITX_APB]		= &t7_sys_hdmitx_apb.hw,
> +	[CLKID_SYS_I2C_S_A]		= &t7_sys_i2c_s_a.hw,
> +	[CLKID_SYS_HDMIRX_PCLK]		= &t7_sys_hdmirx_pclk.hw,
> +	[CLKID_SYS_MMC_APB]		= &t7_sys_mmc_apb.hw,
> +	[CLKID_SYS_MIPI_ISP_PCLK]	= &t7_sys_mipi_isp_pclk.hw,
> +	[CLKID_SYS_RSA]			= &t7_sys_rsa.hw,
> +	[CLKID_SYS_PCLK_SYS_APB]	= &t7_sys_pclk_sys_apb.hw,
> +	[CLKID_SYS_A73PCLK_APB]		= &t7_sys_a73pclk_apb.hw,
> +	[CLKID_SYS_DSPA]		= &t7_sys_dspa.hw,
> +	[CLKID_SYS_DSPB]		= &t7_sys_dspb.hw,
> +	[CLKID_SYS_VPU_INTR]		= &t7_sys_vpu_intr.hw,
> +	[CLKID_SYS_SAR_ADC]		= &t7_sys_sar_adc.hw,
> +	[CLKID_SYS_GIC]			= &t7_sys_gic.hw,
> +	[CLKID_SYS_TS_GPU]		= &t7_sys_ts_gpu.hw,
> +	[CLKID_SYS_TS_NNA]		= &t7_sys_ts_nna.hw,
> +	[CLKID_SYS_TS_VPU]		= &t7_sys_ts_vpu.hw,
> +	[CLKID_SYS_TS_HEVC]		= &t7_sys_ts_hevc.hw,
> +	[CLKID_SYS_PWM_AO_AB]		= &t7_sys_pwm_ao_ab.hw,
> +	[CLKID_SYS_PWM_AO_CD]		= &t7_sys_pwm_ao_cd.hw,
> +	[CLKID_SYS_PWM_AO_EF]		= &t7_sys_pwm_ao_ef.hw,
> +	[CLKID_SYS_PWM_AO_GH]		= &t7_sys_pwm_ao_gh.hw,
> +	[CLKID_SYS_PWM_AB]		= &t7_sys_pwm_ab.hw,
> +	[CLKID_SYS_PWM_CD]		= &t7_sys_pwm_cd.hw,
> +	[CLKID_SYS_PWM_EF]		= &t7_sys_pwm_ef.hw,
> +};
> +
> +static const struct meson_clkc_data t7_peripherals_data = {
> +	.hw_clks = {
> +		.hws = t7_peripherals_hw_clks,
> +		.num = ARRAY_SIZE(t7_peripherals_hw_clks),
> +	},
> +};
> +
> +static const struct of_device_id t7_peripherals_clkc_match_table[] = {
> +	{ .compatible = "amlogic,t7-peripherals-clkc", .data = &t7_peripherals_data },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, t7_peripherals_clkc_match_table);
> +
> +static struct platform_driver t7_peripherals_clkc_driver = {
> +	.probe = meson_clkc_mmio_probe,
> +	.driver = {
> +		.name = "t7-peripherals-clkc",
> +		.of_match_table = t7_peripherals_clkc_match_table,
> +	},
> +};
> +
> +MODULE_DESCRIPTION("Amlogic T7 Peripherals Clock Controller driver");
> +module_platform_driver(t7_peripherals_clkc_driver);

This is an odd placement for this.
Please move this right after the platform_driver definition. Same goes
for the other controller

> +MODULE_AUTHOR("Jian Hu <jian.hu at amlogic.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("CLK_MESON");

-- 
Jerome


From linnaea-von-lavia at live.com  Fri Oct 31 05:26:42 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Fri, 31 Oct 2025 20:26:42 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <59baecc0-bc28-4411-bf83-37ff9e7dd193@linaro.org>
References: <20251029171542.GA1566240@bhelgaas>
 <DM4PR05MB10270506AAC1FCE53C4915CC2C7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>
 <59baecc0-bc28-4411-bf83-37ff9e7dd193@linaro.org>
Message-ID: <DM4PR05MB1027077E1F4CD8B1A7EDADF1DC7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>

On 10/31/2025 4:50 PM, Neil Armstrong wrote:
> On 10/31/25 06:34, Linnaea Lavia wrote:
>> On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
>>> On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
>>>> On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
>>>
>>>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>>>> index 214ed060ca1b..9cd12924b5cb 100644
>>>>> --- a/drivers/pci/quirks.c
>>>>> +++ b/drivers/pci/quirks.c
>>>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>>> ??? * disable both L0s and L1 for now to be safe.
>>>>> ??? */
>>>>> ?? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>>>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>>> ?? /*
>>>>> ??? * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
>>>>
>>>> I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
>>>
>>> Sorry, my fault, I should have made that fixup run earlier, so the
>>> patch should be this instead:
>>>
>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>> index 214ed060ca1b..4fc04015ca0c 100644
>>> --- a/drivers/pci/quirks.c
>>> +++ b/drivers/pci/quirks.c
>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>> ?? * disable both L0s and L1 for now to be safe.
>>> ?? */
>>> ? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>
>> L1 still got enabled
> 
> <snip>
> 
>>
>> The card works just fine. I'm thinking the ASPM issue is probably from the glue driver reporting the link to be down when it's really just in low power state.
> 
> You're probbaly right, the meson_pcie_link_up() not only checks the LTSSM but also the speed, which is probably wrong.
> 
> Can you try removing the test for speed ?
> 
> -???????????????? if (smlh_up && rdlh_up && ltssm_up && speed_okay)
> +???????????????? if (smlh_up && rdlh_up && ltssm_up)
> 
> The other drivers just checks the link, and some only the smlh_up && rdlh_up. So you can also probably drop ltssm_up aswell.
> 

I can confirm that removing the check for ltssm_up and speed_okay made ASPM work.

We still need a solution to the original issue that's preventing the controller from being initialized.

My kernel has the following patch applied, but I think it's not suitable for upstream as this changes device tree bindings for PCIe controller on meson.

diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index dcc927a9da80..ca455f634834 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -138,7 +138,7 @@ pcie: pcie at fc000000 {
  			reg = <0x0 0xfc000000 0x0 0x400000>,
  			      <0x0 0xff648000 0x0 0x2000>,
  			      <0x0 0xfc400000 0x0 0x200000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
  			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
  			#interrupt-cells = <1>;
  			interrupt-map-mask = <0 0 0 0>;
diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 787469d1b396..404c4d9e1900 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -109,10 +109,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
  {
  	struct dw_pcie *pci = &mp->pci;
  
-	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi");
-	if (IS_ERR(pci->dbi_base))
-		return PTR_ERR(pci->dbi_base);
-
  	mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg");
  	if (IS_ERR(mp->cfg_base))
  		return PTR_ERR(mp->cfg_base);

> Neil
> 
> 



From chuan.liu at amlogic.com  Fri Oct 31 08:09:13 2025
From: chuan.liu at amlogic.com (Chuan Liu)
Date: Fri, 31 Oct 2025 23:09:13 +0800
Subject: [PATCH v3 0/4] clk: amlogic: optimize the PLL driver
In-Reply-To: <1jms57xx05.fsf@starbuckisacylon.baylibre.com>
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
 <1jms57xx05.fsf@starbuckisacylon.baylibre.com>
Message-ID: <9751014d-926e-4d42-b8e1-5a4d3e734457@amlogic.com>

Hi Jerome,

On 10/31/2025 5:04 PM, Jerome Brunet wrote:
> [ EXTERNAL EMAIL ]
> 
> On Fri 31 Oct 2025 at 16:10, Chuan Liu via B4 Relay <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
> 
>> This patch series consists of four topics involving the amlogic PLL
>> driver:
>> - Fix out-of-range PLL frequency setting.
>> - Improve the issue of PLL lock failures.
>> - Add handling for PLL lock failure.
>> - Optimize PLL enable timing.
>>
>> For easier review and management, these are submitted as a single
>> patch series.
>>
>> The PLL timing optimization changes were merged into our internal
>> repository quite some time ago and have been verified on a large
>> number of SoCs:
>> - Already supported upstream: G12A, G12B, SM1, S4, A1, C3.
>> - Planned for upstream support: T7, A5, A4, S7, S7D, S6, etc.
>>
>> Based on the upstream code base, I have performed functional testing
>> on G12A, A1, A5, A4, T7, S7, S7D, and S6, all of which passed.
>>
>> Additionally, stress testing using scripts was conducted on A5 and
>> A1, with over 40,000 and 50,000 iterations respectively, and no
>> abnormalities were observed. Below is a portion of the stress test
>> log (CLOCK_ALLOW_WRITE_DEBUGFS has been manually enabled):
> 
> Okay, this little game has been going on long enough.
> 
> You've posted v2 24h hours ago
> You've got feedback within hours
> There was still a 1 question pending
> The rest of community had no chance to review.
> 

There might be a serious misunderstanding here.

In recent years, we've mainly been maintaining our code in our
internal repository, which has led to some differences between our
internal codebase and the upstream version. The patches that account
for these differences are already queued for submission, and several
SoCs are also waiting in line to be submitted. As a result, quite a
few patches have piled up, waiting to go upstream.

Previously, I had been waiting for your clock driver restructuring
patches to be ready (which have recently been merged), so for almost
a year, we haven't made much progress on clock driver?related
upstreaming.

Other drivers that depend on the clock driver have also been blocked.
This situation has been very stressful for me. I've been doing my
best to update versions as soon as possible in response to review
feedback.

> and yet, here the v3 already ! still with bearing pr_warn().
> 

Regarding pr_warn(), I explained in a previous email why I didn't
choose to use pr_warn_once(). The quick iteration of versions wasn't
an intentional disregard of your suggestions.

It's just that the upstream submission process has been severely
jammed. I admit I've been anxious, because at the previous pace, our
chips have already been in mass production for quite some time while
our clock driver still hasn't been submitted upstream, which puts us
in a difficult position, so please understand.

> Chuan, the community is not dedicated to reviewing your submission.
> Time and time again you ignore the feedback provided in reviews and the
> documentation. I've had enough of your sloppy submission.
> 
> I will not review or apply anything from you in this cycle.
> 
> You have been warned multiple times. Every time you ignore a review,
> you'll get ignored in return. This is how it will be from now on.
> 

Seeing your message was really disheartening. I want to clarify that
I've always been very grateful to and respectful of you, as well as
Neil, Martin, and others. Throughout the upstreaming process, your
feedback has been extremely helpful.

I've always taken your reviews seriously and communicate frendly. I
truly never meant to ignore your comments, please don't misunderstand.

>>
>> - For A5:
>>    # echo 491520000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
>>    # cnt=0
>>    # while true; do
>>    >     echo "------------ cnt=$cnt -----------"
>>    >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>>    >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
>>    >     if [ "$en" != "1" ]; then
>>    >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
>>    >         break
>>    >     fi
>>    >
>>    >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>>    >     cnt=$((cnt + 1))
>>    >     echo -e "sleep time: 1 s."
>>    >     sleep 1
>>    > done &
>>    # ------------ cnt=0 -----------
>>    sleep time: 1 s.
>>    ------------ cnt=1 -----------
>>    sleep time: 1 s.
>>    ------------ cnt=2 -----------
>>    sleep time: 1 s.
>>    ...
>>    ------------ cnt=42076 -----------
>>    sleep time: 1 s.
>>
>> - For A1:
>>    # echo 983040000 > /sys/kernel/debug/clk/hifi_pll/clk_rate
>>    # cnt=0
>>    # while true; do
>>    >     echo "------------ cnt=$cnt -----------"
>>    >     echo 1 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>>    >     en=$(cat /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable 2>/dev/null)
>>    >     if [ "$en" != "1" ]; then
>>    >         echo "[ERROR] PLL enable test failed! (clk_prepare_enable=$en)"
>>    >         break
>>    >     fi
>>    >
>>    >     echo 0 > /sys/kernel/debug/clk/hifi_pll/clk_prepare_enable
>>    >     cnt=$((cnt + 1))
>>    >     echo -e "sleep time: 1 s."
>>    >     sleep 1
>>    > done &
>>    # ------------ cnt=0 -----------
>>    sleep time: 1 s.
>>    ------------ cnt=1 -----------
>>    sleep time: 1 s.
>>    ------------ cnt=2 -----------
>>    sleep time: 1 s.
>>    ...
>>    ------------ cnt=55051 -----------
>>    sleep time: 1 s.
>>
>> Signed-off-by: Chuan Liu <chuan.liu at amlogic.com>
>> ---
>> Changes in v3:
>> - Fix some formatting issues.
>> - Move the 20 us delay after reset into the corresponding if
>> condition (no delay is needed if there is no reset).
>> - Move the code that releases rst back to execute before current_en.
>> - Remove the patch that changes the active level of l_detect.
>> - Link to v2: https://lore.kernel.org/r/20251030-optimize_pll_driver-v2-0-37273f5b25ab at amlogic.com
>>
>> Changes in v2:
>> - Modify the judgment condition of 'm' out of range.
>> - Split the PLL timing optimization patch to make it easier to review.
>> - Link to v1: https://lore.kernel.org/r/20251022-optimize_pll_driver-v1-0-a275722fb6f4 at amlogic.com
>>
>> ---
>> Chuan Liu (4):
>>        clk: amlogic: Fix out-of-range PLL frequency setting
>>        clk: amlogic: Improve the issue of PLL lock failures
>>        clk: amlogic: Add handling for PLL lock failure
>>        clk: amlogic: Optimize PLL enable timing
>>
>>   drivers/clk/meson/clk-pll.c | 64 +++++++++++++++++++++++++++------------------
>>   1 file changed, 39 insertions(+), 25 deletions(-)
>> ---
>> base-commit: 01f3a6d1d59b8e25a6de243b0d73075cf0415eaf
>> change-id: 20251020-optimize_pll_driver-7bef91876c41
>>
>> Best regards,
> 
> --
> Jerome



From helgaas at kernel.org  Fri Oct 31 09:13:23 2025
From: helgaas at kernel.org (Bjorn Helgaas)
Date: Fri, 31 Oct 2025 11:13:23 -0500
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <DM4PR05MB1027077E1F4CD8B1A7EDADF1DC7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>
Message-ID: <20251031161323.GA1688975@bhelgaas>

On Fri, Oct 31, 2025 at 08:26:42PM +0800, Linnaea Lavia wrote:
> On 10/31/2025 4:50 PM, Neil Armstrong wrote:
> > On 10/31/25 06:34, Linnaea Lavia wrote:
> > > On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
> > > > On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
> > > > > On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
> > > > 
> > > > > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > > > > > index 214ed060ca1b..9cd12924b5cb 100644
> > > > > > --- a/drivers/pci/quirks.c
> > > > > > +++ b/drivers/pci/quirks.c
> > > > > > @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
> > > > > > ??? * disable both L0s and L1 for now to be safe.
> > > > > > ??? */
> > > > > > ?? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> > > > > > +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
> > > > > > ?? /*
> > > > > > ??? * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
> > > > > 
> > > > > I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
> > > > 
> > > > Sorry, my fault, I should have made that fixup run earlier, so the
> > > > patch should be this instead:
> > > > 
> > > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > > > index 214ed060ca1b..4fc04015ca0c 100644
> > > > --- a/drivers/pci/quirks.c
> > > > +++ b/drivers/pci/quirks.c
> > > > @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
> > > > ?? * disable both L0s and L1 for now to be safe.
> > > > ?? */
> > > > ? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> > > > +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
> > > 
> > > L1 still got enabled

Is that based on the output below?

  [    5.445853] [     T48] pci 0000:00:00.0: Disabling ASPM L0s/L1
  [    5.560448] [     T48] pci 0000:01:00.0: ASPM: default states L1

If so, this doesn't necessarily mean L1 was enabled.  It means the
quirk marked the 00:00.0 Root Port so we shouldn't ever enable L0s or
L1, and when we enumerated 01:00.0, we set its default ASPM state to
L1.

But I don't *think* L1 should actually be enabled unless we can enable
it for both 00:00.0 and 01:00.0, and the quirk should mean that we
can't enable it for 00:00.0.

This muddle of "capable" (per Link Capabilities) vs "disabled" (either
the Link Control shows disabled, or software said "don't ever use L1")
is part of what makes aspm.c so confusing.

> > > The card works just fine. I'm thinking the ASPM issue is
> > > probably from the glue driver reporting the link to be down when
> > > it's really just in low power state.
> > 
> > You're probably right, the meson_pcie_link_up() not only checks
> > the LTSSM but also the speed, which is probably wrong.
> > 
> > Can you try removing the test for speed ?
> > 
> > -???????????????? if (smlh_up && rdlh_up && ltssm_up && speed_okay)
> > +???????????????? if (smlh_up && rdlh_up && ltssm_up)
> > 
> > The other drivers just checks the link, and some only the smlh_up
> > && rdlh_up. So you can also probably drop ltssm_up aswell.
> 
> I can confirm that removing the check for ltssm_up and speed_okay
> made ASPM work.

I don't think meson_pcie_link_up() should have the loop in it, so the
ltssm_up and speed_okay checks, the loop, the delay, and the timeout
message should probably all be removed.  That method is supposed to be
a simple true/false check, and any waiting required should be done in
dw_pcie_wait_for_link().

The link was clearly up when we discovered 01:00.0, so the "wait
linkup timeout" messages from meson_pcie_link_up() after that must be
from dw_pcie_link_up() being called via the .map_bus() call in
pci_generic_config_read() or pci_generic_config_write().

When meson_pcie_link_up() returns false in those config accessors,
the config accesses will fail (they won't even be attempted), so we'll
see things like this:

  pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)

and "Unknown header type 7f" from lspci.

Can you drop the ASPM quirk patch and instead try the
meson_pcie_link_up() patch below on top of v6.18-rc3?

> We still need a solution to the original issue that's preventing the
> controller from being initialized.
> 
> My kernel has the following patch applied, but I think it's not
> suitable for upstream as this changes device tree bindings for PCIe
> controller on meson.

I assume the original issue is this:

  meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]

and you confirmed that it wasn't fixed by a1978b692a39 ("PCI: dwc: Use
custom pci_ops for root bus DBI vs ECAM config access"), which
appeared in v6.18-rc3?

If it's still broken in v6.18-rc3, and the dtsi and
meson_pcie_get_mems() patch below makes it work, we have more work to
do, and maybe Krishna has some ideas.

> diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
> index dcc927a9da80..ca455f634834 100644
> --- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
> +++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
> @@ -138,7 +138,7 @@ pcie: pcie at fc000000 {
>  			reg = <0x0 0xfc000000 0x0 0x400000>,
>  			      <0x0 0xff648000 0x0 0x2000>,
>  			      <0x0 0xfc400000 0x0 0x200000>;
> -			reg-names = "elbi", "cfg", "config";
> +			reg-names = "dbi", "cfg", "config";
>  			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
>  			#interrupt-cells = <1>;
>  			interrupt-map-mask = <0 0 0 0>;
> diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
> index 787469d1b396..404c4d9e1900 100644
> --- a/drivers/pci/controller/dwc/pci-meson.c
> +++ b/drivers/pci/controller/dwc/pci-meson.c
> @@ -109,10 +109,6 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
>  {
>  	struct dw_pcie *pci = &mp->pci;
> -	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi");
> -	if (IS_ERR(pci->dbi_base))
> -		return PTR_ERR(pci->dbi_base);
> -
>  	mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg");
>  	if (IS_ERR(mp->cfg_base))
>  		return PTR_ERR(mp->cfg_base);

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 787469d1b396..13685d89227a 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -338,40 +338,10 @@ static struct pci_ops meson_pci_ops = {
 static bool meson_pcie_link_up(struct dw_pcie *pci)
 {
 	struct meson_pcie *mp = to_meson_pcie(pci);
-	struct device *dev = pci->dev;
-	u32 speed_okay = 0;
-	u32 cnt = 0;
-	u32 state12, state17, smlh_up, ltssm_up, rdlh_up;
+	u32 state12;
 
-	do {
-		state12 = meson_cfg_readl(mp, PCIE_CFG_STATUS12);
-		state17 = meson_cfg_readl(mp, PCIE_CFG_STATUS17);
-		smlh_up = IS_SMLH_LINK_UP(state12);
-		rdlh_up = IS_RDLH_LINK_UP(state12);
-		ltssm_up = IS_LTSSM_UP(state12);
-
-		if (PM_CURRENT_STATE(state17) < PCIE_GEN3)
-			speed_okay = 1;
-
-		if (smlh_up)
-			dev_dbg(dev, "smlh_link_up is on\n");
-		if (rdlh_up)
-			dev_dbg(dev, "rdlh_link_up is on\n");
-		if (ltssm_up)
-			dev_dbg(dev, "ltssm_up is on\n");
-		if (speed_okay)
-			dev_dbg(dev, "speed_okay\n");
-
-		if (smlh_up && rdlh_up && ltssm_up && speed_okay)
-			return true;
-
-		cnt++;
-
-		udelay(10);
-	} while (cnt < WAIT_LINKUP_TIMEOUT);
-
-	dev_err(dev, "error: wait linkup timeout\n");
-	return false;
+	state12 = meson_cfg_readl(mp, PCIE_CFG_STATUS12);
+	return IS_SMLH_LINK_UP(state12) && IS_RDLH_LINK_UP(state12);
 }
 
 static int meson_pcie_host_init(struct dw_pcie_rp *pp)


From jbrunet at baylibre.com  Fri Oct 31 09:27:58 2025
From: jbrunet at baylibre.com (Jerome Brunet)
Date: Fri, 31 Oct 2025 17:27:58 +0100
Subject: [PATCH v3 0/4] clk: amlogic: optimize the PLL driver
In-Reply-To: <9751014d-926e-4d42-b8e1-5a4d3e734457@amlogic.com> (Chuan Liu's
	message of "Fri, 31 Oct 2025 23:09:13 +0800")
References: <20251031-optimize_pll_driver-v3-0-92f3b2f36a83@amlogic.com>
	<1jms57xx05.fsf@starbuckisacylon.baylibre.com>
	<9751014d-926e-4d42-b8e1-5a4d3e734457@amlogic.com>
Message-ID: <1j5xbvxchd.fsf@starbuckisacylon.baylibre.com>

On Fri 31 Oct 2025 at 23:09, Chuan Liu <chuan.liu at amlogic.com> wrote:

> Hi Jerome,
>
> On 10/31/2025 5:04 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>> On Fri 31 Oct 2025 at 16:10, Chuan Liu via B4 Relay
>> <devnull+chuan.liu.amlogic.com at kernel.org> wrote:
>> 
>>> This patch series consists of four topics involving the amlogic PLL
>>> driver:
>>> - Fix out-of-range PLL frequency setting.
>>> - Improve the issue of PLL lock failures.
>>> - Add handling for PLL lock failure.
>>> - Optimize PLL enable timing.
>>>
>>> For easier review and management, these are submitted as a single
>>> patch series.
>>>
>>> The PLL timing optimization changes were merged into our internal
>>> repository quite some time ago and have been verified on a large
>>> number of SoCs:
>>> - Already supported upstream: G12A, G12B, SM1, S4, A1, C3.
>>> - Planned for upstream support: T7, A5, A4, S7, S7D, S6, etc.
>>>
>>> Based on the upstream code base, I have performed functional testing
>>> on G12A, A1, A5, A4, T7, S7, S7D, and S6, all of which passed.
>>>
>>> Additionally, stress testing using scripts was conducted on A5 and
>>> A1, with over 40,000 and 50,000 iterations respectively, and no
>>> abnormalities were observed. Below is a portion of the stress test
>>> log (CLOCK_ALLOW_WRITE_DEBUGFS has been manually enabled):
>> Okay, this little game has been going on long enough.
>> You've posted v2 24h hours ago
>> You've got feedback within hours
>> There was still a 1 question pending
>> The rest of community had no chance to review.
>> 
>
> There might be a serious misunderstanding here.
>
> In recent years, we've mainly been maintaining our code in our
> internal repository, which has led to some differences between our
> internal codebase and the upstream version. The patches that account
> for these differences are already queued for submission, and several
> SoCs are also waiting in line to be submitted. As a result, quite a
> few patches have piled up, waiting to go upstream.
>
> Previously, I had been waiting for your clock driver restructuring
> patches to be ready (which have recently been merged), so for almost
> a year, we haven't made much progress on clock driver?related
> upstreaming.

Ohoh now you are just teasing me !

That work was made necessary because of all the copy/paste Amlogic was
submitting. Despite many requests, this was never addressed so I had
to step in.

If you want things to go faster, then *really* pay attention to the review
you are getting, do not ask question to ignore the answers and stop
making people repeat themselves over and over.



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 10:42:58 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Fri, 31 Oct 2025 23:12:58 +0530
Subject: [PATCH 0/3] PCI: meson: Fix the parsing of DBI region
Message-ID: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>

Hi,

This compile tested only series aims to fix the DBI parsing issue repored in
[1]. The issue stems from the fact that the DT and binding describing 'dbi'
region as 'elbi' from the start.

Now, both binding and DTs are fixed and the driver is reworked to work with both
old and new DTs.

Note: The driver patch is OK to be backported till 6.2 where the common resource
parsing code was introduced. But the DTS patch should not be backported. And I'm
not sure about the backporting of the binding.

Please test this series on the Meson board with old and new DTs.

- Mani

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
Manivannan Sadhasivam (3):
      dt-bindings: PCI: amlogic: Fix the register name of the DBI region
      arm64: dts: amlogic: Fix the register name of the 'DBI' region
      PCI: meson: Fix parsing the DBI register region

 .../devicetree/bindings/pci/amlogic,axg-pcie.yaml      |  6 +++---
 arch/arm64/boot/dts/amlogic/meson-axg.dtsi             |  4 ++--
 arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi      |  2 +-
 drivers/pci/controller/dwc/pci-meson.c                 | 18 +++++++++++++++---
 drivers/pci/controller/dwc/pcie-designware.c           | 12 +++++++-----
 5 files changed, 28 insertions(+), 14 deletions(-)
---
base-commit: 3a8660878839faadb4f1a6dd72c3179c1df56787
change-id: 20251031-pci-meson-fix-c8b651bc6662

Best regards,
-- 
Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 10:42:59 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Fri, 31 Oct 2025 23:12:59 +0530
Subject: [PATCH 1/3] dt-bindings: PCI: amlogic: Fix the register name of
 the DBI region
In-Reply-To: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>
References: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>
Message-ID: <20251031-pci-meson-fix-v1-1-ed29ee5b54f9@oss.qualcomm.com>

Binding incorrectly specifies the 'DBI' region as 'ELBI'. DBI is a must
have region for DWC controllers as it has the Root Port and controller
specific registers, while ELBI has optional registers.

Hence, fix the binding. Though this is an ABI break, this change is needed
to accurately describe the PCI memory map.

Fixes: 7cd210391101 ("dt-bindings: PCI: meson: add DT bindings for Amlogic Meson PCIe controller")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml b/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
index 79a21ba0f9fd62804ba95fe8a6cc3252cf652197..c8258ef4032834d87cf3160ffd1d93812801b62a 100644
--- a/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
@@ -36,13 +36,13 @@ properties:
 
   reg:
     items:
-      - description: External local bus interface registers
+      - description: Data Bus Interface registers
       - description: Meson designed configuration registers
       - description: PCIe configuration space
 
   reg-names:
     items:
-      - const: elbi
+      - const: dbi
       - const: cfg
       - const: config
 
@@ -113,7 +113,7 @@ examples:
     pcie: pcie at f9800000 {
         compatible = "amlogic,axg-pcie", "snps,dw-pcie";
         reg = <0xf9800000 0x400000>, <0xff646000 0x2000>, <0xf9f00000 0x100000>;
-        reg-names = "elbi", "cfg", "config";
+        reg-names = "dbi", "cfg", "config";
         interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
         clocks = <&pclk>, <&clk_port>, <&clk_phy>;
         clock-names = "pclk", "port", "general";

-- 
2.48.1



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 10:43:00 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Fri, 31 Oct 2025 23:13:00 +0530
Subject: [PATCH 2/3] arm64: dts: amlogic: Fix the register name of the
 'DBI' region
In-Reply-To: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>
References: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>
Message-ID: <20251031-pci-meson-fix-v1-2-ed29ee5b54f9@oss.qualcomm.com>

DT incorrectly specifies the 'DBI' region as 'ELBI'. DBI is a must have
region for DWC controllers as it has the Root Port and controller specific
registers, while ELBI has optional registers.

Hence, fix the DT for both Meson platforms.

Cc: stable+noautosel at kernel.org # Driver dependency
Fixes: 5b3a9c20926e ("arm64: dts: meson-axg: add PCIe nodes")
Fixes: 1f8607d59763 ("arm64: dts: meson-g12a: Add PCIe node")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
 arch/arm64/boot/dts/amlogic/meson-axg.dtsi        | 4 ++--
 arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 04fb130ac7c6a498f7e8029aeaa7e511cbfe815d..e95c91894968b2c8b3b8e96a5f5e85cd60f3e085 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -208,7 +208,7 @@ pcieA: pcie at f9800000 {
 			reg = <0x0 0xf9800000 0x0 0x400000>,
 			      <0x0 0xff646000 0x0 0x2000>,
 			      <0x0 0xf9f00000 0x0 0x100000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
 			interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0>;
@@ -234,7 +234,7 @@ pcieB: pcie at fa000000 {
 			reg = <0x0 0xfa000000 0x0 0x400000>,
 			      <0x0 0xff648000 0x0 0x2000>,
 			      <0x0 0xfa400000 0x0 0x100000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
 			interrupts = <GIC_SPI 167 IRQ_TYPE_EDGE_RISING>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index dcc927a9da80246da43391f9f90049c3570f10d2..ca455f634834b5a52db8ff4e6ebca35a87ea17b7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -138,7 +138,7 @@ pcie: pcie at fc000000 {
 			reg = <0x0 0xfc000000 0x0 0x400000>,
 			      <0x0 0xff648000 0x0 0x2000>,
 			      <0x0 0xfc400000 0x0 0x200000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
 			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0>;

-- 
2.48.1



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 10:43:01 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Fri, 31 Oct 2025 23:13:01 +0530
Subject: [PATCH 3/3] PCI: meson: Fix parsing the DBI register region
In-Reply-To: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>
References: <20251031-pci-meson-fix-v1-0-ed29ee5b54f9@oss.qualcomm.com>
Message-ID: <20251031-pci-meson-fix-v1-3-ed29ee5b54f9@oss.qualcomm.com>

First of all, the driver was parsing the 'dbi' register region as 'elbi'.
This was due to DT mistakenly passing 'dbi' as 'elbi'. Since the DT is
now fixed to supply 'dbi' region, this driver can rely on the DWC core
driver to parse and map it.

However, to support the old DTs, if the 'elbi' region is found in DT, parse
and map the region as both 'dw_pcie::elbi_base' as 'dw_pcie::dbi_base'.
This will allow the driver to work with both broken and fixed DTs.

Also, skip parsing the 'elbi' region in DWC core if 'pci->elbi_base' was
already populated.

Cc: <stable at vger.kernel.org> # 6.2
Reported-by: Linnaea Lavia <linnaea-von-lavia at live.com>
Closes: https://lore.kernel.org/linux-pci/DM4PR05MB102707B8CDF84D776C39F22F2C7F0A at DM4PR05MB10270.namprd05.prod.outlook.com/
Fixes: 9c0ef6d34fdb ("PCI: amlogic: Add the Amlogic Meson PCIe controller driver")
Fixes: c96992a24bec ("PCI: dwc: Add support for ELBI resource mapping")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
 drivers/pci/controller/dwc/pci-meson.c       | 18 +++++++++++++++---
 drivers/pci/controller/dwc/pcie-designware.c | 12 +++++++-----
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 787469d1b396d4c7b3e28edfe276b7b997fb8aee..54b6a4196f1767a3c14c6c901bfee3505588134c 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -108,10 +108,22 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
 			       struct meson_pcie *mp)
 {
 	struct dw_pcie *pci = &mp->pci;
+	struct resource *res;
 
-	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi");
-	if (IS_ERR(pci->dbi_base))
-		return PTR_ERR(pci->dbi_base);
+	/*
+	 * For the broken DTs that supply 'dbi' as 'elbi', parse the 'elbi'
+	 * region and assign it to both 'pci->elbi_base' and 'pci->dbi_space' so
+	 * that the DWC core can skip parsing both regions.
+	 */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
+	if (res) {
+		pci->elbi_base = devm_pci_remap_cfg_resource(pci->dev, res);
+		if (IS_ERR(pci->elbi_base))
+			return PTR_ERR(pci->elbi_base);
+
+		pci->dbi_base = pci->elbi_base;
+		pci->dbi_phys_addr = res->start;
+	}
 
 	mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg");
 	if (IS_ERR(mp->cfg_base))
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index c644216995f69cbf065e61a0392bf1e5e32cf56e..06eca858eb1b3c7a8a833df6616febcdbe854850 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -168,11 +168,13 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
 	}
 
 	/* ELBI is an optional resource */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
-	if (res) {
-		pci->elbi_base = devm_ioremap_resource(pci->dev, res);
-		if (IS_ERR(pci->elbi_base))
-			return PTR_ERR(pci->elbi_base);
+	if (!pci->elbi_base) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
+		if (res) {
+			pci->elbi_base = devm_ioremap_resource(pci->dev, res);
+			if (IS_ERR(pci->elbi_base))
+				return PTR_ERR(pci->elbi_base);
+		}
 	}
 
 	/* LLDD is supposed to manually switch the clocks and resets state */

-- 
2.48.1



From mani at kernel.org  Fri Oct 31 10:47:45 2025
From: mani at kernel.org (Manivannan Sadhasivam)
Date: Fri, 31 Oct 2025 23:17:45 +0530
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <20251031161323.GA1688975@bhelgaas>
References: <DM4PR05MB1027077E1F4CD8B1A7EDADF1DC7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>
 <20251031161323.GA1688975@bhelgaas>
Message-ID: <agqyqr7c6wwkr4fewt3szomd7c57eeujkal7modj46ssbngxf7@f7t56i723mvx>

On Fri, Oct 31, 2025 at 11:13:23AM -0500, Bjorn Helgaas wrote:
> On Fri, Oct 31, 2025 at 08:26:42PM +0800, Linnaea Lavia wrote:
> > On 10/31/2025 4:50 PM, Neil Armstrong wrote:
> > > On 10/31/25 06:34, Linnaea Lavia wrote:
> > > > On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
> > > > > On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
> > > > > > On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
> > > > > 
> > > > > > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > > > > > > index 214ed060ca1b..9cd12924b5cb 100644
> > > > > > > --- a/drivers/pci/quirks.c
> > > > > > > +++ b/drivers/pci/quirks.c
> > > > > > > @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
> > > > > > > ??? * disable both L0s and L1 for now to be safe.
> > > > > > > ??? */
> > > > > > > ?? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> > > > > > > +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
> > > > > > > ?? /*
> > > > > > > ??? * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
> > > > > > 
> > > > > > I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
> > > > > 
> > > > > Sorry, my fault, I should have made that fixup run earlier, so the
> > > > > patch should be this instead:
> > > > > 
> > > > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
> > > > > index 214ed060ca1b..4fc04015ca0c 100644
> > > > > --- a/drivers/pci/quirks.c
> > > > > +++ b/drivers/pci/quirks.c
> > > > > @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
> > > > > ?? * disable both L0s and L1 for now to be safe.
> > > > > ?? */
> > > > > ? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
> > > > > +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
> > > > 
> > > > L1 still got enabled
> 
> Is that based on the output below?
> 
>   [    5.445853] [     T48] pci 0000:00:00.0: Disabling ASPM L0s/L1
>   [    5.560448] [     T48] pci 0000:01:00.0: ASPM: default states L1
> 
> If so, this doesn't necessarily mean L1 was enabled.  It means the
> quirk marked the 00:00.0 Root Port so we shouldn't ever enable L0s or
> L1, and when we enumerated 01:00.0, we set its default ASPM state to
> L1.
> 
> But I don't *think* L1 should actually be enabled unless we can enable
> it for both 00:00.0 and 01:00.0, and the quirk should mean that we
> can't enable it for 00:00.0.
> 
> This muddle of "capable" (per Link Capabilities) vs "disabled" (either
> the Link Control shows disabled, or software said "don't ever use L1")
> is part of what makes aspm.c so confusing.
> 
> > > > The card works just fine. I'm thinking the ASPM issue is
> > > > probably from the glue driver reporting the link to be down when
> > > > it's really just in low power state.
> > > 
> > > You're probably right, the meson_pcie_link_up() not only checks
> > > the LTSSM but also the speed, which is probably wrong.
> > > 
> > > Can you try removing the test for speed ?
> > > 
> > > -???????????????? if (smlh_up && rdlh_up && ltssm_up && speed_okay)
> > > +???????????????? if (smlh_up && rdlh_up && ltssm_up)
> > > 
> > > The other drivers just checks the link, and some only the smlh_up
> > > && rdlh_up. So you can also probably drop ltssm_up aswell.
> > 
> > I can confirm that removing the check for ltssm_up and speed_okay
> > made ASPM work.
> 
> I don't think meson_pcie_link_up() should have the loop in it, so the
> ltssm_up and speed_okay checks, the loop, the delay, and the timeout
> message should probably all be removed.  That method is supposed to be
> a simple true/false check, and any waiting required should be done in
> dw_pcie_wait_for_link().
> 
> The link was clearly up when we discovered 01:00.0, so the "wait
> linkup timeout" messages from meson_pcie_link_up() after that must be
> from dw_pcie_link_up() being called via the .map_bus() call in
> pci_generic_config_read() or pci_generic_config_write().
> 
> When meson_pcie_link_up() returns false in those config accessors,
> the config accesses will fail (they won't even be attempted), so we'll
> see things like this:
> 
>   pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
> 
> and "Unknown header type 7f" from lspci.
> 
> Can you drop the ASPM quirk patch and instead try the
> meson_pcie_link_up() patch below on top of v6.18-rc3?
> 
> > We still need a solution to the original issue that's preventing the
> > controller from being initialized.
> > 
> > My kernel has the following patch applied, but I think it's not
> > suitable for upstream as this changes device tree bindings for PCIe
> > controller on meson.
> 
> I assume the original issue is this:
> 
>   meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
> 
> and you confirmed that it wasn't fixed by a1978b692a39 ("PCI: dwc: Use
> custom pci_ops for root bus DBI vs ECAM config access"), which
> appeared in v6.18-rc3?
> 
> If it's still broken in v6.18-rc3, and the dtsi and
> meson_pcie_get_mems() patch below makes it work, we have more work to
> do, and maybe Krishna has some ideas.
> 

We have two issues on this platform:

1. DT represents 'dbi' region as 'elbi', which was wrong as both are different
address spaces. ELBI is an optional region, whereas DBI has Root Port and
controller configuration registers, which is mandatory.

2. Driver parses/maps the 'elbi' region and stores it in 'pci->dbi_base'. So
this made sure that the code depending on the 'pci->dbi_base' work as expected.

Commit c96992a24bec, moved the ELBI parsing logic to the core code, and it also
removed the custom parsing from glue drivers. But since this driver was using
'pci->dbi_base' instead of 'pci->elbi_base', it was not caught during the move.

I've submitted a series [1] that hopefully would fix this resource parsing
issue. Please test it out.

- Mani

[1] https://lore.kernel.org/linux-pci/20251031-pci-meson-fix-v1-0-ed29ee5b54f9 at oss.qualcomm.com

-- 
????????? ????????


From alexandre.belloni at bootlin.com  Fri Oct 31 13:47:23 2025
From: alexandre.belloni at bootlin.com (alexandre.belloni at bootlin.com)
Date: Fri, 31 Oct 2025 21:47:23 +0100
Subject: [PATCH] rtc: amlogic-a4: simplify probe
Message-ID: <20251031204724.756857-1-alexandre.belloni@bootlin.com>

From: Alexandre Belloni <alexandre.belloni at bootlin.com>

Use devm_device_init_wakeup to simplify probe and remove .remove as it is now
empty.

Also remove the unnecessary error string as there are no error path without an
error message in devm_rtc_register_device.

Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
---
 drivers/rtc/rtc-amlogic-a4.c | 28 +++++-----------------------
 1 file changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
index a993d35e1d6b..123fb372fc9f 100644
--- a/drivers/rtc/rtc-amlogic-a4.c
+++ b/drivers/rtc/rtc-amlogic-a4.c
@@ -361,38 +361,26 @@ static int aml_rtc_probe(struct platform_device *pdev)
 				     "failed to get_enable rtc sys clk\n");
 	aml_rtc_init(rtc);
 
-	device_init_wakeup(dev, true);
+	devm_device_init_wakeup(dev);
 	platform_set_drvdata(pdev, rtc);
 
 	rtc->rtc_dev = devm_rtc_allocate_device(dev);
-	if (IS_ERR(rtc->rtc_dev)) {
-		ret = PTR_ERR(rtc->rtc_dev);
-		goto err_clk;
-	}
+	if (IS_ERR(rtc->rtc_dev))
+		return PTR_ERR(rtc->rtc_dev);
 
 	ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
 			       IRQF_ONESHOT, "aml-rtc alarm", rtc);
 	if (ret) {
 		dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
 			      rtc->irq, ret);
-		goto err_clk;
+		return ret;
 	}
 
 	rtc->rtc_dev->ops = &aml_rtc_ops;
 	rtc->rtc_dev->range_min = 0;
 	rtc->rtc_dev->range_max = U32_MAX;
 
-	ret = devm_rtc_register_device(rtc->rtc_dev);
-	if (ret) {
-		dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret);
-		goto err_clk;
-	}
-
-	return 0;
-err_clk:
-	device_init_wakeup(dev, false);
-
-	return ret;
+	return devm_rtc_register_device(rtc->rtc_dev);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -420,11 +408,6 @@ static int aml_rtc_resume(struct device *dev)
 static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
 			 aml_rtc_suspend, aml_rtc_resume);
 
-static void aml_rtc_remove(struct platform_device *pdev)
-{
-	device_init_wakeup(&pdev->dev, false);
-}
-
 static const struct aml_rtc_config a5_rtc_config = {
 };
 
@@ -447,7 +430,6 @@ MODULE_DEVICE_TABLE(of, aml_rtc_device_id);
 
 static struct platform_driver aml_rtc_driver = {
 	.probe = aml_rtc_probe,
-	.remove = aml_rtc_remove,
 	.driver = {
 		.name = "aml-rtc",
 		.pm = &aml_rtc_pm_ops,
-- 
2.51.1



From alexandre.belloni at bootlin.com  Fri Oct 31 16:02:19 2025
From: alexandre.belloni at bootlin.com (Alexandre Belloni)
Date: Sat, 1 Nov 2025 00:02:19 +0100
Subject: [PATCH v2] rtc: amlogic-a4: fix double free caused by devm
In-Reply-To: <20251021103559.1903-1-vulab@iscas.ac.cn>
References: <20251020150956.491-1-vulab@iscas.ac.cn>
 <20251021103559.1903-1-vulab@iscas.ac.cn>
Message-ID: <176195170903.843198.16395014691314193568.b4-ty@bootlin.com>

On Tue, 21 Oct 2025 18:35:59 +0800, Haotian Zhang wrote:
> The clock obtained via devm_clk_get_enabled() is automatically managed
> by devres and will be disabled and freed on driver detach. Manually
> calling clk_disable_unprepare() in error path and remove function
> causes double free.
> 
> Remove the redundant clk_disable_unprepare() calls from the probe
> error path and aml_rtc_remove(), allowing the devm framework to
> automatically manage the clock lifecycle.
> 
> [...]

Applied, thanks!

[1/1] rtc: amlogic-a4: fix double free caused by devm
      https://git.kernel.org/abelloni/c/384150d7a5b6

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


From linnaea-von-lavia at live.com  Fri Oct 31 19:23:52 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Sat, 1 Nov 2025 10:23:52 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <20251031161323.GA1688975@bhelgaas>
References: <20251031161323.GA1688975@bhelgaas>
Message-ID: <DM4PR05MB102701671A4743DD0DB3D622AC7F9A@DM4PR05MB10270.namprd05.prod.outlook.com>

On 11/1/2025 12:13 AM, Bjorn Helgaas wrote:
> On Fri, Oct 31, 2025 at 08:26:42PM +0800, Linnaea Lavia wrote:
>> On 10/31/2025 4:50 PM, Neil Armstrong wrote:
>>> On 10/31/25 06:34, Linnaea Lavia wrote:
>>>> On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
>>>>> On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
>>>>>> On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
>>>>>
>>>>>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>>>>>> index 214ed060ca1b..9cd12924b5cb 100644
>>>>>>> --- a/drivers/pci/quirks.c
>>>>>>> +++ b/drivers/pci/quirks.c
>>>>>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>>>>>  ??? * disable both L0s and L1 for now to be safe.
>>>>>>>  ??? */
>>>>>>>  ?? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>>>>>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>>>>>  ?? /*
>>>>>>>  ??? * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
>>>>>>
>>>>>> I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
>>>>>
>>>>> Sorry, my fault, I should have made that fixup run earlier, so the
>>>>> patch should be this instead:
>>>>>
>>>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>>>> index 214ed060ca1b..4fc04015ca0c 100644
>>>>> --- a/drivers/pci/quirks.c
>>>>> +++ b/drivers/pci/quirks.c
>>>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>>>  ?? * disable both L0s and L1 for now to be safe.
>>>>>  ?? */
>>>>>  ? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>>>> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>>
>>>> L1 still got enabled
> 
> Is that based on the output below?
> 
>    [    5.445853] [     T48] pci 0000:00:00.0: Disabling ASPM L0s/L1
>    [    5.560448] [     T48] pci 0000:01:00.0: ASPM: default states L1
> 
> If so, this doesn't necessarily mean L1 was enabled.  It means the
> quirk marked the 00:00.0 Root Port so we shouldn't ever enable L0s or
> L1, and when we enumerated 01:00.0, we set its default ASPM state to
> L1.
> 
> But I don't *think* L1 should actually be enabled unless we can enable
> it for both 00:00.0 and 01:00.0, and the quirk should mean that we
> can't enable it for 00:00.0.

It's from the output of lspci -vv, even with the patch applied.

   LnkCtl: ASPM L1 Enabled; RCB 64 bytes, LnkDisable- CommClk+
           ExtSynch- ClockPM- AutWidDis- BWInt+ AutBWInt+

> 
> This muddle of "capable" (per Link Capabilities) vs "disabled" (either
> the Link Control shows disabled, or software said "don't ever use L1")
> is part of what makes aspm.c so confusing.
> 
>>>> The card works just fine. I'm thinking the ASPM issue is
>>>> probably from the glue driver reporting the link to be down when
>>>> it's really just in low power state.
>>>
>>> You're probably right, the meson_pcie_link_up() not only checks
>>> the LTSSM but also the speed, which is probably wrong.
>>>
>>> Can you try removing the test for speed ?
>>>
>>> -???????????????? if (smlh_up && rdlh_up && ltssm_up && speed_okay)
>>> +???????????????? if (smlh_up && rdlh_up && ltssm_up)
>>>
>>> The other drivers just checks the link, and some only the smlh_up
>>> && rdlh_up. So you can also probably drop ltssm_up aswell.
>>
>> I can confirm that removing the check for ltssm_up and speed_okay
>> made ASPM work.
> 
> I don't think meson_pcie_link_up() should have the loop in it, so the
> ltssm_up and speed_okay checks, the loop, the delay, and the timeout
> message should probably all be removed.  That method is supposed to be
> a simple true/false check, and any waiting required should be done in
> dw_pcie_wait_for_link().
> 
> The link was clearly up when we discovered 01:00.0, so the "wait
> linkup timeout" messages from meson_pcie_link_up() after that must be
> from dw_pcie_link_up() being called via the .map_bus() call in
> pci_generic_config_read() or pci_generic_config_write().
> 
> When meson_pcie_link_up() returns false in those config accessors,
> the config accesses will fail (they won't even be attempted), so we'll
> see things like this:
> 
>    pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
> 
> and "Unknown header type 7f" from lspci.
> 
> Can you drop the ASPM quirk patch and instead try the
> meson_pcie_link_up() patch below on top of v6.18-rc3?
> 

I have tested and can report that with the patch ASPM works out of the box.

>> We still need a solution to the original issue that's preventing the
>> controller from being initialized.
>>
>> My kernel has the following patch applied, but I think it's not
>> suitable for upstream as this changes device tree bindings for PCIe
>> controller on meson.
> 
> I assume the original issue is this:
> 
>    meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
> 
> and you confirmed that it wasn't fixed by a1978b692a39 ("PCI: dwc: Use
> custom pci_ops for root bus DBI vs ECAM config access"), which
> appeared in v6.18-rc3?
> 
> If it's still broken in v6.18-rc3, and the dtsi and
> meson_pcie_get_mems() patch below makes it work, we have more work to
> do, and maybe Krishna has some ideas.
> 


From linnaea-von-lavia at live.com  Fri Oct 31 19:26:17 2025
From: linnaea-von-lavia at live.com (Linnaea Lavia)
Date: Sat, 1 Nov 2025 10:26:17 +0800
Subject: PCIe probe failure on AmLogic A311D after 6.18-rc1
In-Reply-To: <agqyqr7c6wwkr4fewt3szomd7c57eeujkal7modj46ssbngxf7@f7t56i723mvx>
References: <DM4PR05MB1027077E1F4CD8B1A7EDADF1DC7F8A@DM4PR05MB10270.namprd05.prod.outlook.com>
 <20251031161323.GA1688975@bhelgaas>
 <agqyqr7c6wwkr4fewt3szomd7c57eeujkal7modj46ssbngxf7@f7t56i723mvx>
Message-ID: <DM4PR05MB102703CA8E86DFA6C43B03582C7F9A@DM4PR05MB10270.namprd05.prod.outlook.com>

On 11/1/2025 1:47 AM, Manivannan Sadhasivam wrote:
> On Fri, Oct 31, 2025 at 11:13:23AM -0500, Bjorn Helgaas wrote:
>> On Fri, Oct 31, 2025 at 08:26:42PM +0800, Linnaea Lavia wrote:
>>> On 10/31/2025 4:50 PM, Neil Armstrong wrote:
>>>> On 10/31/25 06:34, Linnaea Lavia wrote:
>>>>> On 10/30/2025 1:15 AM, Bjorn Helgaas wrote:
>>>>>> On Wed, Oct 29, 2025 at 06:50:46PM +0800, Linnaea Lavia wrote:
>>>>>>> On 10/29/2025 6:16 AM, Bjorn Helgaas wrote:
>>>>>>
>>>>>>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>>>>>>> index 214ed060ca1b..9cd12924b5cb 100644
>>>>>>>> --- a/drivers/pci/quirks.c
>>>>>>>> +++ b/drivers/pci/quirks.c
>>>>>>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>>>>>>  ??? * disable both L0s and L1 for now to be safe.
>>>>>>>>  ??? */
>>>>>>>>  ?? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>>>>>>> +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>>>>>>  ?? /*
>>>>>>>>  ??? * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
>>>>>>>
>>>>>>> I have applied the patch on 6.18-rc3 but it's still trying to enable ASPM for some reasons.
>>>>>>
>>>>>> Sorry, my fault, I should have made that fixup run earlier, so the
>>>>>> patch should be this instead:
>>>>>>
>>>>>> diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
>>>>>> index 214ed060ca1b..4fc04015ca0c 100644
>>>>>> --- a/drivers/pci/quirks.c
>>>>>> +++ b/drivers/pci/quirks.c
>>>>>> @@ -2524,6 +2524,7 @@ static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
>>>>>>  ?? * disable both L0s and L1 for now to be safe.
>>>>>>  ?? */
>>>>>>  ? DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
>>>>>> +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, quirk_disable_aspm_l0s_l1);
>>>>>
>>>>> L1 still got enabled
>>
>> Is that based on the output below?
>>
>>    [    5.445853] [     T48] pci 0000:00:00.0: Disabling ASPM L0s/L1
>>    [    5.560448] [     T48] pci 0000:01:00.0: ASPM: default states L1
>>
>> If so, this doesn't necessarily mean L1 was enabled.  It means the
>> quirk marked the 00:00.0 Root Port so we shouldn't ever enable L0s or
>> L1, and when we enumerated 01:00.0, we set its default ASPM state to
>> L1.
>>
>> But I don't *think* L1 should actually be enabled unless we can enable
>> it for both 00:00.0 and 01:00.0, and the quirk should mean that we
>> can't enable it for 00:00.0.
>>
>> This muddle of "capable" (per Link Capabilities) vs "disabled" (either
>> the Link Control shows disabled, or software said "don't ever use L1")
>> is part of what makes aspm.c so confusing.
>>
>>>>> The card works just fine. I'm thinking the ASPM issue is
>>>>> probably from the glue driver reporting the link to be down when
>>>>> it's really just in low power state.
>>>>
>>>> You're probably right, the meson_pcie_link_up() not only checks
>>>> the LTSSM but also the speed, which is probably wrong.
>>>>
>>>> Can you try removing the test for speed ?
>>>>
>>>> -???????????????? if (smlh_up && rdlh_up && ltssm_up && speed_okay)
>>>> +???????????????? if (smlh_up && rdlh_up && ltssm_up)
>>>>
>>>> The other drivers just checks the link, and some only the smlh_up
>>>> && rdlh_up. So you can also probably drop ltssm_up aswell.
>>>
>>> I can confirm that removing the check for ltssm_up and speed_okay
>>> made ASPM work.
>>
>> I don't think meson_pcie_link_up() should have the loop in it, so the
>> ltssm_up and speed_okay checks, the loop, the delay, and the timeout
>> message should probably all be removed.  That method is supposed to be
>> a simple true/false check, and any waiting required should be done in
>> dw_pcie_wait_for_link().
>>
>> The link was clearly up when we discovered 01:00.0, so the "wait
>> linkup timeout" messages from meson_pcie_link_up() after that must be
>> from dw_pcie_link_up() being called via the .map_bus() call in
>> pci_generic_config_read() or pci_generic_config_write().
>>
>> When meson_pcie_link_up() returns false in those config accessors,
>> the config accesses will fail (they won't even be attempted), so we'll
>> see things like this:
>>
>>    pci 0000:01:00.0: BAR 0: error updating (0xfc700004 != 0xffffffff)
>>
>> and "Unknown header type 7f" from lspci.
>>
>> Can you drop the ASPM quirk patch and instead try the
>> meson_pcie_link_up() patch below on top of v6.18-rc3?
>>
>>> We still need a solution to the original issue that's preventing the
>>> controller from being initialized.
>>>
>>> My kernel has the following patch applied, but I think it's not
>>> suitable for upstream as this changes device tree bindings for PCIe
>>> controller on meson.
>>
>> I assume the original issue is this:
>>
>>    meson-pcie fc000000.pcie: error -EBUSY: can't request region for resource [mem 0xfc000000-0xfc3fffff]
>>
>> and you confirmed that it wasn't fixed by a1978b692a39 ("PCI: dwc: Use
>> custom pci_ops for root bus DBI vs ECAM config access"), which
>> appeared in v6.18-rc3?
>>
>> If it's still broken in v6.18-rc3, and the dtsi and
>> meson_pcie_get_mems() patch below makes it work, we have more work to
>> do, and maybe Krishna has some ideas.
>>
> 
> We have two issues on this platform:
> 
> 1. DT represents 'dbi' region as 'elbi', which was wrong as both are different
> address spaces. ELBI is an optional region, whereas DBI has Root Port and
> controller configuration registers, which is mandatory.
> 
> 2. Driver parses/maps the 'elbi' region and stores it in 'pci->dbi_base'. So
> this made sure that the code depending on the 'pci->dbi_base' work as expected.
> 
> Commit c96992a24bec, moved the ELBI parsing logic to the core code, and it also
> removed the custom parsing from glue drivers. But since this driver was using
> 'pci->dbi_base' instead of 'pci->elbi_base', it was not caught during the move.
> 
> I've submitted a series [1] that hopefully would fix this resource parsing
> issue. Please test it out.
> 
> - Mani
> 
> [1] https://lore.kernel.org/linux-pci/20251031-pci-meson-fix-v1-0-ed29ee5b54f9 at oss.qualcomm.com
> 

Applied on vanilla 6.18-rc3 with Bjorn's patch, PCIe now works out of the box on the board.


From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 21:29:39 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Sat, 01 Nov 2025 09:59:39 +0530
Subject: [PATCH RESEND 0/3] PCI: meson: Fix the parsing of DBI region
Message-ID: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>

Hi,

This compile tested only series aims to fix the DBI parsing issue repored in
[1]. The issue stems from the fact that the DT and binding described 'dbi'
region as 'elbi' from the start.

Now, both binding and DTs are fixed and the driver is reworked to work with both
old and new DTs.

Note: The driver patch is OK to be backported till 6.2 where the common resource
parsing code was introduced. But the DTS patch should not be backported. And I'm
not sure about the backporting of the binding.

Please test this series on the Meson board with old and new DTs.

- Mani

[1] https://lore.kernel.org/linux-pci/DM4PR05MB102707B8CDF84D776C39F22F2C7F0A at DM4PR05MB10270.namprd05.prod.outlook.com/

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
Resending as the git sendemail config got messed up

---
Manivannan Sadhasivam (3):
      dt-bindings: PCI: amlogic: Fix the register name of the DBI region
      arm64: dts: amlogic: Fix the register name of the 'DBI' region
      PCI: meson: Fix parsing the DBI register region

 .../devicetree/bindings/pci/amlogic,axg-pcie.yaml      |  6 +++---
 arch/arm64/boot/dts/amlogic/meson-axg.dtsi             |  4 ++--
 arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi      |  2 +-
 drivers/pci/controller/dwc/pci-meson.c                 | 18 +++++++++++++++---
 drivers/pci/controller/dwc/pcie-designware.c           | 12 +++++++-----
 5 files changed, 28 insertions(+), 14 deletions(-)
---
base-commit: 3a8660878839faadb4f1a6dd72c3179c1df56787
change-id: 20251031-pci-meson-fix-c8b651bc6662

Best regards,
-- 
Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 21:29:40 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Sat, 01 Nov 2025 09:59:40 +0530
Subject: [PATCH RESEND 1/3] dt-bindings: PCI: amlogic: Fix the register
 name of the DBI region
In-Reply-To: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>
References: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>
Message-ID: <20251101-pci-meson-fix-v1-1-c50dcc56ed6a@oss.qualcomm.com>

Binding incorrectly specifies the 'DBI' region as 'ELBI'. DBI is a must
have region for DWC controllers as it has the Root Port and controller
specific registers, while ELBI has optional registers.

Hence, fix the binding. Though this is an ABI break, this change is needed
to accurately describe the PCI memory map.

Fixes: 7cd210391101 ("dt-bindings: PCI: meson: add DT bindings for Amlogic Meson PCIe controller")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
 Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml b/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
index 79a21ba0f9fd62804ba95fe8a6cc3252cf652197..c8258ef4032834d87cf3160ffd1d93812801b62a 100644
--- a/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
@@ -36,13 +36,13 @@ properties:
 
   reg:
     items:
-      - description: External local bus interface registers
+      - description: Data Bus Interface registers
       - description: Meson designed configuration registers
       - description: PCIe configuration space
 
   reg-names:
     items:
-      - const: elbi
+      - const: dbi
       - const: cfg
       - const: config
 
@@ -113,7 +113,7 @@ examples:
     pcie: pcie at f9800000 {
         compatible = "amlogic,axg-pcie", "snps,dw-pcie";
         reg = <0xf9800000 0x400000>, <0xff646000 0x2000>, <0xf9f00000 0x100000>;
-        reg-names = "elbi", "cfg", "config";
+        reg-names = "dbi", "cfg", "config";
         interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
         clocks = <&pclk>, <&clk_port>, <&clk_phy>;
         clock-names = "pclk", "port", "general";

-- 
2.48.1



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 21:29:41 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Sat, 01 Nov 2025 09:59:41 +0530
Subject: [PATCH RESEND 2/3] arm64: dts: amlogic: Fix the register name of
 the 'DBI' region
In-Reply-To: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>
References: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>
Message-ID: <20251101-pci-meson-fix-v1-2-c50dcc56ed6a@oss.qualcomm.com>

DT incorrectly specifies the 'DBI' region as 'ELBI'. DBI is a must have
region for DWC controllers as it has the Root Port and controller specific
registers, while ELBI has optional registers.

Hence, fix the DT for both Meson platforms.

Cc: stable+noautosel at kernel.org # Driver dependency
Fixes: 5b3a9c20926e ("arm64: dts: meson-axg: add PCIe nodes")
Fixes: 1f8607d59763 ("arm64: dts: meson-g12a: Add PCIe node")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
 arch/arm64/boot/dts/amlogic/meson-axg.dtsi        | 4 ++--
 arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 04fb130ac7c6a498f7e8029aeaa7e511cbfe815d..e95c91894968b2c8b3b8e96a5f5e85cd60f3e085 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -208,7 +208,7 @@ pcieA: pcie at f9800000 {
 			reg = <0x0 0xf9800000 0x0 0x400000>,
 			      <0x0 0xff646000 0x0 0x2000>,
 			      <0x0 0xf9f00000 0x0 0x100000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
 			interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0>;
@@ -234,7 +234,7 @@ pcieB: pcie at fa000000 {
 			reg = <0x0 0xfa000000 0x0 0x400000>,
 			      <0x0 0xff648000 0x0 0x2000>,
 			      <0x0 0xfa400000 0x0 0x100000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
 			interrupts = <GIC_SPI 167 IRQ_TYPE_EDGE_RISING>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index dcc927a9da80246da43391f9f90049c3570f10d2..ca455f634834b5a52db8ff4e6ebca35a87ea17b7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -138,7 +138,7 @@ pcie: pcie at fc000000 {
 			reg = <0x0 0xfc000000 0x0 0x400000>,
 			      <0x0 0xff648000 0x0 0x2000>,
 			      <0x0 0xfc400000 0x0 0x200000>;
-			reg-names = "elbi", "cfg", "config";
+			reg-names = "dbi", "cfg", "config";
 			interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
 			#interrupt-cells = <1>;
 			interrupt-map-mask = <0 0 0 0>;

-- 
2.48.1



From manivannan.sadhasivam at oss.qualcomm.com  Fri Oct 31 21:29:42 2025
From: manivannan.sadhasivam at oss.qualcomm.com (Manivannan Sadhasivam)
Date: Sat, 01 Nov 2025 09:59:42 +0530
Subject: [PATCH RESEND 3/3] PCI: meson: Fix parsing the DBI register region
In-Reply-To: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>
References: <20251101-pci-meson-fix-v1-0-c50dcc56ed6a@oss.qualcomm.com>
Message-ID: <20251101-pci-meson-fix-v1-3-c50dcc56ed6a@oss.qualcomm.com>

First of all, the driver was parsing the 'dbi' register region as 'elbi'.
This was due to DT mistakenly passing 'dbi' as 'elbi'. Since the DT is
now fixed to supply 'dbi' region, this driver can rely on the DWC core
driver to parse and map it.

However, to support the old DTs, if the 'elbi' region is found in DT, parse
and map the region as both 'dw_pcie::elbi_base' as 'dw_pcie::dbi_base'.
This will allow the driver to work with both broken and fixed DTs.

Also, skip parsing the 'elbi' region in DWC core if 'pci->elbi_base' was
already populated.

Cc: <stable at vger.kernel.org> # 6.2
Reported-by: Linnaea Lavia <linnaea-von-lavia at live.com>
Closes: https://lore.kernel.org/linux-pci/DM4PR05MB102707B8CDF84D776C39F22F2C7F0A at DM4PR05MB10270.namprd05.prod.outlook.com/
Fixes: 9c0ef6d34fdb ("PCI: amlogic: Add the Amlogic Meson PCIe controller driver")
Fixes: c96992a24bec ("PCI: dwc: Add support for ELBI resource mapping")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at oss.qualcomm.com>
---
 drivers/pci/controller/dwc/pci-meson.c       | 18 +++++++++++++++---
 drivers/pci/controller/dwc/pcie-designware.c | 12 +++++++-----
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
index 787469d1b396d4c7b3e28edfe276b7b997fb8aee..54b6a4196f1767a3c14c6c901bfee3505588134c 100644
--- a/drivers/pci/controller/dwc/pci-meson.c
+++ b/drivers/pci/controller/dwc/pci-meson.c
@@ -108,10 +108,22 @@ static int meson_pcie_get_mems(struct platform_device *pdev,
 			       struct meson_pcie *mp)
 {
 	struct dw_pcie *pci = &mp->pci;
+	struct resource *res;
 
-	pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "elbi");
-	if (IS_ERR(pci->dbi_base))
-		return PTR_ERR(pci->dbi_base);
+	/*
+	 * For the broken DTs that supply 'dbi' as 'elbi', parse the 'elbi'
+	 * region and assign it to both 'pci->elbi_base' and 'pci->dbi_space' so
+	 * that the DWC core can skip parsing both regions.
+	 */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
+	if (res) {
+		pci->elbi_base = devm_pci_remap_cfg_resource(pci->dev, res);
+		if (IS_ERR(pci->elbi_base))
+			return PTR_ERR(pci->elbi_base);
+
+		pci->dbi_base = pci->elbi_base;
+		pci->dbi_phys_addr = res->start;
+	}
 
 	mp->cfg_base = devm_platform_ioremap_resource_byname(pdev, "cfg");
 	if (IS_ERR(mp->cfg_base))
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index c644216995f69cbf065e61a0392bf1e5e32cf56e..06eca858eb1b3c7a8a833df6616febcdbe854850 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -168,11 +168,13 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
 	}
 
 	/* ELBI is an optional resource */
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
-	if (res) {
-		pci->elbi_base = devm_ioremap_resource(pci->dev, res);
-		if (IS_ERR(pci->elbi_base))
-			return PTR_ERR(pci->elbi_base);
+	if (!pci->elbi_base) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
+		if (res) {
+			pci->elbi_base = devm_ioremap_resource(pci->dev, res);
+			if (IS_ERR(pci->elbi_base))
+				return PTR_ERR(pci->elbi_base);
+		}
 	}
 
 	/* LLDD is supposed to manually switch the clocks and resets state */

-- 
2.48.1



