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 <thar...@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

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.st...@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.st...@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 <ma...@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 <ma...@denx.de>
+Signed-off-by: Lucas Stach <l.st...@pengutronix.de>
+Reviewed-by: Peng Fan <peng....@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 <ma...@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 <ma...@denx.de>
+Signed-off-by: Lucas Stach <l.st...@pengutronix.de>
+Reviewed-by: Peng Fan <peng....@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.st...@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.st...@pengutronix.de>
+Reviewed-by: Peng Fan <peng....@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.st...@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.st...@pengutronix.de>
+Reviewed-by: Peng Fan <peng....@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.st...@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.st...@pengutronix.de>
+Reviewed-by: Peng Fan <peng....@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.st...@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.st...@pengutronix.de>
+Acked-by: Peng Fan <peng....@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.st...@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.st...@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.st...@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.st...@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.st...@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.st...@pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinch...@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....@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....@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswi...@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....@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....@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....@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....@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswi...@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....@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....@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswi...@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....@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....@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswi...@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....@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....@nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswi...@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 <thar...@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 <thar...@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
+
-- 
2.25.1


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to