Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/4] arm64: dts: imx95: switch usb3 controller to flattened model
From: Frank Li @ 2026-04-22  3:53 UTC (permalink / raw)
  To: Xu Yang
  Cc: robh, krzk+dt, conor+dt, s.hauer, kernel, festevam, devicetree,
	imx, linux-arm-kernel, linux-kernel, jun.li
In-Reply-To: <20260421105503.1416566-2-xu.yang_2@nxp.com>

On Tue, Apr 21, 2026 at 06:55:01PM +0800, Xu Yang wrote:
> Switch to use flattened model for USB3 controller. To enable USB
> controller with restricted DMA access range to work correctly, add a
> pseudo simple-bus to constrain the dma address.

i.mx95 should fix >4G dma space's problem. Does it impact other no-nxp
boards?

Need do break compatible judgement such as

i.MX95 is new SoC and still is heave development. The break compatible is
accepable at development early phase.

You can rephrase it.

Frank

>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx95.dtsi | 48 ++++++++++++------------
>  1 file changed, 24 insertions(+), 24 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
> index 71394871d8dd..91048501a692 100644
> --- a/arch/arm64/boot/dts/freescale/imx95.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
> @@ -1772,45 +1772,45 @@ smmu: iommu@490d0000 {
>  			};
>  		};
>
> -		usb3: usb@4c010010 {
> -			compatible = "fsl,imx95-dwc3", "fsl,imx8mp-dwc3";
> -			reg = <0x0 0x4c010010 0x0 0x04>,
> -			      <0x0 0x4c1f0000 0x0 0x20>;
> -			clocks = <&scmi_clk IMX95_CLK_HSIO>,
> -				 <&scmi_clk IMX95_CLK_32K>;
> -			clock-names = "hsio", "suspend";
> -			interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
> +		hsio_blk_ctl: syscon@4c0100c0 {
> +			compatible = "nxp,imx95-hsio-blk-ctl", "syscon";
> +			reg = <0x0 0x4c0100c0 0x0 0x1>;
> +			#clock-cells = <1>;
> +			clocks = <&clk_sys100m>;
> +			power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
> +		};
> +
> +		bus@4c100000 {
> +			compatible = "simple-bus";
>  			#address-cells = <2>;
>  			#size-cells = <2>;
> -			ranges;
> -			power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
>  			dma-ranges = <0x0 0x0 0x0 0x0 0x10 0x0>;
> -			status = "disabled";
> +			ranges;
>
> -			usb3_dwc3: usb@4c100000 {
> -				compatible = "snps,dwc3";
> -				reg = <0x0 0x4c100000 0x0 0x10000>;
> +			usb3: usb3_dwc3: usb@4c100000 {
> +				compatible = "nxp,imx8mp-dwc3";
> +				reg = <0x0 0x4c100000 0x0 0x10000>,
> +				      <0x0 0x4c010010 0x0 0x04>,
> +				      <0x0 0x4c1f0000 0x0 0x20>;
> +				reg-names = "core", "blkctl", "glue";
>  				clocks = <&scmi_clk IMX95_CLK_HSIO>,
> +					 <&scmi_clk IMX95_CLK_HSIO>,
>  					 <&scmi_clk IMX95_CLK_24M>,
>  					 <&scmi_clk IMX95_CLK_32K>;
> -				clock-names = "bus_early", "ref", "suspend";
> -				interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
> +				clock-names = "hsio", "bus_early", "ref", "suspend";
> +				interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-names = "dwc_usb3", "wakeup";
> +				power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
>  				phys = <&usb3_phy>, <&usb3_phy>;
>  				phy-names = "usb2-phy", "usb3-phy";
>  				snps,gfladj-refclk-lpm-sel-quirk;
>  				snps,parkmode-disable-ss-quirk;
>  				iommus = <&smmu 0xe>;
> +				status = "disabled";
>  			};
>  		};
>
> -		hsio_blk_ctl: syscon@4c0100c0 {
> -			compatible = "nxp,imx95-hsio-blk-ctl", "syscon";
> -			reg = <0x0 0x4c0100c0 0x0 0x1>;
> -			#clock-cells = <1>;
> -			clocks = <&clk_sys100m>;
> -			power-domains = <&scmi_devpd IMX95_PD_HSIO_TOP>;
> -		};
> -
>  		usb3_phy: phy@4c1f0040 {
>  			compatible = "fsl,imx95-usb-phy", "fsl,imx8mp-usb-phy";
>  			reg = <0x0 0x4c1f0040 0x0 0x40>,
> --
> 2.34.1
>


^ permalink raw reply

* New warning in linus/master
From: Ricardo Ribalda @ 2026-04-22  3:51 UTC (permalink / raw)
  To: Thomas Weißschuh, linux-arm-kernel,
	Linux Kernel Mailing List, linuxppc-dev

Hi Thomas

Media-CI has found a couple of new warnings in the latest kernel
version for aarch64 and powerpc. They get fixed with this patch and
before moving I wanted to know if this was under your radar.



diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..65914842fae0 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -50,7 +50,7 @@ CFLAGS_vgettimeofday.o = $(CC_FLAGS_ADD_VDSO)
 CFLAGS_vgetrandom.o = $(CC_FLAGS_ADD_VDSO)

 ifneq ($(c-gettimeofday-y),)
-  CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
+  CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
-Wno-maybe-uninitialized
 endif

 ifneq ($(c-getrandom-y),)
diff --git a/arch/powerpc/kernel/vdso/Makefile
b/arch/powerpc/kernel/vdso/Makefile
index 8834dfe9d727..4b8d40b1dfeb 100644
--- a/arch/powerpc/kernel/vdso/Makefile
+++ b/arch/powerpc/kernel/vdso/Makefile
@@ -12,12 +12,12 @@ obj-vdso32 += getrandom-32.o vgetrandom-chacha-32.o
 obj-vdso64 += getrandom-64.o vgetrandom-chacha-64.o

 ifneq ($(c-gettimeofday-y),)
-  CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y)
+  CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y)
-Wno-maybe-uninitialized
 # Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code.
That used to be true
 # by accident when the VDSO was hand-written asm code, but may not be
now that the VDSO is
 # compiler generated. To avoid breaking Go tell GCC not to use r30.
Impact on code
 # generation is minimal, it will just use r29 instead.
-  CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) $(call
cc-option, -ffixed-r30)
+  CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) $(call
cc-option, -ffixed-r30) -Wno-maybe-uninitialized
 endif

 ifneq ($(c-getrandom-y),)


https://gitlab.freedesktop.org/linux-media/users/ribalda/-/pipelines/1649144/test_report?job_name=cross-gcc


CONFIG_CC_VERSION_TEXT="aarch64-linux-gnu-gcc (Debian 15.2.0-16) 15.2.0"
  SYNC    include/config/auto.conf
  CC      arch/arm64/kernel/vdso/vgettimeofday.o
In file included from <command-line>:
In function ‘vdso_set_timespec’,
    inlined from ‘do_aux’ at /workdir/lib/vdso/gettimeofday.c:266:2,
    inlined from ‘__cvdso_clock_gettime_common’ at
/workdir/lib/vdso/gettimeofday.c:293:10,
    inlined from ‘__cvdso_clock_gettime_data.constprop’ at
/workdir/lib/vdso/gettimeofday.c:306:7:
/workdir/lib/vdso/gettimeofday.c:104:26: warning: ‘sec’ may be used
uninitialized [-Wmaybe-uninitialized]
  104 |         ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
      |                      ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/workdir/lib/vdso/gettimeofday.c: In function
‘__cvdso_clock_gettime_data.constprop’:
/workdir/lib/vdso/gettimeofday.c:242:13: note: ‘sec’ was declared here
  242 |         u64 sec, ns;
      |             ^~~
In file included from /workdir/lib/vdso/gettimeofday.c:11:
In function ‘__iter_div_u64_rem’,
    inlined from ‘vdso_set_timespec’ at /workdir/lib/vdso/gettimeofday.c:104:21,
    inlined from ‘do_aux’ at /workdir/lib/vdso/gettimeofday.c:266:2,
    inlined from ‘__cvdso_clock_gettime_common’ at
/workdir/lib/vdso/gettimeofday.c:293:10,
    inlined from ‘__cvdso_clock_gettime_data.constprop’ at
