[PATCH] imx: add imx8 support
Tim Harvey
tharvey at gateworks.com
Wed Mar 8 16:20:31 PST 2023
Add imx8 support:
- add a cortexa53 subtarget
- move ARCH, KERNELNAME, and some FEATURES to cortexa7/cortexa9 subtargets
- add a small series of backports from 6.2 to fix hang on USB init and
add PCIe support
No device-specific targets or firmware images are created yet.
The resulting openwrt-imx-cortexa53-vmlinux-initramfs has been booted on
Gateworks Venice boards and the imx8mm-evk using dtb's from $LINUX_DIR
and verifying usb, pci, mmc, and fec networking work.
Signed-off-by: Tim Harvey <tharvey at 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.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 14:48:52 +0200
+Subject: [PATCH 01/17] soc: imx: gpcv2: allow to disable individual power
+ domains
+
+Some board designs don't supply power to all of the power domains,
+as they are not used anyways. In that case we must make sure to
+not touch those power domains at all, as trying to power up a
+domain that has no power supplied to it will obviously end in a
+system crash. Allow to disable those domains via the standard DT
+status property.
+
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+---
+ drivers/soc/imx/gpcv2.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 4dc3a3f73511..60566bdcb51f 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -989,6 +989,9 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
+ struct imx_pgc_domain *domain;
+ u32 domain_index;
+
++ if (!of_device_is_available(np))
++ continue;
++
+ ret = of_property_read_u32(np, "reg", &domain_index);
+ if (ret) {
+ dev_err(dev, "Failed to read 'reg' property\n");
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch b/target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch
new file mode 100644
index 000000000000..b1ec4c7beaa2
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0002-soc-imx-gpcv2-Turn-domain-pgc-into-bitfield.patch
@@ -0,0 +1,327 @@
+From 6dbb5cd7006a5382ab02282b7b39e0edc8e15331 Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex at denx.de>
+Date: Sat, 2 Oct 2021 02:59:38 +0200
+Subject: [PATCH 02/17] soc: imx: gpcv2: Turn domain->pgc into bitfield
+
+There is currently the MX8MM GPU domain, which is in fact a composite domain
+for both GPU2D and GPU3D. To correctly configure this domain, it is necessary
+to control both GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) at the same
+time. This is currently not possible.
+
+Turn the domain->pgc from value into bitfield and use for_each_set_bit() to
+iterate over all bits set in domain->pgc when configuring GPC_PGC_nCTRL
+register array. This way it is possible to configure all GPC_PGC_nCTRL
+registers required in a particular domain.
+
+This is a preparatory patch, no functional change.
+
+Signed-off-by: Marek Vasut <marex at denx.de>
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan at nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 72 ++++++++++++++++++++++-------------------
+ 1 file changed, 38 insertions(+), 34 deletions(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 60566bdcb51f..8341b03eec92 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -192,7 +192,7 @@ struct imx_pgc_domain {
+ struct clk_bulk_data *clks;
+ int num_clks;
+
+- unsigned int pgc;
++ unsigned long pgc;
+
+ const struct {
+ u32 pxx;
+@@ -220,7 +220,7 @@ to_imx_pgc_domain(struct generic_pm_domain *genpd)
+ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ {
+ struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+- u32 reg_val;
++ u32 reg_val, pgc;
+ int ret;
+
+ ret = pm_runtime_get_sync(domain->dev);
+@@ -267,8 +267,10 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ }
+
+ /* disable power control */
+- regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+- GPC_PGC_CTRL_PCR);
++ for_each_set_bit(pgc, &domain->pgc, 32) {
++ regmap_clear_bits(domain->regmap, GPC_PGC_CTRL(pgc),
++ GPC_PGC_CTRL_PCR);
++ }
+ }
+
+ /* delay for reset to propagate */
+@@ -314,7 +316,7 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ {
+ struct imx_pgc_domain *domain = to_imx_pgc_domain(genpd);
+- u32 reg_val;
++ u32 reg_val, pgc;
+ int ret;
+
+ /* Enable reset clocks for all devices in the domain */
+@@ -341,8 +343,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+
+ if (domain->bits.pxx) {
+ /* enable power control */
+- regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+- GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
++ for_each_set_bit(pgc, &domain->pgc, 32) {
++ regmap_update_bits(domain->regmap, GPC_PGC_CTRL(pgc),
++ GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
++ }
+
+ /* request the domain to power down */
+ regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
+@@ -392,7 +396,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
+ .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
+ },
+ .voltage = 1000000,
+- .pgc = IMX7_PGC_MIPI,
++ .pgc = BIT(IMX7_PGC_MIPI),
+ },
+
+ [IMX7_POWER_DOMAIN_PCIE_PHY] = {
+@@ -404,7 +408,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
+ .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
+ },
+ .voltage = 1000000,
+- .pgc = IMX7_PGC_PCIE,
++ .pgc = BIT(IMX7_PGC_PCIE),
+ },
+
+ [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
+@@ -416,7 +420,7 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
+ .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
+ },
+ .voltage = 1200000,
+- .pgc = IMX7_PGC_USB_HSIC,
++ .pgc = BIT(IMX7_PGC_USB_HSIC),
+ },
+ };
+
+@@ -451,7 +455,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_MIPI_SW_Pxx_REQ,
+ .map = IMX8M_MIPI_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_MIPI,
++ .pgc = BIT(IMX8M_PGC_MIPI),
+ },
+
+ [IMX8M_POWER_DOMAIN_PCIE1] = {
+@@ -462,7 +466,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
+ .map = IMX8M_PCIE1_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_PCIE1,
++ .pgc = BIT(IMX8M_PGC_PCIE1),
+ },
+
+ [IMX8M_POWER_DOMAIN_USB_OTG1] = {
+@@ -473,7 +477,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_OTG1_SW_Pxx_REQ,
+ .map = IMX8M_OTG1_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_OTG1,
++ .pgc = BIT(IMX8M_PGC_OTG1),
+ },
+
+ [IMX8M_POWER_DOMAIN_USB_OTG2] = {
+@@ -484,7 +488,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_OTG2_SW_Pxx_REQ,
+ .map = IMX8M_OTG2_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_OTG2,
++ .pgc = BIT(IMX8M_PGC_OTG2),
+ },
+
+ [IMX8M_POWER_DOMAIN_DDR1] = {
+@@ -495,7 +499,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_DDR1_SW_Pxx_REQ,
+ .map = IMX8M_DDR2_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_DDR1,
++ .pgc = BIT(IMX8M_PGC_DDR1),
+ },
+
+ [IMX8M_POWER_DOMAIN_GPU] = {
+@@ -508,7 +512,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .hskreq = IMX8M_GPU_HSK_PWRDNREQN,
+ .hskack = IMX8M_GPU_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8M_PGC_GPU,
++ .pgc = BIT(IMX8M_PGC_GPU),
+ },
+
+ [IMX8M_POWER_DOMAIN_VPU] = {
+@@ -521,7 +525,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .hskreq = IMX8M_VPU_HSK_PWRDNREQN,
+ .hskack = IMX8M_VPU_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8M_PGC_VPU,
++ .pgc = BIT(IMX8M_PGC_VPU),
+ },
+
+ [IMX8M_POWER_DOMAIN_DISP] = {
+@@ -534,7 +538,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .hskreq = IMX8M_DISP_HSK_PWRDNREQN,
+ .hskack = IMX8M_DISP_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8M_PGC_DISP,
++ .pgc = BIT(IMX8M_PGC_DISP),
+ },
+
+ [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
+@@ -545,7 +549,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
+ .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_MIPI_CSI1,
++ .pgc = BIT(IMX8M_PGC_MIPI_CSI1),
+ },
+
+ [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
+@@ -556,7 +560,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
+ .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_MIPI_CSI2,
++ .pgc = BIT(IMX8M_PGC_MIPI_CSI2),
+ },
+
+ [IMX8M_POWER_DOMAIN_PCIE2] = {
+@@ -567,7 +571,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
+ .map = IMX8M_PCIE2_A53_DOMAIN,
+ },
+- .pgc = IMX8M_PGC_PCIE2,
++ .pgc = BIT(IMX8M_PGC_PCIE2),
+ },
+ };
+
+@@ -630,7 +634,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_PCIE_SW_Pxx_REQ,
+ .map = IMX8MM_PCIE_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_PCIE,
++ .pgc = BIT(IMX8MM_PGC_PCIE),
+ },
+
+ [IMX8MM_POWER_DOMAIN_OTG1] = {
+@@ -641,7 +645,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_OTG1_SW_Pxx_REQ,
+ .map = IMX8MM_OTG1_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_OTG1,
++ .pgc = BIT(IMX8MM_PGC_OTG1),
+ },
+
+ [IMX8MM_POWER_DOMAIN_OTG2] = {
+@@ -652,7 +656,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_OTG2_SW_Pxx_REQ,
+ .map = IMX8MM_OTG2_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_OTG2,
++ .pgc = BIT(IMX8MM_PGC_OTG2),
+ },
+
+ [IMX8MM_POWER_DOMAIN_GPUMIX] = {
+@@ -665,7 +669,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN,
+ .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8MM_PGC_GPUMIX,
++ .pgc = BIT(IMX8MM_PGC_GPUMIX),
+ },
+
+ [IMX8MM_POWER_DOMAIN_GPU] = {
+@@ -678,7 +682,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+ .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8MM_PGC_GPU2D,
++ .pgc = BIT(IMX8MM_PGC_GPU2D),
+ },
+
+ [IMX8MM_POWER_DOMAIN_VPUMIX] = {
+@@ -691,7 +695,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN,
+ .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8MM_PGC_VPUMIX,
++ .pgc = BIT(IMX8MM_PGC_VPUMIX),
+ },
+
+ [IMX8MM_POWER_DOMAIN_VPUG1] = {
+@@ -702,7 +706,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_VPUG1_SW_Pxx_REQ,
+ .map = IMX8MM_VPUG1_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_VPUG1,
++ .pgc = BIT(IMX8MM_PGC_VPUG1),
+ },
+
+ [IMX8MM_POWER_DOMAIN_VPUG2] = {
+@@ -713,7 +717,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_VPUG2_SW_Pxx_REQ,
+ .map = IMX8MM_VPUG2_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_VPUG2,
++ .pgc = BIT(IMX8MM_PGC_VPUG2),
+ },
+
+ [IMX8MM_POWER_DOMAIN_VPUH1] = {
+@@ -724,7 +728,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_VPUH1_SW_Pxx_REQ,
+ .map = IMX8MM_VPUH1_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_VPUH1,
++ .pgc = BIT(IMX8MM_PGC_VPUH1),
+ },
+
+ [IMX8MM_POWER_DOMAIN_DISPMIX] = {
+@@ -737,7 +741,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN,
+ .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8MM_PGC_DISPMIX,
++ .pgc = BIT(IMX8MM_PGC_DISPMIX),
+ },
+
+ [IMX8MM_POWER_DOMAIN_MIPI] = {
+@@ -748,7 +752,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .pxx = IMX8MM_MIPI_SW_Pxx_REQ,
+ .map = IMX8MM_MIPI_A53_DOMAIN,
+ },
+- .pgc = IMX8MM_PGC_MIPI,
++ .pgc = BIT(IMX8MM_PGC_MIPI),
+ },
+ };
+
+@@ -815,7 +819,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+ .pxx = IMX8MN_OTG1_SW_Pxx_REQ,
+ .map = IMX8MN_OTG1_A53_DOMAIN,
+ },
+- .pgc = IMX8MN_PGC_OTG1,
++ .pgc = BIT(IMX8MN_PGC_OTG1),
+ },
+
+ [IMX8MN_POWER_DOMAIN_GPUMIX] = {
+@@ -828,7 +832,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+ .hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN,
+ .hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN,
+ },
+- .pgc = IMX8MN_PGC_GPUMIX,
++ .pgc = BIT(IMX8MN_PGC_GPUMIX),
+ },
+ };
+
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch b/target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch
new file mode 100644
index 000000000000..4ea5b3b0b0ff
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0003-soc-imx-gpcv2-Set-both-GPC_PGC_nCTRL-GPU_2D-GPU_3D-f.patch
@@ -0,0 +1,40 @@
+From f05c5d9450c83ab64a7e313ada06129721f29c7f Mon Sep 17 00:00:00 2001
+From: Marek Vasut <marex at denx.de>
+Date: Sat, 2 Oct 2021 02:59:39 +0200
+Subject: [PATCH 03/17] soc: imx: gpcv2: Set both GPC_PGC_nCTRL(GPU_2D|GPU_3D)
+ for MX8MM GPU domain
+
+To bring up the MX8MM GPU domain, it is necessary to configure both
+GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) registers. Without
+this configuration, the system might hang on boot when bringing up
+the GPU power domain. This is sporadically observed on multiple
+disparate systems.
+
+Add the GPU3D bit into MX8MM GPU domain pgc bitfield, so that both
+GPC_PGC_nCTRL(GPU_2D) and GPC_PGC_nCTRL(GPU_3D) registers are
+configured when bringing up the GPU domain. This fixes the sporadic
+hang.
+
+Signed-off-by: Marek Vasut <marex at denx.de>
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan at nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 8341b03eec92..afc309aff0f0 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -682,7 +682,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskreq = IMX8MM_GPU_HSK_PWRDNREQN,
+ .hskack = IMX8MM_GPU_HSK_PWRDNACKN,
+ },
+- .pgc = BIT(IMX8MM_PGC_GPU2D),
++ .pgc = BIT(IMX8MM_PGC_GPU2D) | BIT(IMX8MM_PGC_GPU3D),
+ },
+
+ [IMX8MM_POWER_DOMAIN_VPUMIX] = {
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch b/target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch
new file mode 100644
index 000000000000..6da19e0be772
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0004-soc-imx-gpcv2-add-lockdep-annotation.patch
@@ -0,0 +1,36 @@
+From 9cdd2d0a39b60929a30b1642e67441ef748509cc Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:40 +0200
+Subject: [PATCH 04/17] soc: imx: gpcv2: add lockdep annotation
+
+Some of the GPCv2 power domains are nested inside each other without
+visibility to lockdep at the genpd level, as they are in separate
+driver instances and don't have a parent/child power-domain relationship.
+
+Add a subclass annotation to the nested domains to let lockdep know that
+it is okay to take the genpd lock in a nested fashion.
+
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan at nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index afc309aff0f0..2761e81abb40 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -901,6 +901,10 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ goto out_domain_unmap;
+ }
+
++ if (IS_ENABLED(CONFIG_LOCKDEP) &&
++ of_property_read_bool(domain->dev->of_node, "power-domains"))
++ lockdep_set_subclass(&domain->genpd.mlock, 1);
++
+ ret = of_genpd_add_provider_simple(domain->dev->of_node,
+ &domain->genpd);
+ if (ret) {
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch b/target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch
new file mode 100644
index 000000000000..b14fe8b90467
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0005-soc-imx-gpcv2-add-domain-option-to-keep-domain-clock.patch
@@ -0,0 +1,60 @@
+From a6ac7c30d1664e6b7336b6bee44c97347c916af4 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:41 +0200
+Subject: [PATCH 05/17] soc: imx: gpcv2: add domain option to keep domain
+ clocks enabled
+
+Some of the MIX domains are using clocks to drive the bus bridges. Those
+must be enabled at all times, as long as the domain is powered up and
+they don't have any other consumer than the power domain. Add an option
+to keep the clocks attached to a domain enabled as long as the domain
+is power up and only disable them after the domain is powered down.
+
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan at nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 2761e81abb40..7e7826bbd3dc 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -202,6 +202,7 @@ struct imx_pgc_domain {
+ } bits;
+
+ const int voltage;
++ const bool keep_clocks;
+ struct device *dev;
+ };
+
+@@ -298,7 +299,8 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+ }
+
+ /* Disable reset clocks for all devices in the domain */
+- clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
++ if (!domain->keep_clocks)
++ clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
+
+ return 0;
+
+@@ -320,10 +322,12 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ int ret;
+
+ /* Enable reset clocks for all devices in the domain */
+- ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
+- if (ret) {
+- dev_err(domain->dev, "failed to enable reset clocks\n");
+- return ret;
++ if (!domain->keep_clocks) {
++ ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
++ if (ret) {
++ dev_err(domain->dev, "failed to enable reset clocks\n");
++ return ret;
++ }
+ }
+
+ /* request the ADB400 to power down */
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch b/target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch
new file mode 100644
index 000000000000..9abf099ae915
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0006-soc-imx-gpcv2-keep-i.MX8M-bus-clocks-enabled.patch
@@ -0,0 +1,69 @@
+From b2a1ee027619413d42cdb3a02459500c9f6f035a Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:42 +0200
+Subject: [PATCH 06/17] soc: imx: gpcv2: keep i.MX8M* bus clocks enabled
+
+Annotate the domains with bus clocks to keep those clocks enabled
+as long as the domain is active.
+
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Reviewed-by: Peng Fan <peng.fan at nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 7e7826bbd3dc..85a922e36f0f 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -530,6 +530,7 @@ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+ .hskack = IMX8M_VPU_HSK_PWRDNACKN,
+ },
+ .pgc = BIT(IMX8M_PGC_VPU),
++ .keep_clocks = true,
+ },
+
+ [IMX8M_POWER_DOMAIN_DISP] = {
+@@ -628,6 +629,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskreq = IMX8MM_HSIO_HSK_PWRDNREQN,
+ .hskack = IMX8MM_HSIO_HSK_PWRDNACKN,
+ },
++ .keep_clocks = true,
+ },
+
+ [IMX8MM_POWER_DOMAIN_PCIE] = {
+@@ -674,6 +676,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN,
+ },
+ .pgc = BIT(IMX8MM_PGC_GPUMIX),
++ .keep_clocks = true,
+ },
+
+ [IMX8MM_POWER_DOMAIN_GPU] = {
+@@ -700,6 +703,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN,
+ },
+ .pgc = BIT(IMX8MM_PGC_VPUMIX),
++ .keep_clocks = true,
+ },
+
+ [IMX8MM_POWER_DOMAIN_VPUG1] = {
+@@ -746,6 +750,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+ .hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN,
+ },
+ .pgc = BIT(IMX8MM_PGC_DISPMIX),
++ .keep_clocks = true,
+ },
+
+ [IMX8MM_POWER_DOMAIN_MIPI] = {
+@@ -813,6 +818,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+ .hskreq = IMX8MN_HSIO_HSK_PWRDNREQN,
+ .hskack = IMX8MN_HSIO_HSK_PWRDNACKN,
+ },
++ .keep_clocks = true,
+ },
+
+ [IMX8MN_POWER_DOMAIN_OTG1] = {
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch b/target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch
new file mode 100644
index 000000000000..6ba284d2aba9
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0007-soc-imx-gpcv2-support-system-suspend-resume.patch
@@ -0,0 +1,74 @@
+From e651a2a4d3ea18fbcee49ff87902625b70644c24 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:43 +0200
+Subject: [PATCH 07/17] soc: imx: gpcv2: support system suspend/resume
+
+Our usage of runtime PM to control the hierarchy of power domains is
+slightly unusual and means that powering up a domain may fail in early
+system resume, as runtime PM is still disallowed at this stage.
+
+However the system suspend/resume path takes care of powering down/up
+the power domains in the order defined by the device parent/child and
+power-domain provider/consumer hierarachy. So we can just runtime
+resume all our power-domain devices to allow the power-up to work
+properly in the resume path. System suspend will still disable all
+domains as intended.
+
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Acked-by: Peng Fan <peng.fan at nxp.com>
+---
+ drivers/soc/imx/gpcv2.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 85a922e36f0f..89e25e123c52 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -951,6 +951,36 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
+ return 0;
+ }
+
++#ifdef CONFIG_PM_SLEEP
++static int imx_pgc_domain_suspend(struct device *dev)
++{
++ int ret;
++
++ /*
++ * This may look strange, but is done so the generic PM_SLEEP code
++ * can power down our domain and more importantly power it up again
++ * after resume, without tripping over our usage of runtime PM to
++ * power up/down the nested domains.
++ */
++ ret = pm_runtime_get_sync(dev);
++ if (ret < 0) {
++ pm_runtime_put_noidle(dev);
++ return ret;
++ }
++
++ return 0;
++}
++
++static int imx_pgc_domain_resume(struct device *dev)
++{
++ return pm_runtime_put(dev);
++}
++#endif
++
++static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
++ SET_SYSTEM_SLEEP_PM_OPS(imx_pgc_domain_suspend, imx_pgc_domain_resume)
++};
++
+ static const struct platform_device_id imx_pgc_domain_id[] = {
+ { "imx-pgc-domain", },
+ { },
+@@ -959,6 +989,7 @@ static const struct platform_device_id imx_pgc_domain_id[] = {
+ static struct platform_driver imx_pgc_domain_driver = {
+ .driver = {
+ .name = "imx-pgc",
++ .pm = &imx_pgc_domain_pm_ops,
+ },
+ .probe = imx_pgc_domain_probe,
+ .remove = imx_pgc_domain_remove,
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch b/target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch
new file mode 100644
index 000000000000..d7bb478745cc
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0008-arm64-dts-imx8mm-add-GPC-node.patch
@@ -0,0 +1,142 @@
+From 744143a80acaeeb10ab6cb1e703b78448ec25c16 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:50 +0200
+Subject: [PATCH 08/17] arm64: dts: imx8mm: add GPC node
+
+Add the DT node for the GPC, including all the PGC power domains,
+some of them are not fully functional yet, as they require interaction
+with the blk-ctrls to properly power up/down the peripherals.
+
+Signed-off-by: Lucas Stach <l.stach at 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 at 30390000 {
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ #reset-cells = <1>;
+ };
++
++ gpc: gpc at 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 at 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 at 1 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_PCIE>;
++ power-domains = <&pgc_hsiomix>;
++ clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>;
++ };
++
++ pgc_otg1: power-domain at 2 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_OTG1>;
++ power-domains = <&pgc_hsiomix>;
++ };
++
++ pgc_otg2: power-domain at 3 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_OTG2>;
++ power-domains = <&pgc_hsiomix>;
++ };
++
++ pgc_gpumix: power-domain at 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 at 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 at 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 at 7 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_VPUG1>;
++ };
++
++ pgc_vpu_g2: power-domain at 8 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_VPUG2>;
++ };
++
++ pgc_vpu_h1: power-domain at 9 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_VPUH1>;
++ };
++
++ pgc_dispmix: power-domain at 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 at 11 {
++ #power-domain-cells = <0>;
++ reg = <IMX8MM_POWER_DOMAIN_MIPI>;
++ };
++ };
++ };
+ };
+
+ aips2: bus at 30400000 {
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch b/target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch
new file mode 100644
index 000000000000..c2d1f577f6a1
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0009-arm64-dts-imx8mm-put-USB-controllers-into-power-doma.patch
@@ -0,0 +1,38 @@
+From 69f9867bcd9c3f956f292e2783e08aa01fef76f4 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Sat, 2 Oct 2021 02:59:51 +0200
+Subject: [PATCH 09/17] arm64: dts: imx8mm: put USB controllers into
+ power-domains
+
+Now that we have support for the power domain controller on the i.MX8MM
+we can put the USB controllers in their respective power domains to allow
+them to power down the PHY when possible.
+
+Signed-off-by: Lucas Stach <l.stach at 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 at 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 at 32e50000 {
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
+ phys = <&usbphynop2>;
+ fsl,usbmisc = <&usbmisc2 0>;
++ power-domains = <&pgc_otg2>;
+ status = "disabled";
+ };
+
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch b/target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch
new file mode 100644
index 000000000000..e5d4ddead71c
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0010-soc-imx-gpcv2-add-PGC-control-register-indirection.patch
@@ -0,0 +1,187 @@
+From fdb04e435edbe614e3565381d85a7e8a3d70f0a4 Mon Sep 17 00:00:00 2001
+From: Lucas Stach <l.stach at pengutronix.de>
+Date: Mon, 28 Feb 2022 21:17:25 +0100
+Subject: [PATCH 10/17] soc: imx: gpcv2: add PGC control register indirection
+
+The PGC control registers in the shared (not per-PGC) region of the
+GPC address space have different offsets on i.MX8MP to make space for
+additional interrupt control registers.
+
+Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
+Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
+---
+ drivers/soc/imx/gpcv2.c | 43 ++++++++++++++++++++++++++++++-----------
+ 1 file changed, 32 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
+index 89e25e123c52..80ba59811a75 100644
+--- a/drivers/soc/imx/gpcv2.c
++++ b/drivers/soc/imx/gpcv2.c
+@@ -184,9 +184,17 @@
+
+ #define GPC_PGC_CTRL_PCR BIT(0)
+
++struct imx_pgc_regs {
++ u16 map;
++ u16 pup;
++ u16 pdn;
++ u16 hsk;
++};
++
+ struct imx_pgc_domain {
+ struct generic_pm_domain genpd;
+ struct regmap *regmap;
++ const struct imx_pgc_regs *regs;
+ struct regulator *regulator;
+ struct reset_control *reset;
+ struct clk_bulk_data *clks;
+@@ -210,6 +218,7 @@ struct imx_pgc_domain_data {
+ const struct imx_pgc_domain *domains;
+ size_t domains_num;
+ const struct regmap_access_table *reg_access_table;
++ const struct imx_pgc_regs *pgc_regs;
+ };
+
+ static inline struct imx_pgc_domain *
+@@ -252,14 +261,14 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+
+ if (domain->bits.pxx) {
+ /* request the domain to power up */
+- regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ,
++ regmap_update_bits(domain->regmap, domain->regs->pup,
+ domain->bits.pxx, domain->bits.pxx);
+ /*
+ * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+ * for PUP_REQ/PDN_REQ bit to be cleared
+ */
+ ret = regmap_read_poll_timeout(domain->regmap,
+- GPC_PU_PGC_SW_PUP_REQ, reg_val,
++ domain->regs->pup, reg_val,
+ !(reg_val & domain->bits.pxx),
+ 0, USEC_PER_MSEC);
+ if (ret) {
+@@ -281,11 +290,11 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
+
+ /* request the ADB400 to power up */
+ if (domain->bits.hskreq) {
+- regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
++ regmap_update_bits(domain->regmap, domain->regs->hsk,
+ domain->bits.hskreq, domain->bits.hskreq);
+
+ /*
+- * ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, reg_val,
++ * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
+ * (reg_val & domain->bits.hskack), 0,
+ * USEC_PER_MSEC);
+ * Technically we need the commented code to wait handshake. But that needs
+@@ -332,10 +341,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+
+ /* request the ADB400 to power down */
+ if (domain->bits.hskreq) {
+- regmap_clear_bits(domain->regmap, GPC_PU_PWRHSK,
++ regmap_clear_bits(domain->regmap, domain->regs->hsk,
+ domain->bits.hskreq);
+
+- ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK,
++ ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
+ reg_val,
+ !(reg_val & domain->bits.hskack),
+ 0, USEC_PER_MSEC);
+@@ -353,14 +362,14 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
+ }
+
+ /* request the domain to power down */
+- regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
++ regmap_update_bits(domain->regmap, domain->regs->pdn,
+ domain->bits.pxx, domain->bits.pxx);
+ /*
+ * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+ * for PUP_REQ/PDN_REQ bit to be cleared
+ */
+ ret = regmap_read_poll_timeout(domain->regmap,
+- GPC_PU_PGC_SW_PDN_REQ, reg_val,
++ domain->regs->pdn, reg_val,
+ !(reg_val & domain->bits.pxx),
+ 0, USEC_PER_MSEC);
+ if (ret) {
+@@ -444,10 +453,18 @@ static const struct regmap_access_table imx7_access_table = {
+ .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges),
+ };
+
++static const struct imx_pgc_regs imx7_pgc_regs = {
++ .map = GPC_PGC_CPU_MAPPING,
++ .pup = GPC_PU_PGC_SW_PUP_REQ,
++ .pdn = GPC_PU_PGC_SW_PDN_REQ,
++ .hsk = GPC_PU_PWRHSK,
++};
++
+ static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
+ .domains = imx7_pgc_domains,
+ .domains_num = ARRAY_SIZE(imx7_pgc_domains),
+ .reg_access_table = &imx7_access_table,
++ .pgc_regs = &imx7_pgc_regs,
+ };
+
+ static const struct imx_pgc_domain imx8m_pgc_domains[] = {
+@@ -616,6 +633,7 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
+ .domains = imx8m_pgc_domains,
+ .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
+ .reg_access_table = &imx8m_access_table,
++ .pgc_regs = &imx7_pgc_regs,
+ };
+
+ static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
+@@ -805,6 +823,7 @@ static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
+ .domains = imx8mm_pgc_domains,
+ .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
+ .reg_access_table = &imx8mm_access_table,
++ .pgc_regs = &imx7_pgc_regs,
+ };
+
+ static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
+@@ -870,6 +889,7 @@ static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
+ .domains = imx8mn_pgc_domains,
+ .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
+ .reg_access_table = &imx8mn_access_table,
++ .pgc_regs = &imx7_pgc_regs,
+ };
+
+ static int imx_pgc_domain_probe(struct platform_device *pdev)
+@@ -902,7 +922,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ pm_runtime_enable(domain->dev);
+
+ if (domain->bits.map)
+- regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
++ regmap_update_bits(domain->regmap, domain->regs->map,
+ domain->bits.map, domain->bits.map);
+
+ ret = pm_genpd_init(&domain->genpd, NULL, true);
+@@ -928,7 +948,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
+ pm_genpd_remove(&domain->genpd);
+ out_domain_unmap:
+ if (domain->bits.map)
+- regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
++ regmap_update_bits(domain->regmap, domain->regs->map,
+ domain->bits.map, 0);
+ pm_runtime_disable(domain->dev);
+
+@@ -943,7 +963,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
+ pm_genpd_remove(&domain->genpd);
+
+ if (domain->bits.map)
+- regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
++ regmap_update_bits(domain->regmap, domain->regs->map,
+ domain->bits.map, 0);
+
+ pm_runtime_disable(domain->dev);
+@@ -1074,6 +1094,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
+
+ domain = pd_pdev->dev.platform_data;
+ domain->regmap = regmap;
++ domain->regs = domain_data->pgc_regs;
+ domain->genpd.power_on = imx_pgc_power_up;
+ domain->genpd.power_off = imx_pgc_power_down;
+
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch b/target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch
new file mode 100644
index 000000000000..022f3c0c5b44
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0011-phy-freescale-pcie-Initialize-the-imx8-pcie-standalo.patch
@@ -0,0 +1,285 @@
+From b90c3fd61d15182da871afb435fc8e72067478f9 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu at nxp.com>
+Date: Thu, 28 Oct 2021 15:27:14 +0800
+Subject: [PATCH 11/17] phy: freescale: pcie: Initialize the imx8 pcie
+ standalone phy driver
+
+Add the standalone i.MX8 PCIe PHY driver.
+
+Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
+---
+ drivers/phy/freescale/Kconfig | 9 +
+ drivers/phy/freescale/Makefile | 1 +
+ drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 233 +++++++++++++++++++++
+ 3 files changed, 243 insertions(+)
+ create mode 100644 drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+
+diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig
+index 320630ffe3cd..de9ee7020f76 100644
+--- a/drivers/phy/freescale/Kconfig
++++ b/drivers/phy/freescale/Kconfig
+@@ -14,3 +14,12 @@ config PHY_MIXEL_MIPI_DPHY
+ help
+ Enable this to add support for the Mixel DSI PHY as found
+ on NXP's i.MX8 family of SOCs.
++
++config PHY_FSL_IMX8M_PCIE
++ tristate "Freescale i.MX8 PCIE PHY"
++ depends on OF && HAS_IOMEM
++ select GENERIC_PHY
++ default ARCH_MXC && ARM64
++ help
++ Enable this to add support for the PCIE PHY as found on
++ i.MX8M family of SOCs.
+diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile
+index 1d02e3869b45..55d07c742ab0 100644
+--- a/drivers/phy/freescale/Makefile
++++ b/drivers/phy/freescale/Makefile
+@@ -1,3 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o
+ obj-$(CONFIG_PHY_MIXEL_MIPI_DPHY) += phy-fsl-imx8-mipi-dphy.o
++obj-$(CONFIG_PHY_FSL_IMX8M_PCIE) += phy-fsl-imx8m-pcie.o
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+new file mode 100644
+index 000000000000..003f575b36f0
+--- /dev/null
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -0,0 +1,233 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright 2021 NXP
++ */
++
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/delay.h>
++#include <linux/mfd/syscon.h>
++#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
++#include <linux/module.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++#include <dt-bindings/phy/phy-imx8-pcie.h>
++
++#define IMX8MM_PCIE_PHY_CMN_REG061 0x184
++#define ANA_PLL_CLK_OUT_TO_EXT_IO_EN BIT(0)
++#define IMX8MM_PCIE_PHY_CMN_REG062 0x188
++#define ANA_PLL_CLK_OUT_TO_EXT_IO_SEL BIT(3)
++#define IMX8MM_PCIE_PHY_CMN_REG063 0x18C
++#define AUX_PLL_REFCLK_SEL_SYS_PLL GENMASK(7, 6)
++#define IMX8MM_PCIE_PHY_CMN_REG064 0x190
++#define ANA_AUX_RX_TX_SEL_TX BIT(7)
++#define ANA_AUX_RX_TERM_GND_EN BIT(3)
++#define ANA_AUX_TX_TERM BIT(2)
++#define IMX8MM_PCIE_PHY_CMN_REG065 0x194
++#define ANA_AUX_RX_TERM (BIT(7) | BIT(4))
++#define ANA_AUX_TX_LVL GENMASK(3, 0)
++#define IMX8MM_PCIE_PHY_CMN_REG75 0x1D4
++#define PCIE_PHY_CMN_REG75_PLL_DONE 0x3
++#define PCIE_PHY_TRSV_REG5 0x414
++#define PCIE_PHY_TRSV_REG5_GEN1_DEEMP 0x2D
++#define PCIE_PHY_TRSV_REG6 0x418
++#define PCIE_PHY_TRSV_REG6_GEN2_DEEMP 0xF
++
++#define IMX8MM_GPR_PCIE_REF_CLK_SEL GENMASK(25, 24)
++#define IMX8MM_GPR_PCIE_REF_CLK_PLL FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3)
++#define IMX8MM_GPR_PCIE_REF_CLK_EXT FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x2)
++#define IMX8MM_GPR_PCIE_AUX_EN BIT(19)
++#define IMX8MM_GPR_PCIE_CMN_RST BIT(18)
++#define IMX8MM_GPR_PCIE_POWER_OFF BIT(17)
++#define IMX8MM_GPR_PCIE_SSC_EN BIT(16)
++#define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE BIT(9)
++
++struct imx8_pcie_phy {
++ void __iomem *base;
++ struct clk *clk;
++ struct phy *phy;
++ struct regmap *iomuxc_gpr;
++ struct reset_control *reset;
++ u32 refclk_pad_mode;
++ u32 tx_deemph_gen1;
++ u32 tx_deemph_gen2;
++ bool clkreq_unused;
++};
++
++static int imx8_pcie_phy_init(struct phy *phy)
++{
++ int ret;
++ u32 val, pad_mode;
++ struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++ reset_control_assert(imx8_phy->reset);
++
++ pad_mode = imx8_phy->refclk_pad_mode;
++ /* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */
++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++ IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE,
++ imx8_phy->clkreq_unused ?
++ 0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE);
++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++ IMX8MM_GPR_PCIE_AUX_EN,
++ IMX8MM_GPR_PCIE_AUX_EN);
++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++ IMX8MM_GPR_PCIE_POWER_OFF, 0);
++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++ IMX8MM_GPR_PCIE_SSC_EN, 0);
++
++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++ IMX8MM_GPR_PCIE_REF_CLK_SEL,
++ pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ?
++ IMX8MM_GPR_PCIE_REF_CLK_EXT :
++ IMX8MM_GPR_PCIE_REF_CLK_PLL);
++ usleep_range(100, 200);
++
++ /* Do the PHY common block reset */
++ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
++ IMX8MM_GPR_PCIE_CMN_RST,
++ IMX8MM_GPR_PCIE_CMN_RST);
++ usleep_range(200, 500);
++
++
++ if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
++ /* Configure the pad as input */
++ val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++ writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++ } else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
++ /* Configure the PHY to output the refclock via pad */
++ writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++ writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
++ writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
++ val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
++ writel(val | ANA_AUX_RX_TERM_GND_EN,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
++ writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
++ }
++
++ /* Tune PHY de-emphasis setting to pass PCIe compliance. */
++ writel(imx8_phy->tx_deemph_gen1, imx8_phy->base + PCIE_PHY_TRSV_REG5);
++ writel(imx8_phy->tx_deemph_gen2, imx8_phy->base + PCIE_PHY_TRSV_REG6);
++
++ reset_control_deassert(imx8_phy->reset);
++
++ /* Polling to check the phy is ready or not. */
++ ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
++ val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
++ 10, 20000);
++ return ret;
++}
++
++static int imx8_pcie_phy_power_on(struct phy *phy)
++{
++ struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++ return clk_prepare_enable(imx8_phy->clk);
++}
++
++static int imx8_pcie_phy_power_off(struct phy *phy)
++{
++ struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++ clk_disable_unprepare(imx8_phy->clk);
++
++ return 0;
++}
++
++static const struct phy_ops imx8_pcie_phy_ops = {
++ .init = imx8_pcie_phy_init,
++ .power_on = imx8_pcie_phy_power_on,
++ .power_off = imx8_pcie_phy_power_off,
++ .owner = THIS_MODULE,
++};
++
++static int imx8_pcie_phy_probe(struct platform_device *pdev)
++{
++ struct phy_provider *phy_provider;
++ struct device *dev = &pdev->dev;
++ struct device_node *np = dev->of_node;
++ struct imx8_pcie_phy *imx8_phy;
++ struct resource *res;
++
++ imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
++ if (!imx8_phy)
++ return -ENOMEM;
++
++ /* get PHY refclk pad mode */
++ of_property_read_u32(np, "fsl,refclk-pad-mode",
++ &imx8_phy->refclk_pad_mode);
++
++ if (of_property_read_u32(np, "fsl,tx-deemph-gen1",
++ &imx8_phy->tx_deemph_gen1))
++ imx8_phy->tx_deemph_gen1 = 0;
++
++ if (of_property_read_u32(np, "fsl,tx-deemph-gen2",
++ &imx8_phy->tx_deemph_gen2))
++ imx8_phy->tx_deemph_gen2 = 0;
++
++ if (of_property_read_bool(np, "fsl,clkreq-unsupported"))
++ imx8_phy->clkreq_unused = true;
++ else
++ imx8_phy->clkreq_unused = false;
++
++ imx8_phy->clk = devm_clk_get(dev, "ref");
++ if (IS_ERR(imx8_phy->clk)) {
++ dev_err(dev, "failed to get imx pcie phy clock\n");
++ return PTR_ERR(imx8_phy->clk);
++ }
++
++ /* Grab GPR config register range */
++ imx8_phy->iomuxc_gpr =
++ syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
++ if (IS_ERR(imx8_phy->iomuxc_gpr)) {
++ dev_err(dev, "unable to find iomuxc registers\n");
++ return PTR_ERR(imx8_phy->iomuxc_gpr);
++ }
++
++ imx8_phy->reset = devm_reset_control_get_exclusive(dev, "pciephy");
++ if (IS_ERR(imx8_phy->reset)) {
++ dev_err(dev, "Failed to get PCIEPHY reset control\n");
++ return PTR_ERR(imx8_phy->reset);
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ imx8_phy->base = devm_ioremap_resource(dev, res);
++ if (IS_ERR(imx8_phy->base))
++ return PTR_ERR(imx8_phy->base);
++
++ imx8_phy->phy = devm_phy_create(dev, NULL, &imx8_pcie_phy_ops);
++ if (IS_ERR(imx8_phy->phy))
++ return PTR_ERR(imx8_phy->phy);
++
++ phy_set_drvdata(imx8_phy->phy, imx8_phy);
++
++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
++
++ return PTR_ERR_OR_ZERO(phy_provider);
++}
++
++static const struct of_device_id imx8_pcie_phy_of_match[] = {
++ {.compatible = "fsl,imx8mm-pcie-phy",},
++ { },
++};
++MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
++
++static struct platform_driver imx8_pcie_phy_driver = {
++ .probe = imx8_pcie_phy_probe,
++ .driver = {
++ .name = "imx8-pcie-phy",
++ .of_match_table = imx8_pcie_phy_of_match,
++ }
++};
++module_platform_driver(imx8_pcie_phy_driver);
++
++MODULE_DESCRIPTION("FSL IMX8 PCIE PHY driver");
++MODULE_LICENSE("GPL");
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch b/target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch
new file mode 100644
index 000000000000..de484006f77e
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0012-phy-freescale-imx8m-pcie-Add-iMX8MP-PCIe-PHY-support.patch
@@ -0,0 +1,305 @@
+From c34c47978eed63a520915fb7e45ef34fe5a551e7 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu at nxp.com>
+Date: Mon, 7 Mar 2022 17:07:30 +0800
+Subject: [PATCH 12/17] phy: freescale: imx8m-pcie: Add iMX8MP PCIe PHY support
+
+Add the i.MX8MP PCIe PHY support
+
+Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
+---
+ drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 202 +++++++++++++++++----
+ 1 file changed, 163 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+index 003f575b36f0..0b9d006a983b 100644
+--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -10,6 +10,8 @@
+ #include <linux/mfd/syscon.h>
+ #include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
+ #include <linux/module.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
+ #include <linux/phy/phy.h>
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+@@ -29,12 +31,10 @@
+ #define IMX8MM_PCIE_PHY_CMN_REG065 0x194
+ #define ANA_AUX_RX_TERM (BIT(7) | BIT(4))
+ #define ANA_AUX_TX_LVL GENMASK(3, 0)
+-#define IMX8MM_PCIE_PHY_CMN_REG75 0x1D4
+-#define PCIE_PHY_CMN_REG75_PLL_DONE 0x3
++#define IMX8MM_PCIE_PHY_CMN_REG075 0x1D4
++#define ANA_PLL_DONE 0x3
+ #define PCIE_PHY_TRSV_REG5 0x414
+-#define PCIE_PHY_TRSV_REG5_GEN1_DEEMP 0x2D
+ #define PCIE_PHY_TRSV_REG6 0x418
+-#define PCIE_PHY_TRSV_REG6_GEN2_DEEMP 0xF
+
+ #define IMX8MM_GPR_PCIE_REF_CLK_SEL GENMASK(25, 24)
+ #define IMX8MM_GPR_PCIE_REF_CLK_PLL FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3)
+@@ -45,16 +45,43 @@
+ #define IMX8MM_GPR_PCIE_SSC_EN BIT(16)
+ #define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE BIT(9)
+
++#define IMX8MP_GPR_REG0 0x0
++#define IMX8MP_GPR_CLK_MOD_EN BIT(0)
++#define IMX8MP_GPR_PHY_APB_RST BIT(4)
++#define IMX8MP_GPR_PHY_INIT_RST BIT(5)
++#define IMX8MP_GPR_REG1 0x4
++#define IMX8MP_GPR_PM_EN_CORE_CLK BIT(0)
++#define IMX8MP_GPR_PLL_LOCK BIT(13)
++#define IMX8MP_GPR_REG2 0x8
++#define IMX8MP_GPR_P_PLL_MASK GENMASK(5, 0)
++#define IMX8MP_GPR_M_PLL_MASK GENMASK(15, 6)
++#define IMX8MP_GPR_S_PLL_MASK GENMASK(18, 16)
++#define IMX8MP_GPR_P_PLL (0xc << 0)
++#define IMX8MP_GPR_M_PLL (0x320 << 6)
++#define IMX8MP_GPR_S_PLL (0x4 << 16)
++#define IMX8MP_GPR_REG3 0xc
++#define IMX8MP_GPR_PLL_CKE BIT(17)
++#define IMX8MP_GPR_PLL_RST BIT(31)
++
++enum imx8_pcie_phy_type {
++ IMX8MM,
++ IMX8MP,
++};
++
+ struct imx8_pcie_phy {
+ void __iomem *base;
++ struct device *dev;
+ struct clk *clk;
+ struct phy *phy;
++ struct regmap *hsio_blk_ctrl;
+ struct regmap *iomuxc_gpr;
+ struct reset_control *reset;
++ struct reset_control *perst;
+ u32 refclk_pad_mode;
+ u32 tx_deemph_gen1;
+ u32 tx_deemph_gen2;
+ bool clkreq_unused;
++ enum imx8_pcie_phy_type variant;
+ };
+
+ static int imx8_pcie_phy_init(struct phy *phy)
+@@ -66,6 +93,87 @@ static int imx8_pcie_phy_init(struct phy *phy)
+ reset_control_assert(imx8_phy->reset);
+
+ pad_mode = imx8_phy->refclk_pad_mode;
++ switch (imx8_phy->variant) {
++ case IMX8MM:
++ /* Tune PHY de-emphasis setting to pass PCIe compliance. */
++ if (imx8_phy->tx_deemph_gen1)
++ writel(imx8_phy->tx_deemph_gen1,
++ imx8_phy->base + PCIE_PHY_TRSV_REG5);
++ if (imx8_phy->tx_deemph_gen2)
++ writel(imx8_phy->tx_deemph_gen2,
++ imx8_phy->base + PCIE_PHY_TRSV_REG6);
++ break;
++ case IMX8MP:
++ reset_control_assert(imx8_phy->perst);
++ /* Set P=12,M=800,S=4 and must set ICP=2'b01. */
++ regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG2,
++ IMX8MP_GPR_P_PLL_MASK |
++ IMX8MP_GPR_M_PLL_MASK |
++ IMX8MP_GPR_S_PLL_MASK,
++ IMX8MP_GPR_P_PLL |
++ IMX8MP_GPR_M_PLL |
++ IMX8MP_GPR_S_PLL);
++ /* wait greater than 1/F_FREF =1/2MHZ=0.5us */
++ udelay(1);
++
++ regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG3,
++ IMX8MP_GPR_PLL_RST,
++ IMX8MP_GPR_PLL_RST);
++ udelay(10);
++
++ /* Set 1 to pll_cke of GPR_REG3 */
++ regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG3,
++ IMX8MP_GPR_PLL_CKE,
++ IMX8MP_GPR_PLL_CKE);
++
++ /* Lock time should be greater than 300cycle=300*0.5us=150us */
++ ret = regmap_read_poll_timeout(imx8_phy->hsio_blk_ctrl,
++ IMX8MP_GPR_REG1, val,
++ val & IMX8MP_GPR_PLL_LOCK,
++ 10, 1000);
++ if (ret) {
++ dev_err(imx8_phy->dev, "PCIe PLL lock timeout\n");
++ return ret;
++ }
++
++ /* pcie_clock_module_en */
++ regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG0,
++ IMX8MP_GPR_CLK_MOD_EN,
++ IMX8MP_GPR_CLK_MOD_EN);
++ udelay(10);
++
++ reset_control_deassert(imx8_phy->reset);
++ reset_control_deassert(imx8_phy->perst);
++
++ /* release pcie_phy_apb_reset and pcie_phy_init_resetn */
++ regmap_update_bits(imx8_phy->hsio_blk_ctrl, IMX8MP_GPR_REG0,
++ IMX8MP_GPR_PHY_APB_RST |
++ IMX8MP_GPR_PHY_INIT_RST,
++ IMX8MP_GPR_PHY_APB_RST |
++ IMX8MP_GPR_PHY_INIT_RST);
++ break;
++ }
++
++ if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
++ /* Configure the pad as input */
++ val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++ writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++ } else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
++ /* Configure the PHY to output the refclock via pad */
++ writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
++ writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
++ writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
++ val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
++ writel(val | ANA_AUX_RX_TERM_GND_EN,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
++ writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
++ }
++
+ /* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */
+ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
+ IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE,
+@@ -90,39 +198,30 @@ static int imx8_pcie_phy_init(struct phy *phy)
+ regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14,
+ IMX8MM_GPR_PCIE_CMN_RST,
+ IMX8MM_GPR_PCIE_CMN_RST);
+- usleep_range(200, 500);
+
+-
+- if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT) {
+- /* Configure the pad as input */
+- val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+- writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+- } else if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT) {
+- /* Configure the PHY to output the refclock via pad */
+- writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061);
+- writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
+- writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
+- val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
+- writel(val | ANA_AUX_RX_TERM_GND_EN,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
+- writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065);
++ switch (imx8_phy->variant) {
++ case IMX8MM:
++ reset_control_deassert(imx8_phy->reset);
++ usleep_range(200, 500);
++ break;
++
++ case IMX8MP:
++ /* wait for core_clk enabled */
++ ret = regmap_read_poll_timeout(imx8_phy->hsio_blk_ctrl,
++ IMX8MP_GPR_REG1, val,
++ val & IMX8MP_GPR_PM_EN_CORE_CLK,
++ 10, 20000);
++ if (ret) {
++ dev_err(imx8_phy->dev, "PCIe CORE CLK enable failed\n");
++ return ret;
++ }
++
++ break;
+ }
+
+- /* Tune PHY de-emphasis setting to pass PCIe compliance. */
+- writel(imx8_phy->tx_deemph_gen1, imx8_phy->base + PCIE_PHY_TRSV_REG5);
+- writel(imx8_phy->tx_deemph_gen2, imx8_phy->base + PCIE_PHY_TRSV_REG6);
+-
+- reset_control_deassert(imx8_phy->reset);
+-
+ /* Polling to check the phy is ready or not. */
+- ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG75,
+- val, val == PCIE_PHY_CMN_REG75_PLL_DONE,
+- 10, 20000);
++ ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075,
++ val, val == ANA_PLL_DONE, 10, 20000);
+ return ret;
+ }
+
+@@ -149,18 +248,33 @@ static const struct phy_ops imx8_pcie_phy_ops = {
+ .owner = THIS_MODULE,
+ };
+
++static const struct of_device_id imx8_pcie_phy_of_match[] = {
++ {.compatible = "fsl,imx8mm-pcie-phy", .data = (void *)IMX8MM},
++ {.compatible = "fsl,imx8mp-pcie-phy", .data = (void *)IMX8MP},
++ { },
++};
++MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
++
+ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+ {
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
++ const struct of_device_id *of_id;
+ struct device_node *np = dev->of_node;
+ struct imx8_pcie_phy *imx8_phy;
+ struct resource *res;
+
++ of_id = of_match_device(imx8_pcie_phy_of_match, dev);
++ if (!of_id)
++ return -EINVAL;
++
+ imx8_phy = devm_kzalloc(dev, sizeof(*imx8_phy), GFP_KERNEL);
+ if (!imx8_phy)
+ return -ENOMEM;
+
++ imx8_phy->dev = dev;
++ imx8_phy->variant = (enum imx8_pcie_phy_type)of_id->data;
++
+ /* get PHY refclk pad mode */
+ of_property_read_u32(np, "fsl,refclk-pad-mode",
+ &imx8_phy->refclk_pad_mode);
+@@ -197,6 +311,22 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+ dev_err(dev, "Failed to get PCIEPHY reset control\n");
+ return PTR_ERR(imx8_phy->reset);
+ }
++ if (imx8_phy->variant == IMX8MP) {
++ /* Grab HSIO MIX config register range */
++ imx8_phy->hsio_blk_ctrl =
++ syscon_regmap_lookup_by_compatible("fsl,imx8mp-hsio-blk-ctrl");
++ if (IS_ERR(imx8_phy->hsio_blk_ctrl)) {
++ dev_err(dev, "unable to find hsio mix registers\n");
++ return PTR_ERR(imx8_phy->hsio_blk_ctrl);
++ }
++
++ imx8_phy->perst =
++ devm_reset_control_get_exclusive(dev, "perst");
++ if (IS_ERR(imx8_phy->perst)) {
++ dev_err(dev, "Failed to get PCIEPHY perst control\n");
++ return PTR_ERR(imx8_phy->perst);
++ }
++ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ imx8_phy->base = devm_ioremap_resource(dev, res);
+@@ -214,12 +344,6 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+ return PTR_ERR_OR_ZERO(phy_provider);
+ }
+
+-static const struct of_device_id imx8_pcie_phy_of_match[] = {
+- {.compatible = "fsl,imx8mm-pcie-phy",},
+- { },
+-};
+-MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
+-
+ static struct platform_driver imx8_pcie_phy_driver = {
+ .probe = imx8_pcie_phy_probe,
+ .driver = {
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch b/target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch
new file mode 100644
index 000000000000..f0989b205ee9
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0013-dt-bindings-phy-phy-imx8-pcie-Add-binding-for-the-pa.patch
@@ -0,0 +1,38 @@
+From 9870dee7766a6b646cc59675b66ed1f70b1c33d4 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu at nxp.com>
+Date: Thu, 28 Oct 2021 15:27:10 +0800
+Subject: [PATCH 13/17] dt-bindings: phy: phy-imx8-pcie: Add binding for the
+ pad modes of imx8 pcie phy
+
+Add binding for reference clock PAD modes of the i.MX8 PCIe PHY.
+
+Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
+---
+ include/dt-bindings/phy/phy-imx8-pcie.h | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+ create mode 100644 include/dt-bindings/phy/phy-imx8-pcie.h
+
+diff --git a/include/dt-bindings/phy/phy-imx8-pcie.h b/include/dt-bindings/phy/phy-imx8-pcie.h
+new file mode 100644
+index 000000000000..8bbe2d6538d8
+--- /dev/null
++++ b/include/dt-bindings/phy/phy-imx8-pcie.h
+@@ -0,0 +1,14 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
++/*
++ * This header provides constants for i.MX8 PCIe.
++ */
++
++#ifndef _DT_BINDINGS_IMX8_PCIE_H
++#define _DT_BINDINGS_IMX8_PCIE_H
++
++/* Reference clock PAD mode */
++#define IMX8_PCIE_REFCLK_PAD_UNUSED 0
++#define IMX8_PCIE_REFCLK_PAD_INPUT 1
++#define IMX8_PCIE_REFCLK_PAD_OUTPUT 2
++
++#endif /* _DT_BINDINGS_IMX8_PCIE_H */
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch b/target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch
new file mode 100644
index 000000000000..1d53a9224238
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0014-PCI-imx-Add-the-imx8mm-pcie-support.patch
@@ -0,0 +1,211 @@
+From cfde3f23ce2fb5a1a1f9d1f841af67110ecefede Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu at nxp.com>
+Date: Thu, 28 Oct 2021 15:27:17 +0800
+Subject: [PATCH 14/17] PCI: imx: Add the imx8mm pcie support
+
+i.MX8MM PCIe works mostly like the i.MX8MQ one, but has a different PHY
+and allows to output the internal PHY reference clock via the refclk pad.
+Add the i.MX8MM PCIe support based on the standalone PHY driver.
+
+Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
+---
+ drivers/pci/controller/dwc/pci-imx6.c | 73 ++++++++++++++++++++++++---
+ 1 file changed, 66 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
+index 67dbf9d88d22..8cc016cea3c4 100644
+--- a/drivers/pci/controller/dwc/pci-imx6.c
++++ b/drivers/pci/controller/dwc/pci-imx6.c
+@@ -29,6 +29,7 @@
+ #include <linux/types.h>
+ #include <linux/interrupt.h>
+ #include <linux/reset.h>
++#include <linux/phy/phy.h>
+ #include <linux/pm_domain.h>
+ #include <linux/pm_runtime.h>
+
+@@ -49,6 +50,7 @@ enum imx6_pcie_variants {
+ IMX6QP,
+ IMX7D,
+ IMX8MQ,
++ IMX8MM,
+ };
+
+ #define IMX6_PCIE_FLAG_IMX6_PHY BIT(0)
+@@ -88,6 +90,7 @@ struct imx6_pcie {
+ struct device *pd_pcie;
+ /* power domain for pcie phy */
+ struct device *pd_pcie_phy;
++ struct phy *phy;
+ const struct imx6_pcie_drvdata *drvdata;
+ };
+
+@@ -372,6 +375,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
+ case IMX7D:
+ case IMX8MQ:
+ reset_control_assert(imx6_pcie->pciephy_reset);
++ fallthrough;
++ case IMX8MM:
+ reset_control_assert(imx6_pcie->apps_reset);
+ break;
+ case IMX6SX:
+@@ -412,7 +417,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
+
+ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
+ {
+- WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ);
++ WARN_ON(imx6_pcie->drvdata->variant != IMX8MQ &&
++ imx6_pcie->drvdata->variant != IMX8MM);
+ return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;
+ }
+
+@@ -451,6 +457,13 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
+ break;
+ case IMX7D:
+ break;
++ case IMX8MM:
++ ret = clk_prepare_enable(imx6_pcie->pcie_aux);
++ if (ret) {
++ dev_err(dev, "unable to enable pcie_aux clock\n");
++ break;
++ }
++ break;
+ case IMX8MQ:
+ ret = clk_prepare_enable(imx6_pcie->pcie_aux);
+ if (ret) {
+@@ -527,6 +540,14 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
+ goto err_ref_clk;
+ }
+
++ switch (imx6_pcie->drvdata->variant) {
++ case IMX8MM:
++ if (phy_power_on(imx6_pcie->phy))
++ dev_err(dev, "unable to power on PHY\n");
++ break;
++ default:
++ break;
++ }
+ /* allow the clocks to stabilize */
+ usleep_range(200, 500);
+
+@@ -534,6 +555,10 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
+ case IMX8MQ:
+ reset_control_deassert(imx6_pcie->pciephy_reset);
+ break;
++ case IMX8MM:
++ if (phy_init(imx6_pcie->phy) != 0)
++ dev_err(dev, "Waiting for PHY ready timeout!\n");
++ break;
+ case IMX7D:
+ reset_control_deassert(imx6_pcie->pciephy_reset);
+
+@@ -619,6 +644,8 @@ static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
+ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+ {
+ switch (imx6_pcie->drvdata->variant) {
++ case IMX8MM:
++ break;
+ case IMX8MQ:
+ /*
+ * TODO: Currently this code assumes external
+@@ -758,6 +785,7 @@ static void imx6_pcie_ltssm_enable(struct device *dev)
+ break;
+ case IMX7D:
+ case IMX8MQ:
++ case IMX8MM:
+ reset_control_deassert(imx6_pcie->apps_reset);
+ break;
+ }
+@@ -870,6 +898,7 @@ static void imx6_pcie_ltssm_disable(struct device *dev)
+ IMX6Q_GPR12_PCIE_CTL_2, 0);
+ break;
+ case IMX7D:
++ case IMX8MM:
+ reset_control_assert(imx6_pcie->apps_reset);
+ break;
+ default:
+@@ -929,6 +958,7 @@ static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
+ IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
+ break;
+ case IMX8MQ:
++ case IMX8MM:
+ clk_disable_unprepare(imx6_pcie->pcie_aux);
+ break;
+ default:
+@@ -1042,11 +1072,6 @@ static int imx6_pcie_probe(struct platform_device *pdev)
+ }
+
+ /* Fetch clocks */
+- imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
+- if (IS_ERR(imx6_pcie->pcie_phy))
+- return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy),
+- "pcie_phy clock source missing or invalid\n");
+-
+ imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
+ if (IS_ERR(imx6_pcie->pcie_bus))
+ return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus),
+@@ -1088,10 +1113,39 @@ static int imx6_pcie_probe(struct platform_device *pdev)
+ dev_err(dev, "Failed to get PCIE APPS reset control\n");
+ return PTR_ERR(imx6_pcie->apps_reset);
+ }
++ break;
++ case IMX8MM:
++ imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux");
++ if (IS_ERR(imx6_pcie->pcie_aux))
++ return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux),
++ "pcie_aux clock source missing or invalid\n");
++ imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
++ "apps");
++ if (IS_ERR(imx6_pcie->apps_reset)) {
++ dev_err(dev, "Failed to get PCIE APPS reset control\n");
++ return PTR_ERR(imx6_pcie->apps_reset);
++ }
++
++ imx6_pcie->phy = devm_phy_get(dev, "pcie-phy");
++ if (IS_ERR(imx6_pcie->phy)) {
++ if (PTR_ERR(imx6_pcie->phy) == -EPROBE_DEFER)
++ return -EPROBE_DEFER;
++ dev_err(dev, "Failed to get PCIE PHY\n");
++ return PTR_ERR(imx6_pcie->phy);
++ }
++
+ break;
+ default:
+ break;
+ }
++ /* Don't fetch the pcie_phy clock, if it has abstract PHY driver */
++ if (imx6_pcie->phy == NULL) {
++ imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
++ if (IS_ERR(imx6_pcie->pcie_phy))
++ return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy),
++ "pcie_phy clock source missing or invalid\n");
++ }
++
+
+ /* Grab turnoff reset */
+ imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
+@@ -1201,6 +1255,10 @@ static const struct imx6_pcie_drvdata drvdata[] = {
+ [IMX8MQ] = {
+ .variant = IMX8MQ,
+ },
++ [IMX8MM] = {
++ .variant = IMX8MM,
++ .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
++ },
+ };
+
+ static const struct of_device_id imx6_pcie_of_match[] = {
+@@ -1208,7 +1266,8 @@ static const struct of_device_id imx6_pcie_of_match[] = {
+ { .compatible = "fsl,imx6sx-pcie", .data = &drvdata[IMX6SX], },
+ { .compatible = "fsl,imx6qp-pcie", .data = &drvdata[IMX6QP], },
+ { .compatible = "fsl,imx7d-pcie", .data = &drvdata[IMX7D], },
+- { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], } ,
++ { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
++ { .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
+ {},
+ };
+
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch b/target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch
new file mode 100644
index 000000000000..0b2a1be05c58
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0015-arm64-dts-imx8mm-Add-the-pcie-phy-support.patch
@@ -0,0 +1,40 @@
+From c488e4b57b69682cf4adb7809d5482165984acc6 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu at nxp.com>
+Date: Thu, 28 Oct 2021 15:27:13 +0800
+Subject: [PATCH 15/17] arm64: dts: imx8mm: Add the pcie phy support
+
+Add the PCIe PHY support on iMX8MM platforms.
+
+Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler at 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 at 32e50200 {
+ reg = <0x32e50200 0x200>;
+ };
+
++ pcie_phy: pcie-phy at 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 at 33000000 {
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch b/target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch
new file mode 100644
index 000000000000..74156015624a
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0016-arm64-dts-imx8mm-Add-the-pcie-support.patch
@@ -0,0 +1,67 @@
+From 527ed85dbb8b89dced54f207cc181062e327f3f8 Mon Sep 17 00:00:00 2001
+From: Richard Zhu <hongxing.zhu at nxp.com>
+Date: Thu, 28 Oct 2021 15:27:15 +0800
+Subject: [PATCH 16/17] arm64: dts: imx8mm: Add the pcie support
+
+Add the PCIe support on i.MX8MM platforms.
+
+Signed-off-by: Richard Zhu <hongxing.zhu at nxp.com>
+Tested-by: Marcel Ziswiler <marcel.ziswiler at 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 at 30330000 {
+ };
+
+ gpr: iomuxc-gpr at 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 at 33002000 {
+ status = "disabled";
+ };
+
++ pcie0: pcie at 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 at 38800000 {
+ compatible = "arm,gic-v3";
+ reg = <0x38800000 0x10000>, /* GIC Dist */
+--
+2.25.1
+
diff --git a/target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch b/target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch
new file mode 100644
index 000000000000..7d873280f848
--- /dev/null
+++ b/target/linux/imx/patches-5.15/0017-arm64-dts-imx8mm-venice-add-PCIe-support.patch
@@ -0,0 +1,437 @@
+From d44610e534d7c978e782b1ba0a5bdb065b4fa3bb Mon Sep 17 00:00:00 2001
+From: Tim Harvey <tharvey at gateworks.com>
+Date: Wed, 13 Jan 2021 14:05:03 -0800
+Subject: [PATCH 17/17] arm64: dts: imx8mm-venice*: add PCIe support
+
+Add PCIe support to GW71xx/GW72xx/GW73xx/GW7901/GW7902
+
+Signed-off-by: Tim Harvey <tharvey at 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 = ð1;
+ 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 at 0,0 {
++ reg = <0x0000 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pcie at 1,0 {
++ reg = <0x0000 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pcie at 2,3 {
++ reg = <0x1800 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ eth1: pcie at 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 = ð1;
+ 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 at 0,0 {
++ reg = <0x0000 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pcie at 1,0 {
++ reg = <0x0000 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pcie at 2,4 {
++ reg = <0x2000 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ eth1: pcie at 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 = ð1;
+ 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 at 0,0 {
++ reg = <0x0000 0 0 0 0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ eth1: pcie at 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
More information about the openwrt-devel
mailing list