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 = ð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@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 = ð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@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 = ð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@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