/workdir/lib/vdso/gettimeofday.c:306:7:
./include/vdso/math64.h:10:25: warning: ‘ns’ may be used uninitialized
[-Wmaybe-uninitialized]
   10 |         while (dividend >= divisor) {
      |                ~~~~~~~~~^~~~~~~~~~
/workdir/lib/vdso/gettimeofday.c: In function
‘__cvdso_clock_gettime_data.constprop’:
/workdir/lib/vdso/gettimeofday.c:242:18: note: ‘ns’ was declared here
  242 |         u64 sec, ns;
      |                  ^~
  LD      arch/arm64/kernel/vdso/vdso.so.dbg
  VDSOSYM include/generated/vdso-offsets.h
  OBJCOPY arch/arm64/kernel/vdso/vdso.so
/workdir/lib/vdso/gettimeofday.c:104:26: warning: ‘sec’ may be used
uninitialized [-Wmaybe-uninitialized]
./include/vdso/math64.h:10:25: warning: ‘ns’ may be used uninitialized
[-Wmaybe-uninitialized]

CONFIG_CC_VERSION_TEXT="powerpc64-linux-gnu-gcc (Debian 15.2.0-15) 15.2.0"
  SYNC    include/config/auto.conf
  VDSO32C arch/powerpc/kernel/vdso/vgettimeofday-32.o
In file included from <command-line>:
In function ‘vdso_set_timespec’,
    inlined from ‘do_aux’ at /workdir/lib/vdso/gettimeofday.c:266:2,
    inlined from ‘__cvdso_clock_gettime_common’ at
/workdir/lib/vdso/gettimeofday.c:293:10,
    inlined from ‘__cvdso_clock_gettime32_data’ at
/workdir/lib/vdso/gettimeofday.c:327:7:
/workdir/lib/vdso/gettimeofday.c:104:26: warning: ‘sec’ may be used
uninitialized [-Wmaybe-uninitialized]
  104 |         ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
      |                      ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/workdir/lib/vdso/gettimeofday.c: In function ‘__cvdso_clock_gettime32_data’:
/workdir/lib/vdso/gettimeofday.c:242:13: note: ‘sec’ was declared here
  242 |         u64 sec, ns;
      |             ^~~
In file included from /workdir/lib/vdso/gettimeofday.c:11:
In function ‘__iter_div_u64_rem’,
    inlined from ‘vdso_set_timespec’ at /workdir/lib/vdso/gettimeofday.c:104:21,
    inlined from ‘do_aux’ at /workdir/lib/vdso/gettimeofday.c:266:2,
    inlined from ‘__cvdso_clock_gettime_common’ at
/workdir/lib/vdso/gettimeofday.c:293:10,
    inlined from ‘__cvdso_clock_gettime32_data’ at
/workdir/lib/vdso/gettimeofday.c:327:7:
./include/vdso/math64.h:10:25: warning: ‘ns’ may be used uninitialized
[-Wmaybe-uninitialized]
   10 |         while (dividend >= divisor) {
      |                ~~~~~~~~~^~~~~~~~~~
/workdir/lib/vdso/gettimeofday.c: In function ‘__cvdso_clock_gettime32_data’:
/workdir/lib/vdso/gettimeofday.c:242:18: note: ‘ns’ was declared here
  242 |         u64 sec, ns;
      |                  ^~
In function ‘vdso_set_timespec’,
    inlined from ‘do_aux’ at /workdir/lib/vdso/gettimeofday.c:266:2,
    inlined from ‘__cvdso_clock_gettime_common’ at
/workdir/lib/vdso/gettimeofday.c:293:10,
    inlined from ‘__cvdso_clock_gettime_data’ at
/workdir/lib/vdso/gettimeofday.c:306:7:
/workdir/lib/vdso/gettimeofday.c:104:26: warning: ‘sec’ may be used
uninitialized [-Wmaybe-uninitialized]
  104 |         ts->tv_sec = sec + __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
      |                      ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/workdir/lib/vdso/gettimeofday.c: In function ‘__cvdso_clock_gettime_data’:
/workdir/lib/vdso/gettimeofday.c:242:13: note: ‘sec’ was declared here
  242 |         u64 sec, ns;
      |             ^~~
In function ‘__iter_div_u64_rem’,
    inlined from ‘vdso_set_timespec’ at /workdir/lib/vdso/gettimeofday.c:104:21,
    inlined from ‘do_aux’ at /workdir/lib/vdso/gettimeofday.c:266:2,
    inlined from ‘__cvdso_clock_gettime_common’ at
/workdir/lib/vdso/gettimeofday.c:293:10,
    inlined from ‘__cvdso_clock_gettime_data’ at
/workdir/lib/vdso/gettimeofday.c:306:7:
./include/vdso/math64.h:10:25: warning: ‘ns’ may be used uninitialized
[-Wmaybe-uninitialized]
   10 |         while (dividend >= divisor) {
      |                ~~~~~~~~~^~~~~~~~~~
/workdir/lib/vdso/gettimeofday.c: In function ‘__cvdso_clock_gettime_data’:
/workdir/lib/vdso/gettimeofday.c:242:18: note: ‘ns’ was declared here
  242 |         u64 sec, ns;
      |                  ^~
  VDSO32L arch/powerpc/kernel/vdso/vdso32.so.dbg
  VDSO32SYM include/generated/vdso32-offsets.h
  CC      arch/powerpc/kernel/vdso/vgettimeofday-64.o
  VDSO64L arch/powerpc/kernel/vdso/vdso64.so.dbg
  VDSO64SYM include/generated/vdso64-offsets.h
/workdir/lib/vdso/gettimeofday.c:104:26: warning: ‘sec’ may be used
uninitialized [-Wmaybe-uninitialized]
./include/vdso/math64.h:10:25: warning: ‘ns’ may be used uninitialized
[-Wmaybe-uninitialized]
/workdir/lib/vdso/gettimeofday.c:104:26: warning: ‘sec’ may be used
uninitialized [-Wmaybe-uninitialized]
./include/vdso/math64.h:10:25: warning: ‘ns’ may be used uninitialized
[-Wmaybe-uninitialized]

Thanks

-- 
Ricardo Ribalda


^ permalink raw reply related

* Re: [PATCH 1/4] arm64: dts: imx8mp: switch usb controller to flattened model
From: Frank Li @ 2026-04-22  3:45 UTC (permalink / raw)
  To: Xu Yang
  Cc: robh, krzk+dt, conor+dt, s.hauer, kernel, festevam, devicetree,
	imx, linux-arm-kernel, linux-kernel, jun.li
In-Reply-To: <20260421105503.1416566-1-xu.yang_2@nxp.com>

On Tue, Apr 21, 2026 at 06:55:00PM +0800, Xu Yang wrote:
> Switch to use flattened model for all USB controllers. To enable USB
> controllers with restricted DMA access range to work correctly, add a
> pseudo simple-bus to constrain the dma address.

This should not "pseudo", and bus is physical existed, which limited dma
range since it transparent to SW, which may not mention in spec.

>
> Also reorder USB-related nodes.

this need new patch to just do reorder.

>
> Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
> ---
>  arch/arm64/boot/dts/freescale/imx8mp.dtsi | 161 ++++++++++------------
>  1 file changed, 76 insertions(+), 85 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> index 90d7bb8f5619..8b3aab14ccf1 100644
> --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
> @@ -2329,6 +2329,82 @@ gpu2d: gpu@38008000 {
>  			power-domains = <&pgc_gpu2d>;
>  		};
>
> +		bus@38100000 {
> +			compatible = "simple-bus";
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			dma-ranges = <0x40000000 0x40000000 0xc0000000>;
> +			ranges;
> +
> +			usb3_0: usb_dwc3_0: usb@38100000 {
> +				compatible = "nxp,imx8mp-dwc3";
> +				reg = <0x38100000 0x10000>,
> +				      <0x32f10100 0x8>,
> +				      <0x381f0000 0x20>;
> +				reg-names = "core", "blkctl", "glue";
> +				clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
> +					 <&clk IMX8MP_CLK_USB_ROOT>,
> +					 <&clk IMX8MP_CLK_USB_CORE_REF>,
> +					 <&clk IMX8MP_CLK_USB_SUSP>;
> +				clock-names = "hsio", "bus_early", "ref", "suspend";
> +				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-names = "dwc_usb3", "wakeup";
> +				power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
> +				phys = <&usb3_phy0>, <&usb3_phy0>;
> +				phy-names = "usb2-phy", "usb3-phy";
> +				snps,gfladj-refclk-lpm-sel-quirk;
> +				snps,parkmode-disable-ss-quirk;
> +				status = "disabled";
> +			};
> +
> +			usb3_1: usb_dwc3_1: usb@38200000 {
> +				compatible = "nxp,imx8mp-dwc3";
> +				reg = <0x38200000 0x10000>,
> +				      <0x32f10108 0x8>,
> +				      <0x382f0000 0x20>;
> +				reg-names = "core", "blkctl", "glue";
> +				clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
> +					 <&clk IMX8MP_CLK_USB_ROOT>,
> +					 <&clk IMX8MP_CLK_USB_CORE_REF>,
> +					 <&clk IMX8MP_CLK_USB_SUSP>;
> +				clock-names = "hsio", "bus_early", "ref", "suspend";
> +				interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
> +					     <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
> +				interrupt-names = "dwc_usb3", "wakeup";
> +				power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
> +				phys = <&usb3_phy1>, <&usb3_phy1>;
> +				phy-names = "usb2-phy", "usb3-phy";
> +				snps,gfladj-refclk-lpm-sel-quirk;
> +				snps,parkmode-disable-ss-quirk;
> +				status = "disabled";
> +			};
> +		};
> +
> +		usb3_phy0: usb-phy@381f0040 {
> +			compatible = "fsl,imx8mp-usb-phy";
> +			reg = <0x381f0040 0x40>;
> +			clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
> +			clock-names = "phy";
> +			assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
> +			assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
> +			power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB_PHY1>;
> +			#phy-cells = <0>;
> +			status = "disabled";
> +		};
> +
> +		usb3_phy1: usb-phy@382f0040 {
> +			compatible = "fsl,imx8mp-usb-phy";
> +			reg = <0x382f0040 0x40>;
> +			clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
> +			clock-names = "phy";
> +			assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
> +			assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
> +			power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB_PHY2>;
> +			#phy-cells = <0>;
> +			status = "disabled";
> +		};
> +
>  		vpu_g1: video-codec@38300000 {
>  			compatible = "nxp,imx8mm-vpu-g1";
>  			reg = <0x38300000 0x10000>;
> @@ -2407,91 +2483,6 @@ ddr-pmu@3d800000 {
>  			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
>  		};
>
> -		usb3_phy0: usb-phy@381f0040 {
> -			compatible = "fsl,imx8mp-usb-phy";
> -			reg = <0x381f0040 0x40>;
> -			clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
> -			clock-names = "phy";
> -			assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
> -			assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
> -			power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB_PHY1>;
> -			#phy-cells = <0>;
> -			status = "disabled";
> -		};
> -
> -		usb3_0: usb@32f10100 {
> -			compatible = "fsl,imx8mp-dwc3";

Delete these will broken back compatible. You can delete later or descript
impact judgement in commit message.

Frank

> -			reg = <0x32f10100 0x8>,
> -			      <0x381f0000 0x20>;
> -			clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
> -				 <&clk IMX8MP_CLK_USB_SUSP>;
> -			clock-names = "hsio", "suspend";
> -			interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
> -			power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
> -			#address-cells = <1>;
> -			#size-cells = <1>;
> -			dma-ranges = <0x40000000 0x40000000 0xc0000000>;
> -			ranges;
> -			status = "disabled";
> -
> -			usb_dwc3_0: usb@38100000 {
> -				compatible = "snps,dwc3";
> -				reg = <0x38100000 0x10000>;
> -				clocks = <&clk IMX8MP_CLK_USB_ROOT>,
> -					 <&clk IMX8MP_CLK_USB_CORE_REF>,
> -					 <&clk IMX8MP_CLK_USB_SUSP>;
> -				clock-names = "bus_early", "ref", "suspend";
> -				interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> -				phys = <&usb3_phy0>, <&usb3_phy0>;
> -				phy-names = "usb2-phy", "usb3-phy";
> -				snps,gfladj-refclk-lpm-sel-quirk;
> -				snps,parkmode-disable-ss-quirk;
> -			};
> -
> -		};
> -
> -		usb3_phy1: usb-phy@382f0040 {
> -			compatible = "fsl,imx8mp-usb-phy";
> -			reg = <0x382f0040 0x40>;
> -			clocks = <&clk IMX8MP_CLK_USB_PHY_ROOT>;
> -			clock-names = "phy";
> -			assigned-clocks = <&clk IMX8MP_CLK_USB_PHY_REF>;
> -			assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
> -			power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB_PHY2>;
> -			#phy-cells = <0>;
> -			status = "disabled";
> -		};
> -
> -		usb3_1: usb@32f10108 {
> -			compatible = "fsl,imx8mp-dwc3";
> -			reg = <0x32f10108 0x8>,
> -			      <0x382f0000 0x20>;
> -			clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
> -				 <&clk IMX8MP_CLK_USB_SUSP>;
> -			clock-names = "hsio", "suspend";
> -			interrupts = <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>;
> -			power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_USB>;
> -			#address-cells = <1>;
> -			#size-cells = <1>;
> -			dma-ranges = <0x40000000 0x40000000 0xc0000000>;
> -			ranges;
> -			status = "disabled";
> -
> -			usb_dwc3_1: usb@38200000 {
> -				compatible = "snps,dwc3";
> -				reg = <0x38200000 0x10000>;
> -				clocks = <&clk IMX8MP_CLK_USB_ROOT>,
> -					 <&clk IMX8MP_CLK_USB_CORE_REF>,
> -					 <&clk IMX8MP_CLK_USB_SUSP>;
> -				clock-names = "bus_early", "ref", "suspend";
> -				interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
> -				phys = <&usb3_phy1>, <&usb3_phy1>;
> -				phy-names = "usb2-phy", "usb3-phy";
> -				snps,gfladj-refclk-lpm-sel-quirk;
> -				snps,parkmode-disable-ss-quirk;
> -			};
> -		};
> -
>  		dsp: dsp@3b6e8000 {
>  			compatible = "fsl,imx8mp-hifi4";
>  			reg = <0x3b6e8000 0x88000>;
> --
> 2.34.1
>


^ permalink raw reply

* Re: [PATCH v2 2/2] arm64: dts: add tqma9596la-mba95xxca
From: Frank Li @ 2026-04-22  3:10 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Geert Uytterhoeven,
	Magnus Damm, Shawn Guo, Markus Niebel, devicetree, linux-kernel,
	imx, linux-arm-kernel, linux, linux-renesas-soc
In-Reply-To: <2831050.mvXUDI8C0e@steina-w>

On Tue, Apr 21, 2026 at 04:09:15PM +0200, Alexander Stein wrote:
> Hi,
>
> Am Donnerstag, 26. März 2026, 12:03:30 CEST schrieb Alexander Stein:
> > From: Markus Niebel <Markus.Niebel@ew.tq-group.com>
> >
> > This adds support for TQMa95xxLA modules, designed to be soldered
> > on a carrier board. MBa95xxCA is a carrier reference board / starter kit
> > design.
> >
> > There is a common device tree for all variants with e.g. reduced
> > CPU core / feature count.
> >
> > Enable the external accessible PCIe controllers as host,
> > add clocking and reset GPIO. While at it, add hogs for GPIO
> > lines from the M.2 slots until M.2 connector driver is available.
> >
> > Signed-off-by: Markus Niebel <Markus.Niebel@ew.tq-group.com>
> > Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
>
> Any feedback on this? Patch 1 is already picked in commit d44627c13049e
> ("dt-bindings: arm: add bindings for TQMa95xxLA")

Most likely missed pick windows, I will take care after v7.1-rc1 out.

Frank

>
> Thank and best regards,
> Alexander
>
> > ---
> > Changes in v2:
> > * removed useless regulator
> > * added USB PD source configuration
> > * Removed unused uart-has-rtscts properties (unused by LPUART)
> > * Fixed RTS/CTS pullups in pinctrl
> > * Added thermalzone on module
> >
> >  arch/arm64/boot/dts/freescale/Makefile        |   1 +
> >  .../freescale/imx95-tqma9596la-mba95xxca.dts  | 947 ++++++++++++++++++
> >  .../boot/dts/freescale/imx95-tqma9596la.dtsi  | 297 ++++++
> >  3 files changed, 1245 insertions(+)
> >  create mode 100644 arch/arm64/boot/dts/freescale/imx95-tqma9596la-mba95xxca.dts
> >  create mode 100644 arch/arm64/boot/dts/freescale/imx95-tqma9596la.dtsi
> >
> > diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
> > index 2879d567dede0..df79e56771319 100644
> > --- a/arch/arm64/boot/dts/freescale/Makefile
> > +++ b/arch/arm64/boot/dts/freescale/Makefile
> > @@ -554,6 +554,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-15x15-frdm.dtb
> >  dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk.dtb
> >  dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-evk-sof.dtb
> >  dtb-$(CONFIG_ARCH_MXC) += imx95-toradex-smarc-dev.dtb
> > +dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596la-mba95xxca.dtb
> >  dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596sa-mb-smarc-2.dtb
> >  dtb-$(CONFIG_ARCH_MXC) += imx95-var-dart-sonata.dtb
> >
> > diff --git a/arch/arm64/boot/dts/freescale/imx95-tqma9596la-mba95xxca.dts b/arch/arm64/boot/dts/freescale/imx95-tqma9596la-mba95xxca.dts
> > new file mode 100644
> > index 0000000000000..f75580bb91e3e
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/freescale/imx95-tqma9596la-mba95xxca.dts
> > @@ -0,0 +1,947 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
> > +/*
> > + * Copyright (c) 2024-2026 TQ-Systems GmbH <linux@ew.tq-group.com>,
> > + * D-82229 Seefeld, Germany.
> > + * Author: Alexander Stein
> > + * Author: Markus Niebel
> > + */
> > +
> > +/dts-v1/;
> > +
> > +#include <dt-bindings/leds/common.h>
> > +#include <dt-bindings/net/ti-dp83867.h>
> > +#include <dt-bindings/pwm/pwm.h>
> > +#include <dt-bindings/usb/pd.h>
> > +#include "imx95-tqma9596la.dtsi"
> > +
> > +/ {
> > +	model = "TQ-Systems i.MX95 TQMa95xxLA on MBa95xxCA";
> > +	compatible = "tq,imx95-tqma9596la-mba95xxca", "tq,imx95-tqma9596la", "fsl,imx95";
> > +	chassis-type = "embedded";
> > +
> > +	aliases {
> > +		ethernet0 = &enetc_port0;
> > +		ethernet1 = &enetc_port1;
> > +		ethernet2 = &enetc_port2;
> > +		gpio0 = &gpio1;
> > +		gpio1 = &gpio2;
> > +		gpio2 = &gpio3;
> > +		gpio3 = &gpio4;
> > +		i2c0 = &lpi2c1;
> > +		i2c1 = &lpi2c2;
> > +		i2c2 = &lpi2c3;
> > +		i2c3 = &lpi2c4;
> > +		i2c4 = &lpi2c5;
> > +		i2c5 = &lpi2c6;
> > +		i2c6 = &lpi2c7;
> > +		i2c7 = &lpi2c8;
> > +		mmc0 = &usdhc1;
> > +		mmc1 = &usdhc2;
> > +		rtc0 = &pcf85063;
> > +		rtc1 = &scmi_bbm;
> > +		serial0 = &lpuart1;
> > +		serial1 = &lpuart2;
> > +		serial2 = &lpuart3;
> > +		serial3 = &lpuart4;
> > +		serial4 = &lpuart5;
> > +		serial5 = &lpuart6;
> > +		serial6 = &lpuart7;
> > +		serial7 = &lpuart8;
> > +		spi0 = &flexspi1;
> > +	};
> > +
> > +	chosen {
> > +		stdout-path = &lpuart1;
> > +	};
> > +
> > +	backlight_lvds: backlight-lvds {
> > +		compatible = "pwm-backlight";
> > +		pwms = <&tpm5 2 100000 0>;
> > +		brightness-levels = <0 4 8 16 32 64 128 255>;
> > +		default-brightness-level = <7>;
> > +		enable-gpios = <&expander2 6 GPIO_ACTIVE_HIGH>;
> > +		power-supply = <&reg_12v0>;
> > +		status = "disabled";
> > +	};
> > +
> > +	clk_eth: clk-eth {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <156250000>;
> > +	};
> > +
> > +	/*
> > +	 * TODO: gate is disabled for now and GPIO are hogged
> > +	 * ENETC driver switches the clock far too late for ENETC2 + SFP
> > +	 */
> > +	clk_eth_gate: clk-eth-gate {
> > +		compatible = "gpio-gate-clock";
> > +		enable-gpios = <&expander2 0 GPIO_ACTIVE_HIGH>;
> > +		clocks = <&clk_eth>;
> > +		#clock-cells = <0>;
> > +		status = "disabled";
> > +	};
> > +
> > +	clk_xtal25: clk-xtal25 {
> > +		compatible = "fixed-clock";
> > +		#clock-cells = <0>;
> > +		clock-frequency = <25000000>;
> > +	};
> > +
> > +	gpio-keys {
> > +		compatible = "gpio-keys";
> > +		autorepeat;
> > +
> > +		button-b {
> > +			label = "BUTTON_B#";
> > +			linux,code = <BTN_1>;
> > +			gpios = <&expander1 0 GPIO_ACTIVE_LOW>;
> > +			wakeup-source;
> > +		};
> > +	};
> > +
> > +	gpio-leds {
> > +		compatible = "gpio-leds";
> > +
> > +		led-1 {
> > +			color = <LED_COLOR_ID_GREEN>;
> > +			function = LED_FUNCTION_STATUS;
> > +			gpios = <&expander2 13 GPIO_ACTIVE_HIGH>;
> > +			linux,default-trigger = "default-on";
> > +		};
> > +
> > +		led-2 {
> > +			color = <LED_COLOR_ID_AMBER>;
> > +			function = LED_FUNCTION_HEARTBEAT;
> > +			gpios = <&expander2 14 GPIO_ACTIVE_HIGH>;
> > +			linux,default-trigger = "heartbeat";
> > +		};
> > +	};
> > +
> > +	iio-hwmon {
> > +		compatible = "iio-hwmon";
> > +		io-channels = <&adc1 0>, <&adc1 1>, <&adc1 2>, <&adc1 3>,
> > +			      <&adc1 4>, <&adc1 5>, <&adc1 6>, <&adc1 7>;
> > +	};
> > +
> > +	reg_v1v8_mb: regulator-v1v8-mb {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "V_1V8_MB";
> > +		regulator-min-microvolt = <1800000>;
> > +		regulator-max-microvolt = <1800000>;
> > +		regulator-always-on;
> > +	};
> > +
> > +	reg_v3v3_mb: regulator-v3v3-mb {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "V_3V3_MB";
> > +		regulator-min-microvolt = <3300000>;
> > +		regulator-max-microvolt = <3300000>;
> > +		regulator-always-on;
> > +	};
> > +
> > +	reg_3v3a_10g: regulator-3v3a-10g {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "3V3A_10G";
> > +		regulator-min-microvolt = <3300000>;
> > +		regulator-max-microvolt = <3300000>;
> > +		gpio = <&expander2 15 GPIO_ACTIVE_HIGH>;
> > +		startup-delay-us = <2000>;
> > +		enable-active-high;
> > +	};
> > +
> > +	reg_12v0: regulator-12v0 {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "12V0";
> > +		regulator-min-microvolt = <12000000>;
> > +		regulator-max-microvolt = <12000000>;
> > +		gpio = <&expander1 15 GPIO_ACTIVE_HIGH>;
> > +		enable-active-high;
> > +	};
> > +
> > +	reg_pwm_fan: regulator-pwm-fan {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "FAN_PWR";
> > +		regulator-min-microvolt = <12000000>;
> > +		regulator-max-microvolt = <12000000>;
> > +		gpio = <&expander3 15 GPIO_ACTIVE_HIGH>;
> > +		enable-active-high;
> > +		vin-supply = <&reg_12v0>;
> > +	};
> > +
> > +	reg_lvds: regulator-lvds {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "LCD_PWR_EN";
> > +		regulator-min-microvolt = <3300000>;
> > +		regulator-max-microvolt = <3300000>;
> > +		gpio = <&expander2 7 GPIO_ACTIVE_HIGH>;
> > +		enable-active-high;
> > +	};
> > +
> > +	/* USB NC limitations, RM 162.1.2 VBUS limitations */
> > +	reg_vbus_usb3: regulator-vbus-usb3 {
> > +		compatible = "regulator-fixed";
> > +		regulator-min-microvolt = <5000000>;
> > +		regulator-max-microvolt = <5000000>;
> > +		regulator-name = "USB3_VBUS";
> > +		gpio = <&gpio4 1 GPIO_ACTIVE_HIGH>;
> > +		enable-active-high;
> > +	};
> > +
> > +	sfp_xfi: sfp-xfi {
> > +		compatible = "sff,sfp";
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_sfp>;
> > +		i2c-bus = <&lpi2c7>;
> > +		maximum-power-milliwatt = <2000>;
> > +		mod-def0-gpios = <&expander1 3 GPIO_ACTIVE_LOW>;
> > +		tx-fault-gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>;
> > +		los-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;
> > +		tx-disable-gpios = <&expander2 2 GPIO_ACTIVE_HIGH>;
> > +	};
> > +
> > +	sound {
> > +		compatible = "fsl,imx-audio-tlv320aic32x4";
> > +		model = "tqm-tlv320aic32";
> > +		audio-codec = <&tlv320aic3x04>;
> > +		audio-cpu = <&sai3>;
> > +		audio-routing =
> > +			"IN3_L", "Mic Jack",
> > +			"Mic Jack", "Mic Bias",
> > +			"Headphone Jack", "HPL",
> > +			"Headphone Jack", "HPR",
> > +			"IN1_L", "Line In Jack",
> > +			"IN1_R", "Line In Jack",
> > +			"Line Out Jack", "LOL",
> > +			"Line Out Jack", "LOR";
> > +	};
> > +};
> > +
> > +&adc1 {
> > +	status = "okay";
> > +};
> > +
> > +&enetc_port0 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_enetc0>;
> > +	phy-handle = <&ethphy0>;
> > +	phy-mode = "rgmii-id";
> > +	status = "okay";
> > +};
> > +
> > +&enetc_port1 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_enetc1>;
> > +	phy-handle = <&ethphy1>;
> > +	phy-mode = "rgmii-id";
> > +	status = "okay";
> > +};
> > +
> > +/* No support for XFI yet */
> > +&enetc_port2 {
> > +	sfp = <&sfp_xfi>;
> > +	phy-mode = "10gbase-r";
> > +	clocks = <&clk_eth>;
> > +	clock-names = "enet_ref_clk";
> > +	managed = "in-band-status";
> > +	status = "disabled";
> > +};
> > +
> > +&flexcan1 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_flexcan1>;
> > +	status = "okay";
> > +};
> > +
> > +&flexcan2 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_flexcan2>;
> > +	status = "okay";
> > +};
> > +
> > +&lpi2c2 {
> > +	tlv320aic3x04: audio-codec@18 {
> > +		compatible = "ti,tlv320aic32x4";
> > +		reg = <0x18>;
> > +		clocks = <&scmi_clk IMX95_CLK_SAI3>;
> > +		clock-names = "mclk";
> > +		reset-gpios = <&expander1 14 GPIO_ACTIVE_LOW>;
> > +		iov-supply = <&reg_v3v3_mb>;
> > +		ldoin-supply = <&reg_v3v3_mb>;
> > +	};
> > +
> > +	fan_controller: fan-controller@2f {
> > +		compatible = "microchip,emc2301", "microchip,emc2305";
> > +		reg = <0x2f>;
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +		#pwm-cells = <3>;
> > +		status = "okay";
> > +
> > +		fan: fan@0 {
> > +			reg = <0x0>;
> > +			pwms = <&fan_controller 40000 PWM_POLARITY_INVERTED 1>;
> > +			#cooling-cells = <2>;
> > +			fan-supply = <&reg_pwm_fan>;
> > +		};
> > +	};
> > +
> > +	ptn5110: usb-typec@50 {
> > +		compatible = "nxp,ptn5110", "tcpci";
> > +		reg = <0x50>;
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_typec>;
> > +		interrupt-parent = <&gpio2>;
> > +		interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
> > +
> > +		typec_con: connector {
> > +			compatible = "usb-c-connector";
> > +			label = "X9";
> > +			power-role = "source";
> > +			data-role = "dual";
> > +			source-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)>;
> > +			self-powered;
> > +
> > +			port {
> > +				typec_con_hs: endpoint {
> > +					remote-endpoint = <&typec_hs>;
> > +				};
> > +			};
> > +		};
> > +	};
> > +
> > +	sensor_mb: temperature-sensor@1e {
> > +		compatible = "nxp,se97b", "jedec,jc-42.4-temp";
> > +		reg = <0x1e>;
> > +	};
> > +
> > +	eeprom_mb: eeprom@56 {
> > +		compatible = "nxp,se97b", "atmel,24c02";
> > +		reg = <0x56>;
> > +		pagesize = <16>;
> > +		vcc-supply = <&reg_v3v3_mb>;
> > +	};
> > +
> > +	pcieclk: clock-generator@68 {
> > +		compatible = "renesas,9fgv0441";
> > +		reg = <0x68>;
> > +		clocks = <&clk_xtal25>;
> > +		#clock-cells = <1>;
> > +	};
> > +
> > +	/* D39 IN/OUT 3V3 */
> > +	expander1: gpio@74 {
> > +		compatible = "ti,tca9539";
> > +		reg = <0x74>;
> > +		vcc-supply = <&reg_v3v3_mb>;
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_expander1>;
> > +		gpio-controller;
> > +		#gpio-cells = <2>;
> > +		interrupt-controller;
> > +		#interrupt-cells = <2>;
> > +		interrupt-parent = <&gpio2>;
> > +		interrupts = <14 IRQ_TYPE_EDGE_FALLING>;
> > +
> > +		gpio-line-names =
> > +			/* 00 */ "BUTTON_B#", "CAM0_SYNC_3V3",
> > +			/* 02 */ "CAM1_SYNC_3V3", "SFP_MOD_ABS",
> > +			/* 04 */ "DIG_IN1", "DIG_IN2",
> > +			/* 06 */ "DIG_IN3", "DIG_IN4",
> > +			/* 08 */ "DIG_OUT_1_2_STATE", "DIG_OUT_3_4_STATE",
> > +			/* 10 */ "DIG_OUT_1_EN", "DIG_OUT_2_EN",
> > +			/* 12 */ "DIG_OUT_3_EN", "DIG_OUT_4_EN",
> > +			/* 14 */ "AUDIO_RST#", "12V_EN";
> > +	};
> > +
> > +	/* D40 OUT 3V3 */
> > +	expander2: gpio@75 {
> > +		compatible = "ti,tca9539";
> > +		reg = <0x75>;
> > +		vcc-supply = <&reg_3v3>;
> > +		gpio-controller;
> > +		#gpio-cells = <2>;
> > +
> > +		gpio-line-names =
> > +			/* 00 */ "ETH10G_REFCLK_EN", "ETH10G_REFCLK_RST#",
> > +			/* 02 */ "SFP_TX_DIS", "USB3_RESET#",
> > +			/* 04 */ "USB2_RESET#", "LCD_RESET#",
> > +			/* 06 */ "LCD_BLT_EN", "LCD_PWR_EN",
> > +			/* 08 */ "M2_KEYE_PERST#", "M2_KEYE_WDISABLE1#",
> > +			/* 10 */ "M2_KEYE_WDISABLE2#", "M2_KEYB_PERST#",
> > +			/* 12 */ "M2_KEYB_WDISABLE1#", "USER_LED1",
> > +			/* 14 */ "USER_LED2", "3V3A_10G_EN";
> > +
> > +		eth10g-refclk-en-hog {
> > +			gpio-hog;
> > +			gpios = <0 GPIO_ACTIVE_HIGH>;
> > +			output-high;
> > +			line-name = "ETH10G_REFCLK_EN";
> > +		};
> > +
> > +		eth10g-refclk-rst-hog {
> > +			gpio-hog;
> > +			gpios = <1 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "ETH10G_REFCLK_RST#";
> > +		};
> > +
> > +		m2_keye_wdisable1_hog: m2-keye-wdisable1-hog {
> > +			gpio-hog;
> > +			gpios = <9 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYE_WDISABLE1#";
> > +		};
> > +
> > +		m2_keye_wdisable2_hog: m2-keye-wdisable2-hog {
> > +			gpio-hog;
> > +			gpios = <10 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYE_WDISABLE2#";
> > +		};
> > +
> > +		m2-keyb-wdisable1-hog {
> > +			gpio-hog;
> > +			gpios = <12 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYB_WDISABLE1#";
> > +		};
> > +	};
> > +
> > +	/* D41 OUT 1V8 */
> > +	expander3: gpio@76 {
> > +		compatible = "ti,tca9539";
> > +		reg = <0x76>;
> > +		vcc-supply = <&reg_v1v8_mb>;
> > +		gpio-controller;
> > +		#gpio-cells = <2>;
> > +
> > +		gpio-line-names =
> > +			/* 00 */ "ENET1_RESET#", "ENET2_RESET#",
> > +			/* 02 */ "M2_KEYE_SDIO_RST#", "M2_KEYE_DEV_WLAN_WAKE#",
> > +			/* 04 */ "M2_KEYE_DEV_BT_WAKE", "M2_KEYB_W_DISABLE2#",
> > +			/* 06 */ "M2_KEYB_RST#", "M2_KEYB_FULL_CARD_PWR_OFF#",
> > +			/* 08 */ "M2_KEYB_DPR", "CAM0_PWR#",
> > +			/* 10 */ "CAM1_PWR#", "CAM0_RST#",
> > +			/* 12 */ "CAM1_RST#", "CAM0_TRIGGER",
> > +			/* 14 */ "CAM1_TRIGGER", "FAN_PWR_EN";
> > +
> > +		m2-keye-sdio-rst-hog {
> > +			gpio-hog;
> > +			gpios = <2 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYE_SDIO_RST#";
> > +		};
> > +
> > +		m2-keye-dev_wlan-wake-hog {
> > +			gpio-hog;
> > +			gpios = <3 GPIO_ACTIVE_LOW>;
> > +			input;
> > +			line-name = "M2_KEYE_DEV_WLAN_WAKE#";
> > +		};
> > +
> > +		m2-keye-dev_bt-wake-hog {
> > +			gpio-hog;
> > +			gpios = <4 GPIO_ACTIVE_LOW>;
> > +			input;
> > +			line-name = "M2_KEYE_DEV_BT_WAKE#";
> > +		};
> > +
> > +		m2-keyb-wdisable2-hog {
> > +			gpio-hog;
> > +			gpios = <5 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYB_WDISABLE1#";
> > +		};
> > +
> > +		m2-keyb-rst-hog {
> > +			gpio-hog;
> > +			gpios = <6 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYB_RST#";
> > +		};
> > +
> > +		m2-keyb-full-card-pwr-off-hog {
> > +			gpio-hog;
> > +			gpios = <7 GPIO_ACTIVE_LOW>;
> > +			output-low;
> > +			line-name = "M2_KEYB_FULL_CARD_PWR_OFF#";
> > +		};
> > +	};
> > +};
> > +
> > +/* X4 + XFP */
> > +&lpi2c7 {
> > +	clock-frequency = <400000>;
> > +	pinctrl-names = "default", "gpio";
> > +	pinctrl-0 = <&pinctrl_lpi2c7>;
> > +	pinctrl-1 = <&pinctrl_lpi2c7_recovery>;
> > +	scl-gpios = <&gpio2 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> > +	sda-gpios = <&gpio2 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> > +	status = "okay";
> > +
> > +	/* TODO: 0x19: retimer */
> > +
> > +	/* 0x50 / 0x51: SFP EEPROM */
> > +};
> > +
> > +/* X4 */
> > +&lpspi4 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpspi4>;
> > +	cs-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>, <&gpio5 14 GPIO_ACTIVE_LOW>;
> > +	status = "okay";
> > +};
> > +
> > +&lpuart1 {
> > +	/* console */
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpuart1>;
> > +	status = "okay";
> > +};
> > +
> > +&lpuart2 {
> > +	/* SM */
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpuart2>;
> > +	status = "reserved";
> > +};
> > +
> > +&lpuart5 {
> > +	/* X16 M.2 KEY E */
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpuart5>;
> > +	status = "okay";
> > +};
> > +
> > +&lpuart7 {
> > +	/* X5 */
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpuart7>;
> > +	status = "okay";
> > +};
> > +
> > +&lpuart8 {
> > +	/* X15 */
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpuart8>;
> > +	linux,rs485-enabled-at-boot-time;
> > +	status = "okay";
> > +};
> > +
> > +&netc_blk_ctrl {
> > +	status = "okay";
> > +};
> > +
> > +&netc_emdio {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_emdio>;
> > +	status = "okay";
> > +
> > +	/* IRQ pin is AON GPIO, not usable */
> > +	ethphy0: ethernet-phy@0 {
> > +		compatible = "ethernet-phy-ieee802.3-c22";
> > +		reg = <0>;
> > +		reset-gpios = <&expander3 0 GPIO_ACTIVE_LOW>;
> > +		reset-assert-us = <500000>;
> > +		reset-deassert-us = <50000>;
> > +		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
> > +		ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
> > +		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
> > +		ti,dp83867-rxctrl-strap-quirk;
> > +		ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
> > +	};
> > +
> > +	ethphy1: ethernet-phy@1 {
> > +		compatible = "ethernet-phy-ieee802.3-c22";
> > +		reg = <1>;
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_ethphy1>;
> > +		reset-gpios = <&expander3 1 GPIO_ACTIVE_LOW>;
> > +		reset-assert-us = <500000>;
> > +		reset-deassert-us = <50000>;
> > +		interrupt-parent = <&gpio4>;
> > +		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
> > +		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
> > +		ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_50_NS>;
> > +		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
> > +		ti,dp83867-rxctrl-strap-quirk;
> > +		ti,clk-output-sel = <DP83867_CLK_O_SEL_OFF>;
> > +	};
> > +};
> > +
> > +&netc_timer {
> > +	status = "okay";
> > +};
> > +
> > +&netcmix_blk_ctrl {
> > +	status = "okay";
> > +};
> > +
> > +/* X16 M2 / E-Key mPCIe */
> > +&pcie0 {
> > +	pinctrl-0 = <&pinctrl_pcie0>;
> > +	pinctrl-names = "default";
> > +	clocks = <&scmi_clk IMX95_CLK_HSIO>,
> > +		 <&scmi_clk IMX95_CLK_HSIOPLL>,
> > +		 <&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
> > +		 <&scmi_clk IMX95_CLK_HSIOPCIEAUX>,
> > +		 <&pcieclk 1>;
> > +	clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux", "ref";
> > +	reset-gpios = <&expander2 8 GPIO_ACTIVE_LOW>;
> > +	/* Not supported on REV.0100 */
> > +	/* supports-clkreq; */
> > +	status = "okay";
> > +};
> > +
> > +/* X17 M2 / B-Key PCIe */
> > +&pcie1 {
> > +	pinctrl-0 = <&pinctrl_pcie1>;
> > +	pinctrl-names = "default";
> > +	clocks = <&scmi_clk IMX95_CLK_HSIO>,
> > +		 <&scmi_clk IMX95_CLK_HSIOPLL>,
> > +		 <&scmi_clk IMX95_CLK_HSIOPLL_VCO>,
> > +		 <&scmi_clk IMX95_CLK_HSIOPCIEAUX>,
> > +		 <&pcieclk 0>;
> > +	clock-names = "pcie", "pcie_bus", "pcie_phy", "pcie_aux", "ref";
> > +	reset-gpios = <&expander2 11 GPIO_ACTIVE_LOW>;
> > +	/* Not supported on REV.0100 */
> > +	/* supports-clkreq; */
> > +	status = "okay";
> > +};
> > +
> > +&reg_sdvmmc {
> > +	status = "okay";
> > +};
> > +
> > +&sai3 {
> > +	#sound-dai-cells = <0>;
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_sai3>;
> > +	assigned-clocks = <&scmi_clk IMX95_CLK_AUDIOPLL1_VCO>,
> > +			  <&scmi_clk IMX95_CLK_AUDIOPLL2_VCO>,
> > +			  <&scmi_clk IMX95_CLK_AUDIOPLL1>,
> > +			  <&scmi_clk IMX95_CLK_AUDIOPLL2>,
> > +			  <&scmi_clk IMX95_CLK_SAI3>;
> > +	assigned-clock-parents = <0>, <0>, <0>, <0>,
> > +				 <&scmi_clk IMX95_CLK_AUDIOPLL1>;
> > +	assigned-clock-rates = <3932160000>,
> > +			       <3612672000>, <393216000>,
> > +			       <361267200>, <12288000>;
> > +	fsl,sai-mclk-direction-output;
> > +	status = "okay";
> > +};
> > +
> > +&scmi_bbm {
> > +	linux,code = <KEY_POWER>;
> > +};
> > +
> > +&thermal_zones {
> > +	a55-thermal {
> > +		trips {
> > +			cpu_active0: trip-active0 {
> > +				temperature = <40000>;
> > +				hysteresis = <5000>;
> > +				type = "active";
> > +			};
> > +
> > +			cpu_active1: trip-active1 {
> > +				temperature = <48000>;
> > +				hysteresis = <3000>;
> > +				type = "active";
> > +			};
> > +
> > +			cpu_active2: trip-active2 {
> > +				temperature = <60000>;
> > +				hysteresis = <10000>;
> > +				type = "active";
> > +			};
> > +		};
> > +
> > +		cooling-maps {
> > +			map1 {
> > +				trip = <&cpu_active0>;
> > +				cooling-device = <&fan 0 2>;
> > +			};
> > +
> > +			map2 {
> > +				trip = <&cpu_active1>;
> > +				cooling-device = <&fan 3 5>;
> > +			};
> > +
> > +			map3 {
> > +				trip = <&cpu_active2>;
> > +				cooling-device = <&fan 6 10>;
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +&tpm3 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_tpm3>;
> > +	status = "okay";
> > +};
> > +
> > +&tpm5 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_tpm5>;
> > +};
> > +
> > +&usb2 {
> > +	dr_mode = "otg";
> > +	hnp-disable;
> > +	srp-disable;
> > +	adp-disable;
> > +	usb-role-switch;
> > +	disable-over-current;
> > +	samsung,picophy-pre-emp-curr-control = <3>;
> > +	samsung,picophy-dc-vol-level-adjust = <7>;
> > +	status = "okay";
> > +
> > +	port {
> > +		typec_hs: endpoint {
> > +			remote-endpoint = <&typec_con_hs>;
> > +		};
> > +	};
> > +};
> > +
> > +&usb3 {
> > +	status = "okay";
> > +};
> > +
> > +&usb3_dwc3 {
> > +	dr_mode = "host";
> > +	#address-cells = <1>;
> > +	#size-cells = <0>;
> > +	status = "okay";
> > +
> > +	hub_2_0: hub@1 {
> > +		compatible = "usb451,8142";
> > +		reg = <1>;
> > +		peer-hub = <&hub_3_0>;
> > +		reset-gpios = <&expander2 3 GPIO_ACTIVE_LOW>;
> > +		vdd-supply = <&reg_v3v3_mb>;
> > +		#address-cells = <1>;
> > +		#size-cells = <0>;
> > +
> > +		hub_2_1: hub@1 {
> > +			compatible = "usb424,2514";
> > +			reg = <1>;
> > +			reset-gpios = <&expander2 4 GPIO_ACTIVE_LOW>;
> > +			vdd-supply = <&reg_v3v3_mb>;
> > +			vdda-supply = <&reg_v3v3_mb>;
> > +		};
> > +	};
> > +
> > +	hub_3_0: hub@2 {
> > +		compatible = "usb451,8140";
> > +		reg = <2>;
> > +		peer-hub = <&hub_2_0>;
> > +		reset-gpios = <&expander2 3 GPIO_ACTIVE_LOW>;
> > +		vdd-supply = <&reg_v3v3_mb>;
> > +	};
> > +};
> > +
> > +&usb3_phy {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_usb3>;
> > +	vbus-supply = <&reg_vbus_usb3>;
> > +	status = "okay";
> > +};
> > +
> > +/* X7 µSD */
> > +&usdhc2 {
> > +	pinctrl-names = "default", "state_100mhz", "state_200mhz";
> > +	pinctrl-0 = <&pinctrl_usdhc2>;
> > +	pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
> > +	pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
> > +	vmmc-supply = <&reg_sdvmmc>;
> > +	cd-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
> > +	no-mmc;
> > +	no-sdio;
> > +	disable-wp;
> > +	bus-width = <4>;
> > +	status = "okay";
> > +};
> > +
> > +&scmi_iomuxc {
> > +	pinctrl_enetc0: enetc0grp {
> > +		fsl,pins = <IMX95_PAD_ENET1_RD0__NETCMIX_TOP_ETH0_RGMII_RD0		0x1100>,
> > +			   <IMX95_PAD_ENET1_RD1__NETCMIX_TOP_ETH0_RGMII_RD1		0x1100>,
> > +			   <IMX95_PAD_ENET1_RD2__NETCMIX_TOP_ETH0_RGMII_RD2		0x1100>,
> > +			   <IMX95_PAD_ENET1_RD3__NETCMIX_TOP_ETH0_RGMII_RD3		0x1100>,
> > +			   <IMX95_PAD_ENET1_RXC__NETCMIX_TOP_ETH0_RGMII_RX_CLK		0x1100>,
> > +			   <IMX95_PAD_ENET1_RX_CTL__NETCMIX_TOP_ETH0_RGMII_RX_CTL	0x1100>,
> > +			   <IMX95_PAD_ENET1_TD0__NETCMIX_TOP_ETH0_RGMII_TD0		0x11e>,
> > +			   <IMX95_PAD_ENET1_TD1__NETCMIX_TOP_ETH0_RGMII_TD1		0x11e>,
> > +			   <IMX95_PAD_ENET1_TD2__NETCMIX_TOP_ETH0_RGMII_TD2		0x11e>,
> > +			   <IMX95_PAD_ENET1_TD3__NETCMIX_TOP_ETH0_RGMII_TD3		0x11e>,
> > +			   <IMX95_PAD_ENET1_TXC__NETCMIX_TOP_ETH0_RGMII_TX_CLK		0x11e>,
> > +			   <IMX95_PAD_ENET1_TX_CTL__NETCMIX_TOP_ETH0_RGMII_TX_CTL	0x11e>;
> > +	};
> > +
> > +	pinctrl_enetc1: enetc1grp {
> > +		fsl,pins = <IMX95_PAD_ENET2_RD0__NETCMIX_TOP_ETH1_RGMII_RD0		0x1100>,
> > +			   <IMX95_PAD_ENET2_RD1__NETCMIX_TOP_ETH1_RGMII_RD1		0x1100>,
> > +			   <IMX95_PAD_ENET2_RD2__NETCMIX_TOP_ETH1_RGMII_RD2		0x1100>,
> > +			   <IMX95_PAD_ENET2_RD3__NETCMIX_TOP_ETH1_RGMII_RD3		0x1100>,
> > +			   <IMX95_PAD_ENET2_RXC__NETCMIX_TOP_ETH1_RGMII_RX_CLK		0x1100>,
> > +			   <IMX95_PAD_ENET2_RX_CTL__NETCMIX_TOP_ETH1_RGMII_RX_CTL	0x1100>,
> > +			   <IMX95_PAD_ENET2_TD0__NETCMIX_TOP_ETH1_RGMII_TD0		0x11e>,
> > +			   <IMX95_PAD_ENET2_TD1__NETCMIX_TOP_ETH1_RGMII_TD1		0x11e>,
> > +			   <IMX95_PAD_ENET2_TD2__NETCMIX_TOP_ETH1_RGMII_TD2		0x11e>,
> > +			   <IMX95_PAD_ENET2_TD3__NETCMIX_TOP_ETH1_RGMII_TD3		0x11e>,
> > +			   <IMX95_PAD_ENET2_TXC__NETCMIX_TOP_ETH1_RGMII_TX_CLK		0x11e>,
> > +			   <IMX95_PAD_ENET2_TX_CTL__NETCMIX_TOP_ETH1_RGMII_TX_CTL	0x11e>;
> > +	};
> > +
> > +	pinctrl_ethphy0: ethphy0grp {
> > +		fsl,pins = <IMX95_PAD_PDM_BIT_STREAM0__AONMIX_TOP_GPIO1_IO_BIT9		0x1100>;
> > +	};
> > +
> > +	pinctrl_ethphy1: ethphy1grp {
> > +		fsl,pins = <IMX95_PAD_ENET1_MDC__GPIO4_IO_BIT0				0x1100>;
> > +	};
> > +
> > +	pinctrl_expander1: expander1grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO14__GPIO2_IO_BIT14				0x1100>;
> > +	};
> > +
> > +	pinctrl_flexcan1: flexcan1grp {
> > +		fsl,pins = <IMX95_PAD_SAI1_TXC__AONMIX_TOP_CAN1_RX		0x1300>,
> > +			   <IMX95_PAD_SAI1_TXD0__AONMIX_TOP_CAN1_TX		0x31e>;
> > +	};
> > +
> > +	pinctrl_flexcan2: flexcan2grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO25__CAN2_TX		0x31e>,
> > +			   <IMX95_PAD_GPIO_IO27__CAN2_RX		0x1300>;
> > +	};
> > +
> > +	pinctrl_lpi2c7: lpi2c7grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO07__LPI2C7_SCL	0x40001b1e>,
> > +			   <IMX95_PAD_GPIO_IO06__LPI2C7_SDA	0x40001b1e>;
> > +	};
> > +
> > +	pinctrl_lpi2c7_recovery: lpi2c7recoverygrp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO07__GPIO2_IO_BIT7	0x40001b1e>,
> > +			   <IMX95_PAD_GPIO_IO06__GPIO2_IO_BIT6	0x40001b1e>;
> > +	};
> > +
> > +	pinctrl_lpspi4: lpspi4grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO37__LPSPI4_SCK	0x91e>,
> > +			   <IMX95_PAD_GPIO_IO19__LPSPI5_SIN	0x191e>,
> > +			   <IMX95_PAD_GPIO_IO36__LPSPI4_SOUT	0x91e>,
> > +			   <IMX95_PAD_GPIO_IO34__GPIO5_IO_BIT14	0x91e>,
> > +			   <IMX95_PAD_GPIO_IO33__GPIO5_IO_BIT13	0x91e>;
> > +	};
> > +
> > +	pinctrl_lpuart1: lpuart1grp {
> > +		fsl,pins = <IMX95_PAD_UART1_TXD__AONMIX_TOP_LPUART1_TX		0x31e>,
> > +			   <IMX95_PAD_UART1_RXD__AONMIX_TOP_LPUART1_RX		0x1300>;
> > +	};
> > +
> > +	pinctrl_lpuart2: lpuart2grp {
> > +		fsl,pins = <IMX95_PAD_UART2_TXD__AONMIX_TOP_LPUART2_TX		0x31e>,
> > +			   <IMX95_PAD_UART2_RXD__AONMIX_TOP_LPUART2_RX		0x1300>;
> > +	};
> > +
> > +	pinctrl_lpuart5: lpuart5grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO00__LPUART5_TX			0x31e>,
> > +			   <IMX95_PAD_GPIO_IO01__LPUART5_RX			0x1300>,
> > +			   <IMX95_PAD_GPIO_IO02__LPUART5_CTS_B			0x1300>,
> > +			   <IMX95_PAD_GPIO_IO03__LPUART5_RTS_B			0x31e>;
> > +	};
> > +
> > +	pinctrl_lpuart7: lpuart7grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO08__LPUART7_TX			0x31e>,
> > +			   <IMX95_PAD_GPIO_IO09__LPUART7_RX			0x1300>,
> > +			   <IMX95_PAD_GPIO_IO10__LPUART7_CTS_B			0x1300>,
> > +			   <IMX95_PAD_GPIO_IO11__LPUART7_RTS_B			0x31e>;
> > +	};
> > +
> > +	pinctrl_lpuart8: lpuart8grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO12__LPUART8_TX			0x31e>,
> > +			   <IMX95_PAD_GPIO_IO13__LPUART8_RX			0x1300>,
> > +			   <IMX95_PAD_GPIO_IO15__LPUART8_RTS_B			0x31e>;
> > +	};
> > +
> > +	pinctrl_emdio: emdiogrp {
> > +		fsl,pins = <IMX95_PAD_ENET2_MDC__NETCMIX_TOP_NETC_MDC		0x51e>,
> > +			   <IMX95_PAD_ENET2_MDIO__NETCMIX_TOP_NETC_MDIO		0x51e>;
> > +	};
> > +
> > +	pinctrl_pcie0: pcie0grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO32__HSIOMIX_TOP_PCIE1_CLKREQ_B	0x111e>;
> > +	};
> > +
> > +	pinctrl_pcie1: pcie1grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO35__HSIOMIX_TOP_PCIE2_CLKREQ_B	0x111e>;
> > +	};
> > +
> > +	pinctrl_sai3: sai3grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO16__SAI3_TX_BCLK			0x51e>,
> > +			   <IMX95_PAD_GPIO_IO17__SAI3_MCLK			0x51e>,
> > +			   <IMX95_PAD_GPIO_IO20__SAI3_RX_DATA_BIT0		0x1300>,
> > +			   <IMX95_PAD_GPIO_IO21__SAI3_TX_DATA_BIT0		0x51e>,
> > +			   <IMX95_PAD_GPIO_IO26__SAI3_TX_SYNC			0x51e>;
> > +	};
> > +
> > +	pinctrl_retimer: retirmergrp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO29__GPIO2_IO_BIT29			0x1100>;
> > +	};
> > +
> > +	pinctrl_sfp: sfpgrp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO30__GPIO2_IO_BIT30			0x1100>,
> > +			   <IMX95_PAD_GPIO_IO31__GPIO2_IO_BIT31			0x1100>;
> > +	};
> > +
> > +	pinctrl_tpm3: tpm3grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO24__TPM3_CH3			0x51e>;
> > +	};
> > +
> > +	pinctrl_tpm5: tpm5grp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO18__TPM5_CH2			0x51e>;
> > +	};
> > +
> > +	pinctrl_typec: typcegrp {
> > +		fsl,pins = <IMX95_PAD_GPIO_IO28__GPIO2_IO_BIT28			0x1100>;
> > +	};
> > +
> > +	pinctrl_usb3: usb3grp {
> > +		fsl,pins = <IMX95_PAD_ENET1_MDIO__GPIO4_IO_BIT1			0x31e>;
> > +	};
> > +
> > +	pinctrl_usdhc2: usdhc2grp {
> > +		fsl,pins = <IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0			0x1100>,
> > +			   <IMX95_PAD_SD2_CLK__USDHC2_CLK			0x51e>,
> > +			   <IMX95_PAD_SD2_CMD__USDHC2_CMD			0x31e>,
> > +			   <IMX95_PAD_SD2_DATA0__USDHC2_DATA0			0x131e>,
> > +			   <IMX95_PAD_SD2_DATA1__USDHC2_DATA1			0x131e>,
> > +			   <IMX95_PAD_SD2_DATA2__USDHC2_DATA2			0x131e>,
> > +			   <IMX95_PAD_SD2_DATA3__USDHC2_DATA3			0x131e>,
> > +			   <IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT		0x51e>;
> > +	};
> > +
> > +	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
> > +		fsl,pins = <IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0			0x1100>,
> > +			   <IMX95_PAD_SD2_CLK__USDHC2_CLK			0x58e>,
> > +			   <IMX95_PAD_SD2_CMD__USDHC2_CMD			0x38e>,
> > +			   <IMX95_PAD_SD2_DATA0__USDHC2_DATA0			0x138e>,
> > +			   <IMX95_PAD_SD2_DATA1__USDHC2_DATA1			0x138e>,
> > +			   <IMX95_PAD_SD2_DATA2__USDHC2_DATA2			0x138e>,
> > +			   <IMX95_PAD_SD2_DATA3__USDHC2_DATA3			0x138e>,
> > +			   <IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT		0x51e>;
> > +	};
> > +
> > +	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
> > +		fsl,pins = <IMX95_PAD_SD2_CD_B__GPIO3_IO_BIT0			0x1100>,
> > +			   <IMX95_PAD_SD2_CLK__USDHC2_CLK			0x5fe>,
> > +			   <IMX95_PAD_SD2_CMD__USDHC2_CMD			0x3fe>,
> > +			   <IMX95_PAD_SD2_DATA0__USDHC2_DATA0			0x13fe>,
> > +			   <IMX95_PAD_SD2_DATA1__USDHC2_DATA1			0x13fe>,
> > +			   <IMX95_PAD_SD2_DATA2__USDHC2_DATA2			0x13fe>,
> > +			   <IMX95_PAD_SD2_DATA3__USDHC2_DATA3			0x13fe>,
> > +			   <IMX95_PAD_SD2_VSELECT__USDHC2_VSELECT		0x51e>;
> > +	};
> > +};
> > diff --git a/arch/arm64/boot/dts/freescale/imx95-tqma9596la.dtsi b/arch/arm64/boot/dts/freescale/imx95-tqma9596la.dtsi
> > new file mode 100644
> > index 0000000000000..cc572171bf253
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/freescale/imx95-tqma9596la.dtsi
> > @@ -0,0 +1,297 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT)
> > +/*
> > + * Copyright (c) 2024-2026 TQ-Systems GmbH <linux@ew.tq-group.com>,
> > + * D-82229 Seefeld, Germany.
> > + * Author: Alexander Stein
> > + * Author: Markus Niebel
> > + */
> > +
> > +/dts-v1/;
> > +
> > +#include <dt-bindings/gpio/gpio.h>
> > +#include "imx95.dtsi"
> > +
> > +/ {
> > +	memory@80000000 {
> > +		device_type = "memory";
> > +		/*
> > +		 * DRAM base addr, size : 2048 MiB DRAM
> > +		 * should be corrected by bootloader
> > +		 */
> > +		reg = <0 0x80000000 0 0x80000000>;
> > +	};
> > +
> > +	reserved-memory {
> > +		#address-cells = <2>;
> > +		#size-cells = <2>;
> > +		ranges;
> > +
> > +		linux_cma: linux,cma {
> > +			compatible = "shared-dma-pool";
> > +			reusable;
> > +			size = <0 0x28000000>;
> > +			alloc-ranges = <0 0x80000000 0 0x80000000>;
> > +			linux,cma-default;
> > +		};
> > +
> > +		vpu_boot: vpu_boot@a0000000 {
> > +			reg = <0 0xa0000000 0 0x100000>;
> > +			no-map;
> > +		};
> > +	};
> > +
> > +	reg_1v8: regulator-1v8 {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "V_1V8";
> > +		regulator-min-microvolt = <1800000>;
> > +		regulator-max-microvolt = <1800000>;
> > +		regulator-always-on;
> > +	};
> > +
> > +	reg_3v3: regulator-3v3 {
> > +		compatible = "regulator-fixed";
> > +		regulator-name = "V_3V3";
> > +		regulator-min-microvolt = <3300000>;
> > +		regulator-max-microvolt = <3300000>;
> > +		regulator-always-on;
> > +	};
> > +
> > +	reg_sdvmmc: regulator-sdvmmc {
> > +		compatible = "regulator-fixed";
> > +		pinctrl-names = "default";
> > +		pinctrl-0 = <&pinctrl_sdvmmc>;
> > +		regulator-name = "SD_PWR_EN";
> > +		regulator-min-microvolt = <3300000>;
> > +		regulator-max-microvolt = <3300000>;
> > +		gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>;
> > +		off-on-delay-us = <12000>;
> > +		enable-active-high;
> > +		/* can be enabled by mainboard with SD-Card support */
> > +		status = "disabled";
> > +	};
> > +};
> > +
> > +&adc1 {
> > +	vref-supply = <&reg_1v8>;
> > +};
> > +
> > +&flexspi1 {
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_flexspi1>;
> > +	status = "okay";
> > +
> > +	flash0: flash@0 {
> > +		compatible = "jedec,spi-nor";
> > +		reg = <0>;
> > +		spi-max-frequency = <66000000>;
> > +		spi-tx-bus-width = <4>;
> > +		spi-rx-bus-width = <4>;
> > +		vcc-supply = <&reg_1v8>;
> > +
> > +		partitions {
> > +			compatible = "fixed-partitions";
> > +			#address-cells = <1>;
> > +			#size-cells = <1>;
> > +		};
> > +	};
> > +};
> > +
> > +/* System Manager */
> > +&gpio1 {
> > +	status = "reserved";
> > +};
> > +
> > +/* System Manager */
> > +&lpi2c1 {
> > +	status = "reserved";
> > +};
> > +
> > +&lpi2c2 {
> > +	clock-frequency = <400000>;
> > +	pinctrl-names = "default";
> > +	pinctrl-0 = <&pinctrl_lpi2c2>;
> > +	status = "okay";
> > +
> > +	pcf85063: rtc@51 {
> > +		compatible = "nxp,pcf85063a";
> > +		reg = <0x51>;
> > +		quartz-load-femtofarads = <7000>;
> > +	};
> > +
> > +	m24c64: eeprom@54 {
> > +		compatible = "atmel,24c64";
> > +		reg = <0x54>;
> > +		pagesize = <32>;
> > +		vcc-supply = <&reg_3v3>;
> > +	};
> > +
> > +	/* protectable identification memory (part of M24C64-D @54) */
> > +	eeprom@5c {
> > +		compatible = "atmel,24c64d-wl";
> > +		reg = <0x5c>;
> > +		pagesize = <32>;
> > +		vcc-supply = <&reg_3v3>;
> > +	};
> > +
> > +	imu@6b {
> > +		compatible = "st,ism330dhcx";
> > +		reg = <0x6b>;
> > +		vdd-supply = <&reg_3v3>;
> > +		vddio-supply = <&reg_3v3>;
> > +	};
> > +};
> > +
> > +&thermal_zones {
> > +	pf09-thermal {
> > +		polling-delay = <2000>;
> > +		polling-delay-passive = <250>;
> > +		thermal-sensors = <&scmi_sensor 2>;
> > +
> > +		trips {
> > +			pf09_alert: trip0 {
> > +				hysteresis = <2000>;
> > +				temperature = <140000>;
> > +				type = "passive";
> > +			};
> > +
> > +			pf09_crit: trip1 {
> > +				hysteresis = <2000>;
> > +				temperature = <155000>;
> > +				type = "critical";
> > +			};
> > +		};
> > +	};
> > +
> > +	pf53arm-thermal {
> > +		polling-delay = <2000>;
> > +		polling-delay-passive = <250>;
> > +		thermal-sensors = <&scmi_sensor 4>;
> > +
> > +		cooling-maps {
> > +			map0 {
> > +				trip = <&pf5301_alert>;
> > +				cooling-device =
> > +					<&A55_0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > +					<&A55_1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > +					<&A55_2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > +					<&A55_3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > +					<&A55_4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
> > +					<&A55_5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
> > +			};
> > +		};
> > +
> > +		trips {
> > +			pf5301_alert: trip0 {
> > +				hysteresis = <2000>;
> > +				temperature = <140000>;
> > +				type = "passive";
> > +			};
> > +
> > +			pf5301_crit: trip1 {
> > +				hysteresis = <2000>;
> > +				temperature = <155000>;
> > +				type = "critical";
> > +			};
> > +		};
> > +	};
> > +
> > +	pf53soc-thermal {
> > +		polling-delay = <2000>;
> > +		polling-delay-passive = <250>;
> > +		thermal-sensors = <&scmi_sensor 3>;
> > +
> > +		trips {
> > +			pf5302_alert: trip0 {
> > +				hysteresis = <2000>;
> > +				temperature = <140000>;
> > +				type = "passive";
> > +			};
> > +
> > +			pf5302_crit: trip1 {
> > +				hysteresis = <2000>;
> > +				temperature = <155000>;
> > +				type = "critical";
> > +			};
> > +		};
> > +	};
> > +};
> > +
> > +&usdhc1 {
> > +	pinctrl-names = "default", "state_100mhz", "state_200mhz";
> > +	pinctrl-0 = <&pinctrl_usdhc1>;
> > +	pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
> > +	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
> > +	bus-width = <8>;
> > +	non-removable;
> > +	no-sdio;
> > +	no-sd;
> > +	status = "okay";
> > +};
> > +
> > +&wdog3 {
> > +	status = "okay";
> > +};
> > +
> > +&scmi_iomuxc {
> > +	pinctrl_flexspi1: flexspi1grp {
> > +		fsl,pins = <IMX95_PAD_XSPI1_SS0_B__FLEXSPI1_A_SS0_B	0x19e>,
> > +			   <IMX95_PAD_XSPI1_DATA0__FLEXSPI1_A_DATA_BIT0	0x19e>,
> > +			   <IMX95_PAD_XSPI1_DATA1__FLEXSPI1_A_DATA_BIT1	0x19e>,
> > +			   <IMX95_PAD_XSPI1_DATA2__FLEXSPI1_A_DATA_BIT2	0x19e>,
> > +			   <IMX95_PAD_XSPI1_DATA3__FLEXSPI1_A_DATA_BIT3	0x19e>,
> > +			   /* SION to allow clock loopback from pad */
> > +			   <IMX95_PAD_XSPI1_SCLK__FLEXSPI1_A_SCLK	0x4000019e>,
> > +			   <IMX95_PAD_XSPI1_DQS__FLEXSPI1_A_DQS		0x4000019e>;
> > +	};
> > +
> > +	pinctrl_lpi2c2: lpi2c2grp {
> > +		fsl,pins = <IMX95_PAD_I2C2_SCL__AONMIX_TOP_LPI2C2_SCL	0x4000191e>,
> > +			   <IMX95_PAD_I2C2_SDA__AONMIX_TOP_LPI2C2_SDA	0x4000191e>;
> > +	};
> > +
> > +	pinctrl_sdvmmc: sdvmmcgrp {
> > +		fsl,pins = <IMX95_PAD_SD2_RESET_B__GPIO3_IO_BIT7	0x11e>;
> > +	};
> > +
> > +	pinctrl_usdhc1: usdhc1grp {
> > +		fsl,pins = <IMX95_PAD_SD1_CLK__USDHC1_CLK	0x158e>,
> > +			   <IMX95_PAD_SD1_CMD__USDHC1_CMD	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA0__USDHC1_DATA0	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA1__USDHC1_DATA1	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA2__USDHC1_DATA2	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA3__USDHC1_DATA3	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA4__USDHC1_DATA4	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA5__USDHC1_DATA5	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA6__USDHC1_DATA6	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA7__USDHC1_DATA7	0x138e>,
> > +			   <IMX95_PAD_SD1_STROBE__USDHC1_STROBE	0x158e>;
> > +	};
> > +
> > +	pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp {
> > +		fsl,pins = <IMX95_PAD_SD1_CLK__USDHC1_CLK	0x158e>,
> > +			   <IMX95_PAD_SD1_CMD__USDHC1_CMD	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA0__USDHC1_DATA0	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA1__USDHC1_DATA1	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA2__USDHC1_DATA2	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA3__USDHC1_DATA3	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA4__USDHC1_DATA4	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA5__USDHC1_DATA5	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA6__USDHC1_DATA6	0x138e>,
> > +			   <IMX95_PAD_SD1_DATA7__USDHC1_DATA7	0x138e>,
> > +			   <IMX95_PAD_SD1_STROBE__USDHC1_STROBE	0x158e>;
> > +	};
> > +
> > +	pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp {
> > +		fsl,pins = <IMX95_PAD_SD1_CLK__USDHC1_CLK	0x15fe>,
> > +			   <IMX95_PAD_SD1_CMD__USDHC1_CMD	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA0__USDHC1_DATA0	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA1__USDHC1_DATA1	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA2__USDHC1_DATA2	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA3__USDHC1_DATA3	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA4__USDHC1_DATA4	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA5__USDHC1_DATA5	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA6__USDHC1_DATA6	0x13fe>,
> > +			   <IMX95_PAD_SD1_DATA7__USDHC1_DATA7	0x13fe>,
> > +			   <IMX95_PAD_SD1_STROBE__USDHC1_STROBE	0x15fe>;
> > +	};
> > +};
> >
>
>
> --
> 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

* Re: [PATCH] arm64: traps: Add a macro to simplify the condition codes check
From: Jinjie Ruan @ 2026-04-22  3:06 UTC (permalink / raw)
  To: catalin.marinas, will, mark.rutland, kees, maz, ada.coupriediaz,
	smostafa, leitao, mrigendra.chaubey, linux-arm-kernel,
	linux-kernel
In-Reply-To: <20260320082846.1235016-1-ruanjinjie@huawei.com>



On 3/20/2026 4:28 PM, Jinjie Ruan wrote:
> Add DEFINE_COND_CHECK macro to define the simple __check_* functions
> to simplify the condition codes check.
> 
> No functional changes.

Gentle ping.

> 
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> ---
>  arch/arm64/kernel/traps.c | 59 ++++++++++-----------------------------
>  1 file changed, 15 insertions(+), 44 deletions(-)
> 
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 914282016069..6216fe9e8e42 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -49,45 +49,21 @@
>  #include <asm/system_misc.h>
>  #include <asm/sysreg.h>
>  
> -static bool __kprobes __check_eq(unsigned long pstate)
> -{
> -	return (pstate & PSR_Z_BIT) != 0;
> -}
> -
> -static bool __kprobes __check_ne(unsigned long pstate)
> -{
> -	return (pstate & PSR_Z_BIT) == 0;
> -}
> -
> -static bool __kprobes __check_cs(unsigned long pstate)
> -{
> -	return (pstate & PSR_C_BIT) != 0;
> -}
> -
> -static bool __kprobes __check_cc(unsigned long pstate)
> -{
> -	return (pstate & PSR_C_BIT) == 0;
> -}
> -
> -static bool __kprobes __check_mi(unsigned long pstate)
> -{
> -	return (pstate & PSR_N_BIT) != 0;
> -}
> -
> -static bool __kprobes __check_pl(unsigned long pstate)
> -{
> -	return (pstate & PSR_N_BIT) == 0;
> -}
> -
> -static bool __kprobes __check_vs(unsigned long pstate)
> -{
> -	return (pstate & PSR_V_BIT) != 0;
> -}
> -
> -static bool __kprobes __check_vc(unsigned long pstate)
> -{
> -	return (pstate & PSR_V_BIT) == 0;
> -}
> +#define DEFINE_COND_CHECK(name, flag, expected)			\
> +static bool __kprobes __check_##name(unsigned long pstate)	\
> +{								\
> +	return ((pstate & (flag)) != 0) == (expected);		\
> +}
> +
> +DEFINE_COND_CHECK(eq, PSR_Z_BIT, true)
> +DEFINE_COND_CHECK(ne, PSR_Z_BIT, false)
> +DEFINE_COND_CHECK(cs, PSR_C_BIT, true)
> +DEFINE_COND_CHECK(cc, PSR_C_BIT, false)
> +DEFINE_COND_CHECK(mi, PSR_N_BIT, true)
> +DEFINE_COND_CHECK(pl, PSR_N_BIT, false)
> +DEFINE_COND_CHECK(vs, PSR_V_BIT, true)
> +DEFINE_COND_CHECK(vc, PSR_V_BIT, false)
> +DEFINE_COND_CHECK(al, 0, false)		/* Always true */
>  
>  static bool __kprobes __check_hi(unsigned long pstate)
>  {
> @@ -131,11 +107,6 @@ static bool __kprobes __check_le(unsigned long pstate)
>  	return (temp & PSR_N_BIT) != 0;
>  }
>  
> -static bool __kprobes __check_al(unsigned long pstate)
> -{
> -	return true;
> -}
> -
>  /*
>   * Note that the ARMv8 ARM calls condition code 0b1111 "nv", but states that
>   * it behaves identically to 0b1110 ("al").



^ permalink raw reply

* Re: [PATCH v2] mm/page_alloc: fix initialization of tags of the huge zero folio with init_on_free
From: Lance Yang @ 2026-04-22  2:47 UTC (permalink / raw)
  To: david
  Cc: linux-arm-kernel, catalin.marinas, will, akpm, ljs, Liam.Howlett,
	vbabka, rppt, surenb, mhocko, jackmanb, hannes, ziy, lance.yang,
	ryan.roberts, broonie, dev.jain, linux-kernel, linux-mm, stable
In-Reply-To: <20260421-zerotags-v2-1-05cb1035482e@kernel.org>


On Tue, Apr 21, 2026 at 05:39:07PM +0200, David Hildenbrand (Arm) wrote:
>__GFP_ZEROTAGS semantics are currently a bit weird, but effectively this
>flag is only ever set alongside __GFP_ZERO and __GFP_SKIP_KASAN.
>
>If we run with init_on_free, we will zero out pages during
>__free_pages_prepare(), to skip zeroing on the allocation path.
>
>However, when allocating with __GFP_ZEROTAG set, post_alloc_hook() will
>consequently not only skip clearing page content, but also skip
>clearing tag memory.
>
>Not clearing tags through __GFP_ZEROTAGS is irrelevant for most pages that
>will get mapped to user space through set_pte_at() later: set_pte_at() and
>friends will detect that the tags have not been initialized yet
>(PG_mte_tagged not set), and initialize them.
>
>However, for the huge zero folio, which will be mapped through a PMD
>marked as special, this initialization will not be performed, ending up
>exposing whatever tags were still set for the pages.
>
>The docs (Documentation/arch/arm64/memory-tagging-extension.rst) state
>that allocation tags are set to 0 when a page is first mapped to user
>space. That no longer holds with the huge zero folio when init_on_free
>is enabled.
>
>Fix it by decoupling __GFP_ZEROTAGS from __GFP_ZERO, passing to
>tag_clear_highpages() whether we want to also clear page content.
>
>Invert the meaning of the tag_clear_highpages() return value to have
>clearer semantics.
>
>Reproduced with the huge zero folio by modifying the check_buffer_fill
>arm64/mte selftest to use a 2 MiB area, after making sure that pages have
>a non-0 tag set when freeing (note that, during boot, we will not
>actually initialize tags, but only set KASAN_TAG_KERNEL in the page
>flags).
>
>	$ ./check_buffer_fill
>	1..20
>	...
>	not ok 17 Check initial tags with private mapping, sync error mode and mmap memory
>	not ok 18 Check initial tags with private mapping, sync error mode and mmap/mprotect memory
>	...
>
>This code needs more cleanups; we'll tackle that next, like
>decoupling __GFP_ZEROTAGS from __GFP_SKIP_KASAN.
>
>Fixes: adfb6609c680 ("mm/huge_memory: initialise the tags of the huge zero folio")
>Cc: stable@vger.kernel.org
>Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
>---

Tested this fix on MTE with both kasan=on and kasan=off. Works as
expected in both cases.

Nothing jumped out at me, LGTM!

Tested-by: Lance Yang <lance.yang@linux.dev>


^ permalink raw reply

* Re: [PATCH v7 1/3] dt-bindings: pinctrl: Add aspeed,ast2700-soc0-pinctrl
From: Andrew Jeffery @ 2026-04-22  2:30 UTC (permalink / raw)
  To: Conor Dooley, Billy Tsai
  Cc: Lee Jones, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Joel Stanley, Linus Walleij, Bartosz Golaszewski, Ryan Chen,
	Andrew Jeffery, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, linux-gpio@vger.kernel.org,
	linux-clk@vger.kernel.org
In-Reply-To: <20260421-valid-expanse-ae6b5a9289f2@spud>

On Tue, 2026-04-21 at 18:57 +0100, Conor Dooley wrote:
> Billy, Linus,
> 
> On Tue, Apr 21, 2026 at 06:15:44AM +0000, Billy Tsai wrote:
> > > > > > > > +    properties:
> > > > > > > > +      function:
> > > > > > > > +        enum:
> > > > > > > > +          - EMMC
> > > > > > > > +          - JTAGDDR
> > > > > > > > +          - JTAGM0
> > > > > > > > +          - JTAGPCIEA
> > > > > > > > +          - JTAGPCIEB
> > > > > > > > +          - JTAGPSP
> > > > > > > > +          - JTAGSSP
> > > > > > > > +          - JTAGTSP
> > > > > > > > +          - JTAGUSB3A
> > > > > > > > +          - JTAGUSB3B
> > > > > > > > +          - PCIERC0PERST
> > > > > > > > +          - PCIERC1PERST
> > > > > > > > +          - TSPRSTN
> > > > > > > > +          - UFSCLKI
> > > > > > > > +          - USB2AD0
> > > > > > > > +          - USB2AD1
> > > > > > > > +          - USB2AH
> > > > > > > > +          - USB2AHP
> > > > > > > > +          - USB2AHPD0
> > > > > > > > +          - USB2AXH
> > > > > > > > +          - USB2AXH2B
> > > > > > > > +          - USB2AXHD1
> > > > > > > > +          - USB2AXHP
> > > > > > > > +          - USB2AXHP2B
> > > > > > > > +          - USB2AXHPD1
> > > > > > > > +          - USB2BD0
> > > > > > > > +          - USB2BD1
> > > > > > > > +          - USB2BH
> > > > > > > > +          - USB2BHP
> > > > > > > > +          - USB2BHPD0
> > > > > > > > +          - USB2BXH
> > > > > > > > +          - USB2BXH2A
> > > > > > > > +          - USB2BXHD1
> > > > > > > > +          - USB2BXHP
> > > > > > > > +          - USB2BXHP2A
> > > > > > > > +          - USB2BXHPD1
> > > > > > > > +          - USB3AXH
> > > > > > > > +          - USB3AXH2B
> > > > > > > > +          - USB3AXHD
> > > > > > > > +          - USB3AXHP
> > > > > > > > +          - USB3AXHP2B
> > > > > > > > +          - USB3AXHPD
> > > > > > > > +          - USB3BXH
> > > > > > > > +          - USB3BXH2A
> > > > > > > > +          - USB3BXHD
> > > > > > > > +          - USB3BXHP
> > > > > > > > +          - USB3BXHP2A
> > > > > > > > +          - USB3BXHPD
> > > > > > > > +          - VB
> > > > > > > > +          - VGADDC
> > > > > > > > +
> > > > > > > > +      groups:
> > > > > > > > +        enum:
> > > > > > > > +          - EMMCCDN
> > > > > > > > +          - EMMCG1
> > > > > > > > +          - EMMCG4
> > > > > > > > +          - EMMCG8
> > > > > > > > +          - EMMCWPN
> > > > > > > > +          - JTAG0
> > > > > > > > +          - PCIERC0PERST
> > > > > > > > +          - PCIERC1PERST
> > > > > > > > +          - TSPRSTN
> > > > > > > > +          - UFSCLKI
> > > > > > > > +          - USB2A
> > > > > > > > +          - USB2AAP
> > > > > > > > +          - USB2ABP
> > > > > > > > +          - USB2ADAP
> > > > > > > > +          - USB2AH
> > > > > > > > +          - USB2AHAP
> > > > > > > > +          - USB2B
> > > > > > > > +          - USB2BAP
> > > > > > > > +          - USB2BBP
> > > > > > > > +          - USB2BDBP
> > > > > > > > +          - USB2BH
> > > > > > > > +          - USB2BHBP
> > > > > > > > +          - USB3A
> > > > > > > > +          - USB3AAP
> > > > > > > > +          - USB3ABP
> > > > > > > > +          - USB3B
> > > > > > > > +          - USB3BAP
> > > > > > > > +          - USB3BBP
> > > > > > > > +          - VB0
> > > > > > > > +          - VB1
> > > > > > > > +          - VGADDC
> > > > > > > > +      pins:
> > > > > > > > +        enum:
> > > > > > > > +          - AB13
> > > > > > > > +          - AB14
> > > > > > > > +          - AC13
> > > > > > > > +          - AC14
> > > > > > > > +          - AD13
> > > > > > > > +          - AD14
> > > > > > > > +          - AE13
> > > > > > > > +          - AE14
> > > > > > > > +          - AE15
> > > > > > > > +          - AF13
> > > > > > > > +          - AF14
> > > > > > > > +          - AF15
> > 
> > > > > > > Why do you have groups and pins?
> > > > > > > Is it valid in your device to have groups and pins in the same node?
> > 
> > > > > > The intent is to support both group-based mux selection and
> > > > > > configuration, as well as per-pin configuration.
> > 
> > > > > > In our hardware:
> > > > > > - `function` + `groups` are used for pinmux selection.
> > > > > > - `pins` is used for per-pin configuration (e.g. drive strength,
> > > > > >   bias settings).
> > > > > > - `groups` may also be used for group-level configuration.
> > 
> > > > > > As a result, both `groups` and `pins` may appear in the same node,
> > > > > > but they serve different purposes and do not conflict:
> > > > > > - `groups` selects the mux function and may apply configuration to
> > > > > >   the entire group.
> > > > > > - `pins` allows overriding or specifying configuration for individual
> > > > > >   pins.
> > 
> > > > > > In most cases, only one of them is needed, but both are allowed when
> > > > > > both group-level and per-pin configuration are required.
> > 
> > > > > To be honest, that sounds like your groups are not sufficiently
> > > > > granular and should be reduced such that you can use them for pin
> > > > > settings.
> > 
> > > > The intent was to keep the binding flexible, but in practice the mixed
> > > > use of `groups` and `pins` in the same node is not expected to be used.
> > > > 
> > > > Given that, I agree this flexibility is unnecessary and makes the
> > > > binding semantics less clear. I'll rework the binding to make the
> > > > expected usage explicit rather than allowing combinations that do not
> > > > correspond to a real use case.
> > > > 
> > > > In particular, I'll split the constraints as follows:
> > > > 
> > > > - For pinmux, the presence of `function` will require `groups`, and
> > > >   `pins` will not be allowed. This reflects the hardware design, where
> > > >   the groups are defined by the pins affected by a given mux expression
> > > > 
> > > > - For pin configuration, exactly one of `groups` or `pins` will be
> > > >   required (using oneOf), so that configuration is applied either at
> > > >   group level or per-pin, but not both.
> > > > 
> > > > 
> > > > - if:
> > > >     required:
> > > >       - function
> > > >   then:
> > > >     required:
> > > >       - groups
> > > >     not:
> > > >       required:
> > > >         - pins
> > > >   else:
> > > >     oneOf:
> > > >       - required:
> > > >           - groups
> > > >         not:
> > > >           required:
> > > >             - pins
> > > >       - required:
> > > >           - pins
> > > >         not:
> > > >           required:
> > > >             - groups
> > > > Does this match what you had in mind?
> > 
> > > It's an improvement I think, but I am wondering why you cannot do
> > > without pins entirely and apply pinconf stuff at the group level?
> > > Of course that may not be possible with the current groups, but if you
> > > made the groups more granular, would it be possible?
> > 
> > Within a given group, it is not always the case that all pins share the
> > same configuration requirements (e.g. drive strength or bias settings),
> > so applying pinconf purely at the group level would be too restrictive.
> 
> Right. That's pretty normal.
> 
> > Making the groups more granular to match all possible configuration
> > combinations would not reflect the actual mux granularity and would
> > significantly increase the number of groups.
> 
> > 
> > For example, we have encountered a timing issue due to the PCB layout,
> > where only the eMMC clock pin requires a different drive strength:
> > 
> >   # The EMMCG4 group includes pins AC14, AE15, AD14, AE14, AF14, AB13
> >   # AC14: clock
> >   # AE15: command
> >   # AD14–AB13: data
> > 
> >   pinconf_emmc_clk: emmc-clk-pinconf {
> >       pins = "AC14";
> >       drive-strength = <8>;
> >   };
> > 
> > In this case, applying pin configuration at the group level would affect
> > all pins in the group, which is not desirable. Allowing per-pin
> > configuration via `pins` is therefore necessary.
> > 
> > For this reason, `groups` is used for mux selection, while `pins` is
> > required to express per-pin configuration where needed.
> 
> Right, yeah, I figured your objection to it was because of how
> annoyingly small it would make the groups. I suppose the alternative is
> going without groups and always using pins.

As the author of the pinctrl drivers and bindings for the earlier
Aspeed SoC families, I prefer we don't discard the groups here.

These legacy pin controller designs from Aspeed are quite complex. The
function and group are often not decoupled in the register interface,
but a given mux function may only reflect a subset of the necessary
behaviour for a bus (or it may not). Thus the groups are intended to
reflect the pins implied by the function - they should be neither
under- nor over- specified with respect to the hardware behaviour. I'm
concerned that shifting the group definitions to the devicetree implies
they are more configurable than is the case, and shifts the group
membership of pins away from related information in the driver. I am
more comfortable with the interface being defined in terms of groups
for the purpose of pinmux.

That said, from a pinconf perspective, it needs to be possible to apply
work-arounds for board design issues as Billy described above.

I feel the constraints that Billy proposed above are reasonable. We
shouldn't see both 'groups' and 'pins' in the same node as a
consequence, rather we can use multiple phandles in the pinctrl-0
property to affect the pinmux and pinconf settings required via
separate nodes.

Andrew

^ permalink raw reply

* Re: [PATCH 3/3] MAINTAINERS: add Axiado SGPIO controller
From: Prasad Bolisetty @ 2026-04-22  1:48 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Petar Stepanovic, Tzu-Hao Wei, Swark Yang,
	Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
  Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <cadd1ab2-a70a-4f7f-9bd8-3146ddacc2cc@kernel.org>


On 4/14/2026 7:12 AM, Krzysztof Kozlowski wrote:
> CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.
>
>
> On 14/04/2026 15:48, Petar Stepanovic wrote:
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 67db88b04537..56835c0a1863 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -4234,6 +4234,15 @@ S:     Maintained
>>   F:   Documentation/devicetree/bindings/sound/axentia,*
>>   F:   sound/soc/atmel/tse850-pcm5142.c
>>
>> +AXIADO SGPIO DRIVER
>> +M:   Petar Stepanovic <pstepanovic@axiado.com>
>> +M:   SriNavmani A <srinavmani@axiado.com>
>> +M:   Prasad Bolisetty <pbolisetty@axiado.com>
>
> I also expect reviews from the remaining maintainers, especially in all
> the trivialities like posting very old code patterns.
>
> Best regards,
> Krzysztof

We had an internal review prior to the submission,
and we will double-check the old code pattern in the future.
Thank you for the review, and we will fix all the review comments.



^ permalink raw reply

* Re: [PATCH v7 2/3] dt-bindings: mfd: aspeed,ast2x00-scu: Describe AST2700 SCU0
From: Billy Tsai @ 2026-04-22  1:06 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lee Jones, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
	Andrew Jeffery, Linus Walleij, Bartosz Golaszewski, Ryan Chen,
	Andrew Jeffery, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org, linux-gpio@vger.kernel.org,
	linux-clk@vger.kernel.org
In-Reply-To: <20260421183955.GA1448377-robh@kernel.org>

> > AST2700 consists of two interconnected SoC instances, each with its own
> > System Control Unit (SCU). The SCU0 provides pin control, interrupt
> > controllers, clocks, resets, and address-space mappings for the
> > Secondary and Tertiary Service Processors (SSP and TSP).
> >
> > Describe the SSP/TSP address mappings using the standard
> > memory-region and memory-region-names properties.
> >
> > Disallow legacy child nodes that are not present on AST2700, including
> > p2a-control and smp-memram. The latter is unnecessary as software can
> > access the scratch registers via the SCU syscon.
> >
> > Also allow the AST2700 SoC0 pin controller to be described as a child
> > node of the SCU0, and add an example illustrating the SCU0 layout,
> > including reserved-memory, interrupt controllers, and pinctrl.
> >
> > Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
> > ---
> >  .../bindings/mfd/aspeed,ast2x00-scu.yaml           | 113 +++++++++++++++++++++
> >  1 file changed, 113 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
> > index a87f31fce019..215ff59b38ea 100644
> > --- a/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
> > +++ b/Documentation/devicetree/bindings/mfd/aspeed,ast2x00-scu.yaml
> > @@ -46,6 +46,17 @@ properties:
> >    '#reset-cells':
> >      const: 1
> >
> > +  memory-region:
> > +    items:
> > +      - description: Region mapped through the first SSP address window.
> > +      - description: Region mapped through the second SSP address window.
> > +      - description: Region mapped through the TSP address window.

> blank line

Got it.

> > +  memory-region-names:
> > +    items:
> > +      - const: ssp-0
> > +      - const: ssp-1
> > +      - const: tsp
> > +
> >  patternProperties:
> >    '^p2a-control@[0-9a-f]+$':
> >      description: >
> > @@ -87,6 +98,7 @@ patternProperties:
> >              - aspeed,ast2400-pinctrl
> >              - aspeed,ast2500-pinctrl
> >              - aspeed,ast2600-pinctrl
> > +            - aspeed,ast2700-soc0-pinctrl
> >
> >      required:
> >        - compatible
> > @@ -156,6 +168,30 @@ required:
> >    - '#clock-cells'
> >    - '#reset-cells'
> >
> > +allOf:
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            anyOf:
> > +              - const: aspeed,ast2700-scu0
> > +              - const: aspeed,ast2700-scu1

> More simply expressed as:
> 
> contains:
>   enum:
>     - aspeed,ast2700-scu0
>     - aspeed,ast2700-scu1


Thanks, I’ll follow this simpler approach.

Billy Tsai

^ permalink raw reply

* [PATCH v4 8/8] unwind: arm64: Use sframe to unwind interrupt frames
From: Dylan Hatch @ 2026-04-21 22:52 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

Add unwind_next_frame_sframe() function to unwind by sframe info if
present. Use this method at exception boundaries, falling back to
frame-pointer unwind only on failure. In such failure cases, the
stacktrace is considered unreliable.

During normal unwind, prefer frame pointer unwind (for better
performance) with sframe as a backup.

This change restores the LR behavior originally introduced in commit
c2c6b27b5aa14fa2 ("arm64: stacktrace: unwind exception boundaries"),
But later removed in commit 32ed1205682e ("arm64: stacktrace: Skip
reporting LR at exception boundaries")

This can be done because the sframe data can be used to determine
whether the LR is current for the PC value recovered from pt_regs at the
exception boundary.

Signed-off-by: Weinan Liu <wnliu@google.com>
Reviewed-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
 arch/arm64/include/asm/stacktrace/common.h |   6 +
 arch/arm64/kernel/stacktrace.c             | 246 +++++++++++++++++++--
 2 files changed, 232 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/stacktrace/common.h b/arch/arm64/include/asm/stacktrace/common.h
index 821a8fdd31af..4df68181e1b5 100644
--- a/arch/arm64/include/asm/stacktrace/common.h
+++ b/arch/arm64/include/asm/stacktrace/common.h
@@ -21,6 +21,8 @@ struct stack_info {
  *
  * @fp:          The fp value in the frame record (or the real fp)
  * @pc:          The lr value in the frame record (or the real lr)
+ * @sp:          The sp value at the call site of the current function.
+ * @unreliable:  Stacktrace is unreliable.
  *
  * @stack:       The stack currently being unwound.
  * @stacks:      An array of stacks which can be unwound.
@@ -29,7 +31,11 @@ struct stack_info {
 struct unwind_state {
 	unsigned long fp;
 	unsigned long pc;
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+	unsigned long sp;
+#endif
 
+	bool unreliable;
 	struct stack_info stack;
 	struct stack_info *stacks;
 	int nr_stacks;
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 3ebcf8c53fb0..c935323f393b 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -14,6 +14,7 @@
 #include <linux/sched/debug.h>
 #include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
+#include <linux/sframe.h>
 
 #include <asm/efi.h>
 #include <asm/irq.h>
@@ -26,6 +27,7 @@ enum kunwind_source {
 	KUNWIND_SOURCE_CALLER,
 	KUNWIND_SOURCE_TASK,
 	KUNWIND_SOURCE_REGS_PC,
+	KUNWIND_SOURCE_REGS_LR,
 };
 
 union unwind_flags {
@@ -85,6 +87,9 @@ kunwind_init_from_regs(struct kunwind_state *state,
 	state->regs = regs;
 	state->common.fp = regs->regs[29];
 	state->common.pc = regs->pc;
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+	state->common.sp = regs->sp;
+#endif
 	state->source = KUNWIND_SOURCE_REGS_PC;
 }
 
@@ -103,6 +108,9 @@ kunwind_init_from_caller(struct kunwind_state *state)
 
 	state->common.fp = (unsigned long)__builtin_frame_address(1);
 	state->common.pc = (unsigned long)__builtin_return_address(0);
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+	state->common.sp = (unsigned long)__builtin_frame_address(0);
+#endif
 	state->source = KUNWIND_SOURCE_CALLER;
 }
 
@@ -124,6 +132,9 @@ kunwind_init_from_task(struct kunwind_state *state,
 
 	state->common.fp = thread_saved_fp(task);
 	state->common.pc = thread_saved_pc(task);
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+	state->common.sp = thread_saved_sp(task);
+#endif
 	state->source = KUNWIND_SOURCE_TASK;
 }
 
@@ -181,7 +192,6 @@ int kunwind_next_regs_pc(struct kunwind_state *state)
 	state->regs = regs;
 	state->common.pc = regs->pc;
 	state->common.fp = regs->regs[29];
-	state->regs = NULL;
 	state->source = KUNWIND_SOURCE_REGS_PC;
 	return 0;
 }
@@ -237,6 +247,9 @@ kunwind_next_frame_record(struct kunwind_state *state)
 
 	unwind_consume_stack(&state->common, info, fp, sizeof(*record));
 
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+	state->common.sp = state->common.fp;
+#endif
 	state->common.fp = new_fp;
 	state->common.pc = new_pc;
 	state->source = KUNWIND_SOURCE_FRAME;
@@ -244,6 +257,176 @@ kunwind_next_frame_record(struct kunwind_state *state)
 	return 0;
 }
 
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+static __always_inline struct stack_info *
+get_word(struct unwind_state *state, unsigned long *word)
+{
+	unsigned long addr = *word;
+	struct stack_info *info;
+
+	info = unwind_find_stack(state, addr, sizeof(addr));
+	if (!info)
+		return info;
+
+	*word = READ_ONCE(*(unsigned long *)addr);
+
+	return info;
+}
+
+static __always_inline int
+get_consume_word(struct unwind_state *state, unsigned long *word)
+{
+	struct stack_info *info;
+	unsigned long addr = *word;
+
+	info = get_word(state, word);
+	if (!info)
+		return -EINVAL;
+
+	unwind_consume_stack(state, info, addr, sizeof(addr));
+	return 0;
+}
+
+/*
+ * Unwind to the next frame according to sframe.
+ */
+static __always_inline int
+unwind_next_frame_sframe(struct kunwind_state *state)
+{
+	struct unwind_frame frame;
+	unsigned long cfa, fp, ra;
+	enum kunwind_source source = KUNWIND_SOURCE_FRAME;
+	struct pt_regs *regs = state->regs;
+
+	int err;
+
+	/* FP/SP alignment 8 bytes */
+	if (state->common.fp & 0x7 || state->common.sp & 0x7)
+		return -EINVAL;
+
+	/*
+	 * Most/all outermost functions are not visible to sframe. So, check for
+	 * a meta frame record if the sframe lookup fails.
+	 */
+	err = sframe_find_kernel(state->common.pc, &frame);
+	if (err)
+		return kunwind_next_frame_record_meta(state);
+
+	if (frame.outermost)
+		return -ENOENT;
+
+	/* Get the Canonical Frame Address (CFA) */
+	switch (frame.cfa.rule) {
+	case UNWIND_CFA_RULE_SP_OFFSET:
+		cfa = state->common.sp;
+		break;
+	case UNWIND_CFA_RULE_FP_OFFSET:
+		if (state->common.fp < state->common.sp)
+			return -EINVAL;
+		cfa = state->common.fp;
+		break;
+	case UNWIND_CFA_RULE_REG_OFFSET:
+	case UNWIND_CFA_RULE_REG_OFFSET_DEREF:
+		/* regs only available in topmost/interrupt frame */
+		if (!regs || frame.cfa.regnum > 30)
+			return -EINVAL;
+		cfa = regs->regs[frame.cfa.regnum];
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+	cfa += frame.cfa.offset;
+
+	/*
+	 * CFA typically points to a higher address than RA or FP, so don't
+	 * consume from the stack when we read it.
+	 */
+	if (frame.cfa.rule & UNWIND_RULE_DEREF &&
+	    !get_word(&state->common, &cfa))
+		return -EINVAL;
+
+	/* CFA alignment 8 bytes */
+	if (cfa & 0x7)
+		return -EINVAL;
+
+	/* Get the Return Address (RA) */
+	switch (frame.ra.rule) {
+	case UNWIND_RULE_RETAIN:
+		/* regs only available in topmost/interrupt frame */
+		if (!regs)
+			return -EINVAL;
+		ra = regs->regs[30];
+		source = KUNWIND_SOURCE_REGS_LR;
+		break;
+	/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
+	case UNWIND_RULE_CFA_OFFSET_DEREF:
+		ra = cfa + frame.ra.offset;
+		break;
+	case UNWIND_RULE_REG_OFFSET:
+	case UNWIND_RULE_REG_OFFSET_DEREF:
+		/* regs only available in topmost/interrupt frame */
+		if (!regs)
+			return -EINVAL;
+		ra = regs->regs[frame.cfa.regnum];
+		ra += frame.ra.offset;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+
+	/* Get the Frame Pointer (FP) */
+	switch (frame.fp.rule) {
+	case UNWIND_RULE_RETAIN:
+		fp = state->common.fp;
+		break;
+	/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
+	case UNWIND_RULE_CFA_OFFSET_DEREF:
+		fp = cfa + frame.fp.offset;
+		break;
+	case UNWIND_RULE_REG_OFFSET:
+	case UNWIND_RULE_REG_OFFSET_DEREF:
+		/* regs only available in topmost/interrupt frame */
+		if (!regs)
+			return -EINVAL;
+		fp = regs->regs[frame.fp.regnum];
+		fp += frame.fp.offset;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+
+	/*
+	 * Consume RA and FP from the stack. The frame record puts FP at a lower
+	 * address than RA, so we always read FP first.
+	 */
+	if (frame.fp.rule & UNWIND_RULE_DEREF &&
+	    !get_word(&state->common, &fp))
+		return -EINVAL;
+
+	if (frame.ra.rule & UNWIND_RULE_DEREF &&
+	    get_consume_word(&state->common, &ra))
+		return -EINVAL;
+
+	state->common.pc = ra;
+	state->common.sp = cfa;
+	state->common.fp = fp;
+
+	state->source = source;
+
+	return 0;
+}
+
+#else /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
+static __always_inline int
+unwind_next_frame_sframe(struct kunwind_state *state) { return -EINVAL; }
+
+#endif /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME*/
+
 /*
  * Unwind from one frame record (A) to the next frame record (B).
  *
@@ -259,12 +442,25 @@ kunwind_next(struct kunwind_state *state)
 	state->flags.all = 0;
 
 	switch (state->source) {
+	case KUNWIND_SOURCE_REGS_PC:
+		err = unwind_next_frame_sframe(state);
+
+		if (err && err != -ENOENT) {
+			/* Fallback to FP based unwinder */
+			err = kunwind_next_frame_record(state);
+			state->common.unreliable = true;
+		}
+		state->regs = NULL;
+		break;
 	case KUNWIND_SOURCE_FRAME:
 	case KUNWIND_SOURCE_CALLER:
 	case KUNWIND_SOURCE_TASK:
-	case KUNWIND_SOURCE_REGS_PC:
+	case KUNWIND_SOURCE_REGS_LR:
 		err = kunwind_next_frame_record(state);
+		if (err && err != -ENOENT)
+			err = unwind_next_frame_sframe(state);
 		break;
+
 	default:
 		err = -EINVAL;
 	}
@@ -350,6 +546,9 @@ kunwind_stack_walk(kunwind_consume_fn consume_state,
 		.common = {
 			.stacks = stacks,
 			.nr_stacks = ARRAY_SIZE(stacks),
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+			.sp = 0,
+#endif
 		},
 	};
 
@@ -390,34 +589,40 @@ noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
 	kunwind_stack_walk(arch_kunwind_consume_entry, &data, task, regs);
 }
 
