* [PATCH] KVM: arm64: Fix meta-page unsharing in pKVM hyp tracing
From: Vincent Donnefort @ 2026-05-21 9:09 UTC (permalink / raw)
To: maz, oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
catalin.marinas, will
Cc: linux-arm-kernel, kvmarm, kernel-team, Vincent Donnefort
As the hyp_trace_buffer_unshare_hyp() function name suggests we should
unshare all the previously shared pages, otherwise we leak hyp-shared
pages which won't be reusable for hyp memory.
Fix the typo by calling __unshare_page() on the meta-page, ensuring all
previously shared pages are correctly unshared.
Fixes: 3aed038aac8d ("KVM: arm64: Add trace remote for the nVHE/pKVM hyp")
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 8b7f2bf2fba8..06805b426101 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -189,7 +189,7 @@ static void hyp_trace_buffer_unshare_hyp(struct hyp_trace_buffer *trace_buffer,
if (cpu > last_cpu)
break;
- __share_page(rb_desc->meta_va);
+ __unshare_page(rb_desc->meta_va);
for (p = 0; p < rb_desc->nr_page_va; p++)
__unshare_page(rb_desc->page_va[p]);
}
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* Re: [PATCH v4 1/2] phy: rockchip: inno-hdmi: Add configure() and validate() ops
From: Heiko Stuebner @ 2026-05-21 9:10 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Jonas Karlman
Cc: linux-phy, linux-rockchip, linux-arm-kernel, linux-kernel,
Jonas Karlman
In-Reply-To: <20260518180722.2480799-2-jonas@kwiboo.se>
Am Montag, 18. Mai 2026, 20:07:20 Mitteleuropäische Sommerzeit schrieb Jonas Karlman:
> The commit 10ed34d6eaaf ("phy: Add HDMI configuration options")
> introduced a way for HDMI PHYs to be configured through the generic
> phy_configure() function.
>
> This driver derives the TMDS character rate from the pixel clock and the
> PHY bus width setting. However, no in-tree consumer of this PHY has ever
> called phy_set_bus_width() to change the TMDS character rate as only
> 8-bit RGB output is supported by the HDMI display driver.
>
> Add configure() and validate() ops to allow consumers to configure the
> TMDS character rate using phy_configure(). Fallback to the deprecated
> way of using the PHY bus width to configure the TMDS character rate.
>
> A typical call chain during DRM modeset on a RK3328 device:
>
> dw_hdmi_rockchip_encoder_atomic_check():
> - inno_hdmi_phy_validate(): pixclock 148500000 tmdsclock 594000000
>
> dw_hdmi_rockchip_encoder_atomic_mode_set():
> - inno_hdmi_phy_configure(): pixclock 148500000
> - inno_hdmi_phy_validate(): pixclock 148500000 tmdsclock 594000000
>
> vop_crtc_atomic_enable():
> - inno_hdmi_phy_rk3328_clk_set_rate(): rate 594000000 tmdsclk 594000000
> inno_hdmi_phy_rk3328_clk_set_rate(): pixclock 594000000 tmdsclock 594000000
> - inno_hdmi_phy_rk3328_clk_recalc_rate(): pixclock 594000000 vco 594000000
>
> dw_hdmi_rockchip_encoder_enable():
> - inno_hdmi_phy_power_on(): Inno HDMI PHY Power On
> - inno_hdmi_phy_rk3328_clk_set_rate(): rate 594000000 tmdsclk 594000000
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de> #rk3328
^ permalink raw reply
* Re: [PATCH v4 2/2] phy: rockchip: inno-hdmi: Remove deprecated way to configure TMDS rate
From: Heiko Stuebner @ 2026-05-21 9:11 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Jonas Karlman
Cc: linux-phy, linux-rockchip, linux-arm-kernel, linux-kernel,
Jonas Karlman
In-Reply-To: <20260518180722.2480799-3-jonas@kwiboo.se>
Am Montag, 18. Mai 2026, 20:07:21 Mitteleuropäische Sommerzeit schrieb Jonas Karlman:
> The TMDS character rate of this PHY is configured using PHY bus width
> in downstream vendor kernel and out-of-tree patches, however no in-tree
> consumer of this PHY has ever called phy_set_bus_width() to change the
> TMDS character rate as currently only 8-bit RGB output is supported by
> the HDMI display driver.
>
> The series "Split Generic PHY consumer and provider" clarifies that
> phy_set_bus_width() is intended as a provider-only function.
>
> Remove the deprecated unused fallback way to configure TMDS character
> rate now that this HDMI PHY support using phy_configure() to configure
> the TMDS character rate.
>
> Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
Tested-by: Heiko Stuebner <heiko@sntech.de> #rk3328
^ permalink raw reply
* [soc:soc/defconfig] BUILD SUCCESS 1440d446ad5df97c46315182cb0d63176e7f0a8c
From: kernel test robot @ 2026-05-21 9:06 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linux-arm-kernel, arm
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/defconfig
branch HEAD: 1440d446ad5df97c46315182cb0d63176e7f0a8c Merge tag 'cix-defconfig-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/cix into soc/defconfig
elapsed time: 733m
configs tested: 186
configs skipped: 149
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-15.2.0
alpha allyesconfig gcc-15.2.0
alpha defconfig gcc-15.2.0
arc allmodconfig clang-16
arc allnoconfig gcc-15.2.0
arc allyesconfig clang-23
arc defconfig gcc-15.2.0
arc randconfig-001-20260521 gcc-8.5.0
arc randconfig-002-20260521 gcc-8.5.0
arm allnoconfig clang-23
arm allnoconfig gcc-15.2.0
arm allyesconfig clang-16
arm defconfig gcc-15.2.0
arm footbridge_defconfig clang-17
arm randconfig-001-20260521 gcc-8.5.0
arm randconfig-002-20260521 gcc-8.5.0
arm randconfig-003-20260521 gcc-8.5.0
arm randconfig-004-20260521 gcc-8.5.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-15.2.0
arm64 defconfig gcc-15.2.0
arm64 randconfig-001-20260521 gcc-8.5.0
arm64 randconfig-002-20260521 gcc-8.5.0
arm64 randconfig-003-20260521 gcc-8.5.0
arm64 randconfig-004-20260521 gcc-8.5.0
csky allmodconfig gcc-15.2.0
csky allnoconfig gcc-15.2.0
csky defconfig gcc-15.2.0
csky randconfig-001-20260521 gcc-8.5.0
csky randconfig-002-20260521 gcc-8.5.0
hexagon allmodconfig gcc-15.2.0
hexagon allnoconfig gcc-15.2.0
hexagon defconfig gcc-15.2.0
hexagon randconfig-001-20260521 gcc-11.5.0
hexagon randconfig-002-20260521 gcc-11.5.0
i386 allmodconfig clang-20
i386 allnoconfig gcc-15.2.0
i386 allyesconfig clang-20
i386 buildonly-randconfig-001-20260521 clang-20
i386 buildonly-randconfig-002-20260521 clang-20
i386 buildonly-randconfig-003-20260521 clang-20
i386 buildonly-randconfig-004-20260521 clang-20
i386 buildonly-randconfig-005-20260521 clang-20
i386 buildonly-randconfig-006-20260521 clang-20
i386 defconfig gcc-15.2.0
i386 randconfig-001-20260521 clang-20
i386 randconfig-002-20260521 clang-20
i386 randconfig-003-20260521 clang-20
i386 randconfig-004-20260521 clang-20
i386 randconfig-005-20260521 clang-20
i386 randconfig-006-20260521 clang-20
i386 randconfig-007-20260521 clang-20
i386 randconfig-011-20260521 gcc-14
i386 randconfig-012-20260521 gcc-14
i386 randconfig-013-20260521 gcc-14
i386 randconfig-014-20260521 gcc-14
i386 randconfig-015-20260521 gcc-14
i386 randconfig-016-20260521 gcc-14
i386 randconfig-017-20260521 gcc-14
loongarch allmodconfig clang-23
loongarch allnoconfig gcc-15.2.0
loongarch defconfig clang-19
loongarch randconfig-001-20260521 gcc-11.5.0
loongarch randconfig-002-20260521 gcc-11.5.0
m68k allmodconfig gcc-15.2.0
m68k allnoconfig gcc-15.2.0
m68k allyesconfig clang-16
m68k defconfig clang-19
microblaze allnoconfig gcc-15.2.0
microblaze allyesconfig gcc-15.2.0
microblaze defconfig clang-19
mips allmodconfig gcc-15.2.0
mips allnoconfig gcc-15.2.0
mips allyesconfig gcc-15.2.0
mips rt305x_defconfig clang-23
nios2 10m50_defconfig gcc-11.5.0
nios2 allmodconfig clang-23
nios2 allnoconfig clang-23
nios2 defconfig clang-19
nios2 randconfig-001-20260521 gcc-11.5.0
nios2 randconfig-002-20260521 gcc-11.5.0
openrisc allmodconfig clang-23
openrisc allnoconfig clang-23
openrisc defconfig gcc-15.2.0
parisc allmodconfig gcc-15.2.0
parisc allnoconfig clang-23
parisc allyesconfig clang-19
parisc defconfig gcc-15.2.0
parisc randconfig-001-20260521 gcc-12.5.0
parisc randconfig-002-20260521 gcc-12.5.0
parisc64 defconfig clang-19
powerpc allmodconfig gcc-15.2.0
powerpc allnoconfig clang-23
powerpc mgcoge_defconfig clang-23
powerpc mpc837x_rdb_defconfig gcc-15.2.0
powerpc randconfig-001-20260521 gcc-12.5.0
powerpc randconfig-002-20260521 gcc-12.5.0
powerpc sam440ep_defconfig gcc-15.2.0
powerpc64 randconfig-001-20260521 gcc-12.5.0
powerpc64 randconfig-002-20260521 gcc-12.5.0
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allyesconfig clang-16
riscv defconfig gcc-15.2.0
riscv randconfig-001-20260521 gcc-15.2.0
riscv randconfig-002-20260521 gcc-15.2.0
s390 allmodconfig clang-19
s390 allnoconfig clang-23
s390 allyesconfig gcc-15.2.0
s390 defconfig gcc-15.2.0
s390 randconfig-001-20260521 gcc-15.2.0
s390 randconfig-002-20260521 gcc-15.2.0
sh allmodconfig gcc-15.2.0
sh allnoconfig clang-23
sh allyesconfig clang-19
sh defconfig gcc-14
sh randconfig-001-20260521 gcc-15.2.0
sh randconfig-002-20260521 gcc-15.2.0
sparc allnoconfig clang-23
sparc defconfig gcc-15.2.0
sparc randconfig-001-20260521 gcc-8.5.0
sparc randconfig-002-20260521 gcc-8.5.0
sparc64 allmodconfig clang-23
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260521 gcc-8.5.0
sparc64 randconfig-002-20260521 gcc-8.5.0
um allmodconfig clang-19
um allnoconfig clang-23
um allyesconfig gcc-15.2.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260521 gcc-8.5.0
um randconfig-002-20260521 gcc-8.5.0
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-20
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-20
x86_64 buildonly-randconfig-001-20260521 clang-20
x86_64 buildonly-randconfig-002-20260521 clang-20
x86_64 buildonly-randconfig-003-20260521 clang-20
x86_64 buildonly-randconfig-004-20260521 clang-20
x86_64 buildonly-randconfig-005-20260521 clang-20
x86_64 buildonly-randconfig-006-20260521 clang-20
x86_64 defconfig gcc-14
x86_64 kexec clang-20
x86_64 randconfig-001-20260521 clang-20
x86_64 randconfig-002-20260521 clang-20
x86_64 randconfig-003-20260521 clang-20
x86_64 randconfig-004-20260521 clang-20
x86_64 randconfig-005-20260521 clang-20
x86_64 randconfig-006-20260521 clang-20
x86_64 randconfig-011 gcc-14
x86_64 randconfig-011-20260521 gcc-14
x86_64 randconfig-012 gcc-14
x86_64 randconfig-012-20260521 gcc-14
x86_64 randconfig-013 gcc-14
x86_64 randconfig-013-20260521 gcc-14
x86_64 randconfig-014 gcc-14
x86_64 randconfig-014-20260521 gcc-14
x86_64 randconfig-015 gcc-14
x86_64 randconfig-015-20260521 gcc-14
x86_64 randconfig-016 gcc-14
x86_64 randconfig-016-20260521 gcc-14
x86_64 randconfig-071 clang-20
x86_64 randconfig-071-20260521 clang-20
x86_64 randconfig-072 clang-20
x86_64 randconfig-072-20260521 clang-20
x86_64 randconfig-073 clang-20
x86_64 randconfig-073-20260521 clang-20
x86_64 randconfig-074 clang-20
x86_64 randconfig-074-20260521 clang-20
x86_64 randconfig-075 clang-20
x86_64 randconfig-075-20260521 clang-20
x86_64 randconfig-076 clang-20
x86_64 randconfig-076-20260521 clang-20
x86_64 rhel-9.4 clang-20
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-20
x86_64 rhel-9.4-kselftests clang-20
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-20
xtensa allnoconfig clang-23
xtensa allyesconfig clang-23
xtensa randconfig-001-20260521 gcc-8.5.0
xtensa randconfig-002-20260521 gcc-8.5.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v7 00/23] drm: bridge: dw_hdmi: Misc enable/disable, CEC and EDID cleanup
From: Heiko Stuebner @ 2026-05-21 9:14 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Jonas Karlman
Cc: Laurent Pinchart, Jernej Skrabec, Luca Ceresoli, Liu Ying,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Sandy Huang, Andy Yan, Chen-Yu Tsai,
Christian Hewitt, Diederik de Haas, Nicolas Frattaroli,
Dmitry Baryshkov, dri-devel, linux-arm-kernel, linux-rockchip,
linux-amlogic, linux-sunxi, imx, linux-kernel, Jonas Karlman
In-Reply-To: <20260518180206.2480119-1-jonas@kwiboo.se>
Am Montag, 18. Mai 2026, 20:01:36 Mitteleuropäische Sommerzeit schrieb Jonas Karlman:
> This is a revival of an old dw-hdmi series and is the first series part
> of a new effort to upstream old LibreELEC HDMI 2.0 patches for Rockchip
> RK33xx devices.
>
> This series ensure poweron/poweroff and CEC phys addr invalidation is
> happening during normal DRM funcs, ensures EDID and CEC phys addr is
> updated in detect() similar to how the bridge connector works with a
> HDMI bridge attached, and also changes to debounce hotplug processing
> to prevent a full disable/enable cycle during a HPD low voltage pulse.
>
> After this series HPD, EDID and CEC handling should work very similar
> regardless is the dw-hdmi connector or the bridge connector is used.
> It should also help ensure a smoother transition when dw-hdmi is fully
> converted into a HDMI bridge in a future series.
>
> These changes have mainly been tested on Rockchip RK3328, RK3399 and
> RK3568 devices using both the dw-hdmi connector and also using a basic
> convert to use a bridge connector. The changes has also been tested on
> Amlogic S905X, S905Y2 and A311D devices that uses the bridge connector.
I now also gave this a spin on a rk3328 board and hdmi still workx :-)
Tested-by: Heiko Stuebner <heiko@sntech.de> #rk3328
^ permalink raw reply
* [soc:soc/dt] BUILD SUCCESS e8a53f2d9c367a454aedf86c964f9c68efc993d9
From: kernel test robot @ 2026-05-21 9:07 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: linux-arm-kernel, arm
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git soc/dt
branch HEAD: e8a53f2d9c367a454aedf86c964f9c68efc993d9 Merge tag 'zx29-dts-for-7.2' of https://gitlab.com/stefandoesinger/zx297520-kernel into soc/dt
elapsed time: 733m
configs tested: 192
configs skipped: 2
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-15.2.0
alpha allyesconfig gcc-15.2.0
alpha defconfig gcc-15.2.0
arc allmodconfig clang-16
arc allnoconfig gcc-15.2.0
arc allyesconfig clang-23
arc defconfig gcc-15.2.0
arc randconfig-001-20260521 gcc-8.5.0
arc randconfig-002-20260521 gcc-8.5.0
arm allnoconfig clang-23
arm allnoconfig gcc-15.2.0
arm allyesconfig clang-16
arm defconfig gcc-15.2.0
arm footbridge_defconfig clang-17
arm randconfig-001-20260521 gcc-8.5.0
arm randconfig-002-20260521 gcc-8.5.0
arm randconfig-003-20260521 gcc-8.5.0
arm randconfig-004-20260521 gcc-8.5.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-15.2.0
arm64 defconfig gcc-15.2.0
arm64 randconfig-001-20260521 gcc-8.5.0
arm64 randconfig-002-20260521 gcc-8.5.0
arm64 randconfig-003-20260521 gcc-8.5.0
arm64 randconfig-004-20260521 gcc-8.5.0
csky allmodconfig gcc-15.2.0
csky allnoconfig gcc-15.2.0
csky defconfig gcc-15.2.0
csky randconfig-001-20260521 gcc-8.5.0
csky randconfig-002-20260521 gcc-8.5.0
hexagon allmodconfig gcc-15.2.0
hexagon allnoconfig clang-23
hexagon allnoconfig gcc-15.2.0
hexagon defconfig gcc-15.2.0
hexagon randconfig-001-20260521 gcc-11.5.0
hexagon randconfig-002-20260521 gcc-11.5.0
i386 allmodconfig clang-20
i386 allnoconfig gcc-14
i386 allnoconfig gcc-15.2.0
i386 allyesconfig clang-20
i386 buildonly-randconfig-001-20260521 clang-20
i386 buildonly-randconfig-002-20260521 clang-20
i386 buildonly-randconfig-003-20260521 clang-20
i386 buildonly-randconfig-004-20260521 clang-20
i386 buildonly-randconfig-005-20260521 clang-20
i386 buildonly-randconfig-006-20260521 clang-20
i386 defconfig gcc-15.2.0
i386 randconfig-001-20260521 clang-20
i386 randconfig-002-20260521 clang-20
i386 randconfig-003-20260521 clang-20
i386 randconfig-004-20260521 clang-20
i386 randconfig-005-20260521 clang-20
i386 randconfig-006-20260521 clang-20
i386 randconfig-007-20260521 clang-20
i386 randconfig-011-20260521 gcc-14
i386 randconfig-012-20260521 gcc-14
i386 randconfig-013-20260521 gcc-14
i386 randconfig-014-20260521 gcc-14
i386 randconfig-015-20260521 gcc-14
i386 randconfig-016-20260521 gcc-14
i386 randconfig-017-20260521 gcc-14
loongarch allmodconfig clang-23
loongarch allnoconfig clang-23
loongarch allnoconfig gcc-15.2.0
loongarch defconfig clang-19
loongarch randconfig-001-20260521 gcc-11.5.0
loongarch randconfig-002-20260521 gcc-11.5.0
m68k allmodconfig gcc-15.2.0
m68k allnoconfig gcc-15.2.0
m68k allyesconfig clang-16
m68k defconfig clang-19
microblaze allnoconfig gcc-15.2.0
microblaze allyesconfig gcc-15.2.0
microblaze defconfig clang-19
mips allmodconfig gcc-15.2.0
mips allnoconfig gcc-15.2.0
mips allyesconfig gcc-15.2.0
mips rt305x_defconfig clang-23
nios2 10m50_defconfig gcc-11.5.0
nios2 allmodconfig clang-23
nios2 allnoconfig clang-23
nios2 defconfig clang-19
nios2 randconfig-001-20260521 gcc-11.5.0
nios2 randconfig-002-20260521 gcc-11.5.0
openrisc allmodconfig clang-23
openrisc allnoconfig clang-23
openrisc defconfig gcc-15.2.0
parisc allmodconfig gcc-15.2.0
parisc allnoconfig clang-23
parisc allyesconfig clang-19
parisc allyesconfig gcc-15.2.0
parisc defconfig gcc-15.2.0
parisc randconfig-001-20260521 gcc-12.5.0
parisc randconfig-002-20260521 gcc-12.5.0
parisc64 defconfig clang-19
powerpc allmodconfig gcc-15.2.0
powerpc allnoconfig clang-23
powerpc mgcoge_defconfig clang-23
powerpc mpc837x_rdb_defconfig gcc-15.2.0
powerpc randconfig-001-20260521 gcc-12.5.0
powerpc randconfig-002-20260521 gcc-12.5.0
powerpc sam440ep_defconfig gcc-15.2.0
powerpc64 randconfig-001-20260521 gcc-12.5.0
powerpc64 randconfig-002-20260521 gcc-12.5.0
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allyesconfig clang-16
riscv defconfig gcc-15.2.0
riscv randconfig-001-20260521 gcc-15.2.0
riscv randconfig-002-20260521 gcc-15.2.0
s390 allmodconfig clang-18
s390 allmodconfig clang-19
s390 allnoconfig clang-23
s390 allyesconfig gcc-15.2.0
s390 defconfig gcc-15.2.0
s390 randconfig-001-20260521 gcc-15.2.0
s390 randconfig-002-20260521 gcc-15.2.0
sh allmodconfig gcc-15.2.0
sh allnoconfig clang-23
sh allyesconfig clang-19
sh allyesconfig gcc-15.2.0
sh defconfig gcc-14
sh randconfig-001-20260521 gcc-15.2.0
sh randconfig-002-20260521 gcc-15.2.0
sparc allnoconfig clang-23
sparc defconfig gcc-15.2.0
sparc randconfig-001-20260521 gcc-8.5.0
sparc randconfig-002-20260521 gcc-8.5.0
sparc64 allmodconfig clang-23
sparc64 defconfig gcc-14
sparc64 randconfig-001-20260521 gcc-8.5.0
sparc64 randconfig-002-20260521 gcc-8.5.0
um allmodconfig clang-19
um allnoconfig clang-23
um allyesconfig gcc-15.2.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001-20260521 gcc-8.5.0
um randconfig-002-20260521 gcc-8.5.0
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-20
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-20
x86_64 buildonly-randconfig-001-20260521 clang-20
x86_64 buildonly-randconfig-002-20260521 clang-20
x86_64 buildonly-randconfig-003-20260521 clang-20
x86_64 buildonly-randconfig-004-20260521 clang-20
x86_64 buildonly-randconfig-005-20260521 clang-20
x86_64 buildonly-randconfig-006-20260521 clang-20
x86_64 defconfig gcc-14
x86_64 kexec clang-20
x86_64 randconfig-001-20260521 clang-20
x86_64 randconfig-002-20260521 clang-20
x86_64 randconfig-003-20260521 clang-20
x86_64 randconfig-004-20260521 clang-20
x86_64 randconfig-005-20260521 clang-20
x86_64 randconfig-006-20260521 clang-20
x86_64 randconfig-011 gcc-14
x86_64 randconfig-011-20260521 gcc-14
x86_64 randconfig-012 gcc-14
x86_64 randconfig-012-20260521 gcc-14
x86_64 randconfig-013 gcc-14
x86_64 randconfig-013-20260521 gcc-14
x86_64 randconfig-014 gcc-14
x86_64 randconfig-014-20260521 gcc-14
x86_64 randconfig-015 gcc-14
x86_64 randconfig-015-20260521 gcc-14
x86_64 randconfig-016 gcc-14
x86_64 randconfig-016-20260521 gcc-14
x86_64 randconfig-071 clang-20
x86_64 randconfig-071-20260521 clang-20
x86_64 randconfig-072 clang-20
x86_64 randconfig-072-20260521 clang-20
x86_64 randconfig-073 clang-20
x86_64 randconfig-073-20260521 clang-20
x86_64 randconfig-074 clang-20
x86_64 randconfig-074-20260521 clang-20
x86_64 randconfig-075 clang-20
x86_64 randconfig-075-20260521 clang-20
x86_64 randconfig-076 clang-20
x86_64 randconfig-076-20260521 clang-20
x86_64 rhel-9.4 clang-20
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-20
x86_64 rhel-9.4-kselftests clang-20
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-20
xtensa allnoconfig clang-23
xtensa allyesconfig clang-23
xtensa randconfig-001-20260521 gcc-8.5.0
xtensa randconfig-002-20260521 gcc-8.5.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] media: s5p-g2d: avoid double free on video register failure
From: Lukasz Stelmach @ 2026-05-21 9:17 UTC (permalink / raw)
To: Guangshuo Li
Cc: Mauro Carvalho Chehab, Kamil Debski, Kyungmin Park,
Marek Szyprowski, linux-arm-kernel, linux-media, linux-kernel
In-Reply-To: <20260517114642.951949-1-lgs201920130244@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2606 bytes --]
It was 2026-05-17 nie 19:46, when Guangshuo Li wrote:
> g2d_probe() allocates a video_device with video_device_alloc() and
> releases it from the rel_vdev error path if video_register_device()
> fails.
>
> This can double free the video_device when __video_register_device()
> reaches device_register() and that call fails:
>
> video_register_device()
> -> __video_register_device()
> -> device_register() fails
> -> put_device(&vdev->dev)
> -> v4l2_device_release()
> -> vdev->release(vdev)
> -> video_device_release(vdev)
>
> g2d_probe()
> -> rel_vdev
> -> video_device_release(vfd)
>
> Use video_device_release_empty() while registering the device so that
> registration failure paths do not free vfd through vdev->release().
> g2d_probe() then releases vfd exactly once from rel_vdev. Restore
> video_device_release() after successful registration so the registered
> device keeps its normal lifetime handling.
>
> This issue was found by a static analysis tool I am developing.
Thank you for taking time to analyze our code. I was going to write
something along the lines Marek Szyprowski has laready written in this
thread https://lore.kernel.org/all/CANUHTR-RfWnoMRRAoDb6CPZsaiAYBLy61dd0P6TnKYgjNeBWpA@mail.gmail.com/
Do follow his advise with this one too.
> Fixes: 918847341af0 ("[media] v4l: add G2D driver for s5p device family")
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
> ---
> drivers/media/platform/samsung/s5p-g2d/g2d.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/media/platform/samsung/s5p-g2d/g2d.c b/drivers/media/platform/samsung/s5p-g2d/g2d.c
> index a18b13db19d5..f38c28abd6d9 100644
> --- a/drivers/media/platform/samsung/s5p-g2d/g2d.c
> +++ b/drivers/media/platform/samsung/s5p-g2d/g2d.c
> @@ -684,6 +684,7 @@ static int g2d_probe(struct platform_device *pdev)
> goto unreg_v4l2_dev;
> }
> *vfd = g2d_videodev;
> + vfd->release = video_device_release_empty;
> set_bit(V4L2_FL_QUIRK_INVERTED_CROP, &vfd->flags);
> vfd->lock = &dev->mutex;
> vfd->v4l2_dev = &dev->v4l2_dev;
> @@ -711,6 +712,8 @@ static int g2d_probe(struct platform_device *pdev)
> v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
> goto free_m2m;
> }
> +
> + vfd->release = video_device_release;
> video_set_drvdata(vfd, dev);
> dev->vfd = vfd;
> v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n",
--
Łukasz Stelmach
Samsung R&D Institute Poland
Samsung Electronics
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]
^ permalink raw reply
* [PATCH v5 0/3] pinctrl: aspeed: Add AST2700 SoC1 support
From: Billy Tsai @ 2026-05-21 9:17 UTC (permalink / raw)
To: Linus Walleij, Tony Lindgren, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Joel Stanley, Andrew Jeffery, Bartosz Golaszewski,
Lee Jones, Ryan Chen
Cc: patrickw3, linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed, BMC-SW, openbmc, Andrew Jeffery, linux-clk,
Billy Tsai, Conor Dooley
Legacy ASPEED pin controllers have historically not had a coherent
register interface. Control fields often had no consistent mapping to
individual pins, and configuring a function frequently required
coordinating multiple control bits across several registers. As a
result, the existing ASPEED pinctrl drivers rely on complex macro
infrastructure to describe the dependencies between pins, functions,
and register fields.
The pin controller for SoC1 in the AST2700 breaks from this legacy
design.
For SoC1, each pin maps directly to a dedicated function field in the
SCU register space that determines the active mux function for that
pin. This results in a much more regular register layout compared to
previous generations.
While the behaviour is conceptually similar to pinctrl-single, the
register layout and configuration model differ enough that reusing
pinctrl-single directly is not practical. Therefore this driver is
implemented as a SoC-specific pinctrl driver using static data tables
to describe the register layout.
The binding reuses the standard pinmux and generic pin configuration
schemas and does not introduce any custom Devicetree properties.
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
Changes in v5:
- pin_config_set: add comment explaining that PIN_CONFIG_BIAS_PULL_UP
and PIN_CONFIG_BIAS_PULL_DOWN both map to "enable bias" because the
hardware pull direction is fixed in silicon per pin.
- Remove custom aspeed_g7_soc1_get_group_pins() helper; replace with
direct calls to pinctrl_generic_get_group_pins() in
pin_config_group_get() and pin_config_group_set().
- MUX_FUNC_MASK: add comment explaining that the mask covers only
bits [2:0] because bit 3 of each 4-bit per-pin slot is reserved
read-only in the hardware and must not be written.
- Link to v4: https://lore.kernel.org/r/20260519-pinctrl-single-bit-v4-0-5fe568a8ffde@aspeedtech.com
Changes in v4:
- Fix SGMII0 mux register: SGMII0's control bit is at SCU47C[0],
outside the contiguous pin-indexed MUX register range. Handle it as
a special case in set_mux (analogous to PCIERC2_PERST) using
field.mask = 0x1 to avoid clobbering adjacent bits in SCU47C.
- Use devm_pinctrl_register_and_init() and pinctrl_enable(): populate
all groups and functions before enabling the controller, closing the
race window where a consumer could observe zero groups/functions.
- pin_config_get: return -EINVAL when BIAS_DISABLE is not active; return
-ENOTSUPP for BIAS_PULL_UP and BIAS_PULL_DOWN because the hardware
has a single 1-bit enable/disable field per pin and pull direction
cannot be read back from the register.
- Probe: preserve const qualification in the pinctrl_generic_add_group()
pin array cast.
- Binding: retain additionalProperties: false for the state-node schema.
The state-node properties block re-declares the four pincfg properties
the hardware supports (bias-disable, bias-pull-up, bias-pull-down,
drive-strength) and intentionally rejects all others.
unevaluatedProperties: false was suggested as an alternative, but that
would permit the full set of pincfg-node.yaml properties
(input-schmitt-enable, slew-rate, etc.) even though the hardware does
not support them. additionalProperties: false is the correct mechanism
when the goal is to restrict the accepted properties to a known subset.
- Link to v3: https://lore.kernel.org/r/20260515-pinctrl-single-bit-v3-0-e97da4312104@aspeedtech.com
Changes in v3:
- Added pin configuration group support for AST2700 SoC1 by
implementing `pin_config_group_get()` and `pin_config_group_set()`.
- Restricted AST2700 SoC1 `drive-strength` settings to the supported
4/8/12/16 mA values in the pinctrl driver.
- Convert kernel-doc comment for aspeed_g7_soc1_drv_map to a regular
comment to avoid kernel-doc warning reported by kernel test robot.
- Update the AST2700 SoC1 pinctrl binding to describe the `reg`
property and require it.
- Allow standard pinconf properties in pin state nodes.
- Add a binding example for the AST2700 SoC1 pinctrl node.
- Add state-node description, function+groups dependency constraint,
and oneOf groups/pins constraint to the binding, matching the SoC0
binding style.
- Add pins enum (212 entries) to the binding to cover all physical pins
that support per-pin configuration.
- Add UART modem-line signals as independent functions/groups:
NCTS0/1/5/6, NDCD0/1/5/6, NDSR0/1/5/6, NDTR0/1/5/6,
NRI0/1/5/6, NRTS0/1/5/6; remove those pins from UART0/1/5/6 groups.
- Add LTPI_PS_I2C0/1/2/3 functions/groups for I2C-over-LTPI;
extend I2C0/1/2/3 functions with the new LTPI groups.
- Fix typo: rename RMII0RCKO/RMII1RCKO to RMII0RCLKO/RMII1RCLKO.
- Fix wrong index: rename DSGPM1 to DSGPM0.
- Kconfig: use "Aspeed G7 SoC1 pin control" to match neighbouring entries.
- pin_config_get: fix BIAS_DISABLE readback (val=!val must be skipped
for BIAS_DISABLE since hardware bit=1 means pull disabled).
- set_mux: remove dead null check on grp; propagate regmap_update_bits()
return value.
- gpio_request_enable: propagate regmap_update_bits() return value.
- Link to v2: https://lore.kernel.org/r/20260306-pinctrl-single-bit-v2-0-79918cfab641@aspeedtech.com
Changes in v2:
- Updated the series title to focus on AST2700 SoC1 support.
- Reworked implementation to use static SoC-specific layout tables
instead of a generic packed-field model.
- Dropped the generic "pinctrl-packed" driver approach.
- Removed custom Devicetree properties.
- Updated binding to reuse standard pinmux and generic pin
configuration schemas.
- Link to v1: https://lore.kernel.org/r/20260213-pinctrl-single-bit-v1-0-c60f2fb80efb@aspeedtech.com
---
Billy Tsai (3):
dt-bindings: mfd: aspeed,ast2x00-scu: Support AST2700 SoC1 pinctrl
dt-bindings: pinctrl: Add aspeed,ast2700-soc1-pinctrl
pinctrl: aspeed: Add AST2700 SoC1 support
.../bindings/mfd/aspeed,ast2x00-scu.yaml | 1 +
.../pinctrl/aspeed,ast2700-soc1-pinctrl.yaml | 760 +++++++++
drivers/pinctrl/aspeed/Kconfig | 14 +
drivers/pinctrl/aspeed/Makefile | 1 +
drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c | 1747 ++++++++++++++++++++
5 files changed, 2523 insertions(+)
---
base-commit: 812e181385abef2fe3a138438326bce844ef7cf0
change-id: 20260211-pinctrl-single-bit-da213f282c95
Best regards,
--
Billy Tsai <billy_tsai@aspeedtech.com>
^ permalink raw reply
* [PATCH v5 3/3] pinctrl: aspeed: Add AST2700 SoC1 support
From: Billy Tsai @ 2026-05-21 9:17 UTC (permalink / raw)
To: Linus Walleij, Tony Lindgren, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Joel Stanley, Andrew Jeffery, Bartosz Golaszewski,
Lee Jones, Ryan Chen
Cc: patrickw3, linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed, BMC-SW, openbmc, Andrew Jeffery, linux-clk,
Billy Tsai
In-Reply-To: <20260521-pinctrl-single-bit-v5-0-308be2c160fc@aspeedtech.com>
Implement pin multiplexing (and pin configuration where applicable)
for the AST2700 SoC1 SCU pinctrl block using static SoC data tables.
Unlike legacy ASPEED pin controllers, the SoC1 pin function control
fields are highly regular, which makes it practical to describe the
packed-field register layout directly in driver data rather than reuse
the existing Aspeed pinctrl macro infrastructure.
The driver uses the generic pinctrl, pinmux and pinconf frameworks.
The controller registers are accessed via regmap from the parent
syscon, allowing shared ownership of the SCU register block.
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
drivers/pinctrl/aspeed/Kconfig | 14 +
drivers/pinctrl/aspeed/Makefile | 1 +
drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c | 1747 +++++++++++++++++++++++
3 files changed, 1762 insertions(+)
diff --git a/drivers/pinctrl/aspeed/Kconfig b/drivers/pinctrl/aspeed/Kconfig
index f9672cca891e..8e1d4da0891d 100644
--- a/drivers/pinctrl/aspeed/Kconfig
+++ b/drivers/pinctrl/aspeed/Kconfig
@@ -40,3 +40,17 @@ config PINCTRL_ASPEED_G7_SOC0
Say Y here to enable pin controller support for the SoC0 instance
of Aspeed's 7th generation SoCs. GPIO is provided by a separate
GPIO driver.
+
+config PINCTRL_ASPEED_G7_SOC1
+ bool "Aspeed G7 SoC1 pin control"
+ depends on (ARCH_ASPEED || COMPILE_TEST) && OF
+ select MFD_SYSCON
+ select PINMUX
+ select GENERIC_PINCTRL_GROUPS
+ select GENERIC_PINMUX_FUNCTIONS
+ select GENERIC_PINCONF
+ select REGMAP_MMIO
+ help
+ Say Y here to enable pin controller support for the SoC1 instance
+ of Aspeed's 7th generation SoCs. GPIO is provided by a separate
+ GPIO driver.
diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
index 0de524ca2c72..7a41ca45c6ba 100644
--- a/drivers/pinctrl/aspeed/Makefile
+++ b/drivers/pinctrl/aspeed/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_PINCTRL_ASPEED_G4) += pinctrl-aspeed-g4.o
obj-$(CONFIG_PINCTRL_ASPEED_G5) += pinctrl-aspeed-g5.o
obj-$(CONFIG_PINCTRL_ASPEED_G6) += pinctrl-aspeed-g6.o
obj-$(CONFIG_PINCTRL_ASPEED_G7_SOC0) += pinctrl-aspeed-g7-soc0.o
+obj-$(CONFIG_PINCTRL_ASPEED_G7_SOC1) += pinctrl-aspeed-g7-soc1.o
diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c
new file mode 100644
index 000000000000..a1ef52ad5c75
--- /dev/null
+++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g7-soc1.c
@@ -0,0 +1,1747 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Pinctrl driver for Aspeed G7 SoC1
+ *
+ * Copyright (C) 2026 Aspeed Technology Inc.
+ */
+
+#include <linux/errno.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "../core.h"
+#include "../pinconf.h"
+#include "../pinctrl-utils.h"
+#include "../pinmux.h"
+
+#define ASPEED_G7_SOC1_NR_PINS 220
+#define ASPEED_G7_SOC1_REG_WIDTH 32
+#define ASPEED_G7_SOC1_REG_STRIDE 4
+
+#define ASPEED_G7_SOC1_MUX_BASE 0x400
+#define ASPEED_G7_SOC1_BIAS_BASE 0x480
+#define ASPEED_G7_SOC1_DRV_BASE 0x4C0
+#define ASPEED_G7_SOC1_PCIE_REG 0x908
+#define ASPEED_G7_SOC1_USB_MODE_REG 0x3B0
+#define ASPEED_G7_SOC1_SGMII_REG 0x47C
+
+/*
+ * Each pin occupies a 4-bit slot in the MUX registers (MUX_BITS_PER_PIN),
+ * but only bits [2:0] select the mux function; bit 3 is reserved read-only
+ * and must not be written. MUX_FUNC_MASK therefore covers 3 bits, not 4.
+ */
+#define ASPEED_G7_SOC1_MUX_FUNC_MASK 0x7
+#define ASPEED_G7_SOC1_MUX_BITS_PER_PIN 4
+#define ASPEED_G7_SOC1_MUX_PINS_PER_REG \
+ (ASPEED_G7_SOC1_REG_WIDTH / ASPEED_G7_SOC1_MUX_BITS_PER_PIN)
+
+#define ASPEED_G7_SOC1_BIAS_FUNC_MASK 0x1
+#define ASPEED_G7_SOC1_BIAS_BITS_PER_PIN 1
+#define ASPEED_G7_SOC1_BIAS_PINS_PER_REG \
+ (ASPEED_G7_SOC1_REG_WIDTH / ASPEED_G7_SOC1_BIAS_BITS_PER_PIN)
+
+#define ASPEED_G7_SOC1_DRV_FUNC_MASK 0x3
+#define ASPEED_G7_SOC1_DRV_BITS_PER_PIN 2
+#define ASPEED_G7_SOC1_DRV_PINS_PER_REG \
+ (ASPEED_G7_SOC1_REG_WIDTH / ASPEED_G7_SOC1_DRV_BITS_PER_PIN)
+
+#define ASPEED_G7_SOC1_DRV_STRENGTH_STEP_MA 4
+#define ASPEED_G7_SOC1_DRV_STRENGTH_HW_BASE 1
+#define ASPEED_G7_SOC1_DRV_STRENGTH_MIN_MA \
+ (ASPEED_G7_SOC1_DRV_STRENGTH_HW_BASE * ASPEED_G7_SOC1_DRV_STRENGTH_STEP_MA)
+#define ASPEED_G7_SOC1_DRV_STRENGTH_MAX_MA \
+ ((ASPEED_G7_SOC1_DRV_FUNC_MASK + ASPEED_G7_SOC1_DRV_STRENGTH_HW_BASE) * \
+ ASPEED_G7_SOC1_DRV_STRENGTH_STEP_MA)
+
+/*
+ * NOTE: The numeric values of these enum entries are significant.
+ * They must match the SoC GPIO numbering / ball-to-GPIO ID mapping.
+ * Do not reorder alphabetically.
+ */
+enum {
+ C16,
+ C14,
+ C11,
+ D9,
+ F14,
+ D10,
+ C12,
+ C13,
+ AC26,
+ AA25,
+ AB23,
+ U22,
+ V21,
+ N26,
+ P25,
+ N25,
+ V23,
+ W22,
+ AB26,
+ AD26,
+ P26,
+ AE26,
+ AF26,
+ AF25,
+ AE25,
+ AD25,
+ AF23,
+ AF20,
+ AF21,
+ AE21,
+ AE23,
+ AD22,
+ AF17,
+ AA16,
+ Y16,
+ V17,
+ J13,
+ AB16,
+ AC16,
+ AF16,
+ AA15,
+ AB15,
+ AC15,
+ AD15,
+ Y15,
+ AA14,
+ W16,
+ V16,
+ AB18,
+ AC18,
+ K13,
+ AA17,
+ AB17,
+ AD16,
+ AC17,
+ AD17,
+ AE16,
+ AE17,
+ AB24,
+ W26,
+ HOLE0,
+ HOLE1,
+ HOLE2,
+ HOLE3,
+ W25,
+ Y23,
+ Y24,
+ W21,
+ AA23,
+ AC22,
+ AB22,
+ Y21,
+ AE20,
+ AF19,
+ Y22,
+ AA20,
+ AA22,
+ AB20,
+ AF18,
+ AE19,
+ AD20,
+ AC20,
+ AA21,
+ AB21,
+ AC19,
+ AE18,
+ AD19,
+ AD18,
+ U25,
+ U26,
+ Y26,
+ AA24,
+ R25,
+ AA26,
+ R26,
+ Y25,
+ B16,
+ D14,
+ B15,
+ B14,
+ C17,
+ B13,
+ E14,
+ C15,
+ D24,
+ B23,
+ B22,
+ C23,
+ B18,
+ B21,
+ M15,
+ B19,
+ B26,
+ A25,
+ A24,
+ B24,
+ E26,
+ A21,
+ A19,
+ A18,
+ D26,
+ C26,
+ A23,
+ A22,
+ B25,
+ F26,
+ A26,
+ A14,
+ E10,
+ E13,
+ D12,
+ F10,
+ E11,
+ F11,
+ F13,
+ N15,
+ C20,
+ C19,
+ A8,
+ R14,
+ A7,
+ P14,
+ D20,
+ A6,
+ B6,
+ N14,
+ B7,
+ B8,
+ B9,
+ M14,
+ J11,
+ E7,
+ D19,
+ B11,
+ D15,
+ B12,
+ B10,
+ P13,
+ C18,
+ C6,
+ C7,
+ D7,
+ N13,
+ C8,
+ C9,
+ C10,
+ M16,
+ A15,
+ G11,
+ H7,
+ H8,
+ H9,
+ H10,
+ H11,
+ J9,
+ J10,
+ E9,
+ F9,
+ F8,
+ M13,
+ F7,
+ D8,
+ E8,
+ L12,
+ F12,
+ E12,
+ J12,
+ G7,
+ G8,
+ G9,
+ G10,
+ K12,
+ W17,
+ V18,
+ W18,
+ Y17,
+ AA18,
+ AA13,
+ Y18,
+ AA12,
+ W20,
+ V20,
+ Y11,
+ V14,
+ V19,
+ W14,
+ Y20,
+ AB19,
+ U21,
+ T24,
+ V24,
+ V22,
+ T23,
+ AC25,
+ AB25,
+ AC24,
+ PCIERC2_PERST,
+ PORTC_MODE,
+ PORTD_MODE,
+ SGMII0,
+};
+
+struct aspeed_g7_soc1_pinctrl {
+ struct device *dev;
+ struct regmap *regmap;
+ struct pinctrl_dev *pctl;
+};
+
+struct aspeed_g7_field {
+ unsigned int reg;
+ unsigned int shift;
+ unsigned int mask;
+};
+
+static struct aspeed_g7_field
+aspeed_g7_soc1_pinmux_field_from_pin(unsigned int pin)
+{
+ return (struct aspeed_g7_field){
+ .reg = ASPEED_G7_SOC1_MUX_BASE +
+ (pin / ASPEED_G7_SOC1_MUX_PINS_PER_REG) *
+ ASPEED_G7_SOC1_REG_STRIDE,
+ .shift = (pin % ASPEED_G7_SOC1_MUX_PINS_PER_REG) *
+ ASPEED_G7_SOC1_MUX_BITS_PER_PIN,
+ .mask = ASPEED_G7_SOC1_MUX_FUNC_MASK,
+ };
+}
+
+static struct aspeed_g7_field
+aspeed_g7_soc1_bias_field_from_pin(unsigned int pin)
+{
+ return (struct aspeed_g7_field){
+ .reg = ASPEED_G7_SOC1_BIAS_BASE +
+ (pin / ASPEED_G7_SOC1_BIAS_PINS_PER_REG) *
+ ASPEED_G7_SOC1_REG_STRIDE,
+ .shift = pin % ASPEED_G7_SOC1_BIAS_PINS_PER_REG,
+ .mask = ASPEED_G7_SOC1_BIAS_FUNC_MASK,
+ };
+}
+
+static struct aspeed_g7_field
+aspeed_g7_soc1_drv_field_from_idx(unsigned int idx)
+{
+ return (struct aspeed_g7_field){
+ .reg = ASPEED_G7_SOC1_DRV_BASE +
+ (idx / ASPEED_G7_SOC1_DRV_PINS_PER_REG) *
+ ASPEED_G7_SOC1_REG_STRIDE,
+ .shift = (idx % ASPEED_G7_SOC1_DRV_PINS_PER_REG) *
+ ASPEED_G7_SOC1_DRV_BITS_PER_PIN,
+ .mask = ASPEED_G7_SOC1_DRV_FUNC_MASK,
+ };
+}
+
+#define PIN(n) PINCTRL_PIN(n, #n)
+
+static const struct pinctrl_pin_desc aspeed_g7_soc1_pins[] = {
+ PIN(C16),
+ PIN(C14),
+ PIN(C11),
+ PIN(D9),
+ PIN(F14),
+ PIN(D10),
+ PIN(C12),
+ PIN(C13),
+ PIN(AC26),
+ PIN(AA25),
+ PIN(AB23),
+ PIN(U22),
+ PIN(V21),
+ PIN(N26),
+ PIN(P25),
+ PIN(N25),
+ PIN(V23),
+ PIN(W22),
+ PIN(AB26),
+ PIN(AD26),
+ PIN(P26),
+ PIN(AE26),
+ PIN(AF26),
+ PIN(AF25),
+ PIN(AE25),
+ PIN(AD25),
+ PIN(AF23),
+ PIN(AF20),
+ PIN(AF21),
+ PIN(AE21),
+ PIN(AE23),
+ PIN(AD22),
+ PIN(AF17),
+ PIN(AA16),
+ PIN(Y16),
+ PIN(V17),
+ PIN(J13),
+ PIN(AB16),
+ PIN(AC16),
+ PIN(AF16),
+ PIN(AA15),
+ PIN(AB15),
+ PIN(AC15),
+ PIN(AD15),
+ PIN(Y15),
+ PIN(AA14),
+ PIN(W16),
+ PIN(V16),
+ PIN(AB18),
+ PIN(AC18),
+ PIN(K13),
+ PIN(AA17),
+ PIN(AB17),
+ PIN(AD16),
+ PIN(AC17),
+ PIN(AD17),
+ PIN(AE16),
+ PIN(AE17),
+ PIN(AB24),
+ PIN(W26),
+ PIN(HOLE0),
+ PIN(HOLE1),
+ PIN(HOLE2),
+ PIN(HOLE3),
+ PIN(W25),
+ PIN(Y23),
+ PIN(Y24),
+ PIN(W21),
+ PIN(AA23),
+ PIN(AC22),
+ PIN(AB22),
+ PIN(Y21),
+ PIN(AE20),
+ PIN(AF19),
+ PIN(Y22),
+ PIN(AA20),
+ PIN(AA22),
+ PIN(AB20),
+ PIN(AF18),
+ PIN(AE19),
+ PIN(AD20),
+ PIN(AC20),
+ PIN(AA21),
+ PIN(AB21),
+ PIN(AC19),
+ PIN(AE18),
+ PIN(AD19),
+ PIN(AD18),
+ PIN(U25),
+ PIN(U26),
+ PIN(Y26),
+ PIN(AA24),
+ PIN(R25),
+ PIN(AA26),
+ PIN(R26),
+ PIN(Y25),
+ PIN(B16),
+ PIN(D14),
+ PIN(B15),
+ PIN(B14),
+ PIN(C17),
+ PIN(B13),
+ PIN(E14),
+ PIN(C15),
+ PIN(D24),
+ PIN(B23),
+ PIN(B22),
+ PIN(C23),
+ PIN(B18),
+ PIN(B21),
+ PIN(M15),
+ PIN(B19),
+ PIN(B26),
+ PIN(A25),
+ PIN(A24),
+ PIN(B24),
+ PIN(E26),
+ PIN(A21),
+ PIN(A19),
+ PIN(A18),
+ PIN(D26),
+ PIN(C26),
+ PIN(A23),
+ PIN(A22),
+ PIN(B25),
+ PIN(F26),
+ PIN(A26),
+ PIN(A14),
+ PIN(E10),
+ PIN(E13),
+ PIN(D12),
+ PIN(F10),
+ PIN(E11),
+ PIN(F11),
+ PIN(F13),
+ PIN(N15),
+ PIN(C20),
+ PIN(C19),
+ PIN(A8),
+ PIN(R14),
+ PIN(A7),
+ PIN(P14),
+ PIN(D20),
+ PIN(A6),
+ PIN(B6),
+ PIN(N14),
+ PIN(B7),
+ PIN(B8),
+ PIN(B9),
+ PIN(M14),
+ PIN(J11),
+ PIN(E7),
+ PIN(D19),
+ PIN(B11),
+ PIN(D15),
+ PIN(B12),
+ PIN(B10),
+ PIN(P13),
+ PIN(C18),
+ PIN(C6),
+ PIN(C7),
+ PIN(D7),
+ PIN(N13),
+ PIN(C8),
+ PIN(C9),
+ PIN(C10),
+ PIN(M16),
+ PIN(A15),
+ PIN(G11),
+ PIN(H7),
+ PIN(H8),
+ PIN(H9),
+ PIN(H10),
+ PIN(H11),
+ PIN(J9),
+ PIN(J10),
+ PIN(E9),
+ PIN(F9),
+ PIN(F8),
+ PIN(M13),
+ PIN(F7),
+ PIN(D8),
+ PIN(E8),
+ PIN(L12),
+ PIN(F12),
+ PIN(E12),
+ PIN(J12),
+ PIN(G7),
+ PIN(G8),
+ PIN(G9),
+ PIN(G10),
+ PIN(K12),
+ PIN(W17),
+ PIN(V18),
+ PIN(W18),
+ PIN(Y17),
+ PIN(AA18),
+ PIN(AA13),
+ PIN(Y18),
+ PIN(AA12),
+ PIN(W20),
+ PIN(V20),
+ PIN(Y11),
+ PIN(V14),
+ PIN(V19),
+ PIN(W14),
+ PIN(Y20),
+ PIN(AB19),
+ PIN(U21),
+ PIN(T24),
+ PIN(V24),
+ PIN(V22),
+ PIN(T23),
+ PIN(AC25),
+ PIN(AB25),
+ PIN(AC24),
+ PIN(PCIERC2_PERST),
+ PIN(PORTC_MODE),
+ PIN(PORTD_MODE),
+ PIN(SGMII0),
+};
+
+static const struct pinctrl_ops aspeed_g7_soc1_pctl_ops = {
+ .get_groups_count = pinctrl_generic_get_group_count,
+ .get_group_name = pinctrl_generic_get_group_name,
+ .get_group_pins = pinctrl_generic_get_group_pins,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinctrl_utils_free_map,
+};
+
+struct aspeed_g7_soc1_function {
+ struct pinfunction pinfunction;
+ const u8 *muxvals;
+};
+
+static int aspeed_g7_soc1_drive_strength_to_hw(u32 strength,
+ unsigned int *val)
+{
+ if (strength < ASPEED_G7_SOC1_DRV_STRENGTH_MIN_MA ||
+ strength > ASPEED_G7_SOC1_DRV_STRENGTH_MAX_MA ||
+ strength % ASPEED_G7_SOC1_DRV_STRENGTH_STEP_MA)
+ return -EINVAL;
+
+ *val = (strength / ASPEED_G7_SOC1_DRV_STRENGTH_STEP_MA) -
+ ASPEED_G7_SOC1_DRV_STRENGTH_HW_BASE;
+
+ return 0;
+}
+
+static int aspeed_g7_soc1_set_mux(struct pinctrl_dev *pctldev,
+ unsigned int fselector, unsigned int group)
+{
+ struct aspeed_g7_soc1_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct aspeed_g7_soc1_function *soc1_func;
+ const struct function_desc *fd;
+ const struct pinfunction *func;
+ const struct pingroup *grp;
+ struct group_desc *gd;
+ const char *gname;
+ int i, g_idx = -1, ret;
+
+ gd = pinctrl_generic_get_group(pctldev, group);
+ if (!gd)
+ return -EINVAL;
+
+ grp = &gd->grp;
+
+ fd = pinmux_generic_get_function(pctldev, fselector);
+ if (!fd)
+ return -EINVAL;
+
+ soc1_func = fd->data;
+ if (!soc1_func)
+ return -EINVAL;
+
+ func = &soc1_func->pinfunction;
+ gname = grp->name;
+
+ for (i = 0; i < func->ngroups; i++) {
+ if (!strcmp(gname, func->groups[i])) {
+ g_idx = i;
+ break;
+ }
+ }
+
+ if (g_idx < 0)
+ return -EINVAL;
+
+ for (i = 0; i < grp->npins; i++) {
+ unsigned int val = soc1_func->muxvals[g_idx];
+ unsigned int pin = grp->pins[i];
+ struct aspeed_g7_field field;
+
+ if (pin == PCIERC2_PERST) {
+ /*
+ * PCIERC2_PERST is a special case: it is managed by a
+ * dedicated control register (0x908) instead of the
+ * standard 4-bit multi-function field.
+ */
+ field.reg = ASPEED_G7_SOC1_PCIE_REG;
+ field.shift = 0;
+ field.mask = 0x1;
+ val = 1;
+ } else if (pin == PORTC_MODE || pin == PORTD_MODE) {
+ /*
+ * PORTC_MODE and PORTD_MODE are virtual "pins" that
+ * control the USB 2.0 controller mode settings.
+ * These reside in a specific control register (0x3B0)
+ * with non-standard bit widths.
+ */
+ field.reg = ASPEED_G7_SOC1_USB_MODE_REG;
+ field.mask = 0x3;
+ field.shift = pin == PORTC_MODE ? 0 : 2;
+ } else if (pin == SGMII0) {
+ /*
+ * SGMII0 is a virtual pin whose mux control resides at
+ * SCU47C bit 0, outside the contiguous pin-indexed MUX
+ * register range starting at MUX_BASE. The field is
+ * 1 bit wide; use a 1-bit mask to avoid clobbering
+ * adjacent bits in SCU47C.
+ */
+ field.reg = ASPEED_G7_SOC1_SGMII_REG;
+ field.shift = 0;
+ field.mask = 0x1;
+ } else {
+ /* Standard 4-bit-per-pin multi-function configuration */
+ field = aspeed_g7_soc1_pinmux_field_from_pin(pin);
+ }
+
+ dev_dbg(pctl->dev,
+ "Setting pin %u reg 0x%x shift %u to function %s (muxval=0x%x)\n",
+ pin, field.reg, field.shift, func->name, val);
+
+ ret = regmap_update_bits(pctl->regmap, field.reg,
+ field.mask << field.shift,
+ val << field.shift);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int aspeed_g7_soc1_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int pin)
+{
+ struct aspeed_g7_soc1_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct aspeed_g7_field field;
+ int ret = -ENOTSUPP;
+
+ if (pin <= AC24) {
+ field = aspeed_g7_soc1_pinmux_field_from_pin(pin);
+ ret = regmap_update_bits(pctl->regmap, field.reg,
+ field.mask << field.shift, 0);
+ }
+
+ return ret;
+}
+
+static const struct pinmux_ops aspeed_g7_soc1_pmx_ops = {
+ .get_functions_count = pinmux_generic_get_function_count,
+ .get_function_name = pinmux_generic_get_function_name,
+ .get_function_groups = pinmux_generic_get_function_groups,
+ .set_mux = aspeed_g7_soc1_set_mux,
+ .gpio_request_enable = aspeed_g7_soc1_gpio_request_enable,
+ .strict = true,
+};
+
+/*
+ * aspeed_g7_soc1_drv_map - Mapping table for pin drive strength control.
+ *
+ * In AST2700 SOC1, drive strength configuration is architecturally decoupled
+ * from the main pin mux registers (0x400 range). It is managed by a separate
+ * set of registers starting at 0x4C0.
+ *
+ * This table is required because:
+ * 1. The mapping between physical pin IDs and drive strength control slots
+ * is non-linear and sparse.
+ * For example, W25 maps to field index 8 (stored as 9),
+ * meaning it occupies bits [17:16] of the first 0x4C0 register.
+ * 2. Only a subset of physical pins supports drive strength configuration.
+ *
+ * The table stores (drive strength field index + 1).
+ * The field index refers to the 2-bit drive strength field position within the
+ * 0x4C0 register range. A value of 0 indicates that the pin does not support
+ * drive strength configuration (returning -ENOTSUPP).
+ * This +1 offset allows us to rely on C's default zero-initialization for
+ * unsupported pins while avoiding compiler warnings regarding overridden
+ * initializers.
+ */
+static const int aspeed_g7_soc1_drv_map[ASPEED_G7_SOC1_NR_PINS] = {
+ [C16] = 1, [C14] = 2, [C11] = 3, [D9] = 4, [F14] = 5, [D10] = 6, [C12] = 7,
+ [C13] = 8, [W25] = 9, [Y23] = 10, [Y24] = 11, [W21] = 12, [AA23] = 13, [AC22] = 14,
+ [AB22] = 15, [Y21] = 16, [AE20] = 17, [AF19] = 18, [Y22] = 19, [AA20] = 20, [AA22] = 21,
+ [AB20] = 22, [AF18] = 23, [AE19] = 24, [AD20] = 25, [AC20] = 26, [AA21] = 27, [AB21] = 28,
+ [AC19] = 29, [AE18] = 30, [AD19] = 31, [AD18] = 32, [U25] = 33, [U26] = 34, [Y26] = 35,
+ [AA24] = 36, [R25] = 37, [AA26] = 38, [R26] = 39, [Y25] = 40, [B16] = 41, [D14] = 42,
+ [B15] = 43, [B14] = 44, [C17] = 45, [B13] = 46, [E14] = 47, [C15] = 48, [D24] = 49,
+ [B23] = 50, [B22] = 51, [C23] = 52, [B18] = 53, [B21] = 54, [M15] = 55, [B19] = 56,
+ [B26] = 57, [A25] = 58, [A24] = 59, [B24] = 60, [E26] = 61, [A21] = 62, [A19] = 63,
+ [A18] = 64, [D26] = 65, [C26] = 66, [A23] = 67, [A22] = 68, [B25] = 69, [F26] = 70,
+ [A26] = 71, [A14] = 72, [E10] = 73, [E13] = 74, [D12] = 75, [F10] = 76, [E11] = 77,
+ [F11] = 78, [F13] = 79, [N15] = 80, [C20] = 81, [C19] = 82, [A8] = 83, [R14] = 84,
+ [A7] = 85, [P14] = 86, [D20] = 87, [A6] = 88, [B6] = 89, [N14] = 90, [B7] = 91,
+ [B8] = 92, [B9] = 93, [M14] = 94, [J11] = 95, [E7] = 96, [D19] = 97, [B11] = 98,
+ [D15] = 99, [B12] = 100, [B10] = 101, [P13] = 102, [C18] = 103, [C6] = 104, [C7] = 105,
+ [D7] = 106, [N13] = 107, [C8] = 108, [C9] = 109, [C10] = 110, [M16] = 111, [A15] = 112,
+ [E9] = 113, [F9] = 114, [F8] = 115, [M13] = 116, [F7] = 117, [D8] = 118, [E8] = 119,
+ [L12] = 120,
+};
+
+static int aspeed_g7_soc1_pin_config_get(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *config)
+{
+ struct aspeed_g7_soc1_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ struct aspeed_g7_field field;
+ unsigned int val, val_raw;
+ int ret, ds_idx;
+
+ if (pin > AC24)
+ return -EINVAL;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ field = aspeed_g7_soc1_bias_field_from_pin(pin);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ /*
+ * The hardware has a single 1-bit enable/disable field per
+ * pin; pull direction is fixed in silicon and cannot be read
+ * back from the register. Reject readback requests for a
+ * specific pull direction.
+ */
+ return -ENOTSUPP;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ds_idx = aspeed_g7_soc1_drv_map[pin];
+ if (!ds_idx)
+ return -ENOTSUPP;
+ ds_idx--; /* Adjust back to 0-based hardware index */
+ field = aspeed_g7_soc1_drv_field_from_idx(ds_idx);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ ret = regmap_read(pctl->regmap, field.reg, &val_raw);
+ if (ret)
+ return ret;
+
+ val = (val_raw & (field.mask << field.shift)) >> field.shift;
+ if (param == PIN_CONFIG_DRIVE_STRENGTH)
+ val = (val + ASPEED_G7_SOC1_DRV_STRENGTH_HW_BASE) *
+ ASPEED_G7_SOC1_DRV_STRENGTH_STEP_MA;
+
+ if (!val)
+ return -EINVAL;
+
+ *config = pinconf_to_config_packed(param, val);
+
+ return 0;
+}
+
+static int aspeed_g7_soc1_pin_config_set(struct pinctrl_dev *pctldev,
+ unsigned int pin,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct aspeed_g7_soc1_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct aspeed_g7_field field;
+ enum pin_config_param param;
+ int i, ret, ds_idx;
+ unsigned int val;
+ u32 arg;
+
+ if (pin > AC24)
+ return -EINVAL;
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ /*
+ * The hardware has one enable/disable bit per pin;
+ * pull direction is fixed in silicon. Both PULL_UP
+ * and PULL_DOWN map to "enable bias"; the caller must
+ * request the direction that the hardware provides.
+ */
+ case PIN_CONFIG_BIAS_DISABLE:
+ field = aspeed_g7_soc1_bias_field_from_pin(pin);
+ val = (param == PIN_CONFIG_BIAS_DISABLE) ? 1 : 0;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ds_idx = aspeed_g7_soc1_drv_map[pin];
+ if (!ds_idx)
+ return -ENOTSUPP;
+ ds_idx--; /* Adjust back to 0-based hardware index */
+ field = aspeed_g7_soc1_drv_field_from_idx(ds_idx);
+ ret = aspeed_g7_soc1_drive_strength_to_hw(arg, &val);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ dev_dbg(pctl->dev,
+ "Configuring pin %u reg 0x%x shift %u param %d arg %u val 0x%x\n",
+ pin, field.reg, field.shift, param, arg, val);
+
+ ret = regmap_update_bits(pctl->regmap, field.reg,
+ field.mask << field.shift,
+ val << field.shift);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int aspeed_g7_soc1_pin_config_group_get(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *config)
+{
+ const unsigned int *pins;
+ unsigned int npins;
+ int ret;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, selector, &pins, &npins);
+ if (ret)
+ return ret;
+ if (!npins)
+ return -ENODEV;
+
+ return aspeed_g7_soc1_pin_config_get(pctldev, pins[0], config);
+}
+
+static int aspeed_g7_soc1_pin_config_group_set(struct pinctrl_dev *pctldev,
+ unsigned int selector,
+ unsigned long *configs,
+ unsigned int num_configs)
+{
+ const unsigned int *pins;
+ unsigned int npins;
+ int ret;
+ int i;
+
+ ret = pinctrl_generic_get_group_pins(pctldev, selector, &pins, &npins);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < npins; i++) {
+ ret = aspeed_g7_soc1_pin_config_set(pctldev, pins[i], configs,
+ num_configs);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops aspeed_g7_soc1_conf_ops = {
+ .is_generic = true,
+ .pin_config_get = aspeed_g7_soc1_pin_config_get,
+ .pin_config_set = aspeed_g7_soc1_pin_config_set,
+ .pin_config_group_get = aspeed_g7_soc1_pin_config_group_get,
+ .pin_config_group_set = aspeed_g7_soc1_pin_config_group_set,
+ .pin_config_config_dbg_show = pinconf_generic_dump_config,
+};
+
+static const struct pinctrl_desc aspeed_g7_soc1_desc = {
+ .name = "aspeed-g7-soc1-pinctrl",
+ .pins = aspeed_g7_soc1_pins,
+ .npins = ARRAY_SIZE(aspeed_g7_soc1_pins),
+ .pctlops = &aspeed_g7_soc1_pctl_ops,
+ .pmxops = &aspeed_g7_soc1_pmx_ops,
+ .confops = &aspeed_g7_soc1_conf_ops,
+ .owner = THIS_MODULE,
+};
+
+ #define PIN_GROUP(name, ...) static const unsigned int name ## _pins[] = { __VA_ARGS__ }
+
+/* Pin Groups and Functions */
+PIN_GROUP(ADC0, W17);
+PIN_GROUP(ADC1, V18);
+PIN_GROUP(ADC10, Y11);
+PIN_GROUP(ADC11, V14);
+PIN_GROUP(ADC12, V19);
+PIN_GROUP(ADC13, W14);
+PIN_GROUP(ADC14, Y20);
+PIN_GROUP(ADC15, AB19);
+PIN_GROUP(ADC2, W18);
+PIN_GROUP(ADC3, Y17);
+PIN_GROUP(ADC4, AA18);
+PIN_GROUP(ADC5, AA13);
+PIN_GROUP(ADC6, Y18);
+PIN_GROUP(ADC7, AA12);
+PIN_GROUP(ADC8, W20);
+PIN_GROUP(ADC9, V20);
+PIN_GROUP(AUXPWRGOOD0, W14);
+PIN_GROUP(AUXPWRGOOD1, Y20);
+PIN_GROUP(CANBUS, G7, G8, G9);
+PIN_GROUP(DI2C0, C16, D9);
+PIN_GROUP(DI2C1, C14, F14);
+PIN_GROUP(DI2C10, R25, AA26);
+PIN_GROUP(DI2C11, R26, Y25);
+PIN_GROUP(DI2C12, W25, Y23);
+PIN_GROUP(DI2C13, Y24, W21);
+PIN_GROUP(DI2C14, AA23, AC22);
+PIN_GROUP(DI2C15, AB22, Y21);
+PIN_GROUP(DI2C2, D10, C12);
+PIN_GROUP(DI2C3, C11, C13);
+PIN_GROUP(DI2C8, U25, U26);
+PIN_GROUP(DI2C9, Y26, AA24);
+PIN_GROUP(DSGPM0, D19, B10, C7, D7);
+PIN_GROUP(ESPI0, B16, D14, B15, B14, C17, B13, E14, C15);
+PIN_GROUP(ESPI1, C16, C14, C11, D9, F14, D10, C12, C13);
+PIN_GROUP(FSI0, AD20, AC20);
+PIN_GROUP(FSI1, AA21, AB21);
+PIN_GROUP(FSI2, AC19, AE18);
+PIN_GROUP(FSI3, AD19, AD18);
+PIN_GROUP(FWQSPI, M16, A15);
+PIN_GROUP(FWSPIABR, A14);
+PIN_GROUP(FWWPN, N15);
+PIN_GROUP(HBLED, V24);
+PIN_GROUP(HVI3C0, U25, U26);
+PIN_GROUP(HVI3C1, Y26, AA24);
+PIN_GROUP(HVI3C12, W25, Y23);
+PIN_GROUP(HVI3C13, Y24, W21);
+PIN_GROUP(HVI3C14, AA23, AC22);
+PIN_GROUP(HVI3C15, AB22, Y21);
+PIN_GROUP(HVI3C2, R25, AA26);
+PIN_GROUP(HVI3C3, R26, Y25);
+PIN_GROUP(I2C0, G11, H7);
+PIN_GROUP(I2C1, H8, H9);
+PIN_GROUP(I2C10, G8, G9);
+PIN_GROUP(I2C11, G10, K12);
+PIN_GROUP(I2C12, AC18, AA17);
+PIN_GROUP(I2C13, AB17, AD16);
+PIN_GROUP(I2C14, AC17, AD17);
+PIN_GROUP(I2C15, AE16, AE17);
+PIN_GROUP(I2C2, H10, H11);
+PIN_GROUP(I2C3, J9, J10);
+PIN_GROUP(I2C4, E9, F9);
+PIN_GROUP(I2C5, F8, M13);
+PIN_GROUP(I2C6, F7, D8);
+PIN_GROUP(I2C7, E8, L12);
+PIN_GROUP(I2C8, F12, E12);
+PIN_GROUP(I2C9, J12, G7);
+PIN_GROUP(I2CF0, F12, E12, J12, G7);
+PIN_GROUP(I2CF1, E9, F9, F8, M13);
+PIN_GROUP(I2CF2, F7, D8, E8, L12);
+PIN_GROUP(I3C10, AC19, AE18);
+PIN_GROUP(I3C11, AD19, AD18);
+PIN_GROUP(I3C4, AE20, AF19);
+PIN_GROUP(I3C5, Y22, AA20);
+PIN_GROUP(I3C6, AA22, AB20);
+PIN_GROUP(I3C7, AF18, AE19);
+PIN_GROUP(I3C8, AD20, AC20);
+PIN_GROUP(I3C9, AA21, AB21);
+PIN_GROUP(JTAGM1, D12, F10, E11, F11, F13);
+PIN_GROUP(LPC0, AF26, AF25, B16, D14, B15, B14, C17, B13, E14, C15);
+PIN_GROUP(LPC1, C16, C14, C11, D9, F14, D10, C12, C13, AE16, AE17);
+PIN_GROUP(LTPI, U25, U26, Y26, AA24);
+PIN_GROUP(LTPI_PS_I2C0, G11, H7);
+PIN_GROUP(LTPI_PS_I2C1, H8, H9);
+PIN_GROUP(LTPI_PS_I2C2, H10, H11);
+PIN_GROUP(LTPI_PS_I2C3, J9, J10);
+PIN_GROUP(MACLINK0, U21);
+PIN_GROUP(MACLINK1, AC24);
+PIN_GROUP(MACLINK2, T24);
+PIN_GROUP(MDIO0, B9, M14);
+PIN_GROUP(MDIO1, C9, C10);
+PIN_GROUP(MDIO2, E10, E13);
+PIN_GROUP(NCTS0, AF17);
+PIN_GROUP(NCTS1, AA15);
+PIN_GROUP(NCTS5, V21);
+PIN_GROUP(NCTS6, AB26);
+PIN_GROUP(NDCD0, AA16);
+PIN_GROUP(NDCD1, AB15);
+PIN_GROUP(NDCD5, N26);
+PIN_GROUP(NDCD6, AD26);
+PIN_GROUP(NDSR0, Y16);
+PIN_GROUP(NDSR1, AC15);
+PIN_GROUP(NDSR5, P25);
+PIN_GROUP(NDSR6, P26);
+PIN_GROUP(NDTR0, J13);
+PIN_GROUP(NDTR1, Y15);
+PIN_GROUP(NDTR5, V23);
+PIN_GROUP(NDTR6, AF26);
+PIN_GROUP(NRI0, V17);
+PIN_GROUP(NRI1, AD15);
+PIN_GROUP(NRI5, N25);
+PIN_GROUP(NRI6, AE26);
+PIN_GROUP(NRTS0, AB16);
+PIN_GROUP(NRTS1, AA14);
+PIN_GROUP(NRTS5, W22);
+PIN_GROUP(NRTS6, AF25);
+PIN_GROUP(OSCCLK, C17);
+PIN_GROUP(PE2SGRSTN, E10, PCIERC2_PERST);
+PIN_GROUP(PWM0, AE25);
+PIN_GROUP(PWM1, AD25);
+PIN_GROUP(PWM10, AB17);
+PIN_GROUP(PWM11, AD16);
+PIN_GROUP(PWM12, AC17);
+PIN_GROUP(PWM13, AD17);
+PIN_GROUP(PWM14, AE16);
+PIN_GROUP(PWM15, AE17);
+PIN_GROUP(PWM2, AF23);
+PIN_GROUP(PWM3, AF20);
+PIN_GROUP(PWM4, AF21);
+PIN_GROUP(PWM5, AE21);
+PIN_GROUP(PWM6, AE23);
+PIN_GROUP(PWM7, AD22);
+PIN_GROUP(PWM8, K13);
+PIN_GROUP(PWM9, AA17);
+PIN_GROUP(QSPI0, C23, B18);
+PIN_GROUP(QSPI1, B24, E26);
+PIN_GROUP(QSPI2, B25, F26);
+PIN_GROUP(RGMII0, C20, C19, A8, R14, A7, P14, D20, A6, B6, N14, B7, B8);
+PIN_GROUP(RGMII1, D19, B11, D15, B12, B10, P13, C18, C6, C7, D7, N13, C8);
+PIN_GROUP(RMII0, C20, A8, R14, A7, P14, A6, B6, N14);
+PIN_GROUP(RMII0RCLKO, D20);
+PIN_GROUP(RMII1, D19, D15, B12, B10, P13, C6, C7, D7);
+PIN_GROUP(RMII1RCLKO, C18);
+PIN_GROUP(SALT0, AC17);
+PIN_GROUP(SALT1, AD17);
+PIN_GROUP(SALT10, Y18);
+PIN_GROUP(SALT11, AA12);
+PIN_GROUP(SALT12, AB26);
+PIN_GROUP(SALT13, AD26);
+PIN_GROUP(SALT14, P26);
+PIN_GROUP(SALT15, AE26);
+PIN_GROUP(SALT2, AC15);
+PIN_GROUP(SALT3, AD15);
+PIN_GROUP(SALT4, W17);
+PIN_GROUP(SALT5, V18);
+PIN_GROUP(SALT6, W18);
+PIN_GROUP(SALT7, Y17);
+PIN_GROUP(SALT8, AA18);
+PIN_GROUP(SALT9, AA13);
+PIN_GROUP(SD, C16, C14, C11, D9, F14, D10, C12, C13);
+PIN_GROUP(SGMII, SGMII0);
+PIN_GROUP(SGPM0, U21, T24, V22, T23);
+PIN_GROUP(SGPM1, AC25, AB25, AB24, W26);
+PIN_GROUP(SGPS, B11, C18, N13, C8);
+PIN_GROUP(SIOONCTRLN0, AE23);
+PIN_GROUP(SIOONCTRLN1, AA15);
+PIN_GROUP(SIOPBIN0, AD25);
+PIN_GROUP(SIOPBIN1, AA16);
+PIN_GROUP(SIOPBON0, AE25);
+PIN_GROUP(SIOPBON1, AF17);
+PIN_GROUP(SIOPWREQN0, AE21);
+PIN_GROUP(SIOPWREQN1, AB16);
+PIN_GROUP(SIOPWRGD1, AB15);
+PIN_GROUP(SIOS3N0, AF20);
+PIN_GROUP(SIOS3N1, V17);
+PIN_GROUP(SIOS5N0, AF21);
+PIN_GROUP(SIOS5N1, J13);
+PIN_GROUP(SIOSCIN0, AF23);
+PIN_GROUP(SIOSCIN1, Y16);
+PIN_GROUP(SMON0, U21, T24, V22, T23);
+PIN_GROUP(SMON1, W26, AC25, AB25);
+PIN_GROUP(SPI0, D24, B23, B22);
+PIN_GROUP(SPI0ABR, M15);
+PIN_GROUP(SPI0CS1, B21);
+PIN_GROUP(SPI0WPN, B19);
+PIN_GROUP(SPI1, B26, A25, A24);
+PIN_GROUP(SPI1ABR, A19);
+PIN_GROUP(SPI1CS1, A21);
+PIN_GROUP(SPI1WPN, A18);
+PIN_GROUP(SPI2, D26, C26, A23, A22);
+PIN_GROUP(SPI2CS1, A26);
+PIN_GROUP(TACH0, AC26);
+PIN_GROUP(TACH1, AA25);
+PIN_GROUP(TACH10, AB26);
+PIN_GROUP(TACH11, AD26);
+PIN_GROUP(TACH12, P26);
+PIN_GROUP(TACH13, AE26);
+PIN_GROUP(TACH14, AF26);
+PIN_GROUP(TACH15, AF25);
+PIN_GROUP(TACH2, AB23);
+PIN_GROUP(TACH3, U22);
+PIN_GROUP(TACH4, V21);
+PIN_GROUP(TACH5, N26);
+PIN_GROUP(TACH6, P25);
+PIN_GROUP(TACH7, N25);
+PIN_GROUP(TACH8, V23);
+PIN_GROUP(TACH9, W22);
+PIN_GROUP(THRU0, AC26, AA25);
+PIN_GROUP(THRU1, AB23, U22);
+PIN_GROUP(THRU2, A19, A18);
+PIN_GROUP(THRU3, B25, F26);
+PIN_GROUP(UART0, AC16, AF16);
+PIN_GROUP(UART1, W16, V16);
+PIN_GROUP(UART2, AB18, AC18);
+PIN_GROUP(UART3, K13, AA17);
+PIN_GROUP(UART5, AB17, AD16);
+PIN_GROUP(UART6, AC17, AD17);
+PIN_GROUP(UART7, AE16, AE17);
+PIN_GROUP(UART8, M15, B19);
+PIN_GROUP(UART9, B26, A25);
+PIN_GROUP(UART10, A24, B24);
+PIN_GROUP(UART11, E26, A21);
+PIN_GROUP(USB2CD, PORTC_MODE);
+PIN_GROUP(USB2CH, PORTC_MODE);
+PIN_GROUP(USB2CU, PORTC_MODE);
+PIN_GROUP(USB2CUD, PORTC_MODE);
+PIN_GROUP(USB2DD, PORTD_MODE);
+PIN_GROUP(USB2DH, PORTD_MODE);
+PIN_GROUP(USBUART, G10, K12);
+PIN_GROUP(VGA, J11, E7);
+PIN_GROUP(VPI, C16, C14, C11, D9, F14, D10, AC26, AA25, AB23, U22, V21, N26,
+ P25, N25, V23, W22, AB26, AD26, P26, AE26, AF26, AF25, AE25, AD25,
+ AF23, AF20, AF21, AE21);
+PIN_GROUP(WDTRST0N, K13);
+PIN_GROUP(WDTRST1N, AA17);
+PIN_GROUP(WDTRST2N, AB17);
+PIN_GROUP(WDTRST3N, AD16);
+PIN_GROUP(WDTRST4N, AC25);
+PIN_GROUP(WDTRST5N, AB25);
+PIN_GROUP(WDTRST6N, AC24);
+PIN_GROUP(WDTRST7N, AB24);
+
+#define GROUP(n) PINCTRL_PINGROUP(#n, n##_pins, ARRAY_SIZE(n##_pins))
+
+static const struct pingroup aspeed_g7_soc1_groups[] = {
+ GROUP(ADC0),
+ GROUP(ADC1),
+ GROUP(ADC10),
+ GROUP(ADC11),
+ GROUP(ADC12),
+ GROUP(ADC13),
+ GROUP(ADC14),
+ GROUP(ADC15),
+ GROUP(ADC2),
+ GROUP(ADC3),
+ GROUP(ADC4),
+ GROUP(ADC5),
+ GROUP(ADC6),
+ GROUP(ADC7),
+ GROUP(ADC8),
+ GROUP(ADC9),
+ GROUP(AUXPWRGOOD0),
+ GROUP(AUXPWRGOOD1),
+ GROUP(CANBUS),
+ GROUP(DI2C0),
+ GROUP(DI2C1),
+ GROUP(DI2C10),
+ GROUP(DI2C11),
+ GROUP(DI2C12),
+ GROUP(DI2C13),
+ GROUP(DI2C14),
+ GROUP(DI2C15),
+ GROUP(DI2C2),
+ GROUP(DI2C3),
+ GROUP(DI2C8),
+ GROUP(DI2C9),
+ GROUP(DSGPM0),
+ GROUP(ESPI0),
+ GROUP(ESPI1),
+ GROUP(FSI0),
+ GROUP(FSI1),
+ GROUP(FSI2),
+ GROUP(FSI3),
+ GROUP(FWQSPI),
+ GROUP(FWSPIABR),
+ GROUP(FWWPN),
+ GROUP(HBLED),
+ GROUP(HVI3C0),
+ GROUP(HVI3C1),
+ GROUP(HVI3C12),
+ GROUP(HVI3C13),
+ GROUP(HVI3C14),
+ GROUP(HVI3C15),
+ GROUP(HVI3C2),
+ GROUP(HVI3C3),
+ GROUP(I2C0),
+ GROUP(I2C1),
+ GROUP(I2C10),
+ GROUP(I2C11),
+ GROUP(I2C12),
+ GROUP(I2C13),
+ GROUP(I2C14),
+ GROUP(I2C15),
+ GROUP(I2C2),
+ GROUP(I2C3),
+ GROUP(I2C4),
+ GROUP(I2C5),
+ GROUP(I2C6),
+ GROUP(I2C7),
+ GROUP(I2C8),
+ GROUP(I2C9),
+ GROUP(I2CF0),
+ GROUP(I2CF1),
+ GROUP(I2CF2),
+ GROUP(I3C10),
+ GROUP(I3C11),
+ GROUP(I3C4),
+ GROUP(I3C5),
+ GROUP(I3C6),
+ GROUP(I3C7),
+ GROUP(I3C8),
+ GROUP(I3C9),
+ GROUP(JTAGM1),
+ GROUP(LPC0),
+ GROUP(LPC1),
+ GROUP(LTPI),
+ GROUP(LTPI_PS_I2C0),
+ GROUP(LTPI_PS_I2C1),
+ GROUP(LTPI_PS_I2C2),
+ GROUP(LTPI_PS_I2C3),
+ GROUP(MACLINK0),
+ GROUP(MACLINK1),
+ GROUP(MACLINK2),
+ GROUP(MDIO0),
+ GROUP(MDIO1),
+ GROUP(MDIO2),
+ GROUP(NCTS0),
+ GROUP(NCTS1),
+ GROUP(NCTS5),
+ GROUP(NCTS6),
+ GROUP(NDCD0),
+ GROUP(NDCD1),
+ GROUP(NDCD5),
+ GROUP(NDCD6),
+ GROUP(NDSR0),
+ GROUP(NDSR1),
+ GROUP(NDSR5),
+ GROUP(NDSR6),
+ GROUP(NDTR0),
+ GROUP(NDTR1),
+ GROUP(NDTR5),
+ GROUP(NDTR6),
+ GROUP(NRI0),
+ GROUP(NRI1),
+ GROUP(NRI5),
+ GROUP(NRI6),
+ GROUP(NRTS0),
+ GROUP(NRTS1),
+ GROUP(NRTS5),
+ GROUP(NRTS6),
+ GROUP(OSCCLK),
+ GROUP(PE2SGRSTN),
+ GROUP(PWM0),
+ GROUP(PWM1),
+ GROUP(PWM10),
+ GROUP(PWM11),
+ GROUP(PWM12),
+ GROUP(PWM13),
+ GROUP(PWM14),
+ GROUP(PWM15),
+ GROUP(PWM2),
+ GROUP(PWM3),
+ GROUP(PWM4),
+ GROUP(PWM5),
+ GROUP(PWM6),
+ GROUP(PWM7),
+ GROUP(PWM8),
+ GROUP(PWM9),
+ GROUP(QSPI0),
+ GROUP(QSPI1),
+ GROUP(QSPI2),
+ GROUP(RGMII0),
+ GROUP(RGMII1),
+ GROUP(RMII0),
+ GROUP(RMII0RCLKO),
+ GROUP(RMII1),
+ GROUP(RMII1RCLKO),
+ GROUP(SALT0),
+ GROUP(SALT1),
+ GROUP(SALT10),
+ GROUP(SALT11),
+ GROUP(SALT12),
+ GROUP(SALT13),
+ GROUP(SALT14),
+ GROUP(SALT15),
+ GROUP(SALT2),
+ GROUP(SALT3),
+ GROUP(SALT4),
+ GROUP(SALT5),
+ GROUP(SALT6),
+ GROUP(SALT7),
+ GROUP(SALT8),
+ GROUP(SALT9),
+ GROUP(SD),
+ GROUP(SGMII),
+ GROUP(SGPM0),
+ GROUP(SGPM1),
+ GROUP(SGPS),
+ GROUP(SIOONCTRLN0),
+ GROUP(SIOONCTRLN1),
+ GROUP(SIOPBIN0),
+ GROUP(SIOPBIN1),
+ GROUP(SIOPBON0),
+ GROUP(SIOPBON1),
+ GROUP(SIOPWREQN0),
+ GROUP(SIOPWREQN1),
+ GROUP(SIOPWRGD1),
+ GROUP(SIOS3N0),
+ GROUP(SIOS3N1),
+ GROUP(SIOS5N0),
+ GROUP(SIOS5N1),
+ GROUP(SIOSCIN0),
+ GROUP(SIOSCIN1),
+ GROUP(SMON0),
+ GROUP(SMON1),
+ GROUP(SPI0),
+ GROUP(SPI0ABR),
+ GROUP(SPI0CS1),
+ GROUP(SPI0WPN),
+ GROUP(SPI1),
+ GROUP(SPI1ABR),
+ GROUP(SPI1CS1),
+ GROUP(SPI1WPN),
+ GROUP(SPI2),
+ GROUP(SPI2CS1),
+ GROUP(TACH0),
+ GROUP(TACH1),
+ GROUP(TACH10),
+ GROUP(TACH11),
+ GROUP(TACH12),
+ GROUP(TACH13),
+ GROUP(TACH14),
+ GROUP(TACH15),
+ GROUP(TACH2),
+ GROUP(TACH3),
+ GROUP(TACH4),
+ GROUP(TACH5),
+ GROUP(TACH6),
+ GROUP(TACH7),
+ GROUP(TACH8),
+ GROUP(TACH9),
+ GROUP(THRU0),
+ GROUP(THRU1),
+ GROUP(THRU2),
+ GROUP(THRU3),
+ GROUP(UART0),
+ GROUP(UART1),
+ GROUP(UART10),
+ GROUP(UART11),
+ GROUP(UART2),
+ GROUP(UART3),
+ GROUP(UART5),
+ GROUP(UART6),
+ GROUP(UART7),
+ GROUP(UART8),
+ GROUP(UART9),
+ GROUP(USB2CD),
+ GROUP(USB2CH),
+ GROUP(USB2CU),
+ GROUP(USB2CUD),
+ GROUP(USB2DD),
+ GROUP(USB2DH),
+ GROUP(USBUART),
+ GROUP(VGA),
+ GROUP(VPI),
+ GROUP(WDTRST0N),
+ GROUP(WDTRST1N),
+ GROUP(WDTRST2N),
+ GROUP(WDTRST3N),
+ GROUP(WDTRST4N),
+ GROUP(WDTRST5N),
+ GROUP(WDTRST6N),
+ GROUP(WDTRST7N),
+};
+
+/**
+ * VM() - Helper macro to unwrap a parenthesized list of arguments.
+ * @...: The parenthesized list to be unwrapped.
+ *
+ * Since the C preprocessor treats commas inside braces {} as argument
+ * separators for macros, we wrap lists (like mux values) in parentheses ()
+ * to protect them during macro expansion. This macro strips those
+ * parentheses when the values are needed for array initialization.
+ */
+#define VM(...) __VA_ARGS__
+
+/**
+ * FUNC() - Macro to initialize an aspeed_g7_soc1_function entry.
+ * @n: Name of the pin function.
+ * @m: Parenthesized list of mux values, mapped 1:1 to the groups list.
+ * @...: Variable list of pin group names associated with this function.
+ *
+ * This macro solves complex static initialization by:
+ * 1. Creating anonymous arrays for both group names and mux values
+ * using C99 Compound Literals.
+ * 2. Using VM(m) to unwrap mux values into the array initializer.
+ * 3. Calculating the number of groups via sizeof() division, which
+ * bypasses the __must_be_array() check performed by ARRAY_SIZE()
+ * that often fails on compound literals in the kernel environment.
+ *
+ * Example: FUNC(i2c0, (1, 4), "i2c0", "di2c0")
+ * Maps "i2c0" group to mux value 1 and "di2c0" group to mux value 4.
+ */
+#define FUNC(n, m, ...) \
+ { \
+ .pinfunction = { \
+ .name = #n, \
+ .groups = (const char *const[]){ __VA_ARGS__ }, \
+ .ngroups = sizeof((const char *const[]){ __VA_ARGS__ }) / sizeof(char *), \
+ }, \
+ .muxvals = (const u8[]){ VM m } \
+ }
+
+static const struct aspeed_g7_soc1_function aspeed_g7_soc1_functions[] = {
+ FUNC(ADC0, (0), "ADC0"),
+ FUNC(ADC1, (0), "ADC1"),
+ FUNC(ADC10, (0), "ADC10"),
+ FUNC(ADC11, (0), "ADC11"),
+ FUNC(ADC12, (0), "ADC12"),
+ FUNC(ADC13, (0), "ADC13"),
+ FUNC(ADC14, (0), "ADC14"),
+ FUNC(ADC15, (0), "ADC15"),
+ FUNC(ADC2, (0), "ADC2"),
+ FUNC(ADC3, (0), "ADC3"),
+ FUNC(ADC4, (0), "ADC4"),
+ FUNC(ADC5, (0), "ADC5"),
+ FUNC(ADC6, (0), "ADC6"),
+ FUNC(ADC7, (0), "ADC7"),
+ FUNC(ADC8, (0), "ADC8"),
+ FUNC(ADC9, (0), "ADC9"),
+ FUNC(AUXPWRGOOD0, (2), "AUXPWRGOOD0"),
+ FUNC(AUXPWRGOOD1, (2), "AUXPWRGOOD1"),
+ FUNC(CANBUS, (2), "CANBUS"),
+ FUNC(ESPI0, (1), "ESPI0"),
+ FUNC(ESPI1, (1), "ESPI1"),
+ FUNC(FSI0, (2), "FSI0"),
+ FUNC(FSI1, (2), "FSI1"),
+ FUNC(FSI2, (2), "FSI2"),
+ FUNC(FSI3, (2), "FSI3"),
+ FUNC(FWQSPI, (1), "FWQSPI"),
+ FUNC(FWSPIABR, (1), "FWSPIABR"),
+ FUNC(FWWPN, (1), "FWWPN"),
+ FUNC(HBLED, (2), "HBLED"),
+ FUNC(I2C0, (1, 2, 4), "I2C0", "LTPI_PS_I2C0", "DI2C0"),
+ FUNC(I2C1, (1, 2, 4), "I2C1", "LTPI_PS_I2C1", "DI2C1"),
+ FUNC(I2C10, (1, 2), "I2C10", "DI2C10"),
+ FUNC(I2C11, (1, 2), "I2C11", "DI2C11"),
+ FUNC(I2C12, (4, 2), "I2C12", "DI2C12"),
+ FUNC(I2C13, (4, 2), "I2C13", "DI2C13"),
+ FUNC(I2C14, (4, 2), "I2C14", "DI2C14"),
+ FUNC(I2C15, (2, 2), "I2C15", "DI2C15"),
+ FUNC(I2C2, (1, 2, 4), "I2C2", "LTPI_PS_I2C2", "DI2C2"),
+ FUNC(I2C3, (1, 2, 4), "I2C3", "LTPI_PS_I2C3", "DI2C3"),
+ FUNC(I2C4, (1), "I2C4"),
+ FUNC(I2C5, (1), "I2C5"),
+ FUNC(I2C6, (1), "I2C6"),
+ FUNC(I2C7, (1), "I2C7"),
+ FUNC(I2C8, (1, 2), "I2C8", "DI2C8"),
+ FUNC(I2C9, (1, 2), "I2C9", "DI2C9"),
+ FUNC(I2CF0, (5), "I2CF0"),
+ FUNC(I2CF1, (5), "I2CF1"),
+ FUNC(I2CF2, (5), "I2CF2"),
+ FUNC(I3C0, (1), "HVI3C0"),
+ FUNC(I3C1, (1), "HVI3C1"),
+ FUNC(I3C10, (1), "I3C10"),
+ FUNC(I3C11, (1), "I3C11"),
+ FUNC(I3C12, (1), "HVI3C12"),
+ FUNC(I3C13, (1), "HVI3C13"),
+ FUNC(I3C14, (1), "HVI3C14"),
+ FUNC(I3C15, (1), "HVI3C15"),
+ FUNC(I3C2, (1), "HVI3C2"),
+ FUNC(I3C3, (1), "HVI3C3"),
+ FUNC(I3C4, (1), "I3C4"),
+ FUNC(I3C5, (1), "I3C5"),
+ FUNC(I3C6, (1), "I3C6"),
+ FUNC(I3C7, (1), "I3C7"),
+ FUNC(I3C8, (1), "I3C8"),
+ FUNC(I3C9, (1), "I3C9"),
+ FUNC(JTAGM1, (1), "JTAGM1"),
+ FUNC(LPC0, (2), "LPC0"),
+ FUNC(LPC1, (2), "LPC1"),
+ FUNC(LTPI, (2), "LTPI"),
+ FUNC(MACLINK0, (4), "MACLINK0"),
+ FUNC(MACLINK1, (3), "MACLINK1"),
+ FUNC(MACLINK2, (4), "MACLINK2"),
+ FUNC(MDIO0, (1), "MDIO0"),
+ FUNC(MDIO1, (1), "MDIO1"),
+ FUNC(MDIO2, (1), "MDIO2"),
+ FUNC(NCTS0, (1), "NCTS0"),
+ FUNC(NCTS1, (1), "NCTS1"),
+ FUNC(NCTS5, (4), "NCTS5"),
+ FUNC(NCTS6, (4), "NCTS6"),
+ FUNC(NDCD0, (1), "NDCD0"),
+ FUNC(NDCD1, (1), "NDCD1"),
+ FUNC(NDCD5, (4), "NDCD5"),
+ FUNC(NDCD6, (4), "NDCD6"),
+ FUNC(NDSR0, (1), "NDSR0"),
+ FUNC(NDSR1, (1), "NDSR1"),
+ FUNC(NDSR5, (4), "NDSR5"),
+ FUNC(NDSR6, (4), "NDSR6"),
+ FUNC(NDTR0, (1), "NDTR0"),
+ FUNC(NDTR1, (1), "NDTR1"),
+ FUNC(NDTR5, (4), "NDTR5"),
+ FUNC(NDTR6, (4), "NDTR6"),
+ FUNC(NRI0, (1), "NRI0"),
+ FUNC(NRI1, (1), "NRI1"),
+ FUNC(NRI5, (4), "NRI5"),
+ FUNC(NRI6, (4), "NRI6"),
+ FUNC(NRTS0, (1), "NRTS0"),
+ FUNC(NRTS1, (1), "NRTS1"),
+ FUNC(NRTS5, (4), "NRTS5"),
+ FUNC(NRTS6, (4), "NRTS6"),
+ FUNC(OSCCLK, (3), "OSCCLK"),
+ FUNC(PCIERC, (2), "PE2SGRSTN"),
+ FUNC(PWM0, (1), "PWM0"),
+ FUNC(PWM1, (1), "PWM1"),
+ FUNC(PWM10, (3), "PWM10"),
+ FUNC(PWM11, (3), "PWM11"),
+ FUNC(PWM12, (3), "PWM12"),
+ FUNC(PWM13, (3), "PWM13"),
+ FUNC(PWM14, (3), "PWM14"),
+ FUNC(PWM15, (3), "PWM15"),
+ FUNC(PWM2, (1), "PWM2"),
+ FUNC(PWM3, (1), "PWM3"),
+ FUNC(PWM4, (1), "PWM4"),
+ FUNC(PWM5, (1), "PWM5"),
+ FUNC(PWM6, (1), "PWM6"),
+ FUNC(PWM7, (1), "PWM7"),
+ FUNC(PWM8, (3), "PWM8"),
+ FUNC(PWM9, (3), "PWM9"),
+ FUNC(QSPI0, (1), "QSPI0"),
+ FUNC(QSPI1, (1), "QSPI1"),
+ FUNC(QSPI2, (1), "QSPI2"),
+ FUNC(RGMII0, (1), "RGMII0"),
+ FUNC(RGMII1, (1), "RGMII1"),
+ FUNC(RMII0, (2), "RMII0"),
+ FUNC(RMII0RCLKO, (2), "RMII0RCLKO"),
+ FUNC(RMII1, (2), "RMII1"),
+ FUNC(RMII1RCLKO, (2), "RMII1RCLKO"),
+ FUNC(SALT0, (2), "SALT0"),
+ FUNC(SALT1, (2), "SALT1"),
+ FUNC(SALT10, (2), "SALT10"),
+ FUNC(SALT11, (2), "SALT11"),
+ FUNC(SALT12, (2), "SALT12"),
+ FUNC(SALT13, (2), "SALT13"),
+ FUNC(SALT14, (2), "SALT14"),
+ FUNC(SALT15, (2), "SALT15"),
+ FUNC(SALT2, (2), "SALT2"),
+ FUNC(SALT3, (2), "SALT3"),
+ FUNC(SALT4, (2), "SALT4"),
+ FUNC(SALT5, (2), "SALT5"),
+ FUNC(SALT6, (2), "SALT6"),
+ FUNC(SALT7, (2), "SALT7"),
+ FUNC(SALT8, (2), "SALT8"),
+ FUNC(SALT9, (2), "SALT9"),
+ FUNC(SD, (3), "SD"),
+ FUNC(SGMII, (1), "SGMII"),
+ FUNC(SGPM0, (1, 4), "SGPM0", "DSGPM0"),
+ FUNC(SGPM1, (1), "SGPM1"),
+ FUNC(SGPS, (5), "SGPS"),
+ FUNC(SIOONCTRLN0, (2), "SIOONCTRLN0"),
+ FUNC(SIOONCTRLN1, (2), "SIOONCTRLN1"),
+ FUNC(SIOPBIN0, (2), "SIOPBIN0"),
+ FUNC(SIOPBIN1, (2), "SIOPBIN1"),
+ FUNC(SIOPBON0, (2), "SIOPBON0"),
+ FUNC(SIOPBON1, (2), "SIOPBON1"),
+ FUNC(SIOPWREQN0, (2), "SIOPWREQN0"),
+ FUNC(SIOPWREQN1, (2), "SIOPWREQN1"),
+ FUNC(SIOPWRGD1, (2), "SIOPWRGD1"),
+ FUNC(SIOS3N0, (2), "SIOS3N0"),
+ FUNC(SIOS3N1, (2), "SIOS3N1"),
+ FUNC(SIOS5N0, (2), "SIOS5N0"),
+ FUNC(SIOS5N1, (2), "SIOS5N1"),
+ FUNC(SIOSCIN0, (2), "SIOSCIN0"),
+ FUNC(SIOSCIN1, (2), "SIOSCIN1"),
+ FUNC(SMON0, (2), "SMON0"),
+ FUNC(SMON1, (4), "SMON1"),
+ FUNC(SPI0, (1), "SPI0"),
+ FUNC(SPI0ABR, (1), "SPI0ABR"),
+ FUNC(SPI0CS1, (1), "SPI0CS1"),
+ FUNC(SPI0WPN, (1), "SPI0WPN"),
+ FUNC(SPI1, (1), "SPI1"),
+ FUNC(SPI1ABR, (1), "SPI1ABR"),
+ FUNC(SPI1CS1, (1), "SPI1CS1"),
+ FUNC(SPI1WPN, (1), "SPI1WPN"),
+ FUNC(SPI2, (1), "SPI2"),
+ FUNC(SPI2CS1, (1), "SPI2CS1"),
+ FUNC(TACH0, (1), "TACH0"),
+ FUNC(TACH1, (1), "TACH1"),
+ FUNC(TACH10, (1), "TACH10"),
+ FUNC(TACH11, (1), "TACH11"),
+ FUNC(TACH12, (1), "TACH12"),
+ FUNC(TACH13, (1), "TACH13"),
+ FUNC(TACH14, (1), "TACH14"),
+ FUNC(TACH15, (1), "TACH15"),
+ FUNC(TACH2, (1), "TACH2"),
+ FUNC(TACH3, (1), "TACH3"),
+ FUNC(TACH4, (1), "TACH4"),
+ FUNC(TACH5, (1), "TACH5"),
+ FUNC(TACH6, (1), "TACH6"),
+ FUNC(TACH7, (1), "TACH7"),
+ FUNC(TACH8, (1), "TACH8"),
+ FUNC(TACH9, (1), "TACH9"),
+ FUNC(THRU0, (2), "THRU0"),
+ FUNC(THRU1, (2), "THRU1"),
+ FUNC(THRU2, (4), "THRU2"),
+ FUNC(THRU3, (4), "THRU3"),
+ FUNC(UART0, (1), "UART0"),
+ FUNC(UART1, (1), "UART1"),
+ FUNC(UART10, (3), "UART10"),
+ FUNC(UART11, (3), "UART11"),
+ FUNC(UART2, (1), "UART2"),
+ FUNC(UART3, (1), "UART3"),
+ FUNC(UART5, (4), "UART5"),
+ FUNC(UART6, (4), "UART6"),
+ FUNC(UART7, (1), "UART7"),
+ FUNC(UART8, (3), "UART8"),
+ FUNC(UART9, (3), "UART9"),
+ FUNC(USB2C, (0, 1, 2, 3), "USB2CUD", "USB2CD", "USB2CH", "USB2CU"),
+ FUNC(USB2D, (1, 2), "USB2DD", "USB2DH"),
+ FUNC(USBUART, (2), "USBUART"),
+ FUNC(VGA, (1), "VGA"),
+ FUNC(VPI, (5), "VPI"),
+ FUNC(WDTRST0N, (2), "WDTRST0N"),
+ FUNC(WDTRST1N, (2), "WDTRST1N"),
+ FUNC(WDTRST2N, (2), "WDTRST2N"),
+ FUNC(WDTRST3N, (2), "WDTRST3N"),
+ FUNC(WDTRST4N, (2), "WDTRST4N"),
+ FUNC(WDTRST5N, (2), "WDTRST5N"),
+ FUNC(WDTRST6N, (2), "WDTRST6N"),
+ FUNC(WDTRST7N, (2), "WDTRST7N"),
+};
+
+static int aspeed_g7_soc1_pinctrl_probe(struct platform_device *pdev)
+{
+ struct aspeed_g7_soc1_pinctrl *pctl;
+ struct device *dev = &pdev->dev;
+ int i, ret;
+
+ pctl = devm_kzalloc(dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+
+ pctl->dev = dev;
+ pctl->regmap = syscon_node_to_regmap(dev->parent->of_node);
+ if (IS_ERR(pctl->regmap)) {
+ dev_err(dev, "Failed to get regmap from parent\n");
+ return PTR_ERR(pctl->regmap);
+ }
+
+ ret = devm_pinctrl_register_and_init(dev, &aspeed_g7_soc1_desc, pctl,
+ &pctl->pctl);
+ if (ret) {
+ dev_err(dev, "Failed to register pinctrl\n");
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(aspeed_g7_soc1_groups); i++) {
+ const struct pingroup *grp = &aspeed_g7_soc1_groups[i];
+
+ ret = pinctrl_generic_add_group(pctl->pctl, grp->name,
+ (const unsigned int *)grp->pins,
+ grp->npins, pctl);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add group %s\n", grp->name);
+ return ret;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(aspeed_g7_soc1_functions); i++) {
+ const struct aspeed_g7_soc1_function *func = &aspeed_g7_soc1_functions[i];
+
+ ret = pinmux_generic_add_function(pctl->pctl, func->pinfunction.name,
+ func->pinfunction.groups,
+ func->pinfunction.ngroups, (void *)func);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add function %s\n", func->pinfunction.name);
+ return ret;
+ }
+ }
+
+ return pinctrl_enable(pctl->pctl);
+}
+
+static const struct of_device_id aspeed_g7_soc1_pinctrl_match[] = {
+ { .compatible = "aspeed,ast2700-soc1-pinctrl" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, aspeed_g7_soc1_pinctrl_match);
+
+static struct platform_driver aspeed_g7_soc1_pinctrl_driver = {
+ .probe = aspeed_g7_soc1_pinctrl_probe,
+ .driver = {
+ .name = "aspeed-g7-soc1-pinctrl",
+ .of_match_table = aspeed_g7_soc1_pinctrl_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+static int __init aspeed_g7_soc1_pinctrl_init(void)
+{
+ return platform_driver_register(&aspeed_g7_soc1_pinctrl_driver);
+}
+arch_initcall(aspeed_g7_soc1_pinctrl_init);
--
2.34.1
^ permalink raw reply related
* [PATCH v5 2/3] dt-bindings: pinctrl: Add aspeed,ast2700-soc1-pinctrl
From: Billy Tsai @ 2026-05-21 9:17 UTC (permalink / raw)
To: Linus Walleij, Tony Lindgren, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Joel Stanley, Andrew Jeffery, Bartosz Golaszewski,
Lee Jones, Ryan Chen
Cc: patrickw3, linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed, BMC-SW, openbmc, Andrew Jeffery, linux-clk,
Billy Tsai, Conor Dooley
In-Reply-To: <20260521-pinctrl-single-bit-v5-0-308be2c160fc@aspeedtech.com>
SoC1 in the AST2700 integrates its own pin controller responsible for
pin multiplexing and pin configuration.
The controller manages various peripheral functions such as eSPI, LPC,
VPI, SD, UART, I2C, I3C, PWM and others through SCU registers.
The binding reuses the standard pinmux and generic pin configuration
schemas and does not introduce custom Devicetree properties.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
.../pinctrl/aspeed,ast2700-soc1-pinctrl.yaml | 760 +++++++++++++++++++++
1 file changed, 760 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc1-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc1-pinctrl.yaml
new file mode 100644
index 000000000000..76944fd14e2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/aspeed,ast2700-soc1-pinctrl.yaml
@@ -0,0 +1,760 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/aspeed,ast2700-soc1-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ASPEED AST2700 SoC1 Pin Controller
+
+maintainers:
+ - Billy Tsai <billy_tsai@aspeedtech.com>
+
+description:
+ The AST2700 features a dual-SoC architecture with two interconnected SoCs,
+ each having its own System Control Unit (SCU) for independent pin control.
+ This pin controller manages the pin multiplexing for SoC1.
+
+ The SoC1 pin controller manages pin functions including eSPI, LPC and I2C,
+ among others.
+
+properties:
+ compatible:
+ const: aspeed,ast2700-soc1-pinctrl
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '-state$':
+ description: |
+ Pin control state.
+
+ If `function` is present, the node describes a pinmux state and must
+ specify `groups`.
+
+ For pin configuration, exactly one of `groups` or `pins` must be
+ specified in each state node. Group-level configuration applies to all
+ pins in the group. Pin-level configuration may be supplied in a
+ separate state node for individual pins; when both group-level and
+ pin-level configuration apply to the same pin, the pin-level
+ configuration takes precedence.
+
+ type: object
+ allOf:
+ - $ref: pinmux-node.yaml#
+ - $ref: pincfg-node.yaml#
+ - if:
+ required:
+ - function
+ then:
+ required:
+ - groups
+ - oneOf:
+ - required:
+ - groups
+ - required:
+ - pins
+ additionalProperties: false
+
+ properties:
+ function:
+ enum:
+ - ADC0
+ - ADC1
+ - ADC10
+ - ADC11
+ - ADC12
+ - ADC13
+ - ADC14
+ - ADC15
+ - ADC2
+ - ADC3
+ - ADC4
+ - ADC5
+ - ADC6
+ - ADC7
+ - ADC8
+ - ADC9
+ - AUXPWRGOOD0
+ - AUXPWRGOOD1
+ - CANBUS
+ - ESPI0
+ - ESPI1
+ - FSI0
+ - FSI1
+ - FSI2
+ - FSI3
+ - FWQSPI
+ - FWSPIABR
+ - FWWPN
+ - HBLED
+ - I2C0
+ - I2C1
+ - I2C10
+ - I2C11
+ - I2C12
+ - I2C13
+ - I2C14
+ - I2C15
+ - I2C2
+ - I2C3
+ - I2C4
+ - I2C5
+ - I2C6
+ - I2C7
+ - I2C8
+ - I2C9
+ - I2CF0
+ - I2CF1
+ - I2CF2
+ - I3C0
+ - I3C1
+ - I3C10
+ - I3C11
+ - I3C12
+ - I3C13
+ - I3C14
+ - I3C15
+ - I3C2
+ - I3C3
+ - I3C4
+ - I3C5
+ - I3C6
+ - I3C7
+ - I3C8
+ - I3C9
+ - JTAGM1
+ - LPC0
+ - LPC1
+ - LTPI
+ - MACLINK0
+ - MACLINK1
+ - MACLINK2
+ - MDIO0
+ - MDIO1
+ - MDIO2
+ - NCTS0
+ - NCTS1
+ - NCTS5
+ - NCTS6
+ - NDCD0
+ - NDCD1
+ - NDCD5
+ - NDCD6
+ - NDSR0
+ - NDSR1
+ - NDSR5
+ - NDSR6
+ - NDTR0
+ - NDTR1
+ - NDTR5
+ - NDTR6
+ - NRI0
+ - NRI1
+ - NRI5
+ - NRI6
+ - NRTS0
+ - NRTS1
+ - NRTS5
+ - NRTS6
+ - OSCCLK
+ - PCIERC
+ - PWM0
+ - PWM1
+ - PWM10
+ - PWM11
+ - PWM12
+ - PWM13
+ - PWM14
+ - PWM15
+ - PWM2
+ - PWM3
+ - PWM4
+ - PWM5
+ - PWM6
+ - PWM7
+ - PWM8
+ - PWM9
+ - QSPI0
+ - QSPI1
+ - QSPI2
+ - RGMII0
+ - RGMII1
+ - RMII0
+ - RMII0RCLKO
+ - RMII1
+ - RMII1RCLKO
+ - SALT0
+ - SALT1
+ - SALT10
+ - SALT11
+ - SALT12
+ - SALT13
+ - SALT14
+ - SALT15
+ - SALT2
+ - SALT3
+ - SALT4
+ - SALT5
+ - SALT6
+ - SALT7
+ - SALT8
+ - SALT9
+ - SD
+ - SGMII
+ - SGPM0
+ - SGPM1
+ - SGPS
+ - SIOONCTRLN0
+ - SIOONCTRLN1
+ - SIOPBIN0
+ - SIOPBIN1
+ - SIOPBON0
+ - SIOPBON1
+ - SIOPWREQN0
+ - SIOPWREQN1
+ - SIOPWRGD1
+ - SIOS3N0
+ - SIOS3N1
+ - SIOS5N0
+ - SIOS5N1
+ - SIOSCIN0
+ - SIOSCIN1
+ - SMON0
+ - SMON1
+ - SPI0
+ - SPI0ABR
+ - SPI0CS1
+ - SPI0WPN
+ - SPI1
+ - SPI1ABR
+ - SPI1CS1
+ - SPI1WPN
+ - SPI2
+ - SPI2CS1
+ - TACH0
+ - TACH1
+ - TACH10
+ - TACH11
+ - TACH12
+ - TACH13
+ - TACH14
+ - TACH15
+ - TACH2
+ - TACH3
+ - TACH4
+ - TACH5
+ - TACH6
+ - TACH7
+ - TACH8
+ - TACH9
+ - THRU0
+ - THRU1
+ - THRU2
+ - THRU3
+ - UART0
+ - UART1
+ - UART10
+ - UART11
+ - UART2
+ - UART3
+ - UART5
+ - UART6
+ - UART7
+ - UART8
+ - UART9
+ - USB2C
+ - USB2D
+ - USBUART
+ - VGA
+ - VPI
+ - WDTRST0N
+ - WDTRST1N
+ - WDTRST2N
+ - WDTRST3N
+ - WDTRST4N
+ - WDTRST5N
+ - WDTRST6N
+ - WDTRST7N
+
+ groups:
+ enum:
+ - ADC0
+ - ADC1
+ - ADC10
+ - ADC11
+ - ADC12
+ - ADC13
+ - ADC14
+ - ADC15
+ - ADC2
+ - ADC3
+ - ADC4
+ - ADC5
+ - ADC6
+ - ADC7
+ - ADC8
+ - ADC9
+ - AUXPWRGOOD0
+ - AUXPWRGOOD1
+ - CANBUS
+ - DI2C0
+ - DI2C1
+ - DI2C10
+ - DI2C11
+ - DI2C12
+ - DI2C13
+ - DI2C14
+ - DI2C15
+ - DI2C2
+ - DI2C3
+ - DI2C8
+ - DI2C9
+ - DSGPM0
+ - ESPI0
+ - ESPI1
+ - FSI0
+ - FSI1
+ - FSI2
+ - FSI3
+ - FWQSPI
+ - FWSPIABR
+ - FWWPN
+ - HBLED
+ - HVI3C0
+ - HVI3C1
+ - HVI3C12
+ - HVI3C13
+ - HVI3C14
+ - HVI3C15
+ - HVI3C2
+ - HVI3C3
+ - I2C0
+ - I2C1
+ - I2C10
+ - I2C11
+ - I2C12
+ - I2C13
+ - I2C14
+ - I2C15
+ - I2C2
+ - I2C3
+ - I2C4
+ - I2C5
+ - I2C6
+ - I2C7
+ - I2C8
+ - I2C9
+ - I2CF0
+ - I2CF1
+ - I2CF2
+ - I3C10
+ - I3C11
+ - I3C4
+ - I3C5
+ - I3C6
+ - I3C7
+ - I3C8
+ - I3C9
+ - JTAGM1
+ - LPC0
+ - LPC1
+ - LTPI
+ - LTPI_PS_I2C0
+ - LTPI_PS_I2C1
+ - LTPI_PS_I2C2
+ - LTPI_PS_I2C3
+ - MACLINK0
+ - MACLINK1
+ - MACLINK2
+ - MDIO0
+ - MDIO1
+ - MDIO2
+ - NCTS0
+ - NCTS1
+ - NCTS5
+ - NCTS6
+ - NDCD0
+ - NDCD1
+ - NDCD5
+ - NDCD6
+ - NDSR0
+ - NDSR1
+ - NDSR5
+ - NDSR6
+ - NDTR0
+ - NDTR1
+ - NDTR5
+ - NDTR6
+ - NRI0
+ - NRI1
+ - NRI5
+ - NRI6
+ - NRTS0
+ - NRTS1
+ - NRTS5
+ - NRTS6
+ - OSCCLK
+ - PE2SGRSTN
+ - PWM0
+ - PWM1
+ - PWM10
+ - PWM11
+ - PWM12
+ - PWM13
+ - PWM14
+ - PWM15
+ - PWM2
+ - PWM3
+ - PWM4
+ - PWM5
+ - PWM6
+ - PWM7
+ - PWM8
+ - PWM9
+ - QSPI0
+ - QSPI1
+ - QSPI2
+ - RGMII0
+ - RGMII1
+ - RMII0
+ - RMII0RCLKO
+ - RMII1
+ - RMII1RCLKO
+ - SALT0
+ - SALT1
+ - SALT10
+ - SALT11
+ - SALT12
+ - SALT13
+ - SALT14
+ - SALT15
+ - SALT2
+ - SALT3
+ - SALT4
+ - SALT5
+ - SALT6
+ - SALT7
+ - SALT8
+ - SALT9
+ - SD
+ - SGMII
+ - SGPM0
+ - SGPM1
+ - SGPS
+ - SIOONCTRLN0
+ - SIOONCTRLN1
+ - SIOPBIN0
+ - SIOPBIN1
+ - SIOPBON0
+ - SIOPBON1
+ - SIOPWREQN0
+ - SIOPWREQN1
+ - SIOPWRGD1
+ - SIOS3N0
+ - SIOS3N1
+ - SIOS5N0
+ - SIOS5N1
+ - SIOSCIN0
+ - SIOSCIN1
+ - SMON0
+ - SMON1
+ - SPI0
+ - SPI0ABR
+ - SPI0CS1
+ - SPI0WPN
+ - SPI1
+ - SPI1ABR
+ - SPI1CS1
+ - SPI1WPN
+ - SPI2
+ - SPI2CS1
+ - TACH0
+ - TACH1
+ - TACH10
+ - TACH11
+ - TACH12
+ - TACH13
+ - TACH14
+ - TACH15
+ - TACH2
+ - TACH3
+ - TACH4
+ - TACH5
+ - TACH6
+ - TACH7
+ - TACH8
+ - TACH9
+ - THRU0
+ - THRU1
+ - THRU2
+ - THRU3
+ - UART0
+ - UART1
+ - UART10
+ - UART11
+ - UART2
+ - UART3
+ - UART5
+ - UART6
+ - UART7
+ - UART8
+ - UART9
+ - USB2CD
+ - USB2CH
+ - USB2CU
+ - USB2CUD
+ - USB2DD
+ - USB2DH
+ - USBUART
+ - VGA
+ - VPI
+ - WDTRST0N
+ - WDTRST1N
+ - WDTRST2N
+ - WDTRST3N
+ - WDTRST4N
+ - WDTRST5N
+ - WDTRST6N
+ - WDTRST7N
+
+ pins:
+ enum:
+ - A14
+ - A15
+ - A18
+ - A19
+ - A21
+ - A22
+ - A23
+ - A24
+ - A25
+ - A26
+ - A6
+ - A7
+ - A8
+ - AA12
+ - AA13
+ - AA14
+ - AA15
+ - AA16
+ - AA17
+ - AA18
+ - AA20
+ - AA21
+ - AA22
+ - AA23
+ - AA24
+ - AA25
+ - AA26
+ - AB15
+ - AB16
+ - AB17
+ - AB18
+ - AB19
+ - AB20
+ - AB21
+ - AB22
+ - AB23
+ - AB24
+ - AB25
+ - AB26
+ - AC15
+ - AC16
+ - AC17
+ - AC18
+ - AC19
+ - AC20
+ - AC22
+ - AC24
+ - AC25
+ - AC26
+ - AD15
+ - AD16
+ - AD17
+ - AD18
+ - AD19
+ - AD20
+ - AD22
+ - AD25
+ - AD26
+ - AE16
+ - AE17
+ - AE18
+ - AE19
+ - AE20
+ - AE21
+ - AE23
+ - AE25
+ - AE26
+ - AF16
+ - AF17
+ - AF18
+ - AF19
+ - AF20
+ - AF21
+ - AF23
+ - AF25
+ - AF26
+ - B10
+ - B11
+ - B12
+ - B13
+ - B14
+ - B15
+ - B16
+ - B18
+ - B19
+ - B21
+ - B22
+ - B23
+ - B24
+ - B25
+ - B26
+ - B6
+ - B7
+ - B8
+ - B9
+ - C10
+ - C11
+ - C12
+ - C13
+ - C14
+ - C15
+ - C16
+ - C17
+ - C18
+ - C19
+ - C20
+ - C23
+ - C26
+ - C6
+ - C7
+ - C8
+ - C9
+ - D10
+ - D12
+ - D14
+ - D15
+ - D19
+ - D20
+ - D24
+ - D26
+ - D7
+ - D8
+ - D9
+ - E10
+ - E11
+ - E12
+ - E13
+ - E14
+ - E26
+ - E7
+ - E8
+ - E9
+ - F10
+ - F11
+ - F12
+ - F13
+ - F14
+ - F26
+ - F7
+ - F8
+ - F9
+ - G10
+ - G11
+ - G7
+ - G8
+ - G9
+ - H10
+ - H11
+ - H7
+ - H8
+ - H9
+ - J10
+ - J11
+ - J12
+ - J13
+ - J9
+ - K12
+ - K13
+ - L12
+ - M13
+ - M14
+ - M15
+ - M16
+ - N13
+ - N14
+ - N15
+ - N25
+ - N26
+ - P13
+ - P14
+ - P25
+ - P26
+ - R14
+ - R25
+ - R26
+ - T23
+ - T24
+ - U21
+ - U22
+ - U25
+ - U26
+ - V14
+ - V16
+ - V17
+ - V18
+ - V19
+ - V20
+ - V21
+ - V22
+ - V23
+ - V24
+ - W14
+ - W16
+ - W17
+ - W18
+ - W20
+ - W21
+ - W22
+ - W25
+ - W26
+ - Y11
+ - Y15
+ - Y16
+ - Y17
+ - Y18
+ - Y20
+ - Y21
+ - Y22
+ - Y23
+ - Y24
+ - Y25
+ - Y26
+
+ drive-strength:
+ enum: [4, 8, 12, 16]
+
+ bias-disable: true
+ bias-pull-up: true
+ bias-pull-down: true
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: pinctrl.yaml#
+
+additionalProperties: false
+
+examples:
+ - |
+ pinctrl@400 {
+ compatible = "aspeed,ast2700-soc1-pinctrl";
+ reg = <0x400 0x2A0>;
+ sgpm0-state {
+ function = "SGPM0";
+ groups = "SGPM0";
+ };
+ };
--
2.34.1
^ permalink raw reply related
* [PATCH v5 1/3] dt-bindings: mfd: aspeed,ast2x00-scu: Support AST2700 SoC1 pinctrl
From: Billy Tsai @ 2026-05-21 9:17 UTC (permalink / raw)
To: Linus Walleij, Tony Lindgren, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Joel Stanley, Andrew Jeffery, Bartosz Golaszewski,
Lee Jones, Ryan Chen
Cc: patrickw3, linux-gpio, devicetree, linux-kernel, linux-arm-kernel,
linux-aspeed, BMC-SW, openbmc, Andrew Jeffery, linux-clk,
Billy Tsai, Conor Dooley
In-Reply-To: <20260521-pinctrl-single-bit-v5-0-308be2c160fc@aspeedtech.com>
The AST2700 SoC integrates two interconnected SoC instances, each
managed by its own System Control Unit (SCU).
Allow the AST2700 SoC1 pin controller to be described as a child
node of the SCU by extending the compatible strings accepted by
the SCU binding.
There is no functional change to the SCU binding beyond permitting
the aspeed,ast2700-soc1-pinctrl compatible string.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
---
Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
index 0d5e168b0309..948ba92ef49b 100644
--- a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
+++ b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
@@ -100,6 +100,7 @@ patternProperties:
- aspeed,ast2500-pinctrl
- aspeed,ast2600-pinctrl
- aspeed,ast2700-soc0-pinctrl
+ - aspeed,ast2700-soc1-pinctrl
required:
- compatible
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 3/4] mfd: max77620: override PSCI poweroff handler on Pixel C
From: Diogo Ivo @ 2026-05-21 9:23 UTC (permalink / raw)
To: Thierry Reding
Cc: Mark Rutland, Lorenzo Pieralisi, Lee Jones, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Thierry Reding,
Jonathan Hunter, linux-arm-kernel, linux-kernel, devicetree,
linux-tegra
In-Reply-To: <ag65LXrLLbbeTbTb@orome>
On 5/21/26 09:52, Thierry Reding wrote:
> On Thu, May 14, 2026 at 04:47:21PM +0200, Diogo Ivo wrote:
>> On Pixel C, shutdown must be handled by the MAX77620 PMIC rather
>> than the PSCI SYSTEM_OFF call, whose firmware implementation is:
>>
>> __dead2 void tegra_system_off(void)
>> {
>> ERROR("Tegra System Off: operation not handled.\n");
>> panic();
>> }
>
> Ugh... sounds very familiar. We have similar stub implementations on
> Jetson TX1 and/or Nano, if I remember correctly. Luckily newer platforms
> seem to have proper implementations for these.
Yes, on my TX1 I was encountering the same problem. However in that case
is it possible to update the firmware with a proper implementation?
> Thanks for doing this. I might want to take inspiration from this for
> these older Jetson platforms.
My pleasure!
Diogo
> Thierry
^ permalink raw reply
* Re: [PATCH 14/16] media: sun6i-isp: Use V4L2 subdev active state
From: arash golgol @ 2026-05-21 9:23 UTC (permalink / raw)
To: Paul Kocialkowski
Cc: linux-media, linux-arm-kernel, linux-sunxi, linux-kernel,
linux-staging, Mauro Carvalho Chehab, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, Greg Kroah-Hartman,
Laurent Pinchart, Nicolas Dufresne
In-Reply-To: <20260518102451.417971-15-paulk@sys-base.io>
Hi Paul,
On Mon, May 18, 2026 at 2:02 PM Paul Kocialkowski <paulk@sys-base.io> wrote:
>
> Store the active format using the common V4L2 subdev active state
> instead of our local copy of it.
>
> Signed-off-by: Paul Kocialkowski <paulk@sys-base.io>
> ---
> .../media/sunxi/sun6i-isp/sun6i_isp_capture.c | 16 ++-
> .../media/sunxi/sun6i-isp/sun6i_isp_params.c | 18 ++-
> .../media/sunxi/sun6i-isp/sun6i_isp_params.h | 4 +-
> .../media/sunxi/sun6i-isp/sun6i_isp_proc.c | 117 ++++++++----------
> .../media/sunxi/sun6i-isp/sun6i_isp_proc.h | 7 --
> 5 files changed, 82 insertions(+), 80 deletions(-)
>
> diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
> index e7b99cee63d6..24e731bcabe9 100644
> --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
> +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c
> @@ -595,11 +595,25 @@ static int sun6i_isp_capture_link_validate(struct media_link *link)
> media_entity_to_video_device(link->sink->entity);
> struct sun6i_isp_device *isp_dev = video_get_drvdata(video_dev);
> struct v4l2_device *v4l2_dev = &isp_dev->v4l2.v4l2_dev;
> + struct v4l2_subdev *proc_subdev =
> + media_entity_to_v4l2_subdev(link->source->entity);
> unsigned int capture_width, capture_height;
> unsigned int proc_width, proc_height;
> + struct v4l2_subdev_format proc_subdev_format = {
> + .which = V4L2_SUBDEV_FORMAT_ACTIVE,
> + .pad = link->source->index,
> + };
> + int ret;
>
> sun6i_isp_capture_dimensions(isp_dev, &capture_width, &capture_height);
> - sun6i_isp_proc_dimensions(isp_dev, &proc_width, &proc_height);
> +
> + ret = v4l2_subdev_call(proc_subdev, pad, get_fmt, NULL,
> + &proc_subdev_format);
> + if (ret)
> + return ret;
> +
> + proc_width = proc_subdev_format.format.width;
> + proc_height = proc_subdev_format.format.height;
>
> /* No cropping/scaling is supported (yet). */
> if (capture_width != proc_width || capture_height != proc_height) {
> diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
> index b7ef33fa2b13..0cc48e2bc8c6 100644
> --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
> +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c
> @@ -43,11 +43,14 @@ static const struct sun6i_isp_params_config sun6i_isp_params_config_default = {
> },
> };
>
> -static void sun6i_isp_params_configure_ob(struct sun6i_isp_device *isp_dev)
> +static void
> +sun6i_isp_params_configure_ob(struct sun6i_isp_device *isp_dev,
> + const struct v4l2_mbus_framefmt *mbus_format)
> {
> unsigned int width, height;
>
> - sun6i_isp_proc_dimensions(isp_dev, &width, &height);
> + width = mbus_format->width;
> + height = mbus_format->height;
>
> sun6i_isp_load_write(isp_dev, SUN6I_ISP_OB_SIZE_REG,
> SUN6I_ISP_OB_SIZE_WIDTH(width) |
> @@ -112,10 +115,12 @@ static void sun6i_isp_params_configure_wb(struct sun6i_isp_device *isp_dev)
> SUN6I_ISP_WB_CFG_CLIP(0xfff));
> }
>
> -static void sun6i_isp_params_configure_base(struct sun6i_isp_device *isp_dev)
> +static void
> +sun6i_isp_params_configure_base(struct sun6i_isp_device *isp_dev,
> + const struct v4l2_mbus_framefmt *mbus_format)
> {
> sun6i_isp_params_configure_ae(isp_dev);
> - sun6i_isp_params_configure_ob(isp_dev);
> + sun6i_isp_params_configure_ob(isp_dev, mbus_format);
> sun6i_isp_params_configure_wb(isp_dev);
> }
>
> @@ -170,14 +175,15 @@ sun6i_isp_params_configure_modules(struct sun6i_isp_device *isp_dev,
> sun6i_isp_load_write(isp_dev, SUN6I_ISP_MODULE_EN_REG, value);
> }
>
> -void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev)
> +void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev,
> + const struct v4l2_mbus_framefmt *mbus_format)
> {
> struct sun6i_isp_params_state *state = &isp_dev->params.state;
> unsigned long flags;
>
> spin_lock_irqsave(&state->lock, flags);
>
> - sun6i_isp_params_configure_base(isp_dev);
> + sun6i_isp_params_configure_base(isp_dev, mbus_format);
>
> /* Default config is only applied at the very first stream start. */
> if (state->configured)
> diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h
> index 50f10f879c42..c0d6cff95d54 100644
> --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h
> +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h
> @@ -36,8 +36,8 @@ struct sun6i_isp_params {
>
> /* Params */
>
> -void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev);
> -
> +void sun6i_isp_params_configure(struct sun6i_isp_device *isp_dev,
> + const struct v4l2_mbus_framefmt *mbus_format);
> /* State */
>
> void sun6i_isp_params_state_update(struct sun6i_isp_device *isp_dev,
> diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
> index 46a334b602f1..9073a7f3f8c8 100644
> --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
> +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c
> @@ -15,17 +15,6 @@
> #include "sun6i_isp_proc.h"
> #include "sun6i_isp_reg.h"
>
> -/* Helpers */
> -
> -void sun6i_isp_proc_dimensions(struct sun6i_isp_device *isp_dev,
> - unsigned int *width, unsigned int *height)
> -{
> - if (width)
> - *width = isp_dev->proc.mbus_format.width;
> - if (height)
> - *height = isp_dev->proc.mbus_format.height;
> -}
> -
> /* Format */
>
> static const struct sun6i_isp_proc_format sun6i_isp_proc_formats[] = {
> @@ -137,9 +126,10 @@ static void sun6i_isp_proc_disable(struct sun6i_isp_device *isp_dev)
> regmap_write(regmap, SUN6I_ISP_FE_CFG_REG, 0);
> }
>
> -static void sun6i_isp_proc_configure(struct sun6i_isp_device *isp_dev)
> +static void
> +sun6i_isp_proc_configure(struct sun6i_isp_device *isp_dev,
> + const struct v4l2_mbus_framefmt *mbus_format)
> {
> - struct v4l2_mbus_framefmt *mbus_format = &isp_dev->proc.mbus_format;
> const struct sun6i_isp_proc_format *format;
> u32 value;
>
> @@ -173,6 +163,8 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
> struct sun6i_isp_proc_source *source;
> struct v4l2_subdev *source_subdev;
> struct media_pad *remote_pad;
> + struct v4l2_subdev_state *state;
> + const struct v4l2_mbus_framefmt *mbus_format;
> int ret;
>
> /* Source */
> @@ -191,6 +183,10 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
> else
> source = &proc->source_csi1;
>
> + /* Active State */
> +
> + state = v4l2_subdev_lock_and_get_active_state(subdev);
> +
> if (!on) {
> sun6i_isp_proc_irq_disable(isp_dev);
> v4l2_subdev_call(source_subdev, video, s_stream, 0);
> @@ -202,7 +198,7 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
>
> ret = pm_runtime_resume_and_get(dev);
> if (ret < 0)
> - return ret;
> + goto unlock;
>
> /* Clear */
>
> @@ -210,9 +206,12 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
>
> /* Configure */
>
> + mbus_format = v4l2_subdev_state_get_format(state,
> + SUN6I_ISP_PROC_PAD_SINK_CSI);
> +
> sun6i_isp_tables_configure(isp_dev);
> - sun6i_isp_params_configure(isp_dev);
> - sun6i_isp_proc_configure(isp_dev);
> + sun6i_isp_params_configure(isp_dev, mbus_format);
> + sun6i_isp_proc_configure(isp_dev, mbus_format);
> sun6i_isp_capture_configure(isp_dev);
>
> /* State Update */
> @@ -230,13 +229,17 @@ static int sun6i_isp_proc_s_stream(struct v4l2_subdev *subdev, int on)
> goto disable;
> }
>
> - return 0;
> + ret = 0;
> + goto unlock;
>
> disable:
> sun6i_isp_proc_disable(isp_dev);
>
> pm_runtime_put(dev);
>
> +unlock:
> + v4l2_subdev_unlock_state(state);
> +
> return ret;
> }
>
> @@ -259,21 +262,22 @@ sun6i_isp_proc_mbus_format_prepare(struct v4l2_mbus_framefmt *mbus_format)
> static int sun6i_isp_proc_init_state(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *state)
> {
> - struct sun6i_isp_device *isp_dev = v4l2_get_subdevdata(subdev);
> - unsigned int pad = SUN6I_ISP_PROC_PAD_SINK_CSI;
> - struct v4l2_mbus_framefmt *mbus_format =
> - v4l2_subdev_state_get_format(state, pad);
> - struct mutex *lock = &isp_dev->proc.lock;
> + unsigned int pad;
>
> - mutex_lock(lock);
> + for (pad = 0; pad < subdev->entity.num_pads; pad++) {
> + struct v4l2_mbus_framefmt *mbus_format;
>
> - mbus_format->code = sun6i_isp_proc_formats[0].mbus_code;
> - mbus_format->width = 1280;
> - mbus_format->height = 720;
> + if (pad == SUN6I_ISP_PROC_PAD_SINK_PARAMS)
> + continue;
>
> - sun6i_isp_proc_mbus_format_prepare(mbus_format);
> + mbus_format = v4l2_subdev_state_get_format(state, pad);
>
> - mutex_unlock(lock);
> + mbus_format->code = sun6i_isp_proc_formats[0].mbus_code;
> + mbus_format->width = 1280;
> + mbus_format->height = 720;
> +
> + sun6i_isp_proc_mbus_format_prepare(mbus_format);
> + }
>
> return 0;
> }
> @@ -291,53 +295,31 @@ sun6i_isp_proc_enum_mbus_code(struct v4l2_subdev *subdev,
> return 0;
> }
>
> -static int sun6i_isp_proc_get_fmt(struct v4l2_subdev *subdev,
> - struct v4l2_subdev_state *state,
> - struct v4l2_subdev_format *format)
> -{
> - struct sun6i_isp_device *isp_dev = v4l2_get_subdevdata(subdev);
> - struct v4l2_mbus_framefmt *mbus_format = &format->format;
> - struct mutex *lock = &isp_dev->proc.lock;
> -
> - mutex_lock(lock);
> -
> - if (format->which == V4L2_SUBDEV_FORMAT_TRY)
> - *mbus_format = *v4l2_subdev_state_get_format(state,
> - format->pad);
> - else
> - *mbus_format = isp_dev->proc.mbus_format;
> -
> - mutex_unlock(lock);
> -
> - return 0;
> -}
> -
> static int sun6i_isp_proc_set_fmt(struct v4l2_subdev *subdev,
> struct v4l2_subdev_state *state,
> struct v4l2_subdev_format *format)
> {
> - struct sun6i_isp_device *isp_dev = v4l2_get_subdevdata(subdev);
> - struct v4l2_mbus_framefmt *mbus_format = &format->format;
> - struct mutex *lock = &isp_dev->proc.lock;
> + struct v4l2_mbus_framefmt *mbus_format;
>
> - mutex_lock(lock);
> + if (format->pad != SUN6I_ISP_PROC_PAD_SINK_CSI)
> + return v4l2_subdev_get_fmt(subdev, state, format);
>
> - sun6i_isp_proc_mbus_format_prepare(mbus_format);
> + sun6i_isp_proc_mbus_format_prepare(&format->format);
>
> - if (format->which == V4L2_SUBDEV_FORMAT_TRY)
> - *v4l2_subdev_state_get_format(state, format->pad) =
> - *mbus_format;
> - else
> - isp_dev->proc.mbus_format = *mbus_format;
> + mbus_format = v4l2_subdev_state_get_format(state, format->pad);
> + *mbus_format = format->format;
>
> - mutex_unlock(lock);
> + /* Propagate the format to the source pad. */
> + mbus_format = v4l2_subdev_state_get_format(state,
> + SUN6I_ISP_PROC_PAD_SOURCE);
> + *mbus_format = format->format;
>
> return 0;
> }
>
> static const struct v4l2_subdev_pad_ops sun6i_isp_proc_pad_ops = {
> .enum_mbus_code = sun6i_isp_proc_enum_mbus_code,
> - .get_fmt = sun6i_isp_proc_get_fmt,
> + .get_fmt = v4l2_subdev_get_fmt,
> .set_fmt = sun6i_isp_proc_set_fmt,
> };
>
> @@ -499,8 +481,6 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
> struct media_pad *pads = proc->pads;
> int ret;
>
> - mutex_init(&proc->lock);
> -
> /* V4L2 Subdev */
>
> v4l2_subdev_init(subdev, &sun6i_isp_proc_subdev_ops);
> @@ -532,10 +512,14 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
>
> /* V4L2 Subdev */
>
> + ret = v4l2_subdev_init_finalize(subdev);
> + if (ret < 0)
> + goto error_media_entity;
> +
> ret = v4l2_device_register_subdev(v4l2_dev, subdev);
> if (ret < 0) {
> v4l2_err(v4l2_dev, "failed to register v4l2 subdev: %d\n", ret);
> - goto error_media_entity;
> + goto error_subdev_finalize;
> }
>
> /* V4L2 Async */
> @@ -562,6 +546,9 @@ int sun6i_isp_proc_setup(struct sun6i_isp_device *isp_dev)
>
> v4l2_device_unregister_subdev(subdev);
>
> +error_subdev_finalize:
> + v4l2_subdev_cleanup(subdev);
> +
> error_media_entity:
> media_entity_cleanup(&subdev->entity);
>
> @@ -577,5 +564,7 @@ void sun6i_isp_proc_cleanup(struct sun6i_isp_device *isp_dev)
> v4l2_async_nf_cleanup(notifier);
>
> v4l2_device_unregister_subdev(subdev);
> + v4l2_subdev_cleanup(subdev);
> +
> media_entity_cleanup(&subdev->entity);
> }
> diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
> index db6738a39147..26c4327c5ed7 100644
> --- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
> +++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h
> @@ -42,18 +42,11 @@ struct sun6i_isp_proc {
> struct v4l2_subdev subdev;
> struct media_pad pads[3];
> struct v4l2_async_notifier notifier;
> - struct v4l2_mbus_framefmt mbus_format;
> - struct mutex lock; /* Mbus format lock. */
>
> struct sun6i_isp_proc_source source_csi0;
> struct sun6i_isp_proc_source source_csi1;
> };
>
> -/* Helpers */
> -
> -void sun6i_isp_proc_dimensions(struct sun6i_isp_device *isp_dev,
> - unsigned int *width, unsigned int *height);
> -
> /* Format */
>
> const struct sun6i_isp_proc_format *sun6i_isp_proc_format_find(u32 mbus_code);
> --
> 2.54.0
>
I used LicheePi Zero Dock (V3s) with the following pipeline as test setup.
ov5647 -> sun6i-mipi-csi2 -> sun6i-csi-bridge -> sun6i-isp-proc ->
sun6i-isp-capture
I verified TRY and ACTIVE state handling, including changing TRY
formats without affecting ACTIVE state. Format propagation from the
sink (csi) pad to the source pad was also tested.
I also tested streaming with the sensor test pattern enabled and
verified the captured output was correct.
Tested-by: Arash Golgol <arash.golgol@gmail.com>
--
Regards
Arash Golgol
^ permalink raw reply
* RE: [PATCH v4 4/6] media: synopsys: Add PHY stopstate wait for i.MX93
From: G.N. Zhou (OSS) @ 2026-05-21 9:29 UTC (permalink / raw)
To: Alexander Stein, Michael Riesch, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Laurent Pinchart, Frank Li, Sakari Ailus, Bryan O'Donoghue,
Mehdi Djait, Hans Verkuil, G.N. Zhou (OSS)
Cc: linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-rockchip@lists.infradead.org, G.N. Zhou (OSS)
In-Reply-To: <10853728.nUPlyArG6x@steina-w>
Hi Alexander,
> -----Original Message-----
> From: Alexander Stein <alexander.stein@ew.tq-group.com>
> Sent: Wednesday, May 20, 2026 7:12 PM
> To: Michael Riesch <michael.riesch@collabora.com>; Mauro Carvalho Chehab
> <mchehab@kernel.org>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski
> <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Heiko Stuebner
> <heiko@sntech.de>; Laurent Pinchart <laurent.pinchart@ideasonboard.com>;
> Frank Li <frank.li@nxp.com>; Sakari Ailus <sakari.ailus@linux.intel.com>; Bryan
> O'Donoghue <bryan.odonoghue@linaro.org>; Mehdi Djait
> <mehdi.djait@linux.intel.com>; Hans Verkuil <hverkuil+cisco@kernel.org>;
> G.N. Zhou (OSS) <guoniu.zhou@oss.nxp.com>
> Cc: linux-media@vger.kernel.org; linux-kernel@vger.kernel.org;
> devicetree@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> kernel@lists.infradead.org; linux-rockchip@lists.infradead.org; G.N. Zhou (OSS)
> <guoniu.zhou@oss.nxp.com>
> Subject: Re: [PATCH v4 4/6] media: synopsys: Add PHY stopstate wait for
> i.MX93
>
> Hi,
>
> Am Dienstag, 19. Mai 2026, 04:07:41 CEST schrieb Guoniu Zhou:
> > Implement waiting for D-PHY lanes to enter stop state on i.MX93. This
> > ensures proper PHY initialization by verifying that the clock lane and
> > all active data lanes have entered the stop state before proceeding
> > with further operations.
> >
> > Reviewed-by: Frank Li <Frank.Li@nxp.com>
> > Signed-off-by: Guoniu Zhou <guoniu.zhou@oss.nxp.com>
> > ---
> > Changes in v2:
> > - Removes redundant register availability check
> > - Uses read_poll_timeout() with dw_mipi_csi2rx_read() instead of
> > readl_poll_timeout() with direct register address
> > - Fixes stopstate condition logic
> > - Check PHY stopstate after sensor enable instead of before to ensure
> > correct timing.
> > - Optimize PHY stopstate polling parameters (1000us->10us, 2s->1ms) to
> > balance performance and responsiveness.
> > ---
> > drivers/media/platform/synopsys/dw-mipi-csi2rx.c | 36
> > ++++++++++++++++++++++++
> > 1 file changed, 36 insertions(+)
> >
> > diff --git a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > index 92178a3dec5d..8a34aec550ad 100644
> > --- a/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > +++ b/drivers/media/platform/synopsys/dw-mipi-csi2rx.c
> > @@ -11,6 +11,7 @@
> > #include <linux/clk.h>
> > #include <linux/delay.h>
> > #include <linux/io.h>
> > +#include <linux/iopoll.h>
> > #include <linux/module.h>
> > #include <linux/of.h>
> > #include <linux/phy/phy.h>
> > @@ -35,6 +36,8 @@
> > #define DW_REG_EXIST BIT(31)
> > #define DW_REG(x) (DW_REG_EXIST | (x))
> >
> > +#define DPHY_STOPSTATE_CLK_LANE BIT(16)
> > +
> > #define DPHY_TEST_CTRL0_TEST_CLR BIT(0)
> >
> > #define IPI_VCID_VC(x) FIELD_PREP(GENMASK(1, 0),
> (x))
> > @@ -65,6 +68,7 @@ enum dw_mipi_csi2rx_regs_index {
> > DW_MIPI_CSI2RX_PHY_TST_CTRL0,
> > DW_MIPI_CSI2RX_PHY_TST_CTRL1,
> > DW_MIPI_CSI2RX_PHY_SHUTDOWNZ,
> > + DW_MIPI_CSI2RX_PHY_STOPSTATE,
> > DW_MIPI_CSI2RX_IPI_DATATYPE,
> > DW_MIPI_CSI2RX_IPI_MEM_FLUSH,
> > DW_MIPI_CSI2RX_IPI_MODE,
> > @@ -87,6 +91,7 @@ struct dw_mipi_csi2rx_drvdata {
> > void (*dphy_assert_reset)(struct dw_mipi_csi2rx_device *csi2);
> > void (*dphy_deassert_reset)(struct dw_mipi_csi2rx_device *csi2);
> > void (*ipi_enable)(struct dw_mipi_csi2rx_device *csi2);
> > + int (*wait_for_phy_stopstate)(struct dw_mipi_csi2rx_device *csi2);
> > };
> >
> > struct dw_mipi_csi2rx_format {
> > @@ -139,6 +144,7 @@ static const u32 imx93_regs[DW_MIPI_CSI2RX_MAX]
> = {
> > [DW_MIPI_CSI2RX_PHY_SHUTDOWNZ] = DW_REG(0x40),
> > [DW_MIPI_CSI2RX_DPHY_RSTZ] = DW_REG(0x44),
> > [DW_MIPI_CSI2RX_PHY_STATE] = DW_REG(0x48),
> > + [DW_MIPI_CSI2RX_PHY_STOPSTATE] = DW_REG(0x4c),
> > [DW_MIPI_CSI2RX_PHY_TST_CTRL0] = DW_REG(0x50),
> > [DW_MIPI_CSI2RX_PHY_TST_CTRL1] = DW_REG(0x54),
> > [DW_MIPI_CSI2RX_IPI_MODE] = DW_REG(0x80), @@ -556,10 +562,19
> @@
> > static int dw_mipi_csi2rx_enable_streams(struct v4l2_subdev *sd,
> > if (ret)
> > goto err_csi_stop;
> >
> > + if (!csi2->enabled_streams &&
> > + csi2->drvdata->wait_for_phy_stopstate) {
> > + ret = csi2->drvdata->wait_for_phy_stopstate(csi2);
> > + if (ret)
> > + goto err_disable_streams;
> > + }
> > +
> > csi2->enabled_streams |= streams_mask;
> >
> > return 0;
> >
> > +err_disable_streams:
> > + v4l2_subdev_disable_streams(remote_sd, remote_pad->index, mask);
> > err_csi_stop:
> > /* Stop CSI hardware if no streams are enabled */
> > if (!csi2->enabled_streams)
> > @@ -871,11 +886,32 @@ static void imx93_csi2rx_dphy_ipi_enable(struct
> dw_mipi_csi2rx_device *csi2)
> > dw_mipi_csi2rx_write(csi2, DW_MIPI_CSI2RX_IPI_MODE, val); }
> >
> > +static int imx93_csi2rx_wait_for_phy_stopstate(struct
> > +dw_mipi_csi2rx_device *csi2) {
> > + struct device *dev = csi2->dev;
> > + u32 stopstate_mask;
> > + u32 val;
> > + int ret;
> > +
> > + stopstate_mask = DPHY_STOPSTATE_CLK_LANE | GENMASK(csi2-
> >lanes_num -
> > +1, 0);
> > +
> > + ret = read_poll_timeout(dw_mipi_csi2rx_read, val,
> > + (val & stopstate_mask) == stopstate_mask,
> > + 10, 1000, true,
> > + csi2, DW_MIPI_CSI2RX_PHY_STOPSTATE);
> > + if (ret)
> > + dev_err(dev, "lanes are not in stop state: %#x,
> expected %#x\n",
> > + val, stopstate_mask);
>
> Did you actually test this on imx93? I'm trying to get my imx327 sensor to run,
> but only run into this error message:
> dw-mipi-csi2rx 4ae00000.mipi-csi: lanes are not in stop state: 0x0, expected
> 0x10003
Thanks for testing. Regarding the lane stop state error on i.MX93 with imx327:
This error indicates the CSI-2 lanes are not in LP-11 (stop) state when
expected. Please check:
1) Verify the sensor PHY is in LP-11 state before returning from the sensor's
s_stream(1) call. The CSI-2 receiver expects lanes to be in stop state
initially.
2) Check if the imx327 driver has a delay between starting the stream and
returning from s_stream(). If the sensor transitions PHY out of LP-11
state during this delay, the CSI driver's lane state check will fail
when it runs later. The sensor should remain in LP-11 until the CSI
controller completes its initialization.
You may need to remove any delays in the imx327 s_stream implementation, or
ensure the sensor stays in LP-11 state until the CSI receiver is ready.
If possible, could you share the imx327 driver code or check its s_stream implementation?
Best Regards
G.N Zhou
>
> Currently I'm using this DT node:
> --8<--
> mipi_csi: mipi-csi@4ae00000 {
> compatible = "fsl,imx93-mipi-csi2";
> reg = <0x4ae00000 0x10000>;
> interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&clk IMX93_CLK_MIPI_CSI_GATE>,
> <&clk IMX93_CLK_CAM_PIX>;
> clock-names = "per", "pixel";
> assigned-clocks = <&clk IMX93_CLK_CAM_PIX>;
> assigned-clock-parents = <&clk IMX93_CLK_VIDEO_PLL>;
> assigned-clock-rates = <140000000>;
> power-domains = <&media_blk_ctrl IMX93_MEDIABLK_PD_MIPI_CSI>;
> phys = <&dphy_rx>;
> phy-names = "dphy-rx";
> status = "disabled";
>
> ports {
> #address-cells = <1>;
> #size-cells = <0>;
>
> port@0 {
> reg = <0>;
>
> mipi_from_sensor: endpoint {
> data-lanes = <1 2>;
> bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
> };
> };
>
> port@1 {
> reg = <1>;
>
> mipi_to_isi: endpoint {
> remote-endpoint = <&isi_in>;
> };
> };
> };
> };
> --8<--
>
> Am I'm missing something?
>
> best regards,
> Alexander
>
> > +
> > + return ret;
> > +}
> > +
> > static const struct dw_mipi_csi2rx_drvdata imx93_drvdata = {
> > .regs = imx93_regs,
> > .dphy_assert_reset = imx93_csi2rx_dphy_assert_reset,
> > .dphy_deassert_reset = imx93_csi2rx_dphy_deassert_reset,
> > .ipi_enable = imx93_csi2rx_dphy_ipi_enable,
> > + .wait_for_phy_stopstate = imx93_csi2rx_wait_for_phy_stopstate,
> > };
> >
> > static const struct of_device_id dw_mipi_csi2rx_of_match[] = {
> >
> >
>
>
> --
> TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
> Amtsgericht München, HRB 105018
> Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
> http://www.tq-group.com/
>
^ permalink raw reply
* [PATCH v5 0/3] Add root port reset to support link recovery
From: Richard Zhu @ 2026-05-21 9:32 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel
Based on the following patch-set[1] issued by Mani.
Add support for resetting the Root Port for i.MX PCIe to enable link recovery.
[1] [PATCH v8 0/5] PCI: Add support for resetting the Root Ports in a platform specific way
PCIe links can go down due to various unexpected circumstances. This patch series
adds root port reset support for link recovery on i.MX PCIe controllers when the
optional "intr" interrupt is present.
When a link down event is detected, the root port reset uninitializes and
reinitializes the PCIe controller, then restarts the PCIe link.
On i.MX95 platforms, link events and PME share the same interrupt line.
Link event interrupts cannot use only an IRQ thread handler because the PME
driver uses request_irq() to bind the PME interrupt directly with only the
IRQF_SHARED flag set.
To address this, we register one handler with IRQF_SHARED for link event
interrupts and manipulate the enable bits of link events to ensure the same
interrupt source is triggered only once at a time.
Additionally, this series adds 'intr', 'aer', and 'pme' interrupt entries to
the i.MX6Q PCIe binding to support PCIe event-based interrupts for general
controller events, Advanced Error Reporting, and Power Management Events
respectively.
Changes in v5:
- Update the commit message of the first dt-binding patch for clarity.
- Add explicit comment explaining that writing 1 to IMX95_LINK_DOWN_INT_STS
clears the bit
Changes in v4:
- Set these new added three interrupts as optional interrupt.
Changes in v3:
- Don't add a new if:block; Drop the maxItems constraint of the interrupts
property for i.MX95 PCIe.
- Add constraints for the interrupts property for other variants.
- Regarding the ABI break: add descriptions explaining why these new
interrupts are mandatory and required by i.MX95 PCIe.
Changes in v2:
- Constrain the new added three interrupt entries to be valid only for the
i.MX95 variant using conditional schemas
[PATCH v5 1/3] dt-bindings: imx6q-pcie: Add optional interrupt
[PATCH v5 2/3] arm64: dts: imx95: Add dma, intr, aer and pme
[PATCH v5 3/3] PCI: imx6: Add root port reset to support link
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml | 6 +++++
arch/arm64/boot/dts/freescale/imx95.dtsi | 16 +++++++++---
drivers/pci/controller/dwc/pci-imx6.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 142 insertions(+), 4 deletions(-)
^ permalink raw reply
* [PATCH v5 1/3] dt-bindings: imx6q-pcie: Add optional interrupt entries for intr, aer and pme
From: Richard Zhu @ 2026-05-21 9:32 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu, Frank Li
In-Reply-To: <20260521093255.61585-1-hongxing.zhu@nxp.com>
The i.MX95 PCIe controller introduces three dedicated hardware interrupt
lines:
- intr: general controller events
- aer: Advanced Error Reporting
- pme: Power Management Events
Earlier i.MX PCIe variants (imx6q, imx6sx, imx6qp, imx7d, imx8mm, imx8mp,
imx8mq, imx8q) do not have these dedicated interrupt lines.
PCIe basic functionality (enumeration, configuration, and data transfer)
works correctly regardless of whether these interrupts are present. Mark
these interrupts as optional to maintain backward compatibility with SoCs
that lack these hardware interrupt lines.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
index 9d1349855b42..cf709132ff1e 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
@@ -58,12 +58,18 @@ properties:
items:
- description: builtin MSI controller.
- description: builtin DMA controller.
+ - description: PCIe event interrupt.
+ - description: builtin AER SPI standalone interrupt line.
+ - description: builtin PME SPI standalone interrupt line.
interrupt-names:
minItems: 1
items:
- const: msi
- const: dma
+ - const: intr
+ - const: aer
+ - const: pme
reset-gpio:
description: Should specify the GPIO for controlling the PCI bus device
--
2.37.1
^ permalink raw reply related
* [PATCH v5 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupts for PCIe
From: Richard Zhu @ 2026-05-21 9:32 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
In-Reply-To: <20260521093255.61585-1-hongxing.zhu@nxp.com>
The current PCIe device tree configuration only defines the MSI
interrupt, which is sufficient for basic PCIe operation but limits
advanced functionality.
Add the following interrupt lines to pcie0 and pcie1 nodes:
- dma: DMA interrupt for PCIe DMA operations
- intr: General controller events and link state changes
- aer: Advanced Error Reporting interrupt
- pme: Power Management Event interrupt
This enables enhanced PCIe features and capabilities that were
previously unavailable due to missing interrupt definitions.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
arch/arm64/boot/dts/freescale/imx95.dtsi | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
index adcc0e1d3696..f40388958717 100644
--- a/arch/arm64/boot/dts/freescale/imx95.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -1948,8 +1948,12 @@ pcie0: pcie@4c300000 {
bus-range = <0x00 0xff>;
num-lanes = <1>;
num-viewport = <8>;
- interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "intr", "aer", "pme";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
@@ -2023,8 +2027,12 @@ pcie1: pcie@4c380000 {
bus-range = <0x00 0xff>;
num-lanes = <1>;
num-viewport = <8>;
- interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "intr", "aer", "pme";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
--
2.37.1
^ permalink raw reply related
* [PATCH v5 3/3] PCI: imx6: Add root port reset to support link recovery
From: Richard Zhu @ 2026-05-21 9:32 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
In-Reply-To: <20260521093255.61585-1-hongxing.zhu@nxp.com>
The PCIe link can go down due to various unexpected circumstances. Add
root port reset support to enable link recovery for the i.MX PCIe
controller when the optional "intr" interrupt is present.
Reset root port to uninitialize, initialize the PCIe controller, and
restart the PCIe link at end when a link down event happens.
On i.MX95 platforms, link events and PME share the same interrupt line.
The link event interrupt cannot use a threaded-only IRQ handler because
the PME driver uses request_irq() with only the IRQF_SHARED flag set,
which requires a primary handler.
To handle this shared interrupt scenario, register a primary interrupt
handler with IRQF_SHARED for link events and manipulate the link event
enable bits to ensure the shared interrupt source triggers only one
handler at a time.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 124 ++++++++++++++++++++++++++
1 file changed, 124 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 1034ac5c5f5c..c286581bede8 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -34,6 +34,7 @@
#include <linux/pm_runtime.h>
#include "../../pci.h"
+#include "../pci-host-common.h"
#include "pcie-designware.h"
#define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9)
@@ -78,6 +79,10 @@
#define IMX95_SID_MASK GENMASK(5, 0)
#define IMX95_MAX_LUT 32
+#define IMX95_LINK_INT_CTRL_STS 0x1040
+#define IMX95_LINK_DOWN_INT_STS BIT(11)
+#define IMX95_LINK_DOWN_INT_EN BIT(10)
+
#define IMX95_PCIE_RST_CTRL 0x3010
#define IMX95_PCIE_COLD_RST BIT(0)
@@ -125,6 +130,8 @@ enum imx_pcie_variants {
#define IMX_PCIE_MAX_INSTANCES 2
struct imx_pcie;
+static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
+ struct pci_dev *pdev);
struct imx_pcie_drvdata {
enum imx_pcie_variants variant;
@@ -158,6 +165,7 @@ struct imx_pcie {
bool supports_clkreq;
bool enable_ext_refclk;
struct regmap *iomuxc_gpr;
+ u32 lnk_intr;
u16 msi_ctrl;
u32 controller_id;
struct reset_control *pciephy_reset;
@@ -1301,6 +1309,13 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
imx_setup_phy_mpll(imx_pcie);
+ /*
+ * Callback invoked by PCI core when link down is detected and
+ * recovery is needed.
+ */
+ if (pp->bridge)
+ pp->bridge->reset_root_port = imx_pcie_reset_root_port;
+
return 0;
err_phy_off:
@@ -1568,6 +1583,9 @@ static int imx_pcie_suspend_noirq(struct device *dev)
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
return 0;
+ if (imx_pcie->lnk_intr)
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
imx_pcie_msi_save_restore(imx_pcie, true);
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_save(imx_pcie);
@@ -1618,6 +1636,9 @@ static int imx_pcie_resume_noirq(struct device *dev)
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_restore(imx_pcie);
imx_pcie_msi_save_restore(imx_pcie, false);
+ if (imx_pcie->lnk_intr)
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
return 0;
}
@@ -1627,6 +1648,85 @@ static const struct dev_pm_ops imx_pcie_pm_ops = {
imx_pcie_resume_noirq)
};
+static irqreturn_t imx_pcie_lnk_irq_isr(int irq, void *priv)
+{
+ struct imx_pcie *imx_pcie = priv;
+ struct dw_pcie *pci = imx_pcie->pci;
+ struct device *dev = pci->dev;
+ u32 val;
+
+ regmap_read(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS, &val);
+ if (val & IMX95_LINK_DOWN_INT_STS) {
+ dev_dbg(dev, "PCIe link down detected, initiating recovery\n");
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+ /* Clear link down interrupt status by writing 1b'1 to it */
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_STS);
+
+ return IRQ_WAKE_THREAD;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static irqreturn_t imx_pcie_lnk_irq_thread(int irq, void *priv)
+{
+ struct imx_pcie *imx_pcie = priv;
+ struct dw_pcie *pci = imx_pcie->pci;
+ struct dw_pcie_rp *pp = &pci->pp;
+ struct pci_dev *port;
+
+ for_each_pci_bridge(port, pp->bridge->bus)
+ if (pci_pcie_type(port) == PCI_EXP_TYPE_ROOT_PORT)
+ pci_host_handle_link_down(port);
+
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+
+ return IRQ_HANDLED;
+}
+
+static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
+ struct pci_dev *pdev)
+{
+ struct pci_bus *bus = bridge->bus;
+ struct dw_pcie_rp *pp = bus->sysdata;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct imx_pcie *imx_pcie = to_imx_pcie(pci);
+ int ret;
+
+ imx_pcie_msi_save_restore(imx_pcie, true);
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_save(imx_pcie);
+ imx_pcie_stop_link(pci);
+ imx_pcie_host_exit(pp);
+
+ ret = imx_pcie_host_init(pp);
+ if (ret) {
+ dev_err(pci->dev, "Failed to re-init PCIe\n");
+ return ret;
+ }
+ ret = dw_pcie_setup_rc(pp);
+ if (ret)
+ goto err_host_deinit;
+
+ imx_pcie_start_link(pci);
+ dw_pcie_wait_for_link(pci);
+
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_restore(imx_pcie);
+ imx_pcie_msi_save_restore(imx_pcie, false);
+
+ dev_dbg(pci->dev, "Root port reset completed\n");
+ return 0;
+
+err_host_deinit:
+ imx_pcie_host_exit(pp);
+
+ return ret;
+}
+
static int imx_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1829,9 +1929,33 @@ static int imx_pcie_probe(struct platform_device *pdev)
val |= PCI_MSI_FLAGS_ENABLE;
dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
}
+
+ /* Get link event irq if it is present */
+ imx_pcie->lnk_intr = platform_get_irq_byname(pdev, "intr");
+ if (imx_pcie->lnk_intr > 0) {
+ ret = devm_request_threaded_irq(dev, imx_pcie->lnk_intr,
+ imx_pcie_lnk_irq_isr,
+ imx_pcie_lnk_irq_thread,
+ IRQF_SHARED,
+ "lnk", imx_pcie);
+ if (ret) {
+ dev_err_probe(dev, ret,
+ "unable to request LNK IRQ\n");
+ goto err_host_deinit;
+ }
+
+ regmap_set_bits(imx_pcie->iomuxc_gpr,
+ IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+ }
}
return 0;
+
+err_host_deinit:
+ dw_pcie_host_deinit(&pci->pp);
+
+ return ret;
}
static void imx_pcie_shutdown(struct platform_device *pdev)
--
2.37.1
^ permalink raw reply related
* Re: [PATCH v2 00/11] drm/rockchip: dw_hdmi: Misc cleanup and propagate bus format
From: Heiko Stuebner @ 2026-05-21 9:40 UTC (permalink / raw)
To: Sandy Huang, Andy Yan, Jonas Karlman, Vladimir Oltean
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, dri-devel, linux-rockchip, linux-arm-kernel,
linux-kernel, Jonas Karlman
In-Reply-To: <20260518193748.2482823-1-jonas@kwiboo.se>
Am Montag, 18. Mai 2026, 21:37:34 Mitteleuropäische Sommerzeit schrieb Jonas Karlman:
> This series include misc cleanup of the dwhdmi-rockchip driver and
> prepares for future support of YCbCr output and Deep Color modes.
>
> Patch 1-7 cleanup and changes to use drmres helpers for the encoder.
> Patch 8 prepare for use of a display-connector bridge for RK3568/RK3566.
> Patch 9-10 prepares for future support of YCbCr and Deep Color modes.
> Patch 11 changes to use resume_early pm ops for system suspend.
>
> This series depends on the patch "drm/rockchip: dw_hdmi: avoid direct
> dereference of phy->dev.of_node" [1] from the series "Split Generic PHY
> consumer and provider API" [2].
>
> [1] https://lore.kernel.org/linux-phy/20260505100523.1922388-16-vladimir.oltean@nxp.com/
> [2] https://lore.kernel.org/linux-phy/20260505100523.1922388-1-vladimir.oltean@nxp.com/
With Vladimir's agreement, I've pulled that patch out of the phy-series
and applied it to drm-misc-next - as it's a change that can stand on
its own.
Series:
Tested-by: Heiko Stuebner <heiko@sntech.de> #rk3328
^ permalink raw reply
* Re: [RFC V2 01/14] mm: Abstract printing of pxd_val()
From: David Laight @ 2026-05-21 9:42 UTC (permalink / raw)
To: Dave Hansen
Cc: Anshuman Khandual, linux-arm-kernel, Catalin Marinas, Will Deacon,
Ryan Roberts, Mark Rutland, Lorenzo Stoakes, Andrew Morton,
David Hildenbrand, Mike Rapoport, Linu Cherian, Usama Arif,
linux-kernel, linux-mm
In-Reply-To: <74f66e30-ab3d-4352-89ef-1bccc7e9daeb@intel.com>
On Tue, 19 May 2026 07:28:17 -0700
Dave Hansen <dave.hansen@intel.com> wrote:
> On 5/12/26 21:45, Anshuman Khandual wrote:
> > if (!p4d_present(p4d) || p4d_leaf(p4d)) {
> > - pr_alert("pgd:%08llx p4d:%08llx\n", pgdv, p4dv);
> > + pr_alert("pgd:%" __PRIpxx " p4d:%" __PRIpxx "\n",
> > + __PRIpxx_args(pgdv), __PRIpxx_args(p4dv));
> > return;
> > }
>
> That's not the most readable result. Could a printk() format specifier
> make this nicer? Maybe use "%pT"?
>
> pr_alert("pgd:%pT p4d:%pT\n", &pgd, &p4d);
>
> I _think_ it could even get rid of the p??v variables.
>
Adding another %p variant that is only used in a few places just makes
it all harder to read.
Perhaps a local helper that lets you do:
char pdgv_buf[??]:
pr_alert("... %s ...", ... fmt_pdgv(pdgv_buf, pdgv) ...)
might be a reasonable compromise.
-- David
^ permalink raw reply
* Re: [PATCH 2/8] bpf: Recover arena kernel faults with scratch page
From: Alexei Starovoitov @ 2026-05-21 9:42 UTC (permalink / raw)
To: Tejun Heo, David Vernet, Andrea Righi, Changwoo Min,
Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Martin KaFai Lau, Kumar Kartikeya Dwivedi
Cc: Peter Zijlstra, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, Andrew Morton,
David Hildenbrand, Mike Rapoport, Emil Tsalapatis, sched-ext, bpf,
x86, linux-arm-kernel, linux-mm, linux-kernel
In-Reply-To: <20260520235052.4180316-3-tj@kernel.org>
On Wed May 20, 2026 at 4:50 PM PDT, Tejun Heo wrote:
>
> v2: Use ptep_get_and_clear() in apply_range_clear_cb(). (David)
>
> Suggested-by: Alexei Starovoitov <ast@kernel.org>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: David Hildenbrand <david@kernel.org>
> ---
> Documentation/bpf/kfuncs.rst | 14 +++
> arch/arm64/mm/fault.c | 10 +-
> arch/x86/mm/fault.c | 12 ++-
> include/linux/bpf.h | 1 +
> include/linux/bpf_defs.h | 11 +++
> kernel/bpf/arena.c | 177 +++++++++++++++++++++++++++--------
> kernel/bpf/core.c | 5 +
> 7 files changed, 183 insertions(+), 47 deletions(-)
> create mode 100644 include/linux/bpf_defs.h
First 5 patches lgtm. Should we create a stable branch out of them
and pull into bpf-next and sched-ext trees?
I'm preparing a followup for slab-over-arena on top of these changes.
^ permalink raw reply
* [PATCH 0/2] Add test for atomic uaccess with permission overlay
From: Kevin Brodsky @ 2026-05-21 9:42 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Kevin Brodsky, Catalin Marinas, Joey Gouly, Mark Brown,
Shuah Khan, Will Deacon, linux-kernel, linux-kselftest
Permission overlays are not currently applied for memory types
configured in PIR_EL1, meaning that even if POE were enabled at EL1,
memory accesses would not be subject to POE restrictions.
A patch [1] in my series adding page table protection using
pkeys/POE [2] enabled overlays for all memory types in PIR_EL1. It
turns out this is wrong, as reported by Sashiko [3]. User memory
types must not have overlays applied in PIR_EL1, otherwise direct
accesses to user memory with privileged loads/stores (and PAN
disabled) will mistakenly be checked against POR_EL1, instead of the
intended POR_EL0.
To avoid any accident in the future, this series adds a comment
above the PIR_EL1 configuration block, and a kselftest to ensure
that atomic futex uaccess (which uses privileged loads/stores unless
FEAT_LSUI is available) does work on memory mapped with a
non-default pkey.
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
[1] https://lore.kernel.org/all/20260505-kpkeys-v7-3-20c0bdd97197@arm.com/
[2] https://lore.kernel.org/all/20260505-kpkeys-v7-0-20c0bdd97197@arm.com/
[3] https://sashiko.dev/#/patchset/20260505-kpkeys-v7-0-20c0bdd97197%40arm.com?part=3
---
To: linux-arm-kernel@lists.infradead.org
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Joey Gouly <joey.gouly@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
---
Kevin Brodsky (2):
arm64: mm: Add note about overlays in PIE_EL1
kselftest/arm64: Add test for atomic futex uaccess with POE
arch/arm64/include/asm/pgtable-prot.h | 7 +++
tools/testing/selftests/arm64/Makefile | 2 +-
tools/testing/selftests/arm64/poe/.gitignore | 2 +
tools/testing/selftests/arm64/poe/Makefile | 6 +++
tools/testing/selftests/arm64/poe/poe_futex.c | 62 +++++++++++++++++++++++++++
5 files changed, 78 insertions(+), 1 deletion(-)
---
base-commit: 5200f5f493f79f14bbdc349e402a40dfb32f23c8
change-id: 20260520-poe_futex-ecb8c2276894
^ permalink raw reply
* [PATCH 1/2] arm64: mm: Add note about overlays in PIE_EL1
From: Kevin Brodsky @ 2026-05-21 9:42 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Kevin Brodsky, Catalin Marinas, Joey Gouly, Mark Brown,
Shuah Khan, Will Deacon, linux-kernel, linux-kselftest
In-Reply-To: <20260521-poe_futex-v1-0-1da286b8f9b2@arm.com>
It isn't completely obvious why user page types do not have overlays
applied in PIE_EL1. Add a comment to that effect, to avoid
unpleasant surprises in the future.
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
arch/arm64/include/asm/pgtable-prot.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 212ce1b02e15..6e2f99820909 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -175,6 +175,13 @@ static inline bool __pure lpa2_is_enabled(void)
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_READONLY), PIE_R_O) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_SHARED), PIE_RW_O))
+/*
+ * Regular user page types such as _PAGE_SHARED must not have overlays applied
+ * in PIE_EL1. If POE is enabled at EL1, and in the absence of FEAT_LSUI, this
+ * would break futex atomic operations on user memory with a non-default
+ * POIndex; the privileged atomic load/store instructions would be mistakenly
+ * checked against POR_EL1.
+ */
#define PIE_E1 ( \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS), PIE_NONE_O) | \
PIRx_ELx_PERM_PREP(pte_pi_index(_PAGE_GCS_RO), PIE_NONE_O) | \
--
2.51.2
^ permalink raw reply related
* Re: [PATCH v2 1/3] interconnect: qcom: Fix indentation
From: Konrad Dybcio @ 2026-05-21 9:42 UTC (permalink / raw)
To: Krzysztof Kozlowski, Georgi Djakov, Bjorn Andersson,
Konrad Dybcio
Cc: linux-arm-msm, linux-pm, linux-kernel, linux-arm-kernel
In-Reply-To: <20260515-interconnect-qcom-clean-arm64-v2-1-adeebc73596d@oss.qualcomm.com>
On 5/15/26 2:11 PM, Krzysztof Kozlowski wrote:
> KConfig entries should be indented starting with one tab, so replace
> spaces with it.
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* [PATCH 2/2] kselftest/arm64: Add test for atomic futex uaccess with POE
From: Kevin Brodsky @ 2026-05-21 9:42 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Kevin Brodsky, Catalin Marinas, Joey Gouly, Mark Brown,
Shuah Khan, Will Deacon, linux-kernel, linux-kselftest
In-Reply-To: <20260521-poe_futex-v1-0-1da286b8f9b2@arm.com>
Add a new test to ensure that atomic futex uaccess succeeds on
memory mapped with a non-default POIndex/pkey.
In the absence of FEAT_LSUI, atomic futex uaccess operations such as
those triggered by FUTEX_WAKE_OP use privileged atomic load/store
instructions and thus cannot have user permission overlays applied
(as per POR_EL0). In case the kernel enabled POE at EL1, it is worth
checking that PIR_EL1 isn't mistakenly configured to have kernel
overlays (POR_EL1) applied instead, as that would fail for non-zero
pkeys.
Note that if such misconfiguration occurs, futex_wake_op() may get
stuck in an infinite loop because futex_atomic_op_inuser() will fail
but fault_in_user_writeable() will still report success.
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
tools/testing/selftests/arm64/Makefile | 2 +-
tools/testing/selftests/arm64/poe/.gitignore | 2 +
tools/testing/selftests/arm64/poe/Makefile | 6 +++
tools/testing/selftests/arm64/poe/poe_futex.c | 62 +++++++++++++++++++++++++++
4 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile
index e456f3b62fa1..bad5c3b33dce 100644
--- a/tools/testing/selftests/arm64/Makefile
+++ b/tools/testing/selftests/arm64/Makefile
@@ -4,7 +4,7 @@
ARCH ?= $(shell uname -m 2>/dev/null || echo not)
ifneq (,$(filter $(ARCH),aarch64 arm64))
-ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi gcs
+ARM64_SUBTARGETS ?= tags signal pauth fp mte bti abi gcs poe
else
ARM64_SUBTARGETS :=
endif
diff --git a/tools/testing/selftests/arm64/poe/.gitignore b/tools/testing/selftests/arm64/poe/.gitignore
new file mode 100644
index 000000000000..0dce4a3aa38b
--- /dev/null
+++ b/tools/testing/selftests/arm64/poe/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+poe_futex
diff --git a/tools/testing/selftests/arm64/poe/Makefile b/tools/testing/selftests/arm64/poe/Makefile
new file mode 100644
index 000000000000..2af2bbf3f6d3
--- /dev/null
+++ b/tools/testing/selftests/arm64/poe/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS += $(KHDR_INCLUDES)
+TEST_GEN_PROGS := poe_futex
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/arm64/poe/poe_futex.c b/tools/testing/selftests/arm64/poe/poe_futex.c
new file mode 100644
index 000000000000..21a2e109ee43
--- /dev/null
+++ b/tools/testing/selftests/arm64/poe/poe_futex.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <linux/futex.h>
+#include <sys/syscall.h>
+
+#include "kselftest_harness.h"
+
+static int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
+{
+ return syscall(__NR_pkey_alloc, flags, init_val);
+}
+
+static int sys_pkey_mprotect(void *ptr, size_t size, int prot, int pkey)
+{
+ return syscall(__NR_pkey_mprotect, ptr, size, prot, pkey);
+}
+
+static int futex_wake_op(uint32_t *uaddr, uint32_t val, uint32_t val2,
+ uint32_t *uaddr2, uint32_t val3)
+{
+ return syscall(SYS_futex, uaddr, FUTEX_WAKE_OP, val, val2,
+ uaddr2, val3);
+}
+
+/*
+ * Trigger some atomic uaccess on a page mapped with a non-default pkey.
+ *
+ * This ensures that such access is not mistakenly checked against the
+ * kernel's POR_EL1 register.
+ */
+TEST(poe_futex)
+{
+ int ret, pkey;
+ void *ptr;
+ size_t size = getpagesize();
+
+ pkey = sys_pkey_alloc(0, 0);
+
+ if (pkey == -1 && errno == ENOSPC)
+ SKIP(return, "pkeys are not supported");
+
+ ASSERT_GT(pkey, 0);
+
+ ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(ptr, MAP_FAILED);
+
+ ret = sys_pkey_mprotect(ptr, size, PROT_READ | PROT_WRITE, pkey);
+ ASSERT_EQ(ret, 0);
+
+ /*
+ * There is no one to wake up so this syscall boils down to *(ptr+4) = 0
+ * (arch_futex_atomic_op_inuser() called with FUTEX_OP_SET and op_arg=0).
+ */
+ ret = futex_wake_op(ptr, 1, 1, ptr + sizeof(uint32_t), 0);
+ ASSERT_EQ(ret, 0);
+}
+
+TEST_HARNESS_MAIN
--
2.51.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox