diff mbox series

imx: add imx8 support

Message ID 20230309002031.3223660-1-tharvey@gateworks.com
State Changes Requested
Delegated to: Petr Štetiar
Headers show
Series imx: add imx8 support | expand

Commit Message

Tim Harvey March 9, 2023, 12:20 a.m. UTC
Add imx8 support:
 - add a cortexa53 subtarget
 - move ARCH, KERNELNAME, and some FEATURES to cortexa7/cortexa9 subtargets
 - add a small series of backports from 6.2 to fix hang on USB init and
   add PCIe support

No device-specific targets or firmware images are created yet.

The resulting openwrt-imx-cortexa53-vmlinux-initramfs has been booted on
Gateworks Venice boards and the imx8mm-evk using dtb's from $LINUX_DIR
and verifying usb, pci, mmc, and fec networking work.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 target/linux/imx/Makefile                     |   7 +-
 target/linux/imx/config-5.15                  |   2 +
 target/linux/imx/cortexa53/config-default     |  89 ++++
 target/linux/imx/cortexa53/target.mk          |   8 +
 target/linux/imx/cortexa7/target.mk           |   3 +
 target/linux/imx/cortexa9/target.mk           |   3 +
 target/linux/imx/image/cortexa53.mk           |  10 +
 ...low-to-disable-individual-power-doma.patch |  35 ++
 ...-gpcv2-Turn-domain-pgc-into-bitfield.patch | 327 +++++++++++++
 ...t-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch |  40 ++
 ...soc-imx-gpcv2-add-lockdep-annotation.patch |  36 ++
 ...d-domain-option-to-keep-domain-clock.patch |  60 +++
 ...gpcv2-keep-i.MX8M-bus-clocks-enabled.patch |  69 +++
 ...-gpcv2-support-system-suspend-resume.patch |  74 +++
 .../0008-arm64-dts-imx8mm-add-GPC-node.patch  | 142 ++++++
 ...-put-USB-controllers-into-power-doma.patch |  38 ++
 ...add-PGC-control-register-indirection.patch | 187 ++++++++
 ...ie-Initialize-the-imx8-pcie-standalo.patch | 285 ++++++++++++
 ...x8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch | 305 ++++++++++++
 ...phy-imx8-pcie-Add-binding-for-the-pa.patch |  38 ++
 ...-PCI-imx-Add-the-imx8mm-pcie-support.patch | 211 +++++++++
 ...-dts-imx8mm-Add-the-pcie-phy-support.patch |  40 ++
 ...rm64-dts-imx8mm-Add-the-pcie-support.patch |  67 +++
 ...4-dts-imx8mm-venice-add-PCIe-support.patch | 437 ++++++++++++++++++
 24 files changed, 2508 insertions(+), 5 deletions(-)
 create mode 100644 target/linux/imx/cortexa53/config-default
 create mode 100644 target/linux/imx/cortexa53/target.mk
 create mode 100644 target/linux/imx/image/cortexa53.mk
 create mode 100644 target/linux/imx/patches-5.15/0001-soc-imx-gpcv2-allow-to-disable-individual-power-doma.patch
 create mode 100644 target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch
 create mode 100644 target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch
 create mode 100644 target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch
 create mode 100644 target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch
 create mode 100644 target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch
 create mode 100644 target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch
 create mode 100644 target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch
 create mode 100644 target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch
 create mode 100644 target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch
 create mode 100644 target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch
 create mode 100644 target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch
 create mode 100644 target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch
 create mode 100644 target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch
 create mode 100644 target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch
 create mode 100644 target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch
 create mode 100644 target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch

Comments

Petr Štetiar March 9, 2023, 11:36 a.m. UTC | #1
Tim Harvey <tharvey@gateworks.com> [2023-03-08 16:20:31]:

Hi Tim,

> Add imx8 support:
>  - add a cortexa53 subtarget
>  - move ARCH, KERNELNAME, and some FEATURES to cortexa7/cortexa9 subtargets
>  - add a small series of backports from 6.2 to fix hang on USB init and
>    add PCIe support

mark those patches clearly as such v6.2 backports, for example:

 0001-v6.2-soc-imx-gpcv2-allow-to-disable-individual-power-doma.patch

> No device-specific targets or firmware images are created yet.

Fine with me, but for the time being we should probably mark this subtarget as
source-only, so we don't waste time on the buildbots as there is not much
usable result yet.

> The resulting openwrt-imx-cortexa53-vmlinux-initramfs has been booted on
> Gateworks Venice boards and the imx8mm-evk using dtb's from $LINUX_DIR
> and verifying usb, pci, mmc, and fec networking work.

Nice, so it boots just fine without any additional post processing/blobs
needed?

As you're not adding bootloader, can add some information about the working
combination in the commit message as well? Simply anything which would help
anyone reproducing the result is welcome.

> -FEATURES:=audio display fpu gpio pcie rtc usb usbgadget squashfs targz nand ubifs boot-part rootfs-part
> +FEATURES:=audio display fpu gpio pcie rtc usb usbgadget squashfs targz boot-part rootfs-part

Is there any specific reason to not have NAND feature available for a53
subtarget? `imx8 NAND` yields bunch of search results, so I'm wondering why
are you bothering with removing this feature, seems like we would likely add
it back in the near future anyway.

> diff --git a/target/linux/imx/cortexa53/target.mk b/target/linux/imx/cortexa53/target.mk
> new file mode 100644
> index 000000000000..b9b32d182905
> --- /dev/null
> +++ b/target/linux/imx/cortexa53/target.mk
> @@ -0,0 +1,8 @@
> +ARCH:=aarch64
> +BOARDNAME:=NXP i.MX with Cortex-A53 (ARM64)
> +CPU_TYPE:=cortex-a53
> +KERNELNAME:=Image dtbs

 FEATURES+=source-only

Cheers,

Petr
Tim Harvey March 9, 2023, 8:19 p.m. UTC | #2
On Thu, Mar 9, 2023 at 3:37 AM Petr Štetiar <ynezz@true.cz> wrote:
>
> Tim Harvey <tharvey@gateworks.com> [2023-03-08 16:20:31]:
>
> Hi Tim,
>

Petr,

Thanks for the quick review!

> > Add imx8 support:
> >  - add a cortexa53 subtarget
> >  - move ARCH, KERNELNAME, and some FEATURES to cortexa7/cortexa9 subtargets
> >  - add a small series of backports from 6.2 to fix hang on USB init and
> >    add PCIe support
>
> mark those patches clearly as such v6.2 backports, for example:
>
>  0001-v6.2-soc-imx-gpcv2-allow-to-disable-individual-power-doma.patch

Will do.

Is there any reason to move them into
target/linux/generic/backport-5.15? These patches are all backports
only relevant to imx8.

>
> > No device-specific targets or firmware images are created yet.
>
> Fine with me, but for the time being we should probably mark this subtarget as
> source-only, so we don't waste time on the buildbots as there is not much
> usable result yet.

Ok, I will add FEATURES+=source-only

>
> > The resulting openwrt-imx-cortexa53-vmlinux-initramfs has been booted on
> > Gateworks Venice boards and the imx8mm-evk using dtb's from $LINUX_DIR
> > and verifying usb, pci, mmc, and fec networking work.
>
> Nice, so it boots just fine without any additional post processing/blobs
> needed?

Yes, assuming you already have boot firmware on the target board. I'm
booting from U-Boot with:

setenv serverip 192.168.1.146
setenv ipaddr 192.168.1.1
tftpboot $fdt_addr_r venice/imx8mm-evk.dtb && tftpboot $kernel_addr_r
venice/Image && booti $kernel_addr_r - $fdt_addr_r

>
> As you're not adding bootloader, can add some information about the working
> combination in the commit message as well? Simply anything which would help
> anyone reproducing the result is welcome.

I'm assuming you mean just add details above on how I'm booting in the
commit message?

I couldn't find any doc dir in OpenWrt to add board level
documentation. I was hoping that something had been created like
U-Boot has with rst docs in doc/board/<mfg>/<board>. Where does the
documentation at
https://openwrt.org/docs/guide-user/installation/installation_methods/x86_installation
for example come from?

The reason right now that I'm avoiding boot firmware is:
1. There was pushback regarding the firmware-imx-8.15.bin license
required to build boot firmware (see
http://lists.openwrt.org/pipermail/openwrt-devel/2022-August/039247.html)
2. The various IMX8 SoC's have incompatible binary boot firmware but
the kernel+rootfs is compatible among all the SoC's so it is nice to
have a single OS distribution that avoids boot firmware
3. I'm contemplating moving our boot firmware to emmc boot0/boot1
leaving emmc user SoC agnostic which greatly simplifies things

>
> > -FEATURES:=audio display fpu gpio pcie rtc usb usbgadget squashfs targz nand ubifs boot-part rootfs-part
> > +FEATURES:=audio display fpu gpio pcie rtc usb usbgadget squashfs targz boot-part rootfs-part
>
> Is there any specific reason to not have NAND feature available for a53
> subtarget? `imx8 NAND` yields bunch of search results, so I'm wondering why
> are you bothering with removing this feature, seems like we would likely add
> it back in the near future anyway.

I removed 'nand ubifs' because it causes a build failure where OpenWrt
assumes root.ubifs is present:
cp /usr/src/openwrt/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-imx_cortexa53/root.ubifs
/usr/src/openwrt/openwrt/bin/targets/imx/cortexa53/openwrt-imx-cortexa53-u
bifs.img
cp: cannot stat
'/usr/src/openwrt/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-imx_cortexa53/root.ubifs':
No such file or directory

This is due FEATURES having ubifs causing USES_UBIFS and
TARGET_ROOTFS_UBIFS getting set but because

Because the arguments to mkfs.ubifs and ubinize are very FLASH device
geometry specific I feel that this should be a device-specific FEATURE
and not target specific or subtarget specific.

>
> > diff --git a/target/linux/imx/cortexa53/target.mk b/target/linux/imx/cortexa53/target.mk
> > new file mode 100644
> > index 000000000000..b9b32d182905
> > --- /dev/null
> > +++ b/target/linux/imx/cortexa53/target.mk
> > @@ -0,0 +1,8 @@
> > +ARCH:=aarch64
> > +BOARDNAME:=NXP i.MX with Cortex-A53 (ARM64)
> > +CPU_TYPE:=cortex-a53
> > +KERNELNAME:=Image dtbs
>
>  FEATURES+=source-only
>

Thanks,

Tim
Petr Štetiar March 10, 2023, 10:21 a.m. UTC | #3
Tim Harvey <tharvey@gateworks.com> [2023-03-09 12:19:24]:

Hi,

> Is there any reason to move them into target/linux/generic/backport-5.15?

sorry for confusing you, but I've just meant to rename the patch files itself,
so they contain bacported kernel version in their filename, making the patch
origin explicit as it makes maintenance of the patches much easier.

There is no need to move it into generic kernel folder and complicate stuff
there.

> I'm assuming you mean just add details above on how I'm booting in the
> commit message?

Yes, just imagine someone buying your board, without much prior knowledge and
would use the commit message as the only source for booting that board with
OpenWrt.

BTW for the folks handling the wiki, the commit message is usually the only
source of information.

> The reason right now that I'm avoiding boot firmware is:
> 1. There was pushback regarding the firmware-imx-8.15.bin license
> required to build boot firmware (see
> http://lists.openwrt.org/pipermail/openwrt-devel/2022-August/039247.html)

Well, IMO its crystal clear, that NXP needs to fix this, we can't do much
about it, unless you plan to host it on your servers :-)

Anyway, it's clear, that there is some interest in this SoC and it would be
helpful to have some common base for development, even in the source-only
form.

Thus I would simply like to merge partial support for this SoC once 23.y is
branched, unless of course NACKed. Its really against FOSS spirit, we
shouldn't promote such SoCs even in the source-only form, but I sincerely
hope, that NXP is going to understand the situation and fix it before next
OpenWrt release. 

If it turns out, that I was very naive, we should probably cast a vote and
either keep it in source-only form or remove it.

> This is due FEATURES having ubifs causing USES_UBIFS and
> TARGET_ROOTFS_UBIFS getting set but because

IMO this is likely due to a fact, that you've not defined any device in your
image file, so you don't define `FILESYSTEMS` variable and thus the build
system uses default `TARGET_FILESYSTEMS` which has `ubifs` defined.

So I would probably try to just define a support for a single device with
empty FILESYSTEMS variable and see how that works.

Cheers,

Petr
Tim Harvey March 10, 2023, 7:36 p.m. UTC | #4
On Fri, Mar 10, 2023 at 2:21 AM Petr Štetiar <ynezz@true.cz> wrote:
>
> Tim Harvey <tharvey@gateworks.com> [2023-03-09 12:19:24]:
>
> Hi,
>
> > Is there any reason to move them into target/linux/generic/backport-5.15?
>
> sorry for confusing you, but I've just meant to rename the patch files itself,
> so they contain bacported kernel version in their filename, making the patch
> origin explicit as it makes maintenance of the patches much easier.
>
> There is no need to move it into generic kernel folder and complicate stuff
> there.
>
> > I'm assuming you mean just add details above on how I'm booting in the
> > commit message?
>
> Yes, just imagine someone buying your board, without much prior knowledge and
> would use the commit message as the only source for booting that board with
> OpenWrt.
>
> BTW for the folks handling the wiki, the commit message is usually the only
> source of information.
>
> > The reason right now that I'm avoiding boot firmware is:
> > 1. There was pushback regarding the firmware-imx-8.15.bin license
> > required to build boot firmware (see
> > http://lists.openwrt.org/pipermail/openwrt-devel/2022-August/039247.html)
>
> Well, IMO its crystal clear, that NXP needs to fix this, we can't do much
> about it, unless you plan to host it on your servers :-)
>
> Anyway, it's clear, that there is some interest in this SoC and it would be
> helpful to have some common base for development, even in the source-only
> form.
>
> Thus I would simply like to merge partial support for this SoC once 23.y is
> branched, unless of course NACKed. Its really against FOSS spirit, we
> shouldn't promote such SoCs even in the source-only form, but I sincerely
> hope, that NXP is going to understand the situation and fix it before next
> OpenWrt release.

if I address your feedback and post a v2 must it wait until after 23.y
branch based on the minimal impact to the imx target?

>
> If it turns out, that I was very naive, we should probably cast a vote and
> either keep it in source-only form or remove it.
>
> > This is due FEATURES having ubifs causing USES_UBIFS and
> > TARGET_ROOTFS_UBIFS getting set but because
>
> IMO this is likely due to a fact, that you've not defined any device in your
> image file, so you don't define `FILESYSTEMS` variable and thus the build
> system uses default `TARGET_FILESYSTEMS` which has `ubifs` defined.
>

True... from include/image/mk:

fs-types-$(CONFIG_TARGET_ROOTFS_UBIFS) += ubifs
...
TARGET_FILESYSTEMS := $(fs-types-y)

The failure is trying to copy the root.ubifs during image copy:
cp /usr/src/openwrt/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-imx_cortexa53/root.ubifs
/usr/src/openwrt/openwrt/bin/targets/imx/cortexa53/openwrt-imx-cortexa53-ubifs.img
cp: cannot stat
'/usr/src/openwrt/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-imx_cortexa53/root.ubifs':
No such file or directory

> So I would probably try to just define a support for a single device with
> empty FILESYSTEMS variable and see how that works.

Adding a FILESYSTEMS:= by itself in image/cortexa53.mk still fails

Adding the following doesn't seem to help either (I don't think this
does anything without something being in TARGET_DEVICES)
define Device/Default
  KERNEL_NAME := Image
  KERNEL := kernel-bin
  DTS_DIR := $(LINUX_DIR)/arch/$(LINUX_KARCH)/boot/dts/freescale
  FILESYSTEMS := squashfs ext4
endef

And adding an actual device and building for it still fails
define Device/Default
  KERNEL_NAME := Image
  KERNEL := kernel-bin
  DTS_DIR := $(LINUX_DIR)/arch/$(LINUX_KARCH)/boot/dts/freescale
  FILESYSTEMS := squashfs ext4
endef

define Device/rootfs_emmc
  $(call Device/Default)
  DEVICE_VARIANT := eMMC rootfs
  FILESYSTEMS :=
endef
TARGET_DEVICES += rootfs_emmc

Perhaps I'm doing something wrong above?

Perhaps its just fine moving ubifs from target/linux/imx/Makefile to
the cortexa7/cortexa9 subtargets until someone finds the need for
ubifs in a specific device?

Thanks,

Tim
diff mbox series

Patch

diff --git a/target/linux/imx/Makefile b/target/linux/imx/Makefile
index 5fb7a4d339ef..1263484316c4 100644
--- a/target/linux/imx/Makefile
+++ b/target/linux/imx/Makefile
@@ -4,18 +4,15 @@ 
 
 include $(TOPDIR)/rules.mk
 
-ARCH:=arm
 BOARD:=imx
 BOARDNAME:=NXP i.MX
-FEATURES:=audio display fpu gpio pcie rtc usb usbgadget squashfs targz nand ubifs boot-part rootfs-part
-SUBTARGETS:=cortexa7 cortexa9
+FEATURES:=audio display fpu gpio pcie rtc usb usbgadget squashfs targz boot-part rootfs-part
+SUBTARGETS:=cortexa7 cortexa9 cortexa53
 
 KERNEL_PATCHVER:=5.15
 
 include $(INCLUDE_DIR)/target.mk
 
-KERNELNAME:=zImage dtbs
-
 DEFAULT_PACKAGES += uboot-envtools mkf2fs e2fsprogs blkid
 
 $(eval $(call BuildTarget))
diff --git a/target/linux/imx/config-5.15 b/target/linux/imx/config-5.15
index 0c9b7d22b4e5..c45872d19c40 100644
--- a/target/linux/imx/config-5.15
+++ b/target/linux/imx/config-5.15
@@ -441,3 +441,5 @@  CONFIG_ZLIB_DEFLATE=y
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZSTD_COMPRESS=y
 CONFIG_ZSTD_DECOMPRESS=y
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_PHY_FSL_IMX8M_PCIE is not set
diff --git a/target/linux/imx/cortexa53/config-default b/target/linux/imx/cortexa53/config-default
new file mode 100644
index 000000000000..b91928f8ec1a
--- /dev/null
+++ b/target/linux/imx/cortexa53/config-default
@@ -0,0 +1,89 @@ 
+CONFIG_64BIT=y
+CONFIG_ARM64=y
+CONFIG_ARM64_4K_PAGES=y
+CONFIG_ARM64_VA_BITS_39=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_AES_ARM64=y
+CONFIG_CRYPTO_AES_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_BLAKE2S=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA256_ARM64=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_SHA512_ARM64=y
+CONFIG_CRYPTO_SHA512_ARM64_CE=y
+CONFIG_CRYPTO_ZSTD=y
+CONFIG_UNMAP_KERNEL_AT_EL0=y
+CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
+CONFIG_ARM64_TAGGED_ADDR_ABI=y
+CONFIG_ARCH_MMAP_RND_BITS=18
+CONFIG_VMAP_STACK=y
+CONFIG_MEMORY_ISOLATION=y
+CONFIG_CMA=y
+CONFIG_CMA_AREAS=7
+# CONFIG_CMA_DEBUG is not set
+# CONFIG_CMA_DEBUGFS is not set
+# CONFIG_CMA_SYSFS is not set
+CONFIG_CONTIG_ALLOC=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ARM_IMX_CPUFREQ_DT=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_EXTRA_FIRMWARE="imx/sdma/sdma-imx7d.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_PCI=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIE_PME=y
+CONFIG_PHY_FSL_IMX8M_PCIE=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIE_DW=y
+CONFIG_PCIE_DW_HOST=y
+CONFIG_PCIE_PME=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_IMX6=y
+CONFIG_PCI_MSI=y
+CONFIG_PCI_MSI_IRQ_DOMAIN=y
+CONFIG_PINCTRL_IMX=y
+CONFIG_DWMAC_DWC_QOS_ETH=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_PINCTRL_IMX=y
+CONFIG_PINCTRL_IMX8MM=y
+CONFIG_PINCTRL_IMX8MN=y
+CONFIG_PINCTRL_IMX8MP=y
+CONFIG_PINCTRL_IMX8MQ=y
+CONFIG_THERMAL=y
+CONFIG_IMX8MM_THERMAL=y
+CONFIG_REGULATOR_MP5416=y
+CONFIG_REGULATOR_PCA9450=y
+CONFIG_USB_CONN_GPIO=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_OTG=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_DUAL_ROLE=y
+# CONFIG_USB_DWC3_GADGET is not set
+# CONFIG_USB_DWC3_HOST is not set
+CONFIG_USB_DWC3_IMX8MP=y
+# CONFIG_MMC_SDHCI_PCI is not set
+CONFIG_CLK_IMX8MM=y
+CONFIG_CLK_IMX8MN=y
+CONFIG_CLK_IMX8MP=y
+CONFIG_CLK_IMX8MQ=y
+CONFIG_CLK_IMX8QXP=y
+CONFIG_SOC_IMX8M=y
+# CONFIG_IMX_DSP is not set
+# CONFIG_IMX_SCU is not set
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_PHY_FSL_IMX8MQ_USB=y
+CONFIG_RESET_IMX7=y
+CONFIG_INTERCONNECT=y
+CONFIG_INTERCONNECT_IMX=y
+CONFIG_INTERCONNECT_IMX8MM=y
+CONFIG_INTERCONNECT_IMX8MN=y
+CONFIG_INTERCONNECT_IMX8MQ=y
+# CONFIG_DMA_CMA is not set
diff --git a/target/linux/imx/cortexa53/target.mk b/target/linux/imx/cortexa53/target.mk
new file mode 100644
index 000000000000..b9b32d182905
--- /dev/null
+++ b/target/linux/imx/cortexa53/target.mk
@@ -0,0 +1,8 @@ 
+ARCH:=aarch64
+BOARDNAME:=NXP i.MX with Cortex-A53 (ARM64)
+CPU_TYPE:=cortex-a53
+KERNELNAME:=Image dtbs
+
+define Target/Description
+	Build firmware images for NXP i.MX (Cortex-A53) based boards.
+endef
diff --git a/target/linux/imx/cortexa7/target.mk b/target/linux/imx/cortexa7/target.mk
index 11de87507d3f..708c6e2bfbb5 100644
--- a/target/linux/imx/cortexa7/target.mk
+++ b/target/linux/imx/cortexa7/target.mk
@@ -1,6 +1,9 @@ 
+ARCH:=arm
 BOARDNAME:=NXP i.MX with Cortex-A7
 CPU_TYPE:=cortex-a7
 CPU_SUBTYPE:=neon-vfpv4
+KERNELNAME:=zImage dtbs
+FEATURES+=nand ubifs
 
 define Target/Description
 	Build firmware images for NXP i.MX (Cortex-A7) based boards.
diff --git a/target/linux/imx/cortexa9/target.mk b/target/linux/imx/cortexa9/target.mk
index 9bd63c7be1cf..fc88486ca3cd 100644
--- a/target/linux/imx/cortexa9/target.mk
+++ b/target/linux/imx/cortexa9/target.mk
@@ -1,6 +1,9 @@ 
+ARCH:=arm
 BOARDNAME:=NXP i.MX with Cortex-A9
 CPU_TYPE:=cortex-a9
 CPU_SUBTYPE:=neon
+KERNELNAME:=zImage dtbs
+FEATURES+=nand ubifs
 
 define Target/Description
 	Build firmware images for NXP i.MX (Cortex-A9) based boards.