+struct kunwind_reliable_consume_entry_data {
+	stack_trace_consume_fn consume_entry;
+	void *cookie;
+	bool unreliable;
+};
+
 static __always_inline bool
-arch_reliable_kunwind_consume_entry(const struct kunwind_state *state, void *cookie)
+arch_kunwind_reliable_consume_entry(const struct kunwind_state *state, void *cookie)
 {
-	/*
-	 * At an exception boundary we can reliably consume the saved PC. We do
-	 * not know whether the LR was live when the exception was taken, and
-	 * so we cannot perform the next unwind step reliably.
-	 *
-	 * All that matters is whether the *entire* unwind is reliable, so give
-	 * up as soon as we hit an exception boundary.
-	 */
-	if (state->source == KUNWIND_SOURCE_REGS_PC)
-		return false;
+	struct kunwind_reliable_consume_entry_data *data = cookie;
 
-	return arch_kunwind_consume_entry(state, cookie);
+	if (state->common.unreliable) {
+		data->unreliable = true;
+		return false;
+	}
+	return data->consume_entry(data->cookie, state->common.pc);
 }
 
-noinline noinstr int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
-					      void *cookie,
-					      struct task_struct *task)
+noinline notrace int arch_stack_walk_reliable(
+				stack_trace_consume_fn consume_entry,
+				void *cookie, struct task_struct *task)
 {
-	struct kunwind_consume_entry_data data = {
+	struct kunwind_reliable_consume_entry_data data = {
 		.consume_entry = consume_entry,
 		.cookie = cookie,
+		.unreliable = false,
 	};
 
-	return kunwind_stack_walk(arch_reliable_kunwind_consume_entry, &data,
-				  task, NULL);
+	kunwind_stack_walk(arch_kunwind_reliable_consume_entry, &data, task, NULL);
+
+	if (data.unreliable)
+		return -EINVAL;
+
+	return 0;
 }
 
 struct bpf_unwind_consume_entry_data {
@@ -452,6 +657,7 @@ static const char *state_source_string(const struct kunwind_state *state)
 	case KUNWIND_SOURCE_CALLER:	return "C";
 	case KUNWIND_SOURCE_TASK:	return "T";
 	case KUNWIND_SOURCE_REGS_PC:	return "P";
+	case KUNWIND_SOURCE_REGS_LR:	return "L";
 	default:			return "U";
 	}
 }
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 7/8] sframe: Introduce in-kernel SFRAME_VALIDATION
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

Generalize the __safe* helpers to support a non-user-access code path.

This requires arch-specific function address validation. This is because
arm64 vmlinux has an .rodata.text section which lies outside the bounds
of the normal .text. It contains code that is never executed by the
kernel mapping, but for which the toolchain nonetheless generates sframe
data, and needs to be considered valid for a PC lookup.

This arch-specific address validation logic is only necessary to support
SFRAME_VALIDATION for the vmlinux .sframe, since these .rodata.text
functions would never be encountered during normal unwinding.

Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
Suggested-by: Jens Remus <jremus@linux.ibm.com>
---
 arch/Kconfig                           |  2 +-
 arch/arm64/include/asm/sections.h      |  1 +
 arch/arm64/include/asm/unwind_sframe.h | 21 +++++++++++++++++++++
 arch/arm64/kernel/vmlinux.lds.S        |  2 ++
 include/linux/sframe.h                 |  2 ++
 kernel/unwind/sframe.c                 | 25 +++++++++++++++++++++++--
 6 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 8d27b3249e7a..cd4849bb675c 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -503,7 +503,7 @@ config HAVE_UNWIND_USER_SFRAME
 
 config SFRAME_VALIDATION
 	bool "Enable .sframe section debugging"
-	depends on HAVE_UNWIND_USER_SFRAME
+	depends on SFRAME_LOOKUP
 	depends on DYNAMIC_DEBUG
 	help
 	  When adding an .sframe section for a task, validate the entire
diff --git a/arch/arm64/include/asm/sections.h b/arch/arm64/include/asm/sections.h
index 51b0d594239e..5edb4304f661 100644
--- a/arch/arm64/include/asm/sections.h
+++ b/arch/arm64/include/asm/sections.h
@@ -23,6 +23,7 @@ extern char __irqentry_text_start[], __irqentry_text_end[];
 extern char __mmuoff_data_start[], __mmuoff_data_end[];
 extern char __entry_tramp_text_start[], __entry_tramp_text_end[];
 extern char __relocate_new_kernel_start[], __relocate_new_kernel_end[];
+extern char _srodatatext[], _erodatatext[];
 
 static inline size_t entry_tramp_text_size(void)
 {
diff --git a/arch/arm64/include/asm/unwind_sframe.h b/arch/arm64/include/asm/unwind_sframe.h
index 876412881196..1e9d7b74c0c8 100644
--- a/arch/arm64/include/asm/unwind_sframe.h
+++ b/arch/arm64/include/asm/unwind_sframe.h
@@ -2,7 +2,28 @@
 #ifndef _ASM_ARM64_UNWIND_SFRAME_H
 #define _ASM_ARM64_UNWIND_SFRAME_H
 
+#include <linux/sframe.h>
+#include <asm/sections.h>
+
 #define SFRAME_REG_SP	31
 #define SFRAME_REG_FP	29
 
+static inline bool sframe_func_start_addr_valid(struct sframe_section *sec,
+						unsigned long func_addr)
+{
+	/*
+	 * The .rodata.text section is outside the normal kernel .text, but the
+	 * toolchain still generates sframe data for it. Allow sframe lookups
+	 * for these functions, even though they are never executed from the
+	 * kernel mapping.
+	 */
+	if (sec->sec_type == SFRAME_KERNEL && sec == &kernel_sfsec &&
+	    func_addr >= (unsigned long)_srodatatext &&
+	    func_addr < (unsigned long)_erodatatext)
+		return true;
+
+	return (sec->text_start <= func_addr && func_addr < sec->text_end);
+}
+#define sframe_func_start_addr_valid sframe_func_start_addr_valid
+
 #endif /* _ASM_ARM64_UNWIND_SFRAME_H */
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 2964aad0362e..8c2dae6e7a86 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -213,12 +213,14 @@ SECTIONS
 
 	/* code sections that are never executed via the kernel mapping */
 	.rodata.text : {
+		_srodatatext = .;
 		TRAMP_TEXT
 		HIBERNATE_TEXT
 		KEXEC_TEXT
 		IDMAP_TEXT
 		. = ALIGN(PAGE_SIZE);
 	}
+	_erodatatext = .;
 
 	idmap_pg_dir = .;
 	. += PAGE_SIZE;
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 27f5a66190af..ac3aa9db7d91 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -34,6 +34,8 @@ struct sframe_section {
 	signed char		fp_off;
 };
 
+extern struct sframe_section kernel_sfsec __ro_after_init;
+
 #endif /* CONFIG_UNWIND_SFRAME_LOOKUP */
 
 #ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index 20178e02f428..d76968547bad 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -21,10 +21,18 @@
 #include "sframe.h"
 #include "sframe_debug.h"
 
+#ifndef sframe_func_start_addr_valid
+static inline bool sframe_func_start_addr_valid(struct sframe_section *sec,
+						unsigned long func_addr)
+{
+	return (sec->text_start <= func_addr && func_addr < sec->text_end);
+}
+#endif
+
 #ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
 
 static bool sframe_init __ro_after_init;
-static struct sframe_section kernel_sfsec __ro_after_init;
+struct sframe_section kernel_sfsec __ro_after_init;
 
 #endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
 
@@ -152,7 +160,7 @@ static __always_inline int __read_fde(struct sframe_section *sec,
 		  sizeof(struct sframe_fde_v3), Efault);
 
 	func_addr = fde_addr + _fde.func_start_off;
-	if (func_addr < sec->text_start || func_addr > sec->text_end)
+	if (!sframe_func_start_addr_valid(sec, func_addr))
 		return -EINVAL;
 
 	fda_addr = sec->fres_start + _fde.fres_off;
@@ -636,6 +644,9 @@ static int safe_read_fde(struct sframe_section *sec,
 {
 	int ret;
 
+	if (sec->sec_type == SFRAME_KERNEL)
+		return __read_fde(sec, fde_num, fde);
+
 	if (!user_read_access_begin((void __user *)sec->sframe_start,
 				    sec->sframe_end - sec->sframe_start))
 		return -EFAULT;
@@ -651,6 +662,9 @@ static int safe_read_fre(struct sframe_section *sec,
 {
 	int ret;
 
+	if (sec->sec_type == SFRAME_KERNEL)
+		return __read_fre(sec, fde, fre_addr, fre);
+
 	if (!user_read_access_begin((void __user *)sec->sframe_start,
 				    sec->sframe_end - sec->sframe_start))
 		return -EFAULT;
@@ -665,6 +679,9 @@ static int safe_read_fre_datawords(struct sframe_section *sec,
 {
 	int ret;
 
+	if (sec->sec_type == SFRAME_KERNEL)
+		return __read_fre_datawords(sec, fde, fre);
+
 	if (!user_read_access_begin((void __user *)sec->sframe_start,
 				    sec->sframe_end - sec->sframe_start))
 		return -EFAULT;
@@ -1013,6 +1030,8 @@ void __init init_sframe_table(void)
 
 	if (WARN_ON(sframe_read_header(&kernel_sfsec)))
 		return;
+	if (WARN_ON(sframe_validate_section(&kernel_sfsec)))
+		return;
 
 	sframe_init = true;
 }
@@ -1031,6 +1050,8 @@ void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
 
 	if (WARN_ON(sframe_read_header(&sec)))
 		return;
+	if (WARN_ON(sframe_validate_section(&sec)))
+		return;
 
 	mod->arch.sframe_sec = sec;
 	mod->arch.sframe_init = true;
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 6/8] arm64/module, sframe: Add sframe support for modules
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

Add sframe table to mod_arch_specific and support sframe PC lookups when
an .sframe section can be found on incoming modules.

Signed-off-by: Weinan Liu <wnliu@google.com>
Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
 arch/arm64/include/asm/module.h |  6 +++++
 arch/arm64/kernel/module.c      |  8 +++++++
 include/linux/sframe.h          |  2 ++
 kernel/unwind/sframe.c          | 40 +++++++++++++++++++++++++++++++--
 4 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h
index fb9b88eebeb1..07f309c51eee 100644
--- a/arch/arm64/include/asm/module.h
+++ b/arch/arm64/include/asm/module.h
@@ -6,6 +6,7 @@
 #define __ASM_MODULE_H
 
 #include <asm-generic/module.h>
+#include <linux/sframe.h>
 
 struct mod_plt_sec {
 	int			plt_shndx;
@@ -17,6 +18,11 @@ struct mod_arch_specific {
 	struct mod_plt_sec	core;
 	struct mod_plt_sec	init;
 
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+	struct sframe_section sframe_sec;
+	bool sframe_init;
+#endif
+
 	/* for CONFIG_DYNAMIC_FTRACE */
 	struct plt_entry	*ftrace_trampolines;
 	struct plt_entry	*init_ftrace_trampolines;
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 24adb581af0e..427f187e9531 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -18,6 +18,7 @@
 #include <linux/moduleloader.h>
 #include <linux/random.h>
 #include <linux/scs.h>
+#include <linux/sframe.h>
 
 #include <asm/alternative.h>
 #include <asm/insn.h>
@@ -515,5 +516,12 @@ int module_finalize(const Elf_Ehdr *hdr,
 		}
 	}
 
+	s = find_section(hdr, sechdrs, ".sframe");
+	if (s) {
+		struct module_memory *t = &me->mem[MOD_TEXT];
+
+		sframe_module_init(me, (void *)s->sh_addr, s->sh_size,
+				   t->base, t->size);
+	}
 	return module_init_ftrace_plt(hdr, sechdrs, me);
 }
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 8ae31ed36226..27f5a66190af 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -81,6 +81,8 @@ extern int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame);
 #else
 
 static inline void __init init_sframe_table(void) {}
+static inline void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
+				      void *text, size_t text_size) {}
 
 #endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
 
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index 243027244854..20178e02f428 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -980,10 +980,27 @@ void sframe_free_mm(struct mm_struct *mm)
 
 int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame)
 {
-	if (!frame || !sframe_init)
+	struct sframe_section *sec;
+
+	if (!frame)
 		return -EINVAL;
 
-	return  __sframe_find(&kernel_sfsec, ip, frame);
+	if (is_ksym_addr(ip)) {
+		if (!sframe_init)
+			return -EINVAL;
+
+		sec = &kernel_sfsec;
+	} else {
+		struct module *mod;
+
+		mod = __module_address(ip);
+		if (!mod || !mod->arch.sframe_init)
+			return -EINVAL;
+
+		sec = &mod->arch.sframe_sec;
+	}
+
+	return  __sframe_find(sec, ip, frame);
 }
 
 void __init init_sframe_table(void)
@@ -1000,4 +1017,23 @@ void __init init_sframe_table(void)
 	sframe_init = true;
 }
 
+void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
+			void *text, size_t text_size)
+{
+	struct sframe_section sec;
+
+	memset(&sec, 0, sizeof(sec));
+	sec.sec_type	 = SFRAME_KERNEL;
+	sec.sframe_start = (unsigned long)sframe;
+	sec.sframe_end   = (unsigned long)sframe + sframe_size;
+	sec.text_start   = (unsigned long)text;
+	sec.text_end     = (unsigned long)text + text_size;
+
+	if (WARN_ON(sframe_read_header(&sec)))
+		return;
+
+	mod->arch.sframe_sec = sec;
+	mod->arch.sframe_init = true;
+}
+
 #endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 5/8] sframe: Allow unsorted FDEs
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