diff --git a/target/linux/imx/image/cortexa53.mk b/target/linux/imx/image/cortexa53.mk
new file mode 100644
index 000000000000..8a5ca8a46c02
--- /dev/null
+++ b/target/linux/imx/image/cortexa53.mk
@@ -0,0 +1,10 @@ 
+define Image/Build/Initramfs
+	$(CP) $(KERNEL_BUILD_DIR)/vmlinux $(BIN_DIR)/$(IMG_PREFIX)-vmlinux
+	$(CP) $(KERNEL_BUILD_DIR)/vmlinux-initramfs $(BIN_DIR)/$(IMG_PREFIX)-vmlinux-initramfs
+endef
+
+define Image/Build
+	$(call Image/Build/$(1))
+	cp $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).img
+	cp $(KDIR)/vmlinux $(BIN_DIR)/$(IMG_PREFIX)-vmlinux
+endef
diff --git a/target/linux/imx/patches-5.15/0001-soc-imx-gpcv2-allow-to-disable-individual-power-doma.patch b/target/linux/imx/patches-5.15/0001-soc-imx-gpcv2-allow-to-disable-individual-power-doma.patch
new file mode 100644
index 000000000000..a092ba497edc
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0001-soc-imx-gpcv2-allow-to-disable-individual-power-doma.patch
@@ -0,0 +1,35 @@ 
+From 43ae58d3793a9275d45d9735d012ed7455fbafbb Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 14:48:52 +0200
+Subject: [PATCH 01/17] soc: imx: gpcv2: allow to disable individual power
+ domains
+
+Some board designs don't supply power to all of the power domains,
+as they are not used anyways. In that case we must make sure to
+not touch those power domains at all, as trying to power up a
+domain that has no power supplied to it will obviously end in a
+system crash. Allow to disable those domains via the standard DT
+status property.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+---
+ drivers/soc/imx/gpcv2.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 4dc3a3f73511..60566bdcb51f 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -989,6 +989,9 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
+ 		struct imx_pgc_domain *domain;
+ 		u32 domain_index;
+ 
++		if (!of_device_is_available(np))
++			continue;
++
+ 		ret = of_property_read_u32(np, "reg", &domain_index);
+ 		if (ret) {
+ 			dev_err(dev, "Failed to read 'reg' property\n");
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch b/target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch
new file mode 100644
index 000000000000..b1ec4c7beaa2
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch
@@ -0,0 +1,327 @@ 
+From 6dbb5cd7006a5382ab02282b7b39e0edc8e15331 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex@denx.de>
+Date: Sat, 2 Oct 2021 02:59:38 +0200
+Subject: [PATCH 02/17] soc: imx: gpcv2: Turn domain->pgc into bitfield
+
+There is currently the MX8MM GPU domain, which is in fact a composite domain
+for both GPU2D and GPU3D. To correctly configure this domain, it is necessary
+to control both GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) at the same
+time. This is currently not possible.
+
+Turn the domain->pgc from value into bitfield and use for_each_set_bit() to
+iterate over all bits set in domain->pgc when configuring GPC_PGC_nCTRL
+register array. This way it is possible to configure all GPC_PGC_nCTRL
+registers required in a particular domain.
+
+This is a preparatory patch, no functional change.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 72 ++++++++++++++++++++++-------------------
+ 1 file changed, 38 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 60566bdcb51f..8341b03eec92 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -192,7 +192,7 @@ struct imx_pgc_domain {
+ 	struct clk_bulk_data *clks;
+ 	int num_clks;
+ 
+-	unsigned int pgc;
++	unsigned long pgc;
+ 
+ 	const struct {
+ 		u32 pxx;
+@@ -220,7 +220,7 @@ to_imx_pgc_domain(struct generic_pm_domain *genpd)
+ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ {
+ 	struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+-	u32 reg_val;
++	u32 reg_val, pgc;
+ 	int ret;
+ 
+ 	ret = pm_runtime_get_sync(domain->dev);
+@@ -267,8 +267,10 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ 		}
+ 
+ 		/* disable power control */
+-		regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+-				  GPC_PGC_CTRL_PCR);
++		for_each_set_bit(pgc, &domain->pgc, 32) {
++			regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
++					  GPC_PGC_CTRL_PCR);
++		}
+ 	}
+ 
+ 	/* delay for reset to propagate */
+@@ -314,7 +316,7 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ {
+ 	struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+-	u32 reg_val;
++	u32 reg_val, pgc;
+ 	int ret;
+ 
+ 	/* Enable reset clocks for all devices in the domain */
+@@ -341,8 +343,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ 
+ 	if (domain->bits.pxx) {
+ 		/* enable power control */
+-		regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+-				   GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
++		for_each_set_bit(pgc, &domain->pgc, 32) {
++			regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
++					   GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
++		}
+ 
+ 		/* request the domain to power down */
+ 		regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
+@@ -392,7 +396,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
+ 			.map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
+ 		},
+ 		.voltage   = 1000000,
+-		.pgc	   = IMX7_PGC_MIPI,
++		.pgc	   = BIT(IMX7_PGC_MIPI),
+ 	},
+ 
+ 	[IMX7_POWER_DOMAIN_PCIE_PHY] = {
+@@ -404,7 +408,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
+ 			.map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
+ 		},
+ 		.voltage   = 1000000,
+-		.pgc	   = IMX7_PGC_PCIE,
++		.pgc	   = BIT(IMX7_PGC_PCIE),
+ 	},
+ 
+ 	[IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
+@@ -416,7 +420,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
+ 			.map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
+ 		},
+ 		.voltage   = 1200000,
+-		.pgc	   = IMX7_PGC_USB_HSIC,
++		.pgc	   = BIT(IMX7_PGC_USB_HSIC),
+ 	},
+ };
+ 
+@@ -451,7 +455,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_MIPI_SW_Pxx_REQ,
+ 			.map = IMX8M_MIPI_A53_DOMAIN,
+ 		},
+-		.pgc	   = IMX8M_PGC_MIPI,
++		.pgc	   = BIT(IMX8M_PGC_MIPI),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_PCIE1] = {
+@@ -462,7 +466,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_PCIE1_SW_Pxx_REQ,
+ 			.map = IMX8M_PCIE1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_PCIE1,
++		.pgc   = BIT(IMX8M_PGC_PCIE1),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_USB_OTG1] = {
+@@ -473,7 +477,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_OTG1_SW_Pxx_REQ,
+ 			.map = IMX8M_OTG1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_OTG1,
++		.pgc   = BIT(IMX8M_PGC_OTG1),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_USB_OTG2] = {
+@@ -484,7 +488,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_OTG2_SW_Pxx_REQ,
+ 			.map = IMX8M_OTG2_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_OTG2,
++		.pgc   = BIT(IMX8M_PGC_OTG2),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_DDR1] = {
+@@ -495,7 +499,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_DDR1_SW_Pxx_REQ,
+ 			.map = IMX8M_DDR2_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_DDR1,
++		.pgc   = BIT(IMX8M_PGC_DDR1),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_GPU] = {
+@@ -508,7 +512,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.hskreq = IMX8M_GPU_HSK_PWRDNREQN,
+ 			.hskack = IMX8M_GPU_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8M_PGC_GPU,
++		.pgc   = BIT(IMX8M_PGC_GPU),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_VPU] = {
+@@ -521,7 +525,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.hskreq = IMX8M_VPU_HSK_PWRDNREQN,
+ 			.hskack = IMX8M_VPU_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8M_PGC_VPU,
++		.pgc   = BIT(IMX8M_PGC_VPU),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_DISP] = {
+@@ -534,7 +538,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.hskreq = IMX8M_DISP_HSK_PWRDNREQN,
+ 			.hskack = IMX8M_DISP_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8M_PGC_DISP,
++		.pgc   = BIT(IMX8M_PGC_DISP),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
+@@ -545,7 +549,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
+ 			.map = IMX8M_MIPI_CSI1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_MIPI_CSI1,
++		.pgc   = BIT(IMX8M_PGC_MIPI_CSI1),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
+@@ -556,7 +560,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
+ 			.map = IMX8M_MIPI_CSI2_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_MIPI_CSI2,
++		.pgc   = BIT(IMX8M_PGC_MIPI_CSI2),
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_PCIE2] = {
+@@ -567,7 +571,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.pxx = IMX8M_PCIE2_SW_Pxx_REQ,
+ 			.map = IMX8M_PCIE2_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8M_PGC_PCIE2,
++		.pgc   = BIT(IMX8M_PGC_PCIE2),
+ 	},
+ };
+ 
+@@ -630,7 +634,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_PCIE_SW_Pxx_REQ,
+ 			.map = IMX8MM_PCIE_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_PCIE,
++		.pgc   = BIT(IMX8MM_PGC_PCIE),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_OTG1] = {
+@@ -641,7 +645,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_OTG1_SW_Pxx_REQ,
+ 			.map = IMX8MM_OTG1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_OTG1,
++		.pgc   = BIT(IMX8MM_PGC_OTG1),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_OTG2] = {
+@@ -652,7 +656,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_OTG2_SW_Pxx_REQ,
+ 			.map = IMX8MM_OTG2_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_OTG2,
++		.pgc   = BIT(IMX8MM_PGC_OTG2),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_GPUMIX] = {
+@@ -665,7 +669,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
+ 			.hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8MM_PGC_GPUMIX,
++		.pgc   = BIT(IMX8MM_PGC_GPUMIX),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_GPU] = {
+@@ -678,7 +682,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+ 			.hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8MM_PGC_GPU2D,
++		.pgc   = BIT(IMX8MM_PGC_GPU2D),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_VPUMIX] = {
+@@ -691,7 +695,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
+ 			.hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8MM_PGC_VPUMIX,
++		.pgc   = BIT(IMX8MM_PGC_VPUMIX),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_VPUG1] = {
+@@ -702,7 +706,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
+ 			.map = IMX8MM_VPUG1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_VPUG1,
++		.pgc   = BIT(IMX8MM_PGC_VPUG1),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_VPUG2] = {
+@@ -713,7 +717,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
+ 			.map = IMX8MM_VPUG2_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_VPUG2,
++		.pgc   = BIT(IMX8MM_PGC_VPUG2),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_VPUH1] = {
+@@ -724,7 +728,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
+ 			.map = IMX8MM_VPUH1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_VPUH1,
++		.pgc   = BIT(IMX8MM_PGC_VPUH1),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_DISPMIX] = {
+@@ -737,7 +741,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
+ 			.hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8MM_PGC_DISPMIX,
++		.pgc   = BIT(IMX8MM_PGC_DISPMIX),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_MIPI] = {
+@@ -748,7 +752,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.pxx = IMX8MM_MIPI_SW_Pxx_REQ,
+ 			.map = IMX8MM_MIPI_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MM_PGC_MIPI,
++		.pgc   = BIT(IMX8MM_PGC_MIPI),
+ 	},
+ };
+ 
+@@ -815,7 +819,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+ 			.pxx = IMX8MN_OTG1_SW_Pxx_REQ,
+ 			.map = IMX8MN_OTG1_A53_DOMAIN,
+ 		},
+-		.pgc   = IMX8MN_PGC_OTG1,
++		.pgc   = BIT(IMX8MN_PGC_OTG1),
+ 	},
+ 
+ 	[IMX8MN_POWER_DOMAIN_GPUMIX] = {
+@@ -828,7 +832,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+ 			.hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
+ 			.hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = IMX8MN_PGC_GPUMIX,
++		.pgc   = BIT(IMX8MN_PGC_GPUMIX),
+ 	},
+ };
+ 
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch b/target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch
new file mode 100644
index 000000000000..4ea5b3b0b0ff
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch
@@ -0,0 +1,40 @@ 
+From f05c5d9450c83ab64a7e313ada06129721f29c7f Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex@denx.de>
+Date: Sat, 2 Oct 2021 02:59:39 +0200
+Subject: [PATCH 03/17] soc: imx: gpcv2: Set both GPC_PGC_nCTRL(GPU_2D|GPU_3D)
+ for MX8MM GPU domain
+
+To bring up the MX8MM GPU domain, it is necessary to configure both
+GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) registers. Without
+this configuration, the system might hang on boot when bringing up
+the GPU power domain. This is sporadically observed on multiple
+disparate systems.
+
+Add the GPU3D bit into MX8MM GPU domain pgc bitfield, so that both
+GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) registers are
+configured when bringing up the GPU domain. This fixes the sporadic
+hang.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 8341b03eec92..afc309aff0f0 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -682,7 +682,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+ 			.hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+ 		},
+-		.pgc   = BIT(IMX8MM_PGC_GPU2D),
++		.pgc   = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_VPUMIX] = {
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch b/target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch
new file mode 100644
index 000000000000..6da19e0be772
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch
@@ -0,0 +1,36 @@ 
+From 9cdd2d0a39b60929a30b1642e67441ef748509cc Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:40 +0200
+Subject: [PATCH 04/17] soc: imx: gpcv2: add lockdep annotation
+
+Some of the GPCv2 power domains are nested inside each other without
+visibility to lockdep at the genpd level, as they are in separate
+driver instances and don't have a parent/child power-domain relationship.
+
+Add a subclass annotation to the nested domains to let lockdep know that
+it is okay to take the genpd lock in a nested fashion.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index afc309aff0f0..2761e81abb40 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -901,6 +901,10 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ 		goto out_domain_unmap;
+ 	}
+ 
++	if (IS_ENABLED(CONFIG_LOCKDEP) &&
++	    of_property_read_bool(domain->dev->of_node, "power-domains"))
++		lockdep_set_subclass(&domain->genpd.mlock, 1);
++
+ 	ret = of_genpd_add_provider_simple(domain->dev->of_node,
+ 					   &domain->genpd);
+ 	if (ret) {
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch b/target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch
new file mode 100644
index 000000000000..b14fe8b90467
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch
@@ -0,0 +1,60 @@ 
+From a6ac7c30d1664e6b7336b6bee44c97347c916af4 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:41 +0200
+Subject: [PATCH 05/17] soc: imx: gpcv2: add domain option to keep domain
+ clocks enabled
+
+Some of the MIX domains are using clocks to drive the bus bridges. Those
+must be enabled at all times, as long as the domain is powered up and
+they don't have any other consumer than the power domain. Add an option
+to keep the clocks attached to a domain enabled as long as the domain
+is power up and only disable them after the domain is powered down.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 2761e81abb40..7e7826bbd3dc 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -202,6 +202,7 @@ struct imx_pgc_domain {
+ 	} bits;
+ 
+ 	const int voltage;
++	const bool keep_clocks;
+ 	struct device *dev;
+ };
+ 
+@@ -298,7 +299,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ 	}
+ 
+ 	/* Disable reset clocks for all devices in the domain */
+-	clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
++	if (!domain->keep_clocks)
++		clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+ 
+ 	return 0;
+ 
+@@ -320,10 +322,12 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ 	int ret;
+ 
+ 	/* Enable reset clocks for all devices in the domain */
+-	ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+-	if (ret) {
+-		dev_err(domain->dev, "failed to enable reset clocks\n");
+-		return ret;
++	if (!domain->keep_clocks) {
++		ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
++		if (ret) {
++			dev_err(domain->dev, "failed to enable reset clocks\n");
++			return ret;
++		}
+ 	}
+ 
+ 	/* request the ADB400 to power down */
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch b/target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch
new file mode 100644
index 000000000000..9abf099ae915
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch
@@ -0,0 +1,69 @@ 
+From b2a1ee027619413d42cdb3a02459500c9f6f035a Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:42 +0200
+Subject: [PATCH 06/17] soc: imx: gpcv2: keep i.MX8M* bus clocks enabled
+
+Annotate the domains with bus clocks to keep those clocks enabled
+as long as the domain is active.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan@nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 7e7826bbd3dc..85a922e36f0f 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -530,6 +530,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ 			.hskack = IMX8M_VPU_HSK_PWRDNACKN,
+ 		},
+ 		.pgc   = BIT(IMX8M_PGC_VPU),
++		.keep_clocks = true,
+ 	},
+ 
+ 	[IMX8M_POWER_DOMAIN_DISP] = {
+@@ -628,6 +629,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
+ 			.hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
+ 		},
++		.keep_clocks = true,
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_PCIE] = {
+@@ -674,6 +676,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+ 		},
+ 		.pgc   = BIT(IMX8MM_PGC_GPUMIX),
++		.keep_clocks = true,
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_GPU] = {
+@@ -700,6 +703,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+ 		},
+ 		.pgc   = BIT(IMX8MM_PGC_VPUMIX),
++		.keep_clocks = true,
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_VPUG1] = {
+@@ -746,6 +750,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ 			.hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+ 		},
+ 		.pgc   = BIT(IMX8MM_PGC_DISPMIX),
++		.keep_clocks = true,
+ 	},
+ 
+ 	[IMX8MM_POWER_DOMAIN_MIPI] = {
+@@ -813,6 +818,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+ 			.hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
+ 			.hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
+ 		},
++		.keep_clocks = true,
+ 	},
+ 
+ 	[IMX8MN_POWER_DOMAIN_OTG1] = {
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch b/target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch
new file mode 100644
index 000000000000..6ba284d2aba9
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch
@@ -0,0 +1,74 @@ 
+From e651a2a4d3ea18fbcee49ff87902625b70644c24 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:43 +0200
+Subject: [PATCH 07/17] soc: imx: gpcv2: support system suspend/resume
+
+Our usage of runtime PM to control the hierarchy of power domains is
+slightly unusual and means that powering up a domain may fail in early
+system resume, as runtime PM is still disallowed at this stage.
+
+However the system suspend/resume path takes care of powering down/up
+the power domains in the order defined by the device parent/child and
+power-domain provider/consumer hierarachy. So we can just runtime
+resume all our power-domain devices to allow the power-up to work
+properly in the resume path. System suspend will still disable all
+domains as intended.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Acked-by: Peng Fan <peng.fan@nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 85a922e36f0f..89e25e123c52 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -951,6 +951,36 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_PM_SLEEP
++static int imx_pgc_domain_suspend(struct device *dev)
++{
++	int ret;
++
++	/*
++	 * This may look strange, but is done so the generic PM_SLEEP code
++	 * can power down our domain and more importantly power it up again
++	 * after resume, without tripping over our usage of runtime PM to
++	 * power up/down the nested domains.
++	 */
++	ret = pm_runtime_get_sync(dev);
++	if (ret < 0) {
++		pm_runtime_put_noidle(dev);
++		return ret;
++	}
++
++	return 0;
++}
++
++static int imx_pgc_domain_resume(struct device *dev)
++{
++	return pm_runtime_put(dev);
++}
++#endif
++
++static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
++	SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume)
++};
++
+ static const struct platform_device_id imx_pgc_domain_id[] = {
+ 	{ "imx-pgc-domain", },
+ 	{ },
+@@ -959,6 +989,7 @@ static const struct platform_device_id imx_pgc_domain_id[] = {
+ static struct platform_driver imx_pgc_domain_driver = {
+ 	.driver = {
+ 		.name = "imx-pgc",
++		.pm = &imx_pgc_domain_pm_ops,
+ 	},
+ 	.probe    = imx_pgc_domain_probe,
+ 	.remove   = imx_pgc_domain_remove,
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch b/target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch
new file mode 100644
index 000000000000..d7bb478745cc
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch
@@ -0,0 +1,142 @@ 
+From 744143a80acaeeb10ab6cb1e703b78448ec25c16 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:50 +0200
+Subject: [PATCH 08/17] arm64: dts: imx8mm: add GPC node
+
+Add the DT node for the GPC, including all the PGC power domains,
+some of them are not fully functional yet, as they require interaction
+with the blk-ctrls to properly power up/down the peripherals.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+---
+ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 107 ++++++++++++++++++++++
+ 1 file changed, 107 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index 67e91fdfaf52..b339da5e0b02 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -7,6 +7,8 @@
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/input/input.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/power/imx8mm-power.h>
++#include <dt-bindings/reset/imx8mq-reset.h>
+ #include <dt-bindings/thermal/thermal.h>
+ 
+ #include "imx8mm-pinfunc.h"
+@@ -610,6 +612,111 @@ src: reset-controller@30390000 {
+ 				interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ 				#reset-cells = <1>;
+ 			};
++
++			gpc: gpc@303a0000 {
++				compatible = "fsl,imx8mm-gpc";
++				reg = <0x303a0000 0x10000>;
++				interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
++				interrupt-parent = <&gic>;
++				interrupt-controller;
++				#interrupt-cells = <3>;
++
++				pgc {
++					#address-cells = <1>;
++					#size-cells = <0>;
++
++					pgc_hsiomix: power-domain@0 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_HSIOMIX>;
++						clocks = <&clk IMX8MM_CLK_USB_BUS>;
++						assigned-clocks = <&clk IMX8MM_CLK_USB_BUS>;
++						assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
++					};
++
++					pgc_pcie: power-domain@1 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_PCIE>;
++						power-domains = <&pgc_hsiomix>;
++						clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>;
++					};
++
++					pgc_otg1: power-domain@2 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_OTG1>;
++						power-domains = <&pgc_hsiomix>;
++					};
++
++					pgc_otg2: power-domain@3 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_OTG2>;
++						power-domains = <&pgc_hsiomix>;
++					};
++
++					pgc_gpumix: power-domain@4 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_GPUMIX>;
++						clocks = <&clk IMX8MM_CLK_GPU_BUS_ROOT>,
++							 <&clk IMX8MM_CLK_GPU_AHB>;
++						assigned-clocks = <&clk IMX8MM_CLK_GPU_AXI>,
++								  <&clk IMX8MM_CLK_GPU_AHB>;
++						assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_800M>,
++									 <&clk IMX8MM_SYS_PLL1_800M>;
++						assigned-clock-rates = <800000000>, <400000000>;
++					};
++
++					pgc_gpu: power-domain@5 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_GPU>;
++						clocks = <&clk IMX8MM_CLK_GPU_AHB>,
++							 <&clk IMX8MM_CLK_GPU_BUS_ROOT>,
++							 <&clk IMX8MM_CLK_GPU2D_ROOT>,
++							 <&clk IMX8MM_CLK_GPU3D_ROOT>;
++						resets = <&src IMX8MQ_RESET_GPU_RESET>;
++						power-domains = <&pgc_gpumix>;
++					};
++
++					pgc_vpumix: power-domain@6 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_VPUMIX>;
++						clocks = <&clk IMX8MM_CLK_VPU_DEC_ROOT>;
++						assigned-clocks = <&clk IMX8MM_CLK_VPU_BUS>;
++						assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_800M>;
++						resets = <&src IMX8MQ_RESET_VPU_RESET>;
++					};
++
++					pgc_vpu_g1: power-domain@7 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_VPUG1>;
++					};
++
++					pgc_vpu_g2: power-domain@8 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_VPUG2>;
++					};
++
++					pgc_vpu_h1: power-domain@9 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_VPUH1>;
++					};
++
++					pgc_dispmix: power-domain@10 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_DISPMIX>;
++						clocks = <&clk IMX8MM_CLK_DISP_APB_ROOT>,
++							 <&clk IMX8MM_CLK_DISP_AXI_ROOT>;
++						assigned-clocks = <&clk IMX8MM_CLK_DISP_AXI>,
++								  <&clk IMX8MM_CLK_DISP_APB>;
++						assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_1000M>,
++									 <&clk IMX8MM_SYS_PLL1_800M>;
++						assigned-clock-rates = <500000000>, <200000000>;
++					};
++
++					pgc_mipi: power-domain@11 {
++						#power-domain-cells = <0>;
++						reg = <IMX8MM_POWER_DOMAIN_MIPI>;
++					};
++				};
++			};
+ 		};
+ 
+ 		aips2: bus@30400000 {
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch b/target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch
new file mode 100644
index 000000000000..c2d1f577f6a1
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch
@@ -0,0 +1,38 @@ 
+From 69f9867bcd9c3f956f292e2783e08aa01fef76f4 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:51 +0200
+Subject: [PATCH 09/17] arm64: dts: imx8mm: put USB controllers into
+ power-domains
+
+Now that we have support for the power domain controller on the i.MX8MM
+we can put the USB controllers in their respective power domains to allow
+them to power down the PHY when possible.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+---
+ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index b339da5e0b02..6708b1bebf5c 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -1078,6 +1078,7 @@ usbotg1: usb@32e40000 {
+ 				assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
+ 				phys = <&usbphynop1>;
+ 				fsl,usbmisc = <&usbmisc1 0>;
++				power-domains = <&pgc_otg1>;
+ 				status = "disabled";
+ 			};
+ 
+@@ -1097,6 +1098,7 @@ usbotg2: usb@32e50000 {
+ 				assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
+ 				phys = <&usbphynop2>;
+ 				fsl,usbmisc = <&usbmisc2 0>;
++				power-domains = <&pgc_otg2>;
+ 				status = "disabled";
+ 			};
+ 
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch b/target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch
new file mode 100644
index 000000000000..e5d4ddead71c
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch
@@ -0,0 +1,187 @@ 
+From fdb04e435edbe614e3565381d85a7e8a3d70f0a4 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach@pengutronix.de>
+Date: Mon, 28 Feb 2022 21:17:25 +0100
+Subject: [PATCH 10/17] soc: imx: gpcv2: add PGC control register indirection
+
+The PGC control registers in the shared (not per-PGC) region of the
+GPC address space have different offsets on i.MX8MP to make space for
+additional interrupt control registers.
+
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+---
+ drivers/soc/imx/gpcv2.c | 43 ++++++++++++++++++++++++++++++-----------
+ 1 file changed, 32 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 89e25e123c52..80ba59811a75 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -184,9 +184,17 @@
+ 
+ #define GPC_PGC_CTRL_PCR		BIT(0)
+ 
++struct imx_pgc_regs {
++	u16 map;
++	u16 pup;
++	u16 pdn;
++	u16 hsk;
++};
++
+ struct imx_pgc_domain {
+ 	struct generic_pm_domain genpd;
+ 	struct regmap *regmap;
++	const struct imx_pgc_regs *regs;
+ 	struct regulator *regulator;
+ 	struct reset_control *reset;
+ 	struct clk_bulk_data *clks;
+@@ -210,6 +218,7 @@ struct imx_pgc_domain_data {
+ 	const struct imx_pgc_domain *domains;
+ 	size_t domains_num;
+ 	const struct regmap_access_table *reg_access_table;
++	const struct imx_pgc_regs *pgc_regs;
+ };
+ 
+ static inline struct imx_pgc_domain *
+@@ -252,14 +261,14 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ 
+ 	if (domain->bits.pxx) {
+ 		/* request the domain to power up */
+-		regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ,
++		regmap_update_bits(domain->regmap, domain->regs->pup,
+ 				   domain->bits.pxx, domain->bits.pxx);
+ 		/*
+ 		 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+ 		 * for PUP_REQ/PDN_REQ bit to be cleared
+ 		 */
+ 		ret = regmap_read_poll_timeout(domain->regmap,
+-					       GPC_PU_PGC_SW_PUP_REQ, reg_val,
++					       domain->regs->pup, reg_val,
+ 					       !(reg_val & domain->bits.pxx),
+ 					       0, USEC_PER_MSEC);
+ 		if (ret) {
+@@ -281,11 +290,11 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ 
+ 	/* request the ADB400 to power up */
+ 	if (domain->bits.hskreq) {
+-		regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
++		regmap_update_bits(domain->regmap, domain->regs->hsk,
+ 				   domain->bits.hskreq, domain->bits.hskreq);
+ 
+ 		/*
+-		 * ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, reg_val,
++		 * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
+ 		 *				  (reg_val & domain->bits.hskack), 0,
+ 		 *				  USEC_PER_MSEC);
+ 		 * Technically we need the commented code to wait handshake. But that needs
+@@ -332,10 +341,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ 
+ 	/* request the ADB400 to power down */
+ 	if (domain->bits.hskreq) {
+-		regmap_clear_bits(domain->regmap, GPC_PU_PWRHSK,
++		regmap_clear_bits(domain->regmap, domain->regs->hsk,
+ 				  domain->bits.hskreq);
+ 
+-		ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK,
++		ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
+ 					       reg_val,
+ 					       !(reg_val & domain->bits.hskack),
+ 					       0, USEC_PER_MSEC);
+@@ -353,14 +362,14 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ 		}
+ 
+ 		/* request the domain to power down */
+-		regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
++		regmap_update_bits(domain->regmap, domain->regs->pdn,
+ 				   domain->bits.pxx, domain->bits.pxx);
+ 		/*
+ 		 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+ 		 * for PUP_REQ/PDN_REQ bit to be cleared
+ 		 */
+ 		ret = regmap_read_poll_timeout(domain->regmap,
+-					       GPC_PU_PGC_SW_PDN_REQ, reg_val,
++					       domain->regs->pdn, reg_val,
+ 					       !(reg_val & domain->bits.pxx),
+ 					       0, USEC_PER_MSEC);
+ 		if (ret) {
+@@ -444,10 +453,18 @@ static const struct regmap_access_table imx7_access_table = {
+ 	.n_yes_ranges	= ARRAY_SIZE(imx7_yes_ranges),
+ };
+ 
++static const struct imx_pgc_regs imx7_pgc_regs = {
++	.map = GPC_PGC_CPU_MAPPING,
++	.pup = GPC_PU_PGC_SW_PUP_REQ,
++	.pdn = GPC_PU_PGC_SW_PDN_REQ,
++	.hsk = GPC_PU_PWRHSK,
++};
++
+ static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
+ 	.domains = imx7_pgc_domains,
+ 	.domains_num = ARRAY_SIZE(imx7_pgc_domains),
+ 	.reg_access_table = &imx7_access_table,
++	.pgc_regs = &imx7_pgc_regs,
+ };
+ 
+ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+@@ -616,6 +633,7 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
+ 	.domains = imx8m_pgc_domains,
+ 	.domains_num = ARRAY_SIZE(imx8m_pgc_domains),
+ 	.reg_access_table = &imx8m_access_table,
++	.pgc_regs = &imx7_pgc_regs,
+ };
+ 
+ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+@@ -805,6 +823,7 @@ static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
+ 	.domains = imx8mm_pgc_domains,
+ 	.domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
+ 	.reg_access_table = &imx8mm_access_table,
++	.pgc_regs = &imx7_pgc_regs,
+ };
+ 
+ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+@@ -870,6 +889,7 @@ static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
+ 	.domains = imx8mn_pgc_domains,
+ 	.domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
+ 	.reg_access_table = &imx8mn_access_table,
++	.pgc_regs = &imx7_pgc_regs,
+ };
+ 
+ static int imx_pgc_domain_probe(struct platform_device *pdev)
+@@ -902,7 +922,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ 	pm_runtime_enable(domain->dev);
+ 
+ 	if (domain->bits.map)
+-		regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
++		regmap_update_bits(domain->regmap, domain->regs->map,
+ 				   domain->bits.map, domain->bits.map);
+ 
+ 	ret = pm_genpd_init(&domain->genpd, NULL, true);
+@@ -928,7 +948,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ 	pm_genpd_remove(&domain->genpd);
+ out_domain_unmap:
+ 	if (domain->bits.map)
+-		regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
++		regmap_update_bits(domain->regmap, domain->regs->map,
+ 				   domain->bits.map, 0);
+ 	pm_runtime_disable(domain->dev);
+ 
+@@ -943,7 +963,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
+ 	pm_genpd_remove(&domain->genpd);
+ 
+ 	if (domain->bits.map)
+-		regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
++		regmap_update_bits(domain->regmap, domain->regs->map,
+ 				   domain->bits.map, 0);
+ 
+ 	pm_runtime_disable(domain->dev);
+@@ -1074,6 +1094,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
+ 
+ 		domain = pd_pdev->dev.platform_data;
+ 		domain->regmap = regmap;
++		domain->regs = domain_data->pgc_regs;
+ 		domain->genpd.power_on  = imx_pgc_power_up;
+ 		domain->genpd.power_off = imx_pgc_power_down;
+ 
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch b/target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch
new file mode 100644
index 000000000000..022f3c0c5b44
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch
@@ -0,0 +1,285 @@ 
+From b90c3fd61d15182da871afb435fc8e72067478f9 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu@nxp.com>
+Date: Thu, 28 Oct 2021 15:27:14 +0800
+Subject: [PATCH 11/17] phy: freescale: pcie: Initialize the imx8 pcie
+ standalone phy driver
+
+Add the standalone i.MX8 PCIe PHY driver.
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+---
+ drivers/phy/freescale/Kconfig              |   9 +
+ drivers/phy/freescale/Makefile             |   1 +
+ drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 233 +++++++++++++++++++++
+ 3 files changed, 243 insertions(+)
+ create mode 100644 drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+
+diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
+index 320630ffe3cd..de9ee7020f76 100644
+--- a/drivers/phy/freescale/Kconfig
++++ b/drivers/phy/freescale/Kconfig
+@@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
+ 	help
+ 	  Enable this to add support for the Mixel DSI PHY as found
+ 	  on NXP's i.MX8 family of SOCs.
++
++config PHY_FSL_IMX8M_PCIE
++	tristate "Freescale i.MX8 PCIE PHY"
++	depends on OF && HAS_IOMEM
++	select GENERIC_PHY
++	default ARCH_MXC && ARM64
++	help
++	  Enable this to add support for the PCIE PHY as found on
++	  i.MX8M family of SOCs.
+diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
+index 1d02e3869b45..55d07c742ab0 100644
+--- a/drivers/phy/freescale/Makefile
++++ b/drivers/phy/freescale/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB)	+= phy-fsl-imx8mq-usb.o
+ obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY)	+= phy-fsl-imx8-mipi-dphy.o
++obj-$(CONFIG_PHY_FSL_IMX8M_PCIE)	+= phy-fsl-imx8m-pcie.o
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+new file mode 100644
+index 000000000000..003f575b36f0
+--- /dev/null
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -0,0 +1,233 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2021 NXP
++ */
++
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/delay.h>
++#include <linux/mfd/syscon.h>
++#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
++#include <linux/module.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
++
++#define IMX8MM_PCIE_PHY_CMN_REG061	0x184
++#define  ANA_PLL_CLK_OUT_TO_EXT_IO_EN	BIT(0)
++#define IMX8MM_PCIE_PHY_CMN_REG062	0x188
++#define  ANA_PLL_CLK_OUT_TO_EXT_IO_SEL	BIT(3)
++#define IMX8MM_PCIE_PHY_CMN_REG063	0x18C
++#define  AUX_PLL_REFCLK_SEL_SYS_PLL	GENMASK(7, 6)
++#define IMX8MM_PCIE_PHY_CMN_REG064	0x190
++#define  ANA_AUX_RX_TX_SEL_TX		BIT(7)
++#define  ANA_AUX_RX_TERM_GND_EN		BIT(3)
++#define  ANA_AUX_TX_TERM		BIT(2)
++#define IMX8MM_PCIE_PHY_CMN_REG065	0x194
++#define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
++#define  ANA_AUX_TX_LVL			GENMASK(3, 0)
++#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
++#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
++#define PCIE_PHY_TRSV_REG5		0x414
++#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
++#define PCIE_PHY_TRSV_REG6		0x418
++#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
++
++#define IMX8MM_GPR_PCIE_REF_CLK_SEL	GENMASK(25, 24)
++#define IMX8MM_GPR_PCIE_REF_CLK_PLL	FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3)
++#define IMX8MM_GPR_PCIE_REF_CLK_EXT	FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x2)
++#define IMX8MM_GPR_PCIE_AUX_EN		BIT(19)
++#define IMX8MM_GPR_PCIE_CMN_RST		BIT(18)
++#define IMX8MM_GPR_PCIE_POWER_OFF	BIT(17)
++#define IMX8MM_GPR_PCIE_SSC_EN		BIT(16)
++#define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE	BIT(9)
++
++struct imx8_pcie_phy {
++	void __iomem		*base;
++	struct clk		*clk;
++	struct phy		*phy;
++	struct regmap		*iomuxc_gpr;
++	struct reset_control	*reset;
++	u32			refclk_pad_mode;
++	u32			tx_deemph_gen1;
++	u32			tx_deemph_gen2;
++	bool			clkreq_unused;
++};
++
++static int imx8_pcie_phy_init(struct phy *phy)
++{
++	int ret;
++	u32 val, pad_mode;
++	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++	reset_control_assert(imx8_phy->reset);
++
++	pad_mode = imx8_phy->refclk_pad_mode;
++	/* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */
++	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++			   IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE,
++			   imx8_phy->clkreq_unused ?
++			   0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE);
++	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++			   IMX8MM_GPR_PCIE_AUX_EN,
++			   IMX8MM_GPR_PCIE_AUX_EN);
++	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++			   IMX8MM_GPR_PCIE_POWER_OFF, 0);
++	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++			   IMX8MM_GPR_PCIE_SSC_EN, 0);
++
++	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++			   IMX8MM_GPR_PCIE_REF_CLK_SEL,
++			   pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ?
++			   IMX8MM_GPR_PCIE_REF_CLK_EXT :
++			   IMX8MM_GPR_PCIE_REF_CLK_PLL);
++	usleep_range(100, 200);
++
++	/* Do the PHY common block reset */
++	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++			   IMX8MM_GPR_PCIE_CMN_RST,
++			   IMX8MM_GPR_PCIE_CMN_RST);
++	usleep_range(200, 500);
++
++
++	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
++		/* Configure the pad as input */
++		val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++		writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
++		/* Configure the PHY to output the refclock via pad */
++		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
++		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
++		val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
++		writel(val | ANA_AUX_RX_TERM_GND_EN,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
++		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
++	}
++
++	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
++	writel(imx8_phy->tx_deemph_gen1, imx8_phy->base + PCIE_PHY_TRSV_REG5);
++	writel(imx8_phy->tx_deemph_gen2, imx8_phy->base + PCIE_PHY_TRSV_REG6);
++
++	reset_control_deassert(imx8_phy->reset);
++
++	/* Polling to check the phy is ready or not. */
++	ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
++				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
++				 10, 20000);
++	return ret;
++}
++
++static int imx8_pcie_phy_power_on(struct phy *phy)
++{
++	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++	return clk_prepare_enable(imx8_phy->clk);
++}
++
++static int imx8_pcie_phy_power_off(struct phy *phy)
++{
++	struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++	clk_disable_unprepare(imx8_phy->clk);
++
++	return 0;
++}
++
++static const struct phy_ops imx8_pcie_phy_ops = {
++	.init		= imx8_pcie_phy_init,
++	.power_on	= imx8_pcie_phy_power_on,
++	.power_off	= imx8_pcie_phy_power_off,
++	.owner		= THIS_MODULE,
++};
++
++static int imx8_pcie_phy_probe(struct platform_device *pdev)
++{
++	struct phy_provider *phy_provider;
++	struct device *dev = &pdev->dev;
++	struct device_node *np = dev->of_node;
++	struct imx8_pcie_phy *imx8_phy;
++	struct resource *res;
++
++	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
++	if (!imx8_phy)
++		return -ENOMEM;
++
++	/* get PHY refclk pad mode */
++	of_property_read_u32(np, "fsl,refclk-pad-mode",
++			     &imx8_phy->refclk_pad_mode);
++
++	if (of_property_read_u32(np, "fsl,tx-deemph-gen1",
++				 &imx8_phy->tx_deemph_gen1))
++		imx8_phy->tx_deemph_gen1 = 0;
++
++	if (of_property_read_u32(np, "fsl,tx-deemph-gen2",
++				 &imx8_phy->tx_deemph_gen2))
++		imx8_phy->tx_deemph_gen2 = 0;
++
++	if (of_property_read_bool(np, "fsl,clkreq-unsupported"))
++		imx8_phy->clkreq_unused = true;
++	else
++		imx8_phy->clkreq_unused = false;
++
++	imx8_phy->clk = devm_clk_get(dev, "ref");
++	if (IS_ERR(imx8_phy->clk)) {
++		dev_err(dev, "failed to get imx pcie phy clock\n");
++		return PTR_ERR(imx8_phy->clk);
++	}
++
++	/* Grab GPR config register range */
++	imx8_phy->iomuxc_gpr =
++		 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
++	if (IS_ERR(imx8_phy->iomuxc_gpr)) {
++		dev_err(dev, "unable to find iomuxc registers\n");
++		return PTR_ERR(imx8_phy->iomuxc_gpr);
++	}
++
++	imx8_phy->reset = devm_reset_control_get_exclusive(dev, "pciephy");
++	if (IS_ERR(imx8_phy->reset)) {
++		dev_err(dev, "Failed to get PCIEPHY reset control\n");
++		return PTR_ERR(imx8_phy->reset);
++	}
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	imx8_phy->base = devm_ioremap_resource(dev, res);
++	if (IS_ERR(imx8_phy->base))
++		return PTR_ERR(imx8_phy->base);
++
++	imx8_phy->phy = devm_phy_create(dev, NULL, &imx8_pcie_phy_ops);
++	if (IS_ERR(imx8_phy->phy))
++		return PTR_ERR(imx8_phy->phy);
++
++	phy_set_drvdata(imx8_phy->phy, imx8_phy);
++
++	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
++
++	return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id imx8_pcie_phy_of_match[] = {
++	{.compatible = "fsl,imx8mm-pcie-phy",},
++	{ },
++};
++MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
++
++static struct platform_driver imx8_pcie_phy_driver = {
++	.probe	= imx8_pcie_phy_probe,
++	.driver = {
++		.name	= "imx8-pcie-phy",
++		.of_match_table	= imx8_pcie_phy_of_match,
++	}
++};
++module_platform_driver(imx8_pcie_phy_driver);
++
++MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
++MODULE_LICENSE("GPL");
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch b/target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch
new file mode 100644
index 000000000000..de484006f77e
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch
@@ -0,0 +1,305 @@ 
+From c34c47978eed63a520915fb7e45ef34fe5a551e7 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu@nxp.com>
+Date: Mon, 7 Mar 2022 17:07:30 +0800
+Subject: [PATCH 12/17] phy: freescale: imx8m-pcie: Add iMX8MP PCIe PHY support
+
+Add the i.MX8MP PCIe PHY support
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+---
+ drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 202 +++++++++++++++++----
+ 1 file changed, 163 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+index 003f575b36f0..0b9d006a983b 100644
+--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -10,6 +10,8 @@
+ #include <linux/mfd/syscon.h>
+ #include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
+ #include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+@@ -29,12 +31,10 @@
+ #define IMX8MM_PCIE_PHY_CMN_REG065	0x194
+ #define  ANA_AUX_RX_TERM		(BIT(7) | BIT(4))
+ #define  ANA_AUX_TX_LVL			GENMASK(3, 0)
+-#define IMX8MM_PCIE_PHY_CMN_REG75	0x1D4
+-#define  PCIE_PHY_CMN_REG75_PLL_DONE	0x3
++#define IMX8MM_PCIE_PHY_CMN_REG075	0x1D4
++#define  ANA_PLL_DONE			0x3
+ #define PCIE_PHY_TRSV_REG5		0x414
+-#define  PCIE_PHY_TRSV_REG5_GEN1_DEEMP	0x2D
+ #define PCIE_PHY_TRSV_REG6		0x418
+-#define  PCIE_PHY_TRSV_REG6_GEN2_DEEMP	0xF
+ 
+ #define IMX8MM_GPR_PCIE_REF_CLK_SEL	GENMASK(25, 24)
+ #define IMX8MM_GPR_PCIE_REF_CLK_PLL	FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3)
+@@ -45,16 +45,43 @@
+ #define IMX8MM_GPR_PCIE_SSC_EN		BIT(16)
+ #define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE	BIT(9)
+ 
++#define IMX8MP_GPR_REG0			0x0
++#define IMX8MP_GPR_CLK_MOD_EN		BIT(0)
++#define IMX8MP_GPR_PHY_APB_RST		BIT(4)
++#define IMX8MP_GPR_PHY_INIT_RST		BIT(5)
++#define IMX8MP_GPR_REG1			0x4
++#define IMX8MP_GPR_PM_EN_CORE_CLK	BIT(0)
++#define IMX8MP_GPR_PLL_LOCK		BIT(13)
++#define IMX8MP_GPR_REG2			0x8
++#define IMX8MP_GPR_P_PLL_MASK		GENMASK(5, 0)
++#define IMX8MP_GPR_M_PLL_MASK		GENMASK(15, 6)
++#define IMX8MP_GPR_S_PLL_MASK		GENMASK(18, 16)
++#define IMX8MP_GPR_P_PLL		(0xc << 0)
++#define IMX8MP_GPR_M_PLL		(0x320 << 6)
++#define IMX8MP_GPR_S_PLL		(0x4 << 16)
++#define IMX8MP_GPR_REG3			0xc
++#define IMX8MP_GPR_PLL_CKE		BIT(17)
++#define IMX8MP_GPR_PLL_RST		BIT(31)
++
++enum imx8_pcie_phy_type {
++	IMX8MM,
++	IMX8MP,
++};
++
+ struct imx8_pcie_phy {
+ 	void __iomem		*base;
++	struct device		*dev;
+ 	struct clk		*clk;
+ 	struct phy		*phy;
++	struct regmap		*hsio_blk_ctrl;
+ 	struct regmap		*iomuxc_gpr;
+ 	struct reset_control	*reset;
++	struct reset_control	*perst;
+ 	u32			refclk_pad_mode;
+ 	u32			tx_deemph_gen1;
+ 	u32			tx_deemph_gen2;
+ 	bool			clkreq_unused;
++	enum imx8_pcie_phy_type	variant;
+ };
+ 
+ static int imx8_pcie_phy_init(struct phy *phy)
+@@ -66,6 +93,87 @@ static int imx8_pcie_phy_init(struct phy *phy)
+ 	reset_control_assert(imx8_phy->reset);
+ 
+ 	pad_mode = imx8_phy->refclk_pad_mode;
++	switch (imx8_phy->variant) {
++	case IMX8MM:
++		/* Tune PHY de-emphasis setting to pass PCIe compliance. */
++		if (imx8_phy->tx_deemph_gen1)
++			writel(imx8_phy->tx_deemph_gen1,
++			       imx8_phy->base + PCIE_PHY_TRSV_REG5);
++		if (imx8_phy->tx_deemph_gen2)
++			writel(imx8_phy->tx_deemph_gen2,
++			       imx8_phy->base + PCIE_PHY_TRSV_REG6);
++		break;
++	case IMX8MP:
++		reset_control_assert(imx8_phy->perst);
++		/* Set P=12,M=800,S=4 and must set ICP=2'b01. */
++		regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG2,
++				   IMX8MP_GPR_P_PLL_MASK |
++				   IMX8MP_GPR_M_PLL_MASK |
++				   IMX8MP_GPR_S_PLL_MASK,
++				   IMX8MP_GPR_P_PLL |
++				   IMX8MP_GPR_M_PLL |
++				   IMX8MP_GPR_S_PLL);
++		/* wait greater than 1/F_FREF =1/2MHZ=0.5us */
++		udelay(1);
++
++		regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG3,
++				   IMX8MP_GPR_PLL_RST,
++				   IMX8MP_GPR_PLL_RST);
++		udelay(10);
++
++		/* Set 1 to pll_cke of GPR_REG3 */
++		regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG3,
++				   IMX8MP_GPR_PLL_CKE,
++				   IMX8MP_GPR_PLL_CKE);
++
++		/* Lock time should be greater than 300cycle=300*0.5us=150us */
++		ret = regmap_read_poll_timeout(imx8_phy->hsio_blk_ctrl,
++					     IMX8MP_GPR_REG1, val,
++					     val & IMX8MP_GPR_PLL_LOCK,
++					     10, 1000);
++		if (ret) {
++			dev_err(imx8_phy->dev, "PCIe PLL lock timeout\n");
++			return ret;
++		}
++
++		/* pcie_clock_module_en */
++		regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG0,
++				   IMX8MP_GPR_CLK_MOD_EN,
++				   IMX8MP_GPR_CLK_MOD_EN);
++		udelay(10);
++
++		reset_control_deassert(imx8_phy->reset);
++		reset_control_deassert(imx8_phy->perst);
++
++		/* release pcie_phy_apb_reset and pcie_phy_init_resetn */
++		regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG0,
++				   IMX8MP_GPR_PHY_APB_RST |
++				   IMX8MP_GPR_PHY_INIT_RST,
++				   IMX8MP_GPR_PHY_APB_RST |
++				   IMX8MP_GPR_PHY_INIT_RST);
++		break;
++	}
++
++	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
++		/* Configure the pad as input */
++		val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++		writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
++		/* Configure the PHY to output the refclock via pad */
++		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
++		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
++		val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
++		writel(val | ANA_AUX_RX_TERM_GND_EN,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
++		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
++		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
++	}
++
+ 	/* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */
+ 	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
+ 			   IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE,
+@@ -90,39 +198,30 @@ static int imx8_pcie_phy_init(struct phy *phy)
+ 	regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
+ 			   IMX8MM_GPR_PCIE_CMN_RST,
+ 			   IMX8MM_GPR_PCIE_CMN_RST);
+-	usleep_range(200, 500);
+ 
+-
+-	if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
+-		/* Configure the pad as input */
+-		val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+-		writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
+-		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+-	} else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
+-		/* Configure the PHY to output the refclock via pad */
+-		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
+-		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+-		writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
+-		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
+-		writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+-		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+-		val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
+-		writel(val | ANA_AUX_RX_TERM_GND_EN,
+-		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
+-		writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
+-		       imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
++	switch (imx8_phy->variant) {
++	case IMX8MM:
++		reset_control_deassert(imx8_phy->reset);
++		usleep_range(200, 500);
++		break;
++
++	case IMX8MP:
++		/* wait for core_clk enabled */
++		ret = regmap_read_poll_timeout(imx8_phy->hsio_blk_ctrl,
++					     IMX8MP_GPR_REG1, val,
++					     val & IMX8MP_GPR_PM_EN_CORE_CLK,
++					     10, 20000);
++		if (ret) {
++			dev_err(imx8_phy->dev, "PCIe CORE CLK enable failed\n");
++			return ret;
++		}
++
++		break;
+ 	}
+ 
+-	/* Tune PHY de-emphasis setting to pass PCIe compliance. */
+-	writel(imx8_phy->tx_deemph_gen1, imx8_phy->base + PCIE_PHY_TRSV_REG5);
+-	writel(imx8_phy->tx_deemph_gen2, imx8_phy->base + PCIE_PHY_TRSV_REG6);
+-
+-	reset_control_deassert(imx8_phy->reset);
+-
+ 	/* Polling to check the phy is ready or not. */
+-	ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
+-				 val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
+-				 10, 20000);
++	ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075,
++				 val, val == ANA_PLL_DONE, 10, 20000);
+ 	return ret;
+ }
+ 
+@@ -149,18 +248,33 @@ static const struct phy_ops imx8_pcie_phy_ops = {
+ 	.owner		= THIS_MODULE,
+ };
+ 
++static const struct of_device_id imx8_pcie_phy_of_match[] = {
++	{.compatible = "fsl,imx8mm-pcie-phy", .data = (void *)IMX8MM},
++	{.compatible = "fsl,imx8mp-pcie-phy", .data = (void *)IMX8MP},
++	{ },
++};
++MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
++
+ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+ {
+ 	struct phy_provider *phy_provider;
+ 	struct device *dev = &pdev->dev;
++	const struct of_device_id *of_id;
+ 	struct device_node *np = dev->of_node;
+ 	struct imx8_pcie_phy *imx8_phy;
+ 	struct resource *res;
+ 
++	of_id = of_match_device(imx8_pcie_phy_of_match, dev);
++	if (!of_id)
++		return -EINVAL;
++
+ 	imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
+ 	if (!imx8_phy)
+ 		return -ENOMEM;
+ 
++	imx8_phy->dev = dev;
++	imx8_phy->variant = (enum imx8_pcie_phy_type)of_id->data;
++
+ 	/* get PHY refclk pad mode */
+ 	of_property_read_u32(np, "fsl,refclk-pad-mode",
+ 			     &imx8_phy->refclk_pad_mode);
+@@ -197,6 +311,22 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+ 		dev_err(dev, "Failed to get PCIEPHY reset control\n");
+ 		return PTR_ERR(imx8_phy->reset);
+ 	}
++	if (imx8_phy->variant == IMX8MP) {
++		/* Grab HSIO MIX config register range */
++		imx8_phy->hsio_blk_ctrl =
++			 syscon_regmap_lookup_by_compatible("fsl,imx8mp-hsio-blk-ctrl");
++		if (IS_ERR(imx8_phy->hsio_blk_ctrl)) {
++			dev_err(dev, "unable to find hsio mix registers\n");
++			return PTR_ERR(imx8_phy->hsio_blk_ctrl);
++		}
++
++		imx8_phy->perst =
++			devm_reset_control_get_exclusive(dev, "perst");
++		if (IS_ERR(imx8_phy->perst)) {
++			dev_err(dev, "Failed to get PCIEPHY perst control\n");
++			return PTR_ERR(imx8_phy->perst);
++		}
++	}
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ 	imx8_phy->base = devm_ioremap_resource(dev, res);
+@@ -214,12 +344,6 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+ 	return PTR_ERR_OR_ZERO(phy_provider);
+ }
+ 
+-static const struct of_device_id imx8_pcie_phy_of_match[] = {
+-	{.compatible = "fsl,imx8mm-pcie-phy",},
+-	{ },
+-};
+-MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
+-
+ static struct platform_driver imx8_pcie_phy_driver = {
+ 	.probe	= imx8_pcie_phy_probe,
+ 	.driver = {
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch b/target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch
new file mode 100644
index 000000000000..f0989b205ee9
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch
@@ -0,0 +1,38 @@ 
+From 9870dee7766a6b646cc59675b66ed1f70b1c33d4 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu@nxp.com>
+Date: Thu, 28 Oct 2021 15:27:10 +0800
+Subject: [PATCH 13/17] dt-bindings: phy: phy-imx8-pcie: Add binding for the
+ pad modes of imx8 pcie phy
+
+Add binding for reference clock PAD modes of the i.MX8 PCIe PHY.
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+---
+ include/dt-bindings/phy/phy-imx8-pcie.h | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+ create mode 100644 include/dt-bindings/phy/phy-imx8-pcie.h
+
+diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h b/include/dt-bindings/phy/phy-imx8-pcie.h
+new file mode 100644
+index 000000000000..8bbe2d6538d8
+--- /dev/null
++++ b/include/dt-bindings/phy/phy-imx8-pcie.h
+@@ -0,0 +1,14 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
++/*
++ * This header provides constants for i.MX8 PCIe.
++ */
++
++#ifndef _DT_BINDINGS_IMX8_PCIE_H
++#define _DT_BINDINGS_IMX8_PCIE_H
++
++/* Reference clock PAD mode */
++#define IMX8_PCIE_REFCLK_PAD_UNUSED	0
++#define IMX8_PCIE_REFCLK_PAD_INPUT	1
++#define IMX8_PCIE_REFCLK_PAD_OUTPUT	2
++
++#endif /* _DT_BINDINGS_IMX8_PCIE_H */
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch b/target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch
new file mode 100644
index 000000000000..1d53a9224238
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch
@@ -0,0 +1,211 @@ 
+From cfde3f23ce2fb5a1a1f9d1f841af67110ecefede Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu@nxp.com>
+Date: Thu, 28 Oct 2021 15:27:17 +0800
+Subject: [PATCH 14/17] PCI: imx: Add the imx8mm pcie support
+
+i.MX8MM PCIe works mostly like the i.MX8MQ one, but has a different PHY
+and allows to output the internal PHY reference clock via the refclk pad.
+Add the i.MX8MM PCIe support based on the standalone PHY driver.
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+---
+ drivers/pci/controller/dwc/pci-imx6.c | 73 ++++++++++++++++++++++++---
+ 1 file changed, 66 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
+index 67dbf9d88d22..8cc016cea3c4 100644
+--- a/drivers/pci/controller/dwc/pci-imx6.c
++++ b/drivers/pci/controller/dwc/pci-imx6.c
+@@ -29,6 +29,7 @@
+ #include <linux/types.h>
+ #include <linux/interrupt.h>
+ #include <linux/reset.h>
++#include <linux/phy/phy.h>
+ #include <linux/pm_domain.h>
+ #include <linux/pm_runtime.h>
+ 
+@@ -49,6 +50,7 @@ enum imx6_pcie_variants {
+ 	IMX6QP,
+ 	IMX7D,
+ 	IMX8MQ,
++	IMX8MM,
+ };
+ 
+ #define IMX6_PCIE_FLAG_IMX6_PHY			BIT(0)
+@@ -88,6 +90,7 @@ struct imx6_pcie {
+ 	struct device		*pd_pcie;
+ 	/* power domain for pcie phy */
+ 	struct device		*pd_pcie_phy;
++	struct phy		*phy;
+ 	const struct imx6_pcie_drvdata *drvdata;
+ };
+ 
+@@ -372,6 +375,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
+ 	case IMX7D:
+ 	case IMX8MQ:
+ 		reset_control_assert(imx6_pcie->pciephy_reset);
++		fallthrough;
++	case IMX8MM:
+ 		reset_control_assert(imx6_pcie->apps_reset);
+ 		break;
+ 	case IMX6SX:
+@@ -412,7 +417,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
+ 
+ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
+ {
+-	WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ);
++	WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ &&
++		imx6_pcie->drvdata->variant != IMX8MM);
+ 	return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;
+ }
+ 
+@@ -451,6 +457,13 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
+ 		break;
+ 	case IMX7D:
+ 		break;
++	case IMX8MM:
++		ret = clk_prepare_enable(imx6_pcie->pcie_aux);
++		if (ret) {
++			dev_err(dev, "unable to enable pcie_aux clock\n");
++			break;
++		}
++		break;
+ 	case IMX8MQ:
+ 		ret = clk_prepare_enable(imx6_pcie->pcie_aux);
+ 		if (ret) {
+@@ -527,6 +540,14 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
+ 		goto err_ref_clk;
+ 	}
+ 
++	switch (imx6_pcie->drvdata->variant) {
++	case IMX8MM:
++		if (phy_power_on(imx6_pcie->phy))
++			dev_err(dev, "unable to power on PHY\n");
++		break;
++	default:
++		break;
++	}
+ 	/* allow the clocks to stabilize */
+ 	usleep_range(200, 500);
+ 
+@@ -534,6 +555,10 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
+ 	case IMX8MQ:
+ 		reset_control_deassert(imx6_pcie->pciephy_reset);
+ 		break;
++	case IMX8MM:
++		if (phy_init(imx6_pcie->phy) != 0)
++			dev_err(dev, "Waiting for PHY ready timeout!\n");
++		break;
+ 	case IMX7D:
+ 		reset_control_deassert(imx6_pcie->pciephy_reset);
+ 
+@@ -619,6 +644,8 @@ static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
+ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+ {
+ 	switch (imx6_pcie->drvdata->variant) {
++	case IMX8MM:
++		break;
+ 	case IMX8MQ:
+ 		/*
+ 		 * TODO: Currently this code assumes external
+@@ -758,6 +785,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev)
+ 		break;
+ 	case IMX7D:
+ 	case IMX8MQ:
++	case IMX8MM:
+ 		reset_control_deassert(imx6_pcie->apps_reset);
+ 		break;
+ 	}
+@@ -870,6 +898,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev)
+ 				   IMX6Q_GPR12_PCIE_CTL_2, 0);
+ 		break;
+ 	case IMX7D:
++	case IMX8MM:
+ 		reset_control_assert(imx6_pcie->apps_reset);
+ 		break;
+ 	default:
+@@ -929,6 +958,7 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
+ 				   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
+ 		break;
+ 	case IMX8MQ:
++	case IMX8MM:
+ 		clk_disable_unprepare(imx6_pcie->pcie_aux);
+ 		break;
+ 	default:
+@@ -1042,11 +1072,6 @@ static int imx6_pcie_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	/* Fetch clocks */
+-	imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
+-	if (IS_ERR(imx6_pcie->pcie_phy))
+-		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy),
+-				     "pcie_phy clock source missing or invalid\n");
+-
+ 	imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
+ 	if (IS_ERR(imx6_pcie->pcie_bus))
+ 		return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus),
+@@ -1088,10 +1113,39 @@ static int imx6_pcie_probe(struct platform_device *pdev)
+ 			dev_err(dev, "Failed to get PCIE APPS reset control\n");
+ 			return PTR_ERR(imx6_pcie->apps_reset);
+ 		}
++		break;
++	case IMX8MM:
++		imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux");
++		if (IS_ERR(imx6_pcie->pcie_aux))
++			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux),
++					     "pcie_aux clock source missing or invalid\n");
++		imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
++									 "apps");
++		if (IS_ERR(imx6_pcie->apps_reset)) {
++			dev_err(dev, "Failed to get PCIE APPS reset control\n");
++			return PTR_ERR(imx6_pcie->apps_reset);
++		}
++
++		imx6_pcie->phy = devm_phy_get(dev, "pcie-phy");
++		if (IS_ERR(imx6_pcie->phy)) {
++			if (PTR_ERR(imx6_pcie->phy) == -EPROBE_DEFER)
++				return -EPROBE_DEFER;
++			dev_err(dev, "Failed to get PCIE PHY\n");
++			return PTR_ERR(imx6_pcie->phy);
++		}
++
+ 		break;
+ 	default:
+ 		break;
+ 	}
++	/* Don't fetch the pcie_phy clock, if it has abstract PHY driver */
++	if (imx6_pcie->phy == NULL) {
++		imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
++		if (IS_ERR(imx6_pcie->pcie_phy))
++			return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy),
++					     "pcie_phy clock source missing or invalid\n");
++	}
++
+ 
+ 	/* Grab turnoff reset */
+ 	imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
+@@ -1201,6 +1255,10 @@ static const struct imx6_pcie_drvdata drvdata[] = {
+ 	[IMX8MQ] = {
+ 		.variant = IMX8MQ,
+ 	},
++	[IMX8MM] = {
++		.variant = IMX8MM,
++		.flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
++	},
+ };
+ 
+ static const struct of_device_id imx6_pcie_of_match[] = {
+@@ -1208,7 +1266,8 @@ static const struct of_device_id imx6_pcie_of_match[] = {
+ 	{ .compatible = "fsl,imx6sx-pcie", .data = &drvdata[IMX6SX], },
+ 	{ .compatible = "fsl,imx6qp-pcie", .data = &drvdata[IMX6QP], },
+ 	{ .compatible = "fsl,imx7d-pcie",  .data = &drvdata[IMX7D],  },
+-	{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], } ,
++	{ .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
++	{ .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
+ 	{},
+ };
+ 
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch b/target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch
new file mode 100644
index 000000000000..0b2a1be05c58
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch
@@ -0,0 +1,40 @@ 
+From c488e4b57b69682cf4adb7809d5482165984acc6 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu@nxp.com>
+Date: Thu, 28 Oct 2021 15:27:13 +0800
+Subject: [PATCH 15/17] arm64: dts: imx8mm: Add the pcie phy support
+
+Add the PCIe PHY support on iMX8MM platforms.
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+---
+ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index 6708b1bebf5c..ec083d3f68d5 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -1108,6 +1108,19 @@ usbmisc2: usbmisc@32e50200 {
+ 				reg = <0x32e50200 0x200>;
+ 			};
+ 
++			pcie_phy: pcie-phy@32f00000 {
++				compatible = "fsl,imx8mm-pcie-phy";
++				reg = <0x32f00000 0x10000>;
++				clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
++				clock-names = "ref";
++				assigned-clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
++				assigned-clock-rates = <100000000>;
++				assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_100M>;
++				resets = <&src IMX8MQ_RESET_PCIEPHY>;
++				reset-names = "pciephy";
++				#phy-cells = <0>;
++				status = "disabled";
++			};
+ 		};
+ 
+ 		dma_apbh: dma-controller@33000000 {
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch b/target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch
new file mode 100644
index 000000000000..74156015624a
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch
@@ -0,0 +1,67 @@ 
+From 527ed85dbb8b89dced54f207cc181062e327f3f8 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu@nxp.com>
+Date: Thu, 28 Oct 2021 15:27:15 +0800
+Subject: [PATCH 16/17] arm64: dts: imx8mm: Add the pcie support
+
+Add the PCIe support on i.MX8MM platforms.
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
+---
+ arch/arm64/boot/dts/freescale/imx8mm.dtsi | 33 ++++++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index ec083d3f68d5..de6b2992f6c3 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -520,7 +520,7 @@ iomuxc: pinctrl@30330000 {
+ 			};
+ 
+ 			gpr: iomuxc-gpr@30340000 {
+-				compatible = "fsl,imx8mm-iomuxc-gpr", "syscon";
++				compatible = "fsl,imx8mm-iomuxc-gpr", "fsl,imx6q-iomuxc-gpr", "syscon";
+ 				reg = <0x30340000 0x10000>;
+ 			};
+ 
+@@ -1152,6 +1152,37 @@ gpmi: nand-controller@33002000 {
+ 			status = "disabled";
+ 		};
+ 
++		pcie0: pcie@33800000 {
++			compatible = "fsl,imx8mm-pcie";
++			reg = <0x33800000 0x400000>, <0x1ff00000 0x80000>;
++			reg-names = "dbi", "config";
++			#address-cells = <3>;
++			#size-cells = <2>;
++			device_type = "pci";
++			bus-range = <0x00 0xff>;
++			ranges =  <0x81000000 0 0x00000000 0x1ff80000 0 0x00010000 /* downstream I/O 64KB */
++				   0x82000000 0 0x18000000 0x18000000 0 0x07f00000>; /* non-prefetchable memory */
++			num-lanes = <1>;
++			num-viewport = <4>;
++			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
++			interrupt-names = "msi";
++			#interrupt-cells = <1>;
++			interrupt-map-mask = <0 0 0 0x7>;
++			interrupt-map = <0 0 0 1 &gic GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
++					<0 0 0 2 &gic GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
++					<0 0 0 3 &gic GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
++					<0 0 0 4 &gic GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
++			fsl,max-link-speed = <2>;
++			linux,pci-domain = <0>;
++			power-domains = <&pgc_pcie>;
++			resets = <&src IMX8MQ_RESET_PCIE_CTRL_APPS_EN>,
++				 <&src IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF>;
++			reset-names = "apps", "turnoff";
++			phys = <&pcie_phy>;
++			phy-names = "pcie-phy";
++			status = "disabled";
++		};
++
+ 		gic: interrupt-controller@38800000 {
+ 			compatible = "arm,gic-v3";
+ 			reg = <0x38800000 0x10000>, /* GIC Dist */
+-- 
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch b/target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch
new file mode 100644
index 000000000000..7d873280f848
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch
@@ -0,0 +1,437 @@ 
+From d44610e534d7c978e782b1ba0a5bdb065b4fa3bb Mon Sep 17 00:00:00 2001
+From: Tim Harvey <tharvey@gateworks.com>
+Date: Wed, 13 Jan 2021 14:05:03 -0800
+Subject: [PATCH 17/17] arm64: dts: imx8mm-venice*: add PCIe support
+
+Add PCIe support to GW71xx/GW72xx/GW73xx/GW7901/GW7902
+
+Signed-off-by: Tim Harvey <tharvey@gateworks.com>
+---
+ .../dts/freescale/imx8mm-venice-gw71xx.dtsi   | 35 +++++++++++
+ .../dts/freescale/imx8mm-venice-gw72xx.dtsi   | 62 +++++++++++++++++++
+ .../dts/freescale/imx8mm-venice-gw73xx.dtsi   | 62 +++++++++++++++++++
+ .../dts/freescale/imx8mm-venice-gw7901.dts    | 36 +++++++++++
+ .../dts/freescale/imx8mm-venice-gw7902.dts    | 50 +++++++++++++++
+ 5 files changed, 245 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+index 7ea909a4c1d5..c2315d3ef4d0 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+@@ -5,6 +5,7 @@
+ 
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/leds/common.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
+ 
+ / {
+ 	aliases {
+@@ -33,6 +34,12 @@ led-1 {
+ 		};
+ 	};
+ 
++	pcie0_refclk: pcie0-refclk {
++		compatible = "fixed-clock";
++		#clock-cells = <0>;
++		clock-frequency = <100000000>;
++	};
++
+ 	pps {
+ 		compatible = "pps-gpio";
+ 		pinctrl-names = "default";
+@@ -87,6 +94,28 @@ &i2c3 {
+ 	status = "okay";
+ };
+ 
++&pcie_phy {
++	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
++	fsl,clkreq-unsupported;
++	clocks = <&pcie0_refclk>;
++	status = "okay";
++};
++
++&pcie0 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_pcie0>;
++	reset-gpio = <&gpio4 6 GPIO_ACTIVE_LOW>;
++	clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>,
++		 <&pcie0_refclk>;
++	clock-names = "pcie", "pcie_aux", "pcie_bus";
++	assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>,
++			  <&clk IMX8MM_CLK_PCIE1_CTRL>;
++	assigned-clock-rates = <10000000>, <250000000>;
++	assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
++				 <&clk IMX8MM_SYS_PLL2_250M>;
++	status = "okay";
++};
++
+ /* GPS */
+ &uart1 {
+ 	pinctrl-names = "default";
+@@ -150,6 +179,12 @@ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA		0x400001c3
+ 		>;
+ 	};
+ 
++	pinctrl_pcie0: pcie0grp {
++		fsl,pins = <
++			MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6	0x41
++		>;
++	};
++
+ 	pinctrl_pps: ppsgrp {
+ 		fsl,pins = <
+ 			MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15	0x41
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
+index 806ee21651d1..84638edbd155 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx.dtsi
+@@ -5,9 +5,11 @@
+ 
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/leds/common.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
+ 
+ / {
+ 	aliases {
++		ethernet1 = &eth1;
+ 		usb0 = &usbotg1;
+ 		usb1 = &usbotg2;
+ 	};
+@@ -33,6 +35,12 @@ led-1 {
+ 		};
+ 	};
+ 
++	pcie0_refclk: pcie0-refclk {
++		compatible = "fixed-clock";
++		#clock-cells = <0>;
++		clock-frequency = <100000000>;
++	};
++
+ 	pps {
+ 		compatible = "pps-gpio";
+ 		pinctrl-names = "default";
+@@ -106,6 +114,54 @@ &i2c3 {
+ 	status = "okay";
+ };
+ 
++&pcie_phy {
++	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
++	fsl,clkreq-unsupported;
++	clocks = <&pcie0_refclk>;
++	status = "okay";
++};
++
++&pcie0 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_pcie0>;
++	reset-gpio = <&gpio4 6 GPIO_ACTIVE_LOW>;
++	clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>,
++		 <&pcie0_refclk>;
++	clock-names = "pcie", "pcie_aux", "pcie_bus";
++	assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>,
++			  <&clk IMX8MM_CLK_PCIE1_CTRL>;
++	assigned-clock-rates = <10000000>, <250000000>;
++	assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
++				 <&clk IMX8MM_SYS_PLL2_250M>;
++	status = "okay";
++
++	pcie@0,0 {
++		reg = <0x0000 0 0 0 0>;
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		pcie@1,0 {
++			reg = <0x0000 0 0 0 0>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++
++			pcie@2,3 {
++				reg = <0x1800 0 0 0 0>;
++				#address-cells = <1>;
++				#size-cells = <0>;
++
++				eth1: pcie@5,0 {
++					reg = <0x0000 0 0 0 0>;
++					#address-cells = <1>;
++					#size-cells = <0>;
++
++					local-mac-address = [00 00 00 00 00 00];
++				};
++			};
++		};
++	};
++};
++
+ /* off-board header */
+ &sai3 {
+ 	pinctrl-names = "default";
+@@ -200,6 +256,12 @@ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA		0x400001c3
+ 		>;
+ 	};
+ 
++	pinctrl_pcie0: pcie0grp {
++		fsl,pins = <
++			MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6	0x41
++		>;
++	};
++
+ 	pinctrl_pps: ppsgrp {
+ 		fsl,pins = <
+ 			MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15	0x41
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
+index 942fed2eed64..457ba82523b6 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx.dtsi
+@@ -5,9 +5,11 @@
+ 
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/leds/common.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
+ 
+ / {
+ 	aliases {
++		ethernet1 = &eth1;
+ 		usb0 = &usbotg1;
+ 		usb1 = &usbotg2;
+ 	};
+@@ -33,6 +35,12 @@ led-1 {
+ 		};
+ 	};
+ 
++	pcie0_refclk: pcie0-refclk {
++		compatible = "fixed-clock";
++		#clock-cells = <0>;
++		clock-frequency = <100000000>;
++	};
++
+ 	pps {
+ 		compatible = "pps-gpio";
+ 		pinctrl-names = "default";
+@@ -126,6 +134,54 @@ &i2c3 {
+ 	status = "okay";
+ };
+ 
++&pcie_phy {
++	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
++	fsl,clkreq-unsupported;
++	clocks = <&pcie0_refclk>;
++	status = "okay";
++};
++
++&pcie0 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_pcie0>;
++	reset-gpio = <&gpio4 6 GPIO_ACTIVE_LOW>;
++	clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>,
++		 <&pcie0_refclk>;
++	clock-names = "pcie", "pcie_aux", "pcie_bus";
++	assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>,
++			  <&clk IMX8MM_CLK_PCIE1_CTRL>;
++	assigned-clock-rates = <10000000>, <250000000>;
++	assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
++				 <&clk IMX8MM_SYS_PLL2_250M>;
++	status = "okay";
++
++	pcie@0,0 {
++		reg = <0x0000 0 0 0 0>;
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		pcie@1,0 {
++			reg = <0x0000 0 0 0 0>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++
++			pcie@2,4 {
++				reg = <0x2000 0 0 0 0>;
++				#address-cells = <1>;
++				#size-cells = <0>;
++
++				eth1: pcie@6,0 {
++					reg = <0x0000 0 0 0 0>;
++					#address-cells = <1>;
++					#size-cells = <0>;
++
++					local-mac-address = [00 00 00 00 00 00];
++				};
++			};
++		};
++	};
++};
++
+ /* off-board header */
+ &sai3 {
+ 	pinctrl-names = "default";
+@@ -243,6 +299,12 @@ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA		0x400001c3
+ 		>;
+ 	};
+ 
++	pinctrl_pcie0: pcie0grp {
++		fsl,pins = <
++			MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6	0x41
++		>;
++	};
++
+ 	pinctrl_pps: ppsgrp {
+ 		fsl,pins = <
+ 			MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15	0x41
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+index f7e41e5c2c7b..da576f02fa31 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+@@ -8,6 +8,7 @@
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/input/linux-event-codes.h>
+ #include <dt-bindings/leds/common.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
+ 
+ #include "imx8mm.dtsi"
+ 
+@@ -179,6 +180,12 @@ led-b {
+ 		};
+ 	};
+ 
++	pcie0_refclk: pcie0-refclk {
++		compatible = "fixed-clock";
++		#clock-cells = <0>;
++		clock-frequency = <100000000>;
++	};
++
+ 	reg_3p3v: regulator-3p3v {
+ 		compatible = "regulator-fixed";
+ 		regulator-name = "3P3V";
+@@ -632,6 +639,28 @@ &i2c4 {
+ 	status = "okay";
+ };
+ 
++&pcie_phy {
++	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
++	fsl,clkreq-unsupported;
++	clocks = <&pcie0_refclk>;
++	status = "okay";
++};
++
++&pcie0 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_pcie0>;
++	reset-gpio = <&gpio5 2 GPIO_ACTIVE_LOW>;
++	clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>,
++		 <&pcie0_refclk>;
++	clock-names = "pcie", "pcie_aux", "pcie_bus";
++	assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>,
++			  <&clk IMX8MM_CLK_PCIE1_CTRL>;
++	assigned-clock-rates = <10000000>, <250000000>;
++	assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
++				 <&clk IMX8MM_SYS_PLL2_250M>;
++	status = "okay";
++};
++
+ &uart1 {
+ 	pinctrl-names = "default";
+ 	pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart1_gpio>;
+@@ -797,6 +826,13 @@ MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19	0x41 /* RST# */
+ 		>;
+ 	};
+ 
++	pinctrl_pcie0: pciegrp {
++		fsl,pins = <
++			MX8MM_IOMUXC_SAI3_TXFS_GPIO4_IO31	0x40000041 /* WDIS# */
++			MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2	0x41
++		>;
++	};
++
+ 	pinctrl_pmic: pmicgrp {
+ 		fsl,pins = <
+ 			MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20	0x41
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
+index d52686f4c059..1b2aaf299b24 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
+@@ -9,6 +9,7 @@
+ #include <dt-bindings/input/linux-event-codes.h>
+ #include <dt-bindings/leds/common.h>
+ #include <dt-bindings/net/ti-dp83867.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
+ 
+ #include "imx8mm.dtsi"
+ 
+@@ -17,6 +18,7 @@ / {
+ 	compatible = "gw,imx8mm-gw7902", "fsl,imx8mm";
+ 
+ 	aliases {
++		ethernet1 = &eth1;
+ 		usb0 = &usbotg1;
+ 		usb1 = &usbotg2;
+ 	};
+@@ -128,6 +130,12 @@ led-4 {
+ 		};
+ 	};
+ 
++	pcie0_refclk: pcie0-refclk {
++		compatible = "fixed-clock";
++		#clock-cells = <0>;
++		clock-frequency = <100000000>;
++	};
++
+ 	pps {
+ 		compatible = "pps-gpio";
+ 		pinctrl-names = "default";
+@@ -547,6 +555,42 @@ &i2c4 {
+ 	status = "okay";
+ };
+ 
++&pcie_phy {
++	fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
++	fsl,clkreq-unsupported;
++	clocks = <&clk IMX8MM_CLK_DUMMY>;
++	status = "okay";
++};
++
++&pcie0 {
++	pinctrl-names = "default";
++	pinctrl-0 = <&pinctrl_pcie0>;
++	reset-gpio = <&gpio4 5 GPIO_ACTIVE_LOW>;
++	clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>,
++		 <&clk IMX8MM_CLK_DUMMY>, <&pcie0_refclk>;
++	clock-names = "pcie", "pcie_aux", "pcie_phy", "pcie_bus";
++	assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>,
++			  <&clk IMX8MM_CLK_PCIE1_CTRL>;
++	assigned-clock-rates = <10000000>, <250000000>;
++	assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
++				 <&clk IMX8MM_SYS_PLL2_250M>;
++	status = "okay";
++
++	pcie@0,0 {
++		reg = <0x0000 0 0 0 0>;
++		#address-cells = <1>;
++		#size-cells = <0>;
++
++		eth1: pcie@1,0 {
++			reg = <0x0000 0 0 0 0>;
++			#address-cells = <1>;
++			#size-cells = <0>;
++
++			local-mac-address = [00 00 00 00 00 00];
++		};
++	};
++};
++
+ /* off-board header */
+ &sai3 {
+ 	pinctrl-names = "default";
+@@ -737,6 +781,12 @@ MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25	0x19
+ 		>;
+ 	};
+ 
++	pinctrl_pcie0: pciegrp {
++		fsl,pins = <
++			MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5	0x41
++		>;
++	};
++
+ 	pinctrl_pmic: pmicgrp {
+ 		fsl,pins = <
+ 			MX8MM_IOMUXC_NAND_DATA02_GPIO3_IO8	0x41
+-- 
+2.25.1
+