The .sframe in kernel modules is built without SFRAME_F_FDE_SORTED set.
In order to allow sframe PC lookup in modules, add a code path to handle
unsorted FDE tables by doing a simple linear search.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
 include/linux/sframe.h |  1 +
 kernel/unwind/sframe.c | 45 +++++++++++++++++++++++++++++++++++++-----
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 5b7341b61a7c..8ae31ed36226 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -28,6 +28,7 @@ struct sframe_section {
 	unsigned long		fres_start;
 	unsigned long		fres_end;
 	unsigned int		num_fdes;
+	bool			fdes_sorted;
 
 	signed char		ra_off;
 	signed char		fp_off;
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index fb3b6b2d8677..243027244854 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -176,9 +176,35 @@ static __always_inline int __read_fde(struct sframe_section *sec,
 	return -EFAULT;
 }
 
-static __always_inline int __find_fde(struct sframe_section *sec,
-				      unsigned long ip,
-				      struct sframe_fde_internal *fde)
+static __always_inline int __find_fde_unsorted(struct sframe_section *sec,
+					       unsigned long ip,
+					       struct sframe_fde_internal *fde)
+{
+	struct sframe_fde_v3 *cur, *start, *end;
+
+	start = (struct sframe_fde_v3 *)sec->fdes_start;
+	end = start + sec->num_fdes;
+
+	for (cur = start; cur < end; cur++) {
+		s64 func_off;
+		u32 func_size;
+		unsigned long func_addr;
+
+		DATA_GET(sec, func_off, &cur->func_start_off, s64, Efault);
+		DATA_GET(sec, func_size, &cur->func_size, u32, Efault);
+		func_addr = (unsigned long)cur + func_off;
+
+		if (ip >= func_addr && ip < func_addr + func_size)
+			return __read_fde(sec, cur - start, fde);
+	}
+	return -EINVAL;
+Efault:
+	return -EFAULT;
+}
+
+static __always_inline int __find_fde_sorted(struct sframe_section *sec,
+					     unsigned long ip,
+					     struct sframe_fde_internal *fde)
 {
 	unsigned long func_addr_low = 0, func_addr_high = ULONG_MAX;
 	struct sframe_fde_v3 *first, *low, *high, *found = NULL;
@@ -233,6 +259,15 @@ static __always_inline int __find_fde(struct sframe_section *sec,
 	return -EFAULT;
 }
 
+static __always_inline int __find_fde(struct sframe_section *sec,
+					     unsigned long ip,
+					     struct sframe_fde_internal *fde)
+{
+	if (sec->fdes_sorted)
+		return __find_fde_sorted(sec, ip, fde);
+	return __find_fde_unsorted(sec, ip, fde);
+}
+
 #define ____GET_INC(sec, to, from, type, label)				\
 ({									\
 	type __to;							\
@@ -657,7 +692,7 @@ static int sframe_validate_section(struct sframe_section *sec)
 			return ret;
 
 		ip = fde.func_addr;
-		if (ip <= prev_ip) {
+		if (sec->fdes_sorted && ip <= prev_ip) {
 			dbg_sec("fde %u not sorted\n", i);
 			return -EFAULT;
 		}
@@ -736,7 +771,6 @@ static int sframe_read_header(struct sframe_section *sec)
 
 	if (shdr.preamble.magic != SFRAME_MAGIC ||
 	    shdr.preamble.version != SFRAME_VERSION_3 ||
-	    !(shdr.preamble.flags & SFRAME_F_FDE_SORTED) ||
 	    !(shdr.preamble.flags & SFRAME_F_FDE_FUNC_START_PCREL) ||
 	    shdr.auxhdr_len) {
 		dbg_sec("bad/unsupported sframe header\n");
@@ -766,6 +800,7 @@ static int sframe_read_header(struct sframe_section *sec)
 		return -EINVAL;
 	}
 
+	sec->fdes_sorted	= shdr.preamble.flags & SFRAME_F_FDE_SORTED;
 	sec->num_fdes		= num_fdes;
 	sec->fdes_start		= fdes_start;
 	sec->fres_start		= fres_start;
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 4/8] sframe: Provide PC lookup for vmlinux .sframe section
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

With SFRAME_UNWINDER, read in the .sframe section at boot. This provides
unwind data as an alternative/supplement to frame pointer-based
unwinding.

Reviewed-by: Jens Remus <jremus@linux.ibm.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
 arch/arm64/kernel/setup.c |  2 ++
 include/linux/sframe.h    | 14 ++++++++++++++
 kernel/unwind/sframe.c    | 36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 23c05dc7a8f2..4a633bc7aefb 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -32,6 +32,7 @@
 #include <linux/sched/task.h>
 #include <linux/scs.h>
 #include <linux/mm.h>
+#include <linux/sframe.h>
 
 #include <asm/acpi.h>
 #include <asm/fixmap.h>
@@ -375,6 +376,7 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
 			"This indicates a broken bootloader or old kernel\n",
 			boot_args[1], boot_args[2], boot_args[3]);
 	}
+	init_sframe_table();
 }
 
 static inline bool cpu_can_disable(unsigned int cpu)
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index 0cb2924367bc..5b7341b61a7c 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -69,4 +69,18 @@ static inline int sframe_find_user(unsigned long ip, struct unwind_frame *frame)
 
 #endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
 
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+void __init init_sframe_table(void);
+void sframe_module_init(struct module *mod, void *sframe, size_t sframe_size,
+			void *text, size_t text_size);
+
+extern int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame);
+
+#else
+
+static inline void __init init_sframe_table(void) {}
+
+#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
 #endif /* _LINUX_SFRAME_H */
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index ae15f5c06939..fb3b6b2d8677 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -14,10 +14,20 @@
 #include <linux/sframe.h>
 #include <linux/unwind_types.h>
 #include <asm/unwind_sframe.h>
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+#include <linux/kallsyms.h>
+#endif
 
 #include "sframe.h"
 #include "sframe_debug.h"
 
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+static bool sframe_init __ro_after_init;
+static struct sframe_section kernel_sfsec __ro_after_init;
+
+#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
 struct sframe_fde_internal {
 	unsigned long	func_addr;
 	u32		func_size;
@@ -930,3 +940,29 @@ void sframe_free_mm(struct mm_struct *mm)
 }
 
 #endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
+
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+int sframe_find_kernel(unsigned long ip, struct unwind_frame *frame)
+{
+	if (!frame || !sframe_init)
+		return -EINVAL;
+
+	return  __sframe_find(&kernel_sfsec, ip, frame);
+}
+
+void __init init_sframe_table(void)
+{
+	kernel_sfsec.sec_type		= SFRAME_KERNEL;
+	kernel_sfsec.sframe_start	= (unsigned long)__start_sframe;
+	kernel_sfsec.sframe_end		= (unsigned long)__end_sframe;
+	kernel_sfsec.text_start		= (unsigned long)_stext;
+	kernel_sfsec.text_end		= (unsigned long)_etext;
+
+	if (WARN_ON(sframe_read_header(&kernel_sfsec)))
+		return;
+
+	sframe_init = true;
+}
+
+#endif /* CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 3/8] arm64: entry: add unwind info for various kernel entries
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

From: Weinan Liu <wnliu@google.com>

DWARF CFI (Call Frame Information) specifies how to recover the return
address and callee-saved registers at each PC in a given function.
Compilers are able to generate the CFI annotations when they compile
the code to assembly language. For handcrafted assembly, we need to
annotate them by hand.

Annotate minimal CFI to enable stacktracing using SFrame for kernel
exception entries through el1*_64_*() paths and irq entries through
call_on_irq_stack()

Signed-off-by: Weinan Liu <wnliu@google.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
Suggested-by: Jens Remus <jremus@linux.ibm.com>
---
 arch/arm64/kernel/entry.S | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index f8018b5c1f9a..dc55b0b19cfa 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -30,6 +30,12 @@
 #include <asm/asm-uaccess.h>
 #include <asm/unistd.h>
 
+/*
+ * Do not generate .eh_frame.  Only generate .debug_frame and optionally
+ * .sframe (via assembler option --gsframe[-N]).
+ */
+	.cfi_sections .debug_frame
+
 	.macro	clear_gp_regs
 	.irp	n,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29
 	mov	x\n, xzr
@@ -575,7 +581,16 @@ SYM_CODE_START_LOCAL(el\el\ht\()_\regsize\()_\label)
 	.if \el == 0
 	b	ret_to_user
 	.else
+	/*
+	 * Minimal DWARF CFI for unwinding across the call above.
+	 * Enable unwinding for el1*_64_*() path only.
+	 */
+	.cfi_startproc
+	.cfi_def_cfa_offset PT_REGS_SIZE
+	.cfi_offset 29, S_FP - PT_REGS_SIZE
+	.cfi_offset 30, S_LR - PT_REGS_SIZE
 	b	ret_to_kernel
+	.cfi_endproc
 	.endif
 SYM_CODE_END(el\el\ht\()_\regsize\()_\label)
 	.endm
@@ -872,6 +887,7 @@ NOKPROBE(ret_from_fork)
  * Calls func(regs) using this CPU's irq stack and shadow irq stack.
  */
 SYM_FUNC_START(call_on_irq_stack)
+	.cfi_startproc
 	save_and_disable_daif x9
 #ifdef CONFIG_SHADOW_CALL_STACK
 	get_current_task x16
@@ -882,6 +898,9 @@ SYM_FUNC_START(call_on_irq_stack)
 	/* Create a frame record to save our LR and SP (implicit in FP) */
 	stp	x29, x30, [sp, #-16]!
 	mov	x29, sp
+	.cfi_def_cfa 29, 16
+	.cfi_offset 29, -16
+	.cfi_offset 30, -8
 
 	ldr_this_cpu x16, irq_stack_ptr, x17
 
@@ -897,9 +916,13 @@ SYM_FUNC_START(call_on_irq_stack)
 	 */
 	mov	sp, x29
 	ldp	x29, x30, [sp], #16
+	.cfi_restore 29
+	.cfi_restore 30
+	.cfi_def_cfa 31, 0
 	scs_load_current
 	restore_irq x9
 	ret
+	.cfi_endproc
 SYM_FUNC_END(call_on_irq_stack)
 NOKPROBE(call_on_irq_stack)
 
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 1/8] sframe: Allow kernelspace sframe sections
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

Generalize the sframe lookup code to support kernelspace sections. This
is done by defining a SFRAME_LOOKUP option that can be activated
separate from HAVE_UNWIND_USER_SFRAME, as there will be other client to
this library than just userspace unwind.

Sframe section location is now tracked in a separate sec_type field to
determine whether user-access functions are necessary to read the sframe
data. Relevant type delarations are moved and renamed to reflect the
non-user sframe support.

Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
 MAINTAINERS                                   |   2 +-
 arch/Kconfig                                  |   4 +
 .../{unwind_user_sframe.h => unwind_sframe.h} |   6 +-
 arch/x86/include/asm/unwind_user.h            |  12 +-
 include/linux/sframe.h                        |  48 ++--
 include/linux/unwind_types.h                  |  46 +++
 include/linux/unwind_user_types.h             |  41 ---
 kernel/unwind/Makefile                        |   2 +-
 kernel/unwind/sframe.c                        | 270 ++++++++++++------
 kernel/unwind/user.c                          |  41 +--
 10 files changed, 293 insertions(+), 179 deletions(-)
 rename arch/x86/include/asm/{unwind_user_sframe.h => unwind_sframe.h} (50%)
 create mode 100644 include/linux/unwind_types.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8c46465ee7a9..cfc7dec88da4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27557,7 +27557,7 @@ F:	Documentation/driver-api/uio-howto.rst
 F:	drivers/uio/
 F:	include/linux/uio_driver.h
 
-USERSPACE STACK UNWINDING
+STACK UNWINDING
 M:	Josh Poimboeuf <jpoimboe@kernel.org>
 M:	Steven Rostedt <rostedt@goodmis.org>
 S:	Maintained
diff --git a/arch/Kconfig b/arch/Kconfig
index f1ed8bc0806d..d7caf2e245ce 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -486,6 +486,9 @@ config AS_SFRAME3
 	def_bool $(as-instr,.cfi_startproc\n.cfi_endproc,-Wa$(comma)--gsframe-3)
 	select AS_SFRAME
 
+config UNWIND_SFRAME_LOOKUP
+	bool
+
 config UNWIND_USER
 	bool
 
@@ -496,6 +499,7 @@ config HAVE_UNWIND_USER_FP
 config HAVE_UNWIND_USER_SFRAME
 	bool
 	select UNWIND_USER
+	select UNWIND_SFRAME_LOOKUP
 
 config SFRAME_VALIDATION
 	bool "Enable .sframe section debugging"
diff --git a/arch/x86/include/asm/unwind_user_sframe.h b/arch/x86/include/asm/unwind_sframe.h
similarity index 50%
rename from arch/x86/include/asm/unwind_user_sframe.h
rename to arch/x86/include/asm/unwind_sframe.h
index d828ae1a4aac..44d42e6ffde4 100644
--- a/arch/x86/include/asm/unwind_user_sframe.h
+++ b/arch/x86/include/asm/unwind_sframe.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_X86_UNWIND_USER_SFRAME_H
-#define _ASM_X86_UNWIND_USER_SFRAME_H
+#ifndef _ASM_X86_UNWIND_SFRAME_H
+#define _ASM_X86_UNWIND_SFRAME_H
 
 #ifdef CONFIG_X86_64
 
@@ -9,4 +9,4 @@
 
 #endif
 
-#endif /* _ASM_X86_UNWIND_USER_SFRAME_H */
+#endif /* _ASM_X86_UNWIND_SFRAME_H */
diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h
index ae46906c3b39..8fdab3581b86 100644
--- a/arch/x86/include/asm/unwind_user.h
+++ b/arch/x86/include/asm/unwind_user.h
@@ -55,30 +55,30 @@ static inline int unwind_user_get_reg(unsigned long *val, unsigned int regnum)
 
 #define ARCH_INIT_USER_FP_FRAME(ws)			\
 	.cfa		= {				\
-		.rule		= UNWIND_USER_CFA_RULE_FP_OFFSET,\
+		.rule		= UNWIND_CFA_RULE_FP_OFFSET,\
 		.offset		=  2*(ws),		\
 			},				\
 	.ra		= {				\
-		.rule		= UNWIND_USER_RULE_CFA_OFFSET_DEREF,\
+		.rule		= UNWIND_RULE_CFA_OFFSET_DEREF,\
 		.offset		= -1*(ws),		\
 			},				\
 	.fp		= {				\
-		.rule		= UNWIND_USER_RULE_CFA_OFFSET_DEREF,\
+		.rule		= UNWIND_RULE_CFA_OFFSET_DEREF,\
 		.offset		= -2*(ws),		\
 			},				\
 	.outermost	= false,
 
 #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws)		\
 	.cfa		= {				\
-		.rule		= UNWIND_USER_CFA_RULE_SP_OFFSET,\
+		.rule		= UNWIND_CFA_RULE_SP_OFFSET,\
 		.offset		=  1*(ws),		\
 			},				\
 	.ra		= {				\
-		.rule		= UNWIND_USER_RULE_CFA_OFFSET_DEREF,\
+		.rule		= UNWIND_RULE_CFA_OFFSET_DEREF,\
 		.offset		= -1*(ws),		\
 			},				\
 	.fp		= {				\
-		.rule		= UNWIND_USER_RULE_RETAIN,\
+		.rule		= UNWIND_RULE_RETAIN,\
 			},				\
 	.outermost	= false,
 
diff --git a/include/linux/sframe.h b/include/linux/sframe.h
index b79c5ec09229..0cb2924367bc 100644
--- a/include/linux/sframe.h
+++ b/include/linux/sframe.h
@@ -3,37 +3,46 @@
 #define _LINUX_SFRAME_H
 
 #include <linux/mm_types.h>
+#include <linux/unwind_types.h>
 #include <linux/srcu.h>
-#include <linux/unwind_user_types.h>
 
-#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+#ifdef CONFIG_UNWIND_SFRAME_LOOKUP
+
+enum sframe_sec_type {
+	SFRAME_KERNEL,
+	SFRAME_USER,
+};
 
 struct sframe_section {
-	struct rcu_head	rcu;
+	struct rcu_head  rcu;
 #ifdef CONFIG_DYNAMIC_DEBUG
-	const char	*filename;
+	const char		*filename;
 #endif
-	unsigned long	sframe_start;
-	unsigned long	sframe_end;
-	unsigned long	text_start;
-	unsigned long	text_end;
-
-	unsigned long	fdes_start;
-	unsigned long	fres_start;
-	unsigned long	fres_end;
-	unsigned int	num_fdes;
-
-	signed char	ra_off;
-	signed char	fp_off;
+	enum sframe_sec_type	sec_type;
+	unsigned long		sframe_start;
+	unsigned long		sframe_end;
+	unsigned long		text_start;
+	unsigned long		text_end;
+
+	unsigned long		fdes_start;
+	unsigned long		fres_start;
+	unsigned long		fres_end;
+	unsigned int		num_fdes;
+
+	signed char		ra_off;
+	signed char		fp_off;
 };
 
+#endif /* CONFIG_UNWIND_SFRAME_LOOKUP */
+
+#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+
 #define INIT_MM_SFRAME .sframe_mt = MTREE_INIT(sframe_mt, 0),
 extern void sframe_free_mm(struct mm_struct *mm);
 
 extern int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
 			      unsigned long text_start, unsigned long text_end);
 extern int sframe_remove_section(unsigned long sframe_addr);
-extern int sframe_find(unsigned long ip, struct unwind_user_frame *frame);
 
 static inline bool current_has_sframe(void)
 {
@@ -42,6 +51,8 @@ static inline bool current_has_sframe(void)
 	return mm && !mtree_empty(&mm->sframe_mt);
 }
 
+extern int sframe_find_user(unsigned long ip, struct unwind_frame *frame);
+
 #else /* !CONFIG_HAVE_UNWIND_USER_SFRAME */
 
 #define INIT_MM_SFRAME
@@ -52,9 +63,10 @@ static inline int sframe_add_section(unsigned long sframe_start, unsigned long s
 	return -ENOSYS;
 }
 static inline int sframe_remove_section(unsigned long sframe_addr) { return -ENOSYS; }
-static inline int sframe_find(unsigned long ip, struct unwind_user_frame *frame) { return -ENOSYS; }
 static inline bool current_has_sframe(void) { return false; }
 
+static inline int sframe_find_user(unsigned long ip, struct unwind_frame *frame) { return -ENOSYS; }
+
 #endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
 
 #endif /* _LINUX_SFRAME_H */
diff --git a/include/linux/unwind_types.h b/include/linux/unwind_types.h
new file mode 100644
index 000000000000..08bcb0aa04aa
--- /dev/null
+++ b/include/linux/unwind_types.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_UNWIND_TYPES_H
+#define _LINUX_UNWIND_TYPES_H
+
+#define UNWIND_RULE_DEREF			BIT(31)
+
+enum unwind_cfa_rule {
+	UNWIND_CFA_RULE_SP_OFFSET,		/* CFA = SP + offset */
+	UNWIND_CFA_RULE_FP_OFFSET,		/* CFA = FP + offset */
+	UNWIND_CFA_RULE_REG_OFFSET,	/* CFA = reg + offset */
+	/* DEREF variants */
+	UNWIND_CFA_RULE_REG_OFFSET_DEREF =	/* CFA = *(reg + offset) */
+		UNWIND_CFA_RULE_REG_OFFSET | UNWIND_RULE_DEREF,
+};
+
+struct unwind_cfa_rule_data {
+	enum unwind_cfa_rule rule;
+	s32 offset;
+	unsigned int regnum;
+};
+
+enum unwind_rule {
+	UNWIND_RULE_RETAIN,		/* entity = entity */
+	UNWIND_RULE_CFA_OFFSET,		/* entity = CFA + offset */
+	UNWIND_RULE_REG_OFFSET,		/* entity = register + offset */
+	/* DEREF variants */
+	UNWIND_RULE_CFA_OFFSET_DEREF =	/* entity = *(CFA + offset) */
+		UNWIND_RULE_CFA_OFFSET | UNWIND_RULE_DEREF,
+	UNWIND_RULE_REG_OFFSET_DEREF =	/* entity = *(register + offset) */
+		UNWIND_RULE_REG_OFFSET | UNWIND_RULE_DEREF,
+};
+
+struct unwind_rule_data {
+	enum unwind_rule rule;
+	s32 offset;
+	unsigned int regnum;
+};
+
+struct unwind_frame {
+	struct unwind_cfa_rule_data cfa;
+	struct unwind_rule_data ra;
+	struct unwind_rule_data fp;
+	bool outermost;
+};
+
+#endif /* _LINUX_UNWIND_TYPES_H */
diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_types.h
index 059e5c76f2f3..646e5fb774db 100644
--- a/include/linux/unwind_user_types.h
+++ b/include/linux/unwind_user_types.h
@@ -27,47 +27,6 @@ struct unwind_stacktrace {
 	unsigned long	*entries;
 };
 
-#define UNWIND_USER_RULE_DEREF			BIT(31)
-
-enum unwind_user_cfa_rule {
-	UNWIND_USER_CFA_RULE_SP_OFFSET,		/* CFA = SP + offset */
-	UNWIND_USER_CFA_RULE_FP_OFFSET,		/* CFA = FP + offset */
-	UNWIND_USER_CFA_RULE_REG_OFFSET,	/* CFA = reg + offset */
-	/* DEREF variants */
-	UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF =	/* CFA = *(reg + offset) */
-		UNWIND_USER_CFA_RULE_REG_OFFSET | UNWIND_USER_RULE_DEREF,
-};
-
-struct unwind_user_cfa_rule_data {
-	enum unwind_user_cfa_rule rule;
-	s32 offset;
-	unsigned int regnum;
-};
-
-enum unwind_user_rule {
-	UNWIND_USER_RULE_RETAIN,		/* entity = entity */
-	UNWIND_USER_RULE_CFA_OFFSET,		/* entity = CFA + offset */
-	UNWIND_USER_RULE_REG_OFFSET,		/* entity = register + offset */
-	/* DEREF variants */
-	UNWIND_USER_RULE_CFA_OFFSET_DEREF =	/* entity = *(CFA + offset) */
-		UNWIND_USER_RULE_CFA_OFFSET | UNWIND_USER_RULE_DEREF,
-	UNWIND_USER_RULE_REG_OFFSET_DEREF =	/* entity = *(register + offset) */
-		UNWIND_USER_RULE_REG_OFFSET | UNWIND_USER_RULE_DEREF,
-};
-
-struct unwind_user_rule_data {
-	enum unwind_user_rule rule;
-	s32 offset;
-	unsigned int regnum;
-};
-
-struct unwind_user_frame {
-	struct unwind_user_cfa_rule_data cfa;
-	struct unwind_user_rule_data ra;
-	struct unwind_user_rule_data fp;
-	bool outermost;
-};
-
 struct unwind_user_state {
 	unsigned long				ip;
 	unsigned long				sp;
diff --git a/kernel/unwind/Makefile b/kernel/unwind/Makefile
index 146038165865..c5f9f8124564 100644
--- a/kernel/unwind/Makefile
+++ b/kernel/unwind/Makefile
@@ -1,2 +1,2 @@
  obj-$(CONFIG_UNWIND_USER)		+= user.o deferred.o
- obj-$(CONFIG_HAVE_UNWIND_USER_SFRAME)	+= sframe.o
+ obj-$(CONFIG_UNWIND_SFRAME_LOOKUP)	+= sframe.o
diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index f24997e84e05..ae15f5c06939 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -12,8 +12,8 @@
 #include <linux/mm.h>
 #include <linux/string_helpers.h>
 #include <linux/sframe.h>
-#include <asm/unwind_user_sframe.h>
-#include <linux/unwind_user_types.h>
+#include <linux/unwind_types.h>
+#include <asm/unwind_sframe.h>
 
 #include "sframe.h"
 #include "sframe_debug.h"
@@ -44,8 +44,6 @@ struct sframe_fre_internal {
 	unsigned char	dw_size;
 };
 
-DEFINE_STATIC_SRCU(sframe_srcu);
-
 static __always_inline unsigned char fre_type_to_size(unsigned char fre_type)
 {
 	if (fre_type > 2)
@@ -60,6 +58,77 @@ static __always_inline unsigned char dataword_size_enum_to_size(unsigned char da
 	return 1 << dataword_size;
 }
 
+#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+
+DEFINE_STATIC_SRCU(sframe_srcu);
+
+#define UNSAFE_USER_COPY(to, from, size, label)				\
+	unsafe_copy_from_user(to, (void __user *)from, size, label)
+
+#define UNSAFE_USER_GET(to, from, type, label)				\
+	unsafe_get_user(to, (type __user *)from, label)
+
+#else /* !CONFIG_HAVE_UNWIND_USER_SFRAME */
+
+#define UNSAFE_USER_COPY(to, from, size, label) do {			\
+	(void)to; (void)from; (void)size;				\
+	goto label;							\
+} while (0)
+
+#define UNSAFE_USER_GET(to, from, type, label) do {			\
+	(void)to; (void)from;						\
+	goto label;							\
+} while (0)
+
+#endif /* !CONFIG_HAVE_UNWIND_USER_SFRAME */
+
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+
+#define KERNEL_COPY(to, from, size, label) memcpy(to, (void *)from, size)
+#define KERNEL_GET(to, from, type, label) ({ (to) = *(type *)(from); })
+
+#else /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
+#define KERNEL_COPY(to, from, size, label) do {				\
+	(void)(to); (void)(from); (void)size;				\
+	goto label;							\
+} while (0)
+
+#define KERNEL_GET(to, from, type, label) do {				\
+	(void)(to); (void)(from);					\
+	goto label;							\
+} while (0)
+
+#endif /* !CONFIG_HAVE_UNWIND_KERNEL_SFRAME */
+
+#define DATA_COPY(sec, to, from, size, label)			\
+({								\
+	switch (sec->sec_type) {				\
+	case SFRAME_KERNEL:					\
+		KERNEL_COPY(to, from, size, label);		\
+		break;						\
+	case SFRAME_USER:					\
+		UNSAFE_USER_COPY(to, from, size, label);	\
+		break;						\
+	default:						\
+		return -EFAULT;					\
+	}							\
+})
+
+#define DATA_GET(sec, to, from, type, label)			\
+({								\
+	switch (sec->sec_type) {				\
+	case SFRAME_KERNEL:					\
+		KERNEL_GET(to, from, type, label);		\
+		break;						\
+	case SFRAME_USER:					\
+		UNSAFE_USER_GET(to, from, type, label);		\
+		break;						\
+	default:						\
+		return -EFAULT;					\
+	}							\
+})
+
 static __always_inline int __read_fde(struct sframe_section *sec,
 				      unsigned int fde_num,
 				      struct sframe_fde_internal *fde)
@@ -69,8 +138,8 @@ static __always_inline int __read_fde(struct sframe_section *sec,
 	struct sframe_fda_v3 _fda;
 
 	fde_addr = sec->fdes_start + (fde_num * sizeof(struct sframe_fde_v3));
-	unsafe_copy_from_user(&_fde, (void __user *)fde_addr,
-			      sizeof(struct sframe_fde_v3), Efault);
+	DATA_COPY(sec, &_fde, fde_addr,
+		  sizeof(struct sframe_fde_v3), Efault);
 
 	func_addr = fde_addr + _fde.func_start_off;
 	if (func_addr < sec->text_start || func_addr > sec->text_end)
@@ -79,8 +148,8 @@ static __always_inline int __read_fde(struct sframe_section *sec,
 	fda_addr = sec->fres_start + _fde.fres_off;
 	if (fda_addr + sizeof(struct sframe_fda_v3) > sec->fres_end)
 		return -EINVAL;
-	unsafe_copy_from_user(&_fda, (void __user *)fda_addr,
-			      sizeof(struct sframe_fda_v3), Efault);
+	DATA_COPY(sec, &_fda, fda_addr,
+		  sizeof(struct sframe_fda_v3), Efault);
 
 	fde->func_addr	= func_addr;
 	fde->func_size	= _fde.func_size;
@@ -102,21 +171,21 @@ static __always_inline int __find_fde(struct sframe_section *sec,
 				      struct sframe_fde_internal *fde)
 {
 	unsigned long func_addr_low = 0, func_addr_high = ULONG_MAX;
-	struct sframe_fde_v3 __user *first, *low, *high, *found = NULL;
+	struct sframe_fde_v3 *first, *low, *high, *found = NULL;
 	int ret;
 
-	first = (void __user *)sec->fdes_start;
+	first = (void *)sec->fdes_start;
 	low = first;
 	high = first + sec->num_fdes - 1;
 
 	while (low <= high) {
-		struct sframe_fde_v3 __user *mid;
+		struct sframe_fde_v3 *mid;
 		s64 func_off;
 		unsigned long func_addr;
 
 		mid = low + ((high - low) / 2);
 
-		unsafe_get_user(func_off, (s64 __user *)mid, Efault);
+		DATA_GET(sec, func_off, mid, s64, Efault);
 		func_addr = (unsigned long)mid + func_off;
 
 		if (ip >= func_addr) {
@@ -154,47 +223,47 @@ static __always_inline int __find_fde(struct sframe_section *sec,
 	return -EFAULT;
 }
 
-#define ____UNSAFE_GET_USER_INC(to, from, type, label)			\
+#define ____GET_INC(sec, to, from, type, label)				\
 ({									\
 	type __to;							\
-	unsafe_get_user(__to, (type __user *)from, label);		\
+	DATA_GET(sec, __to, from, type, label);				\
 	from += sizeof(__to);						\
 	to = __to;							\
 })
 
-#define __UNSAFE_GET_USER_INC(to, from, size, label, u_or_s)		\
+#define __GET_INC(sec, to, from, size, label, u_or_s)			\
 ({									\
 	switch (size) {							\
 	case 1:								\
-		____UNSAFE_GET_USER_INC(to, from, u_or_s##8, label);	\
+		____GET_INC(sec, to, from, u_or_s##8, label);		\
 		break;							\
 	case 2:								\
-		____UNSAFE_GET_USER_INC(to, from, u_or_s##16, label);	\
+		____GET_INC(sec, to, from, u_or_s##16, label);		\
 		break;							\
 	case 4:								\
-		____UNSAFE_GET_USER_INC(to, from, u_or_s##32, label);	\
+		____GET_INC(sec, to, from, u_or_s##32, label);		\
 		break;							\
 	default:							\
 		return -EFAULT;						\
 	}								\
 })
 
-#define UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label)		\
-	__UNSAFE_GET_USER_INC(to, from, size, label, u)
+#define GET_UNSIGNED_INC(sec, to, from, size, label)			\
+	__GET_INC(sec, to, from, size, label, u)
 
-#define UNSAFE_GET_USER_SIGNED_INC(to, from, size, label)		\
-	__UNSAFE_GET_USER_INC(to, from, size, label, s)
+#define GET_SIGNED_INC(sec, to, from, size, label)			\
+	__GET_INC(sec, to, from, size, label, s)
 
-#define UNSAFE_GET_USER_INC(to, from, size, label)				\
-	_Generic(to,								\
-		 u8 :	UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label),	\
-		 u16 :	UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label),	\
-		 u32 :	UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label),	\
-		 u64 :	UNSAFE_GET_USER_UNSIGNED_INC(to, from, size, label),	\
-		 s8 :	UNSAFE_GET_USER_SIGNED_INC(to, from, size, label),	\
-		 s16 :	UNSAFE_GET_USER_SIGNED_INC(to, from, size, label),	\
-		 s32 :	UNSAFE_GET_USER_SIGNED_INC(to, from, size, label),	\
-		 s64 :	UNSAFE_GET_USER_SIGNED_INC(to, from, size, label))
+#define GET_INC(sec, to, from, size, label)				\
+	_Generic(to,							\
+		 u8 :	GET_UNSIGNED_INC(sec, to, from, size, label),	\
+		 u16 :	GET_UNSIGNED_INC(sec, to, from, size, label),	\
+		 u32 :	GET_UNSIGNED_INC(sec, to, from, size, label),	\
+		 u64 :	GET_UNSIGNED_INC(sec, to, from, size, label),	\
+		 s8 :	GET_SIGNED_INC(sec, to, from, size, label),	\
+		 s16 :	GET_SIGNED_INC(sec, to, from, size, label),	\
+		 s32 :	GET_SIGNED_INC(sec, to, from, size, label),	\
+		 s64 :	GET_SIGNED_INC(sec, to, from, size, label))
 
 static __always_inline int
 __read_regular_fre_datawords(struct sframe_section *sec,
@@ -207,19 +276,19 @@ __read_regular_fre_datawords(struct sframe_section *sec,
 	s32 cfa_off, ra_off, fp_off;
 	unsigned int cfa_regnum;
 
-	UNSAFE_GET_USER_INC(cfa_off, cur, dataword_size, Efault);
+	GET_INC(sec, cfa_off, cur, dataword_size, Efault);
 	dataword_count--;
 
 	ra_off = sec->ra_off;
 	if (!ra_off && dataword_count) {
 		dataword_count--;
-		UNSAFE_GET_USER_INC(ra_off, cur, dataword_size, Efault);
+		GET_INC(sec, ra_off, cur, dataword_size, Efault);
 	}
 
 	fp_off = sec->fp_off;
 	if (!fp_off && dataword_count) {
 		dataword_count--;
-		UNSAFE_GET_USER_INC(fp_off, cur, dataword_size, Efault);
+		GET_INC(sec, fp_off, cur, dataword_size, Efault);
 	}
 
 	if (dataword_count)
@@ -255,17 +324,17 @@ __read_flex_fde_fre_datawords(struct sframe_section *sec,
 
 	if (dataword_count < 2)
 		return -EFAULT;
-	UNSAFE_GET_USER_INC(cfa_ctl, cur, dataword_size, Efault);
-	UNSAFE_GET_USER_INC(cfa_off, cur, dataword_size, Efault);
+	GET_INC(sec, cfa_ctl, cur, dataword_size, Efault);
+	GET_INC(sec, cfa_off, cur, dataword_size, Efault);
 	dataword_count -= 2;
 
 	ra_off = sec->ra_off;
 	ra_ctl = ra_off ? 2 : 0; /* regnum=0, deref_p=(ra_off != 0), reg_p=0 */
 	if (dataword_count >= 2) {
-		UNSAFE_GET_USER_INC(ra_ctl, cur, dataword_size, Efault);
+		GET_INC(sec, ra_ctl, cur, dataword_size, Efault);
 		dataword_count--;
 		if (ra_ctl) {
-			UNSAFE_GET_USER_INC(ra_off, cur, dataword_size, Efault);
+			GET_INC(sec, ra_off, cur, dataword_size, Efault);
 			dataword_count--;
 		} else {
 			/* Padding RA location info */
@@ -276,10 +345,10 @@ __read_flex_fde_fre_datawords(struct sframe_section *sec,
 	fp_off = sec->fp_off;
 	fp_ctl = fp_off ? 2 : 0; /* regnum=0, deref_p=(fp_off != 0), reg_p=0 */
 	if (dataword_count >= 2) {
-		UNSAFE_GET_USER_INC(fp_ctl, cur, dataword_size, Efault);
+		GET_INC(sec, fp_ctl, cur, dataword_size, Efault);
 		dataword_count--;
 		if (fp_ctl) {
-			UNSAFE_GET_USER_INC(fp_off, cur, dataword_size, Efault);
+			GET_INC(sec, fp_off, cur, dataword_size, Efault);
 			dataword_count--;
 		} else {
 			/* Padding FP location info */
@@ -353,11 +422,11 @@ static __always_inline int __read_fre(struct sframe_section *sec,
 	if (fre_addr + addr_size + 1 > sec->fres_end)
 		return -EFAULT;
 
-	UNSAFE_GET_USER_INC(ip_off, cur, addr_size, Efault);
+	GET_INC(sec, ip_off, cur, addr_size, Efault);
 	if (fde_pctype == SFRAME_FDE_PCTYPE_INC && ip_off > fde->func_size)
 		return -EFAULT;
 
-	UNSAFE_GET_USER_INC(info, cur, 1, Efault);
+	GET_INC(sec, info, cur, 1, Efault);
 	dataword_count = SFRAME_V3_FRE_DATAWORD_COUNT(info);
 	dataword_size  = dataword_size_enum_to_size(SFRAME_V3_FRE_DATAWORD_SIZE(info));
 	if (!dataword_size)
@@ -380,7 +449,7 @@ static __always_inline int __read_fre(struct sframe_section *sec,
 }
 
 static __always_inline int
-sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
+sframe_init_cfa_rule_data(struct unwind_cfa_rule_data *cfa_rule_data,
 			  u32 ctlword, s32 offset)
 {
 	bool deref_p = SFRAME_V3_FLEX_FDE_CTLWORD_DEREF_P(ctlword);
@@ -391,13 +460,13 @@ sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
 
 		switch (regnum) {
 		case SFRAME_REG_SP:
-			cfa_rule_data->rule = UNWIND_USER_CFA_RULE_SP_OFFSET;
+			cfa_rule_data->rule = UNWIND_CFA_RULE_SP_OFFSET;
 			break;
 		case SFRAME_REG_FP:
-			cfa_rule_data->rule = UNWIND_USER_CFA_RULE_FP_OFFSET;
+			cfa_rule_data->rule = UNWIND_CFA_RULE_FP_OFFSET;
 			break;
 		default:
-			cfa_rule_data->rule = UNWIND_USER_CFA_RULE_REG_OFFSET;
+			cfa_rule_data->rule = UNWIND_CFA_RULE_REG_OFFSET;
 			cfa_rule_data->regnum = regnum;
 		}
 	} else {
@@ -405,7 +474,7 @@ sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
 	}
 
 	if (deref_p)
-		cfa_rule_data->rule |= UNWIND_USER_RULE_DEREF;
+		cfa_rule_data->rule |= UNWIND_RULE_DEREF;
 
 	cfa_rule_data->offset = offset;
 
@@ -413,27 +482,27 @@ sframe_init_cfa_rule_data(struct unwind_user_cfa_rule_data *cfa_rule_data,
 }
 
 static __always_inline void
-sframe_init_rule_data(struct unwind_user_rule_data *rule_data,
+sframe_init_rule_data(struct unwind_rule_data *rule_data,
 		      u32 ctlword, s32 offset)
 {
 	bool deref_p = SFRAME_V3_FLEX_FDE_CTLWORD_DEREF_P(ctlword);
 	bool reg_p = SFRAME_V3_FLEX_FDE_CTLWORD_REG_P(ctlword);
 
 	if (!ctlword && !offset) {
-		rule_data->rule = UNWIND_USER_RULE_RETAIN;
+		rule_data->rule = UNWIND_RULE_RETAIN;
 		return;
 	}
 	if (reg_p) {
 		unsigned int regnum = SFRAME_V3_FLEX_FDE_CTLWORD_REGNUM(ctlword);
 
-		rule_data->rule = UNWIND_USER_RULE_REG_OFFSET;
+		rule_data->rule = UNWIND_RULE_REG_OFFSET;
 		rule_data->regnum = regnum;
 	} else {
-		rule_data->rule = UNWIND_USER_RULE_CFA_OFFSET;
+		rule_data->rule = UNWIND_RULE_CFA_OFFSET;
 	}
 
 	if (deref_p)
-		rule_data->rule |= UNWIND_USER_RULE_DEREF;
+		rule_data->rule |= UNWIND_RULE_DEREF;
 
 	rule_data->offset = offset;
 }
@@ -441,7 +510,7 @@ sframe_init_rule_data(struct unwind_user_rule_data *rule_data,
 static __always_inline int __find_fre(struct sframe_section *sec,
 				      struct sframe_fde_internal *fde,
 				      unsigned long ip,
-				      struct unwind_user_frame *frame)
+				      struct unwind_frame *frame)
 {
 	unsigned char fde_pctype = SFRAME_V3_FDE_PCTYPE(fde->info);
 	struct sframe_fre_internal *fre, *prev_fre = NULL;
@@ -501,40 +570,18 @@ static __always_inline int __find_fre(struct sframe_section *sec,
 	return 0;
 }
 
-int sframe_find(unsigned long ip, struct unwind_user_frame *frame)
+static __always_inline int __sframe_find(struct sframe_section *sec,
+					 unsigned long ip,
+					 struct unwind_frame *frame)
 {
-	struct mm_struct *mm = current->mm;
-	struct sframe_section *sec;
 	struct sframe_fde_internal fde;
 	int ret;
 
-	if (!mm)
-		return -EINVAL;
-
-	guard(srcu)(&sframe_srcu);
-
-	sec = mtree_load(&mm->sframe_mt, ip);
-	if (!sec)
-		return -EINVAL;
-
-	if (!user_read_access_begin((void __user *)sec->sframe_start,
-				    sec->sframe_end - sec->sframe_start))
-		return -EFAULT;
-
 	ret = __find_fde(sec, ip, &fde);
 	if (ret)
-		goto end;
-
-	ret = __find_fre(sec, &fde, ip, frame);
-end:
-	user_read_access_end();
-
-	if (ret == -EFAULT) {
-		dbg_sec("removing bad .sframe section\n");
-		WARN_ON_ONCE(sframe_remove_section(sec->sframe_start));
-	}
+		return ret;
 
-	return ret;
+	return __find_fre(sec, &fde, ip, frame);
 }
 
 #ifdef CONFIG_SFRAME_VALIDATION
@@ -657,20 +704,23 @@ static int sframe_validate_section(struct sframe_section *sec) { return 0; }
 #endif /* !CONFIG_SFRAME_VALIDATION */
 
 
-static void free_section(struct sframe_section *sec)
-{
-	dbg_free(sec);
-	kfree(sec);
-}
-
 static int sframe_read_header(struct sframe_section *sec)
 {
 	unsigned long header_end, fdes_start, fdes_end, fres_start, fres_end;
 	struct sframe_header shdr;
 	unsigned int num_fdes;
 
-	if (copy_from_user(&shdr, (void __user *)sec->sframe_start, sizeof(shdr))) {
-		dbg_sec("header usercopy failed\n");
+	switch (sec->sec_type) {
+	case SFRAME_USER:
+		if (copy_from_user(&shdr, (void __user *)sec->sframe_start, sizeof(shdr))) {
+			dbg_sec("header usercopy failed\n");
+			return -EFAULT;
+		}
+		break;
+	case SFRAME_KERNEL:
+		shdr = *(struct sframe_header *)sec->sframe_start;
+		break;
+	default:
 		return -EFAULT;
 	}
 
@@ -717,6 +767,45 @@ static int sframe_read_header(struct sframe_section *sec)
 	return 0;
 }
 
+#ifdef CONFIG_HAVE_UNWIND_USER_SFRAME
+
+int sframe_find_user(unsigned long ip, struct unwind_frame *frame)
+{
+	struct mm_struct *mm = current->mm;
+	struct sframe_section *sec;
+	int ret;
+
+	if (!mm)
+		return -EINVAL;
+
+	guard(srcu)(&sframe_srcu);
+
+	sec = mtree_load(&mm->sframe_mt, ip);
+	if (!sec)
+		return -EINVAL;
+
+	if (!user_read_access_begin((void __user *)sec->sframe_start,
+				    sec->sframe_end - sec->sframe_start))
+		return -EFAULT;
+
+	ret = __sframe_find(sec, ip, frame);
+
+	user_read_access_end();
+
+	if (ret == -EFAULT) {
+		dbg_sec("removing bad .sframe section\n");
+		WARN_ON_ONCE(sframe_remove_section(sec->sframe_start));
+	}
+
+	return ret;
+}
+
+static void free_section(struct sframe_section *sec)
+{
+	dbg_free(sec);
+	kfree(sec);
+}
+
 int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
 		       unsigned long text_start, unsigned long text_end)
 {
@@ -753,6 +842,7 @@ int sframe_add_section(unsigned long sframe_start, unsigned long sframe_end,
 	if (!sec)
 		return -ENOMEM;
 
+	sec->sec_type		= SFRAME_USER;
 	sec->sframe_start	= sframe_start;
 	sec->sframe_end		= sframe_end;
 	sec->text_start		= text_start;
@@ -838,3 +928,5 @@ void sframe_free_mm(struct mm_struct *mm)
 
 	mtree_destroy(&mm->sframe_mt);
 }
+
+#endif /* CONFIG_HAVE_UNWIND_USER_SFRAME */
diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c
index eb7d9489f671..9e57dd79559a 100644
--- a/kernel/unwind/user.c
+++ b/kernel/unwind/user.c
@@ -8,6 +8,7 @@
 #include <linux/unwind_user.h>
 #include <linux/uaccess.h>
 #include <linux/sframe.h>
+#include <linux/unwind_types.h>
 
 #define for_each_user_frame(state) \
 	for (unwind_user_start(state); !(state)->done; unwind_user_next(state))
@@ -28,7 +29,7 @@ get_user_word(unsigned long *word, unsigned long base, int off, unsigned int ws)
 }
 
 static int unwind_user_next_common(struct unwind_user_state *state,
-				   const struct unwind_user_frame *frame)
+				   const struct unwind_frame *frame)
 {
 	unsigned long cfa, fp, ra;
 
@@ -40,16 +41,16 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 
 	/* Get the Canonical Frame Address (CFA) */
 	switch (frame->cfa.rule) {
-	case UNWIND_USER_CFA_RULE_SP_OFFSET:
+	case UNWIND_CFA_RULE_SP_OFFSET:
 		cfa = state->sp;
 		break;
-	case UNWIND_USER_CFA_RULE_FP_OFFSET:
+	case UNWIND_CFA_RULE_FP_OFFSET:
 		if (state->fp < state->sp)
 			return -EINVAL;
 		cfa = state->fp;
 		break;
-	case UNWIND_USER_CFA_RULE_REG_OFFSET:
-	case UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF:
+	case UNWIND_CFA_RULE_REG_OFFSET:
+	case UNWIND_CFA_RULE_REG_OFFSET_DEREF:
 		if (!state->topmost || unwind_user_get_reg(&cfa, frame->cfa.regnum))
 			return -EINVAL;
 		break;
@@ -58,7 +59,7 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 		return -EINVAL;
 	}
 	cfa += frame->cfa.offset;
-	if (frame->cfa.rule & UNWIND_USER_RULE_DEREF &&
+	if (frame->cfa.rule & UNWIND_RULE_DEREF &&
 	    get_user_word(&cfa, cfa, 0, state->ws))
 		return -EINVAL;
 
@@ -76,16 +77,16 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 
 	/* Get the Return Address (RA) */
 	switch (frame->ra.rule) {
-	case UNWIND_USER_RULE_RETAIN:
+	case UNWIND_RULE_RETAIN:
 		if (!state->topmost || unwind_user_get_ra_reg(&ra))
 			return -EINVAL;
 		break;
 	/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
-	case UNWIND_USER_RULE_CFA_OFFSET_DEREF:
+	case UNWIND_RULE_CFA_OFFSET_DEREF:
 		ra = cfa + frame->ra.offset;
 		break;
-	case UNWIND_USER_RULE_REG_OFFSET:
-	case UNWIND_USER_RULE_REG_OFFSET_DEREF:
+	case UNWIND_RULE_REG_OFFSET:
+	case UNWIND_RULE_REG_OFFSET_DEREF:
 		if (!state->topmost || unwind_user_get_reg(&ra, frame->ra.regnum))
 			return -EINVAL;
 		ra += frame->ra.offset;
@@ -94,21 +95,21 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 		WARN_ON_ONCE(1);
 		return -EINVAL;
 	}
-	if (frame->ra.rule & UNWIND_USER_RULE_DEREF &&
+	if (frame->ra.rule & UNWIND_RULE_DEREF &&
 	    get_user_word(&ra, ra, 0, state->ws))
 		return -EINVAL;
 
 	/* Get the Frame Pointer (FP) */
 	switch (frame->fp.rule) {
-	case UNWIND_USER_RULE_RETAIN:
+	case UNWIND_RULE_RETAIN:
 		fp = state->fp;
 		break;
 	/* UNWIND_USER_RULE_CFA_OFFSET not implemented on purpose */
-	case UNWIND_USER_RULE_CFA_OFFSET_DEREF:
+	case UNWIND_RULE_CFA_OFFSET_DEREF:
 		fp = cfa + frame->fp.offset;
 		break;
-	case UNWIND_USER_RULE_REG_OFFSET:
-	case UNWIND_USER_RULE_REG_OFFSET_DEREF:
+	case UNWIND_RULE_REG_OFFSET:
+	case UNWIND_RULE_REG_OFFSET_DEREF:
 		if (!state->topmost || unwind_user_get_reg(&fp, frame->fp.regnum))
 			return -EINVAL;
 		fp += frame->fp.offset;
@@ -117,7 +118,7 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 		WARN_ON_ONCE(1);
 		return -EINVAL;
 	}
-	if (frame->fp.rule & UNWIND_USER_RULE_DEREF &&
+	if (frame->fp.rule & UNWIND_RULE_DEREF &&
 	    get_user_word(&fp, fp, 0, state->ws))
 		return -EINVAL;
 
@@ -133,13 +134,13 @@ static int unwind_user_next_fp(struct unwind_user_state *state)
 	struct pt_regs *regs = task_pt_regs(current);
 
 	if (state->topmost && unwind_user_at_function_start(regs)) {
-		const struct unwind_user_frame fp_entry_frame = {
+		const struct unwind_frame fp_entry_frame = {
 			ARCH_INIT_USER_FP_ENTRY_FRAME(state->ws)
 		};
 		return unwind_user_next_common(state, &fp_entry_frame);
 	}
 
-	const struct unwind_user_frame fp_frame = {
+	const struct unwind_frame fp_frame = {
 		ARCH_INIT_USER_FP_FRAME(state->ws)
 	};
 	return unwind_user_next_common(state, &fp_frame);
@@ -147,10 +148,10 @@ static int unwind_user_next_fp(struct unwind_user_state *state)
 
 static int unwind_user_next_sframe(struct unwind_user_state *state)
 {
-	struct unwind_user_frame frame;
+	struct unwind_frame frame;
 
 	/* sframe expects the frame to be local storage */
-	if (sframe_find(state->ip, &frame))
+	if (sframe_find_user(state->ip, &frame))
 		return -ENOENT;
 	return unwind_user_next_common(state, &frame);
 }
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 2/8] arm64, unwind: build kernel with sframe V3 info
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap
In-Reply-To: <20260421225200.1198447-1-dylanbhatch@google.com>

Build with -Wa,--gsframe-3 flags to generate a .sframe section. This
will be used for in-kernel reliable stacktrace in cases where the frame
pointer alone is insufficient.

Currently, the sframe format only supports arm64, x86_64 and s390x
architectures.

Signed-off-by: Weinan Liu <wnliu@google.com>
Reviewed-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
---
 MAINTAINERS                            |  1 +
 Makefile                               |  8 ++++++++
 arch/Kconfig                           | 21 +++++++++++++++++++++
 arch/arm64/Kconfig                     |  1 +
 arch/arm64/include/asm/unwind_sframe.h |  8 ++++++++
 arch/arm64/kernel/vdso/Makefile        |  2 +-
 include/asm-generic/sections.h         |  4 ++++
 include/asm-generic/vmlinux.lds.h      | 15 +++++++++++++++
 8 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/unwind_sframe.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cfc7dec88da4..a7d75f9cb5f4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27561,6 +27561,7 @@ STACK UNWINDING
 M:	Josh Poimboeuf <jpoimboe@kernel.org>
 M:	Steven Rostedt <rostedt@goodmis.org>
 S:	Maintained
+F:	arch/*/include/asm/unwind_sframe.h
 F:	include/linux/sframe.h
 F:	include/linux/unwind*.h
 F:	kernel/unwind/
diff --git a/Makefile b/Makefile
index 2b15f0b4a0cb..6c94a5257679 100644
--- a/Makefile
+++ b/Makefile
@@ -1110,6 +1110,14 @@ endif
 # Ensure compilers do not transform certain loops into calls to wcslen()
 KBUILD_CFLAGS += -fno-builtin-wcslen
 
+# build with sframe table
+ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+CC_FLAGS_SFRAME := -Wa,--gsframe-3
+KBUILD_CFLAGS	+= $(CC_FLAGS_SFRAME)
+KBUILD_AFLAGS	+= $(CC_FLAGS_SFRAME)
+export CC_FLAGS_SFRAME
+endif
+
 # change __FILE__ to the relative path to the source directory
 ifdef building_out_of_srctree
 KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=
diff --git a/arch/Kconfig b/arch/Kconfig
index d7caf2e245ce..8d27b3249e7a 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -520,6 +520,27 @@ config SFRAME_VALIDATION
 
 	  If unsure, say N.
 
+config ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
+	bool
+	help
+	  An architecture can select this if it enables the SFrame (Simple
+	  Frame) unwinder for unwinding kernel stack traces. It uses an unwind
+	  table that is directly generated by the toolchain based on DWARF CFI
+	  information.
+
+config HAVE_UNWIND_KERNEL_SFRAME
+	bool "Sframe unwinder"
+	depends on AS_SFRAME3
+	depends on 64BIT
+	depends on ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
+	select UNWIND_SFRAME_LOOKUP
+	help
+	  This option enables the SFrame (Simple Frame) unwinder for unwinding
+	  kernel stack traces. It uses unwind an table that is directly
+	  generated by the toolchain based on DWARF CFI information. In
+	  practice, this can provide more reliable stacktrace results than
+	  unwinding with frame pointers alone.
+
 config HAVE_PERF_REGS
 	bool
 	help
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 38dba5f7e4d2..f7ae8eaaadc4 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -112,6 +112,7 @@ config ARM64
 	select ARCH_SUPPORTS_SCHED_SMT
 	select ARCH_SUPPORTS_SCHED_CLUSTER
 	select ARCH_SUPPORTS_SCHED_MC
+	select ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
 	select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH
 	select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT
 	select ARCH_WANT_DEFAULT_BPF_JIT
diff --git a/arch/arm64/include/asm/unwind_sframe.h b/arch/arm64/include/asm/unwind_sframe.h
new file mode 100644
index 000000000000..876412881196
--- /dev/null
+++ b/arch/arm64/include/asm/unwind_sframe.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_UNWIND_SFRAME_H
+#define _ASM_ARM64_UNWIND_SFRAME_H
+
+#define SFRAME_REG_SP	31
+#define SFRAME_REG_FP	29
+
+#endif /* _ASM_ARM64_UNWIND_SFRAME_H */
diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile
index 7dec05dd33b7..c60ef921956f 100644
--- a/arch/arm64/kernel/vdso/Makefile
+++ b/arch/arm64/kernel/vdso/Makefile
@@ -38,7 +38,7 @@ ccflags-y += -DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
 CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) \
 			$(RANDSTRUCT_CFLAGS) $(KSTACK_ERASE_CFLAGS) \
 			$(GCC_PLUGINS_CFLAGS) \
-			$(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \
+			$(CC_FLAGS_LTO) $(CC_FLAGS_CFI) $(CC_FLAGS_SFRAME) \
 			-Wmissing-prototypes -Wmissing-declarations
 
 CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 0755bc39b0d8..336d27011a58 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -31,6 +31,7 @@
  *	__irqentry_text_start, __irqentry_text_end
  *	__softirqentry_text_start, __softirqentry_text_end
  *	__start_opd, __end_opd
+ *	__start_sframe, __end_sframe
  */
 extern char _text[], _stext[], _etext[];
 extern char _data[], _sdata[], _edata[];
@@ -53,6 +54,9 @@ extern char __ctors_start[], __ctors_end[];
 /* Start and end of .opd section - used for function descriptors. */
 extern char __start_opd[], __end_opd[];
 
+/* Start and end of .sframe section - used for stack unwinding. */
+extern char __start_sframe[], __end_sframe[];
+
 /* Start and end of instrumentation protected text section */
 extern char __noinstr_text_start[], __noinstr_text_end[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 1e1580febe4b..090da633db92 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -491,6 +491,8 @@
 		*(.rodata1)						\
 	}								\
 									\
+	SFRAME								\
+									\
 	/* PCI quirks */						\
 	.pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {	\
 		BOUNDED_SECTION_PRE_LABEL(.pci_fixup_early,  _pci_fixups_early,  __start, __end) \
@@ -911,6 +913,19 @@
 #define TRACEDATA
 #endif
 
+#ifdef CONFIG_HAVE_UNWIND_KERNEL_SFRAME
+#define SFRAME							\
+	/* sframe */						\
+	.sframe : AT(ADDR(.sframe) - LOAD_OFFSET) {		\
+		__start_sframe = .;			\
+		KEEP(*(.sframe))				\
+		KEEP(*(.init.sframe))				\
+		__end_sframe = .;			\
+	}
+#else
+#define SFRAME
+#endif
+
 #ifdef CONFIG_PRINTK_INDEX
 #define PRINTK_INDEX							\
 	.printk_index : AT(ADDR(.printk_index) - LOAD_OFFSET) {		\
-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply related

* [PATCH v4 0/8] unwind, arm64: add sframe unwinder for kernel
From: Dylan Hatch @ 2026-04-21 22:51 UTC (permalink / raw)
  To: Roman Gushchin, Weinan Liu, Will Deacon, Josh Poimboeuf,
	Indu Bhagat, Peter Zijlstra, Steven Rostedt, Catalin Marinas,
	Jiri Kosina, Jens Remus
  Cc: Dylan Hatch, Mark Rutland, Prasanna Kumar T S M, Puranjay Mohan,
	Song Liu, joe.lawrence, linux-toolchains, linux-kernel,
	live-patching, linux-arm-kernel, Randy Dunlap

Implement a generic kernel sframe-based [1] unwinder. The main goal is
to improve reliable stacktrace on arm64 by unwinding across exception
boundaries.

On x86, the ORC unwinder provides reliable stacktrace through similar
methodology, but arm64 lacks the necessary support from objtool to
create ORC unwind tables.

Currently, there's already a sframe unwinder proposed for userspace: [2].
To maintain common definitions and algorithms for sframe lookup, a
substantial portion of this patch series aims to refactor the sframe
lookup code to support both kernel and userspace sframe sections.

Currently, only GNU Binutils support sframe. This series relies on the
Sframe V3 format, which is supported in binutils 2.46.

These patches are based on Steven Rostedt's sframe/core branch [3],
which is and aggregation of existing work done for x86 sframe userspace
unwind, and contains [2]. This branch is, in turn, based on Linux
v7.0-rc3. This full series (applied to the sframe/core branch) is
available on github: [4].

Ref:
[1]: https://sourceware.org/binutils/docs/sframe-spec.html
[2]: https://lore.kernel.org/lkml/20260127150554.2760964-1-jremus@linux.ibm.com/
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git/log/?h=sframe/core
[4]: https://github.com/dylanbhatch/linux/tree/sframe-v3-with-v3

Changes since v3:

  - (Jens) Clean up patch summaries.
  - (Jens) Rename SFRAME_LOOKUP -> UNWIND_SFRAME_LOOKUP to fit existing
    naming convention.
  - (Randy) Correct typo errors in new config options.
  - (Jens) Move unwind types to a new unwind_types.h to match their
    usage.
  - (Jens) Update KERNEL_[COPY|GET] to use label-based error handling
    like their userspace counterparts.
  - (Jens) Rename SFRAME_UNWINDER -> HAVE_UNWIND_KERNEL_SFRAME and
    ARCH_SUPPORTS_SFRAME_UNWINDER -> ARCH_SUPPORTS_UNWIND_KERNEL_SFRAME
    to match existing naming convention.
  - (Jens) Move HAVE_UNWIND_KERNEL_SFRAME config option to arch/Kconfig.
  - (Jens) Rename/move extern definitions of __[start|end]_sframe into
    include/asm-generic/sections.h.
  - (Jens) Fix up CFI annotations at kernel entry.
  - (Jens) Fix error path for unsorted FDE lookup.
  - (Jens) Zero-out module sframe_section before init.
  - (Jens) For SFRAME_VALIDATION, use an arch-specific function-address
    validation helper so that .rodata.text can be correctly handled on
    arm64 vmlinux.
  - (Jens) Fixup and better comment kernel stacktrace code.

Changes since v2:

The biggest change from v2 is the switch from adding a dedicated,
in-kernel sframe-lookup library, to refactoring/using the existing
library developed by Josh, Jens, and Steve. Consequently, this series
now depends on Sframe V3, though this upgrade would likely have been
necessary anyway. Below is a full accounting of the changes since v2.

  - (Josh) Add stricter reliability checks during unwind.
  - (Puranjay, Indu, Jens) Update to use a common sframe library with
    userpace unwind, thus resolving the need to support
    SFRAME_F_FDE_FUNC_START_PCREL, added in binutils 2.45.
  - (Jens) Add check for sframe V3, thus resolving the prior need for V2
    and SFRAME_F_FDE_FUNC_START_PCREL support.
  - (Will) Add ARCH_SUPPORTS_SFRAME_UNWINDER, remove SFRAME_UNWIND_TABLE
  - (Indu) add support for unsorted FDE tables, allowing for module
    sframe lookups.
  - (Mark) Prefer frame-pointer unwind when possible, for better
    performance.
  - Simplify compile-time logic, adding stubbs when necessary.
  - Add support for in-kernel SFRAME_VALIDATION.
  - Rebase onto core/sframe (with v7.0-rc3 base)

Dylan Hatch (7):
  sframe: Allow kernelspace sframe sections
  arm64, unwind: build kernel with sframe V3 info
  sframe: Provide PC lookup for vmlinux .sframe section
  sframe: Allow unsorted FDEs
  arm64/module, sframe: Add sframe support for modules
  sframe: Introduce in-kernel SFRAME_VALIDATION
  unwind: arm64: Use sframe to unwind interrupt frames

Weinan Liu (1):
  arm64: entry: add unwind info for various kernel entries

 MAINTAINERS                                   |   3 +-
 Makefile                                      |   8 +
 arch/Kconfig                                  |  27 +-
 arch/arm64/Kconfig                            |   1 +
 arch/arm64/include/asm/module.h               |   6 +
 arch/arm64/include/asm/sections.h             |   1 +
 arch/arm64/include/asm/stacktrace/common.h    |   6 +
 arch/arm64/include/asm/unwind_sframe.h        |  29 ++
 arch/arm64/kernel/entry.S                     |  23 +
 arch/arm64/kernel/module.c                    |   8 +
 arch/arm64/kernel/setup.c                     |   2 +
 arch/arm64/kernel/stacktrace.c                | 246 ++++++++++-
 arch/arm64/kernel/vdso/Makefile               |   2 +-
 arch/arm64/kernel/vmlinux.lds.S               |   2 +
 .../{unwind_user_sframe.h => unwind_sframe.h} |   6 +-
 arch/x86/include/asm/unwind_user.h            |  12 +-
 include/asm-generic/sections.h                |   4 +
 include/asm-generic/vmlinux.lds.h             |  15 +
 include/linux/sframe.h                        |  67 ++-
 include/linux/unwind_types.h                  |  46 ++
 include/linux/unwind_user_types.h             |  41 --
 kernel/unwind/Makefile                        |   2 +-
 kernel/unwind/sframe.c                        | 410 ++++++++++++++----
 kernel/unwind/user.c                          |  41 +-
 24 files changed, 801 insertions(+), 207 deletions(-)
 create mode 100644 arch/arm64/include/asm/unwind_sframe.h
 rename arch/x86/include/asm/{unwind_user_sframe.h => unwind_sframe.h} (50%)
 create mode 100644 include/linux/unwind_types.h

-- 
2.54.0.rc1.555.g9c883467ad-goog



^ permalink raw reply

* [PATCH v1 4/7] ARM: dts: aspeed: system1: Enable temp sensors
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Ninad Palsule
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

Enable temperature sensors for PCIe devices in the system1 BMC machine.
There is mux on each sensor card.

Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 .../dts/aspeed/aspeed-bmc-ibm-system1.dts     | 496 ++++++++++++++++++
 1 file changed, 496 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index b0eb1767c485..a5252cec9903 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -68,6 +68,38 @@ aliases {
 		i2c69 = &i2c15mux0chn5;
 		i2c70 = &i2c15mux0chn6;
 		i2c71 = &i2c15mux0chn7;
+		i2c72 = &i2c8mux2chn0;
+		i2c73 = &i2c8mux2chn1;
+		i2c74 = &i2c8mux3chn0;
+		i2c75 = &i2c8mux3chn1;
+		i2c76 = &i2c8mux4chn0;
+		i2c77 = &i2c8mux4chn1;
+		i2c78 = &i2c8mux5chn0;
+		i2c79 = &i2c8mux5chn1;
+		i2c80 = &i2c8mux6chn0;
+		i2c81 = &i2c8mux6chn1;
+		i2c82 = &i2c8mux7chn0;
+		i2c83 = &i2c8mux7chn1;
+		i2c84 = &i2c8mux8chn0;
+		i2c85 = &i2c8mux8chn1;
+		i2c86 = &i2c8mux9chn0;
+		i2c87 = &i2c8mux9chn1;
+		i2c88 = &i2c15mux2chn0;
+		i2c89 = &i2c15mux2chn1;
+		i2c90 = &i2c15mux3chn0;
+		i2c91 = &i2c15mux3chn1;
+		i2c92 = &i2c15mux4chn0;
+		i2c93 = &i2c15mux4chn1;
+		i2c94 = &i2c15mux5chn0;
+		i2c95 = &i2c15mux5chn1;
+		i2c96 = &i2c15mux6chn0;
+		i2c97 = &i2c15mux6chn1;
+		i2c98 = &i2c15mux7chn0;
+		i2c99 = &i2c15mux7chn1;
+		i2c100 = &i2c15mux8chn0;
+		i2c101 = &i2c15mux8chn1;
+		i2c102 = &i2c15mux9chn0;
+		i2c103 = &i2c15mux9chn1;
 	};
 
 	chosen {
@@ -1148,48 +1180,280 @@ i2c8mux1chn0: i2c@0 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <0>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux2chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux2chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn1: i2c@1 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <1>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux3chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux3chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn2: i2c@2 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <2>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux4chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux4chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn3: i2c@3 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <3>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux5chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux5chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn4: i2c@4 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <4>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux6chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux6chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn5: i2c@5 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <5>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux7chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux7chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn6: i2c@6 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <6>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux8chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux8chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c8mux1chn7: i2c@7 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <7>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c8mux9chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c8mux9chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 			};
 		};
@@ -1593,48 +1857,280 @@ i2c15mux1chn0: i2c@0 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <0>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux2chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux2chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn1: i2c@1 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <1>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux3chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux3chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn2: i2c@2 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <2>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux4chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux4chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn3: i2c@3 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <3>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux5chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux5chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn4: i2c@4 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <4>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux6chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux6chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn5: i2c@5 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <5>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux7chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux7chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn6: i2c@6 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <6>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux8chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux8chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 
 				i2c15mux1chn7: i2c@7 {
 					#address-cells = <1>;
 					#size-cells = <0>;
 					reg = <7>;
+					i2c-mux@76 {
+						compatible = "nxp,pca9548";
+						reg = <0x76>;
+						#address-cells = <1>;
+						#size-cells = <0>;
+						i2c-mux-idle-disconnect;
+
+						i2c15mux9chn0: i2c@0 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <0>;
+
+							temperature-sensor@4b {
+								compatible = "ti,tmp112";
+								reg = <0x4b>;
+							};
+						};
+
+						i2c15mux9chn1: i2c@1 {
+							#address-cells = <1>;
+							#size-cells = <0>;
+							reg = <1>;
+
+							temperature-sensor@48 {
+								compatible = "ti,tmp112";
+								reg = <0x48>;
+							};
+						};
+					};
 				};
 			};
 		};
-- 
2.51.0



^ permalink raw reply related

* [PATCH v1 6/7] ARM: dts: aspeed: system1: Added status LEDs
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Ninad Palsule
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

Added four LEDs controllers to show the FPGA status in system1 BMC
machine. These LEDs provide faults and pgood states of the system.

Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 .../dts/aspeed/aspeed-bmc-ibm-system1.dts     | 917 ++++++++++++++++++
 1 file changed, 917 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index 3ccf932832f1..91c317267d6b 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -564,6 +564,923 @@ &vhub {
 &i2c0 {
 	status = "okay";
 
+	led-controller@61 {
+		compatible = "nxp,pca9552";
+		reg = <0x61>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"pgood0_flt_latched", "pgood1_flt_latched",
+			"pgood2_flt_latched", "pgood3_flt_latched",
+			"pgood4_flt_latched", "pgood5_flt_latched",
+			"pgood6_flt_latched", "pgood7_flt_latched",
+			"pgood8_flt_latched", "pgood9_flt_latched",
+			"pgood10_flt_latched", "pgood11_flt_latched",
+			"pgood12_flt_latched", "pgood13_flt_latched",
+			"pgood14_flt_latched", "pgood15_flt_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
+	led-controller@62 {
+		compatible = "nxp,pca9552";
+		reg = <0x62>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"pgood16_flt_latched", "pgood17_flt_latched",
+			"pgood18_flt_latched", "pgood19_flt_latched",
+			"pgood20_flt_latched", "pgood21_flt_latched",
+			"pgood22_flt_latched", "pgood23_flt_latched",
+			"pgood24_flt_latched", "pgood25_flt_latched",
+			"pgood26_flt_latched", "pgood27_flt_latched",
+			"pgood28_flt_latched", "pgood29_flt_latched",
+			"pgood30_flt_latched", "pgood31_flt_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
+	led-controller@63 {
+		compatible = "nxp,pca9552";
+		reg = <0x63>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"pgood32_flt_latched", "pgood33_flt_latched",
+			"pgood34_flt_latched", "pgood35_flt_latched",
+			"pgood36_flt_latched", "pgood37_flt_latched",
+			"pgood38_flt_latched", "pgood39_flt_latched",
+			"pgood40_flt_latched", "pgood41_flt_latched",
+			"pgood42_flt_latched", "pgood43_flt_latched",
+			"pgood44_flt_latched", "pgood45_flt_latched",
+			"pgood46_flt_latched", "pgood47_flt_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
+	led-controller@64 {
+		compatible = "nxp,pca9552";
+		reg = <0x64>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"fault0_latched", "fault1_latched",
+			"fault2_latched", "fault3_latched",
+			"fault4_latched", "fault5_latched",
+			"fault6_latched", "fault7_latched",
+			"fault8_latched", "fault9_latched",
+			"fault10_latched", "fault11_latched",
+			"fault12_latched", "fault13_latched",
+			"fault14_latched", "fault15_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
+	led-controller@65 {
+		compatible = "nxp,pca9552";
+		reg = <0x65>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"fault16_latched", "fault17_latched",
+			"fault18_latched", "fault19_latched",
+			"fault20_latched", "fault21_latched",
+			"fault22_latched", "fault23_latched",
+			"fault24_latched", "fault25_latched",
+			"fault26_latched", "fault27_latched",
+			"fault28_latched", "fault29_latched",
+			"fault30_latched", "fault31_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
+	led-controller@66 {
+		compatible = "nxp,pca9552";
+		reg = <0x66>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"fault32_latched", "fault33_latched",
+			"fault34_latched", "fault35_latched",
+			"fault36_latched", "fault37_latched",
+			"fault38_latched", "fault39_latched",
+			"fault40_latched", "fault41_latched",
+			"fault42_latched", "fault43_latched",
+			"fault44_latched", "fault45_latched",
+			"fault46_latched", "fault47_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
+	led-controller@67 {
+		compatible = "nxp,pca9552";
+		reg = <0x67>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names =
+			"fault48_latched", "fault49_latched",
+			"fault50_latched", "fault51_latched",
+			"fault52_latched", "fault53_latched",
+			"fault54_latched", "fault55_latched",
+			"fault56_latched", "fault57_latched",
+			"fault58_latched", "fault59_latched",
+			"fault60_latched", "fault61_latched",
+			"fault62_latched", "fault63_latched";
+
+		led@0 {
+			reg = <0>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@1 {
+			reg = <1>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@2 {
+			reg = <2>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@3 {
+			reg = <3>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@4 {
+			reg = <4>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@5 {
+			reg = <5>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@6 {
+			reg = <6>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@7 {
+			reg = <7>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@8 {
+			reg = <8>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@9 {
+			reg = <9>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@a {
+			reg = <0xa>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@b {
+			reg = <0xb>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@c {
+			reg = <0xc>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@d {
+			reg = <0xd>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@e {
+			reg = <0xe>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+
+		led@f {
+			reg = <0xf>;
+			retain-state-shutdown;
+			default-state = "keep";
+			type = <PCA955X_TYPE_LED>;
+		};
+	};
+
 	eeprom@50 {
 		compatible = "atmel,24c64";
 		reg = <0x50>;
-- 
2.51.0



^ permalink raw reply related

* [PATCH v1 5/7] ARM: dts: aspeed: system1: disable NCSI net port
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Andrew Geissler, ninad
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

From: Andrew Geissler <geissonator@yahoo.com>

There appears to be a hardware issue on system1 with the shared NCSI
network port, eth2. Our use cases don't require the use of this shared
network port by the BMC so just remove it from our device tree.

The symptom is that intermittently the entire BMC network stack will
stop working during a chassis power on or off. Any active ssh sessions
to the BMC will completely hang, and then come back after 5-60 seconds.

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index a5252cec9903..3ccf932832f1 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -519,16 +519,6 @@ &mac2 {
 	use-ncsi;
 };
 
-&mac3 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_rmii4_default>;
-	clocks = <&syscon ASPEED_CLK_GATE_MAC4CLK>,
-		 <&syscon ASPEED_CLK_MAC4RCLK>;
-	clock-names = "MACCLK", "RCLK";
-	use-ncsi;
-};
-
 &wdt1 {
 	aspeed,reset-type = "none";
 	aspeed,external-signal;
-- 
2.51.0



^ permalink raw reply related

* [PATCH v1 7/7] ARM: dts: aspeed: system1: DTS updates
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Ninad Palsule
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

- Removed SGPIO node as not in use anymore.
- Updated chassis power related pins as per the new hardware design

Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index 91c317267d6b..d7a934fe5860 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -424,7 +424,7 @@ &pinctrl_gpiol6_unbiased
 	/*E0-E7*/	"","","","","","","","",
 	/*F0-F7*/	"","","","","","","","",
 	/*G0-G7*/	"","","","","","","","",
-	/*H0-H7*/	"","","","","","","","",
+	/*H0-H7*/	"power-chassis-good","power-chassis-reboot","","","","","","",
 	/*I0-I7*/	"","","","","","","","",
 	/*J0-J7*/	"","","","","","","","",
 	/*K0-K7*/	"","","","","","","","",
@@ -440,7 +440,7 @@ &pinctrl_gpiol6_unbiased
 	/*U0-U7*/	"","","","","","","","",
 	/*V0-V7*/	"","rtc-battery-voltage-read-enable","","power-chassis-control","","","","",
 	/*W0-W7*/	"","","","","","","","",
-	/*X0-X7*/	"fpga-pgood","power-chassis-good","pch-pgood","","","","","",
+	/*X0-X7*/	"fpga-pgood","","pch-pgood","","","","","",
 	/*Y0-Y7*/	"","","","","","","","",
 	/*Z0-Z7*/	"","","","","","","","";
 
@@ -486,12 +486,6 @@ &emmc {
 	clk-phase-mmc-hs200 = <180>, <180>;
 };
 
-&sgpiom0 {
-	status = "okay";
-	ngpios = <128>;
-	bus-frequency = <500000>;
-};
-
 &ibt {
 	status = "okay";
 };
-- 
2.51.0



^ permalink raw reply related

* [PATCH v1 3/7] ARM: dts: aspeed: system1: Add usb virtual hub dev
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Manojkiran Eda, ninad
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

From: Manojkiran Eda <manojkiran.eda@gmail.com>

The usb virtual hub device is required to pass the typed keystrokes to
the Host OS as part of enabling the KVM (Keyboard-video-mouse) function.

Signed-off-by: Manojkiran Eda <manojkiran.eda@gmail.com>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index 0ca799893791..b0eb1767c485 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -535,6 +535,10 @@ &video {
 	status = "okay";
 };
 
+&vhub {
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 
-- 
2.51.0



^ permalink raw reply related

* [PATCH v1 2/7] ARM: dts: aspeed: system1: Enable video engine
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Manojkiran Eda, ninad
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

From: Manojkiran Eda <manojkiran.eda@gmail.com>

This patch enables the aspeed video engine support in ASPEED BMC for
IBM System1. It is crucial for facilitating the BMC's video capture
and redirection capabilities, which are integral to remote management
and KVM (Keyboard-Video-Mouse) over IP functionality.

Signed-off-by: Manojkiran Eda <manojkiran.eda@gmail.com>
Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index 488d0b3916a1..0ca799893791 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -531,6 +531,10 @@ &lpc_snoop {
 	snoop-ports = <0x80>, <0x81>;
 };
 
+&video {
+	status = "okay";
+};
+
 &i2c0 {
 	status = "okay";
 
-- 
2.51.0



^ permalink raw reply related

* [PATCH v1 1/7] ARM: dts: aspeed: system1: Disable vuart2
From: Ninad Palsule @ 2026-04-21 22:45 UTC (permalink / raw)
  To: eajames, robh, krzk+dt, conor+dt, joel, andrew, devicetree,
	linux-arm-kernel, linux-aspeed, linux-kernel
  Cc: Ninad Palsule
In-Reply-To: <20260421224551.1611818-1-ninad@linux.ibm.com>

system1 BMC machine does not wire vuart2 to host hence disable it to
avoid any errors in the journal.

Signed-off-by: Ninad Palsule <ninad@linux.ibm.com>
---
 arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
index c8267c97a44e..488d0b3916a1 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-ibm-system1.dts
@@ -472,10 +472,6 @@ &vuart1 {
 	status = "okay";
 };
 
-&vuart2 {
-	status = "okay";
-};
-
 &lpc_ctrl {
 	status = "okay";
 	memory-region = <&flash_memory>;
-- 
2.51.0



^ permalink raw reply related


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