From d6fef27f2dd4a852ed7846e4aa5f06dcd8df91b6 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 22 May 2023 22:58:58 +0100 Subject: [PATCH 01/43] mediatek: mt7623: build SD card without all filesystems Allow building SD card images without having both initramfs and squashfs present on the card, just like it has already been done for the mt7622 and filogic subtargets. Signed-off-by: Daniel Golle --- target/linux/mediatek/image/mt7623.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/target/linux/mediatek/image/mt7623.mk b/target/linux/mediatek/image/mt7623.mk index 26befc1c1e5..1645ecd5450 100644 --- a/target/linux/mediatek/image/mt7623.mk +++ b/target/linux/mediatek/image/mt7623.mk @@ -104,8 +104,12 @@ define Device/bananapi_bpi-r2 pad-to 2k | append-preloader $$(UBOOT_TARGET) |\ pad-to $$(UBOOT_OFFSET) | append-bootloader $$(UBOOT_TARGET) |\ pad-to 4092k | mt7623-mbr emmc |\ + $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),\ pad-to 4M | append-image-stage initramfs-recovery.itb |\ + ) \ + $(if $(CONFIG_TARGET_ROOTFS_SQUASHFS),\ pad-to 48M | append-image squashfs-sysupgrade.itb |\ + ) \ gzip ARTIFACTS := u-boot.bin preloader.bin sdcard.img.gz SUPPORTED_DEVICES := bananapi,bpi-r2 @@ -135,8 +139,12 @@ define Device/unielec_u7623-02 # but OpenWrt expects 'SDMM' magic for sysupgrade. ARTIFACT/emmc.img.gz := mt7623-mbr sdmmc |\ pad-to $$(UBOOT_OFFSET) | append-bootloader $$(UBOOT_TARGET) |\ + $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),\ pad-to 4M | append-image-stage initramfs-recovery.itb |\ + ) \ + $(if $(CONFIG_TARGET_ROOTFS_SQUASHFS),\ pad-to 48M | append-image squashfs-sysupgrade.itb |\ + ) \ gzip | append-metadata ARTIFACT/scatter.txt := scatterfile emmc.img.gz ARTIFACTS := u-boot.bin scatter.txt emmc.img.gz From bc4ba54a09927e98752a3e38199c728a3e7f40d2 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 23 May 2023 13:29:49 +0200 Subject: [PATCH 02/43] mac80211: backport merged version of A-MSDU mesh patch Kernel 6.1 now has fortify_memcpy_chk() and it is causing the following warning while trying to compile backports: CC [M] /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/net/wireless/util.o In file included from ./include/linux/string.h:253, from /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/backport-include/linux/string.h:3, from ./include/linux/bitmap.h:11, from ./include/linux/cpumask.h:12, from ./include/linux/smp.h:13, from ./arch/arm64/include/asm/arch_timer.h:18, from ./arch/arm64/include/asm/timex.h:8, from ./include/linux/timex.h:67, from ./include/linux/time32.h:13, from ./include/linux/time.h:60, from /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/backport-include/linux/time.h:3, from ./include/linux/skbuff.h:15, from /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/backport-include/linux/skbuff.h:3, from ./include/linux/if_ether.h:19, from /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/backport-include/linux/if_ether.h:3, from ./include/linux/etherdevice.h:20, from /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/backport-include/linux/etherdevice.h:3, from /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/net/wireless/util.c:12: In function 'fortify_memcpy_chk', inlined from 'ieee80211_strip_8023_mesh_hdr' at /home/robimarko/Building/AX3600/ipq807x-5.15/build_dir/target-aarch64_cortex-a53_musl/linux-ipq807x_generic/backports-6.1.24/net/wireless/util.c:590:3: ./include/linux/fortify-string.h:404:25: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning] 404 | __write_overflow_field(p_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors This issue was fixed in the final version of ("wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces") that was merged upstream but we have a older version that is using: memcpy(&payload.eth.h_dest, mesh_addr, 2 * ETH_ALEN); instead of: memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN); So, lets just backport the merged version of patch to fix the issue. Signed-off-by: Robert Marko --- package/kernel/mac80211/Makefile | 2 +- ...211-fix-receiving-A-MSDU-frames-on-mesh-in.patch | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 248b48c3c15..a7472ee7794 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=6.1.24 -PKG_RELEASE:=3 +PKG_RELEASE:=4 # PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.58/ PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/ PKG_HASH:=5d39aca7e34c33cb9b3e366117b2e86841b7bdd37933679d6b1e61be6b150648 diff --git a/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch b/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch index 6aec9bc85fc..59b799b6b17 100644 --- a/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch +++ b/package/kernel/mac80211/patches/subsys/315-v6.3-wifi-mac80211-fix-receiving-A-MSDU-frames-on-mesh-in.patch @@ -1,5 +1,6 @@ +From 986e43b19ae9176093da35e0a844e65c8bf9ede7 Mon Sep 17 00:00:00 2001 From: Felix Fietkau -Date: Tue, 6 Dec 2022 11:15:02 +0100 +Date: Mon, 13 Feb 2023 11:08:54 +0100 Subject: [PATCH] wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces @@ -33,7 +34,15 @@ For locally received packets, the Mesh Control header is stripped away. For forwarded packets, a new 802.11 header gets added. Signed-off-by: Felix Fietkau +Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name +[fix fortify build error] +Signed-off-by: Johannes Berg --- + .../wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- + include/net/cfg80211.h | 27 +- + net/mac80211/rx.c | 350 ++++++++++-------- + net/wireless/util.c | 120 +++--- + 4 files changed, 297 insertions(+), 202 deletions(-) --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -557,7 +566,7 @@ Signed-off-by: Felix Fietkau + memcpy(&payload.eth.h_source, mesh_addr, ETH_ALEN); + break; + case MESH_FLAGS_AE_A5_A6: -+ memcpy(&payload.eth.h_dest, mesh_addr, 2 * ETH_ALEN); ++ memcpy(&payload.eth, mesh_addr, 2 * ETH_ALEN); + break; + default: + break; From 4f197f91342bc5e1f202c091c2c2f90e949d0749 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Mon, 22 May 2023 23:27:52 +0200 Subject: [PATCH 03/43] kernel: sort generic configuration This was done by executing these commands: $ ./scripts/kconfig.pl '+' target/linux/generic/config-5.15 /dev/null > target/linux/generic/config-5.15-new $ mv target/linux/generic/config-5.15-new target/linux/generic/config-5.15 $ ./scripts/kconfig.pl '+' target/linux/generic/config-6.1 /dev/null > target/linux/generic/config-6.1-new $ mv target/linux/generic/config-6.1-new target/linux/generic/config-6.1 Signed-off-by: Aleksander Jan Bajkowski --- target/linux/generic/config-5.15 | 2 +- target/linux/generic/config-6.1 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index f13af8ba268..d00080c72ec 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -7262,7 +7262,6 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HI556 is not set # CONFIG_VIDEO_I2C is not set -# CONFIG_VIDEO_IMX_PXP is not set # CONFIG_VIDEO_IMX208 is not set # CONFIG_VIDEO_IMX214 is not set # CONFIG_VIDEO_IMX219 is not set @@ -7276,6 +7275,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_IMX412 is not set # CONFIG_VIDEO_IMX477 is not set # CONFIG_VIDEO_IMX8_JPEG is not set +# CONFIG_VIDEO_IMX_PXP is not set # CONFIG_VIDEO_IRS1125 is not set # CONFIG_VIDEO_IR_I2C is not set # CONFIG_VIDEO_IVTV is not set diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 48485051cb9..408c2a9fc33 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -912,8 +912,8 @@ CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CEPH_FS is not set # CONFIG_CEPH_LIB is not set # CONFIG_CFG80211 is not set -CONFIG_CFG80211_HEADERS=y # CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_HEADERS=y # CONFIG_CGROUPS is not set # CONFIG_CGROUP_FAVOR_DYNMODS is not set # CONFIG_CGROUP_MISC is not set @@ -7450,7 +7450,6 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_HI846 is not set # CONFIG_VIDEO_HI847 is not set # CONFIG_VIDEO_I2C is not set -# CONFIG_VIDEO_IMX_PXP is not set # CONFIG_VIDEO_IMX208 is not set # CONFIG_VIDEO_IMX214 is not set # CONFIG_VIDEO_IMX219 is not set @@ -7464,6 +7463,7 @@ CONFIG_VHOST_MENU=y # CONFIG_VIDEO_IMX412 is not set # CONFIG_VIDEO_IMX477 is not set # CONFIG_VIDEO_IMX8_JPEG is not set +# CONFIG_VIDEO_IMX_PXP is not set # CONFIG_VIDEO_IRS1125 is not set # CONFIG_VIDEO_IR_I2C is not set # CONFIG_VIDEO_ISL7998X is not set From cec0a38adeee1779890c3267574a102f81c041a4 Mon Sep 17 00:00:00 2001 From: Aleksander Jan Bajkowski Date: Mon, 22 May 2023 23:29:02 +0200 Subject: [PATCH 04/43] kernel: add disabled symbol CONFIG_CPU_LITTLE_ENDIAN on 6.1 The identical change was previously added to the 5.15 kernel in the commit 9226f1e41948 ("kernel: disable CONFIG_CPU_LITTLE_ENDIAN in generic config"). Signed-off-by: Aleksander Jan Bajkowski --- target/linux/generic/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 408c2a9fc33..1b06116234b 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -1070,6 +1070,7 @@ CONFIG_CONSTRUCTORS=y # CONFIG_CPU_IDLE_GOV_TEO is not set # CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set # CONFIG_CPU_ISOLATION is not set +# CONFIG_CPU_LITTLE_ENDIAN is not set # CONFIG_CPU_NO_EFFICIENT_FFS is not set CONFIG_CPU_SW_DOMAIN_PAN=y # CONFIG_CPU_THERMAL is not set From 11bb5337b8d8b5018e48f0df415efb99e2f49d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Sun, 21 May 2023 18:43:53 +0200 Subject: [PATCH 05/43] Revert "feeds: use git-src-full to allow Git versioning" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This partially reverts commit 7fae1e5677e9bb4979c8d4ac99be4de6955b13d0 as it should be no longer necessary to do a full clone since commit 48ed07bc0b94 ("treewide: replace AUTORELEASE with real PKG_RELEASE"). Suggested-by: Thibaut VARÈNE Signed-off-by: Petr Štetiar --- feeds.conf.default | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/feeds.conf.default b/feeds.conf.default index 50ae67cb9db..fc679335e0e 100644 --- a/feeds.conf.default +++ b/feeds.conf.default @@ -1,8 +1,8 @@ -src-git-full packages https://git.openwrt.org/feed/packages.git -src-git-full luci https://git.openwrt.org/project/luci.git -src-git-full routing https://git.openwrt.org/feed/routing.git -src-git-full telephony https://git.openwrt.org/feed/telephony.git -#src-git-full video https://github.com/openwrt/video.git -#src-git-full targets https://github.com/openwrt/targets.git -#src-git-full oldpackages http://git.openwrt.org/packages.git +src-git packages https://git.openwrt.org/feed/packages.git +src-git luci https://git.openwrt.org/project/luci.git +src-git routing https://git.openwrt.org/feed/routing.git +src-git telephony https://git.openwrt.org/feed/telephony.git +#src-git video https://github.com/openwrt/video.git +#src-git targets https://github.com/openwrt/targets.git +#src-git oldpackages http://git.openwrt.org/packages.git #src-link custom /usr/src/openwrt/custom-feed From c2d194a34eb1a62a610f0437287db6c3eca64d5a Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Thu, 4 May 2023 19:17:35 -0700 Subject: [PATCH 06/43] kernel: enable (ARM|ARM64)_MODULE_PLTS in generic config This allows loading modules with large memory requirements, recently needed while testing on armvirt/32. Past forum discussions [1] and bug reports [2] also raised this and the ipq806x target already set it in response [3]. Given this increases kernel image size by only ~1KB, is generally useful on multi-platform kernels, and enabled by default on upstream arm32 Linux, add it to the generic config. The setting has similar utility on arm64, is a requirement for KASLR, and already enabled on most OpenWrt aarch64 targets, so pull this into the top-level generic config. [1]: https://forum.openwrt.org/t/vmap-allocation-for-size-442368-failed-use-vmalloc-size-to-increase-size/34545/7 [2]: https://github.com/openwrt/openwrt/issues/8282 [3]: f81e148eb6 ("ipq806x: update 4.19 kernel config"). Signed-off-by: Tony Ambardar --- target/linux/armvirt/64/config-5.15 | 1 - target/linux/bcm27xx/bcm2710/config-5.15 | 1 - target/linux/bcm27xx/bcm2711/config-5.15 | 1 - target/linux/generic/config-5.15 | 4 ++-- target/linux/generic/config-6.1 | 4 ++-- target/linux/ipq806x/config-5.15 | 1 - target/linux/ipq806x/config-6.1 | 1 - target/linux/layerscape/armv8_64b/config-5.15 | 1 - target/linux/mediatek/filogic/config-5.15 | 1 - target/linux/mediatek/mt7622/config-5.15 | 1 - target/linux/octeontx/config-5.15 | 1 - target/linux/rockchip/armv8/config-5.15 | 1 - 12 files changed, 4 insertions(+), 14 deletions(-) diff --git a/target/linux/armvirt/64/config-5.15 b/target/linux/armvirt/64/config-5.15 index 19ae3dc0cfa..eb5405eb1ef 100644 --- a/target/linux/armvirt/64/config-5.15 +++ b/target/linux/armvirt/64/config-5.15 @@ -23,7 +23,6 @@ CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/bcm27xx/bcm2710/config-5.15 b/target/linux/bcm27xx/bcm2710/config-5.15 index 477d70fc66c..193bc7d5ee3 100644 --- a/target/linux/bcm27xx/bcm2710/config-5.15 +++ b/target/linux/bcm27xx/bcm2710/config-5.15 @@ -27,7 +27,6 @@ CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/bcm27xx/bcm2711/config-5.15 b/target/linux/bcm27xx/bcm2711/config-5.15 index 2f8f9dccb1b..e18728e49d6 100644 --- a/target/linux/bcm27xx/bcm2711/config-5.15 +++ b/target/linux/bcm27xx/bcm2711/config-5.15 @@ -27,7 +27,6 @@ CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index d00080c72ec..934af3a7681 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -343,7 +343,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_858921 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set -# CONFIG_ARM64_MODULE_PLTS is not set +CONFIG_ARM64_MODULE_PLTS=y # CONFIG_ARM64_MTE is not set # CONFIG_ARM64_PAN is not set # CONFIG_ARM64_PMEM is not set @@ -408,7 +408,7 @@ CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_ARM_LPAE is not set # CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set # CONFIG_ARM_MHU is not set -# CONFIG_ARM_MODULE_PLTS is not set +CONFIG_ARM_MODULE_PLTS=y # CONFIG_ARM_PATCH_PHYS_VIRT is not set # CONFIG_ARM_PSCI is not set # CONFIG_ARM_PSCI_CHECKER is not set diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 1b06116234b..b6ece6c6e1a 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -367,7 +367,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARM64_ERRATUM_858921 is not set # CONFIG_ARM64_HW_AFDBM is not set # CONFIG_ARM64_LSE_ATOMICS is not set -# CONFIG_ARM64_MODULE_PLTS is not set +CONFIG_ARM64_MODULE_PLTS=y # CONFIG_ARM64_MTE is not set # CONFIG_ARM64_PAN is not set # CONFIG_ARM64_PMEM is not set @@ -433,7 +433,7 @@ CONFIG_ARM_GIC_MAX_NR=1 # CONFIG_ARM_LPAE is not set # CONFIG_ARM_MEDIATEK_CPUFREQ_HW is not set # CONFIG_ARM_MHU is not set -# CONFIG_ARM_MODULE_PLTS is not set +CONFIG_ARM_MODULE_PLTS=y # CONFIG_ARM_PATCH_PHYS_VIRT is not set # CONFIG_ARM_PSCI is not set # CONFIG_ARM_PSCI_CHECKER is not set diff --git a/target/linux/ipq806x/config-5.15 b/target/linux/ipq806x/config-5.15 index 69e17cfa504..286f327e39d 100644 --- a/target/linux/ipq806x/config-5.15 +++ b/target/linux/ipq806x/config-5.15 @@ -39,7 +39,6 @@ CONFIG_ARM_HAS_SG_CHAIN=y # CONFIG_ARM_KRAIT_CACHE_DEVFREQ is not set CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_MODULE_PLTS=y CONFIG_ARM_PATCH_IDIV=y CONFIG_ARM_PATCH_PHYS_VIRT=y # CONFIG_ARM_QCOM_CPUFREQ_HW is not set diff --git a/target/linux/ipq806x/config-6.1 b/target/linux/ipq806x/config-6.1 index aae2f8a0b0f..4f8c3c88dfc 100644 --- a/target/linux/ipq806x/config-6.1 +++ b/target/linux/ipq806x/config-6.1 @@ -43,7 +43,6 @@ CONFIG_ARM_HAS_SG_CHAIN=y # CONFIG_ARM_KRAIT_CACHE_DEVFREQ is not set CONFIG_ARM_L1_CACHE_SHIFT=6 CONFIG_ARM_L1_CACHE_SHIFT_6=y -CONFIG_ARM_MODULE_PLTS=y CONFIG_ARM_PATCH_IDIV=y CONFIG_ARM_PATCH_PHYS_VIRT=y # CONFIG_ARM_QCOM_CPUFREQ_HW is not set diff --git a/target/linux/layerscape/armv8_64b/config-5.15 b/target/linux/layerscape/armv8_64b/config-5.15 index 3fe55e61188..df0a3fd849c 100644 --- a/target/linux/layerscape/armv8_64b/config-5.15 +++ b/target/linux/layerscape/armv8_64b/config-5.15 @@ -30,7 +30,6 @@ CONFIG_ARM64_ERRATUM_832075=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 96ff95be13d..9df1494ca09 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -20,7 +20,6 @@ CONFIG_ARM64_4K_PAGES=y CONFIG_ARM64_CRYPTO=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PA_BITS=48 CONFIG_ARM64_PA_BITS_48=y diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 1ce6d852ba1..ac09c8a9c47 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -22,7 +22,6 @@ CONFIG_ARM64_CRYPTO=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_ERRATUM_845719=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PA_BITS=48 CONFIG_ARM64_PA_BITS_48=y diff --git a/target/linux/octeontx/config-5.15 b/target/linux/octeontx/config-5.15 index c2ad7e7ab9d..9ca15896432 100644 --- a/target/linux/octeontx/config-5.15 +++ b/target/linux/octeontx/config-5.15 @@ -26,7 +26,6 @@ CONFIG_ARM64_ERRATUM_827319=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 diff --git a/target/linux/rockchip/armv8/config-5.15 b/target/linux/rockchip/armv8/config-5.15 index 2359fd8729e..0ed009004f1 100644 --- a/target/linux/rockchip/armv8/config-5.15 +++ b/target/linux/rockchip/armv8/config-5.15 @@ -31,7 +31,6 @@ CONFIG_ARM64_ERRATUM_858921=y CONFIG_ARM64_ERRATUM_1742098=y CONFIG_ARM64_HW_AFDBM=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_ARM64_PAGE_SHIFT=12 CONFIG_ARM64_PAN=y CONFIG_ARM64_PA_BITS=48 From b2beb4c68849c804a8b9441f776a6918d433fb1e Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Mon, 1 May 2023 23:20:28 +0800 Subject: [PATCH 07/43] mediatek: mt7981: usb enable 3.0 by default There is no reason to limit USB to 2.0 mode by default, delete this limit. Signed-off-by: Chukun Pan --- .../mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi | 1 - 1 file changed, 1 deletion(-) diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi index 279bce14e86..dbcf4bb28b8 100644 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi @@ -640,7 +640,6 @@ phys = <&u2port0 PHY_TYPE_USB2>, <&u3port0 PHY_TYPE_USB3>; vusb33-supply = <®_3p3v>; - mediatek,u3p-dis-msk = <0x01>; status = "disabled"; }; From a9989b30d01e534288928d7ef48df3eb9fe3150b Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Tue, 23 May 2023 02:14:32 +0100 Subject: [PATCH 08/43] mediatek: mt7981: setup all clocks needed for eMMC Setup all necessary clocks to get MMC to work on MT7981, similar to how it is done also on MT7986. Signed-off-by: Daniel Golle --- .../files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi index dbcf4bb28b8..95b548143b4 100644 --- a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7981.dtsi @@ -555,14 +555,15 @@ "mediatek,mt7981-mmc"; reg = <0 0x11230000 0 0x1000>, <0 0x11c20000 0 0x1000>; interrupts = ; - clocks = <&topckgen CLK_TOP_EMMC_208M>, - <&topckgen CLK_TOP_EMMC_400M>, - <&infracfg CLK_INFRA_MSDC_CK>; + clocks = <&infracfg CLK_INFRA_MSDC_CK>, + <&infracfg CLK_INFRA_MSDC_HCK_CK>, + <&infracfg CLK_INFRA_MSDC_66M_CK>, + <&infracfg CLK_INFRA_MSDC_133M_CK>; assigned-clocks = <&topckgen CLK_TOP_EMMC_208M_SEL>, <&topckgen CLK_TOP_EMMC_400M_SEL>; assigned-clock-parents = <&topckgen CLK_TOP_CB_M_D2>, <&topckgen CLK_TOP_CB_NET2_D2>; - clock-names = "source", "hclk", "source_cg"; + clock-names = "source", "hclk", "axi_cg", "ahb_cg"; status = "disabled"; }; From b33c1858767e5109913ac2195ec2b2b8ef0e726a Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Sun, 19 Feb 2023 10:11:50 +0800 Subject: [PATCH 09/43] mediatek: add mt7988 clock drivers support This adds clock drivers for the MediaTek MT7988 SoC Signed-off-by: Sam Shih Signed-off-by: Daniel Golle --- .../drivers/clk/mediatek/clk-mt7988-apmixed.c | 113 ++++ .../drivers/clk/mediatek/clk-mt7988-eth.c | 299 ++++++++++ .../clk/mediatek/clk-mt7988-infracfg.c | 399 +++++++++++++ .../clk/mediatek/clk-mt7988-topckgen.c | 522 ++++++++++++++++++ .../dt-bindings/clock/mediatek,mt7988-clk.h | 276 +++++++++ target/linux/mediatek/filogic/config-5.15 | 1 + target/linux/mediatek/mt7622/config-5.15 | 1 + target/linux/mediatek/mt7623/config-5.15 | 1 + target/linux/mediatek/mt7629/config-5.15 | 1 + ...k-mediatek-Add-pcw-chg-shift-control.patch | 24 + ...lk-mediatek-add-mt7988-clock-support.patch | 31 ++ 11 files changed, 1668 insertions(+) create mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c create mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c create mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c create mode 100644 target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c create mode 100644 target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h create mode 100644 target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch create mode 100644 target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c new file mode 100644 index 00000000000..587b70767eb --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-apmixed.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Sam Shih + * Author: Xiufeng Li + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" +#include + +#define MT7988_PLL_FMAX (2500UL * MHZ) +#define MT7988_PCW_CHG_SHIFT 2 + +#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ + _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, \ + _div_table) \ + { \ + .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, .flags = _flags, \ + .rst_bar_mask = BIT(_rst_bar_mask), .fmax = MT7988_PLL_FMAX, \ + .pcwbits = _pcwbits, .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + .pcw_chg_shift = MT7988_PCW_CHG_SHIFT, \ + .div_table = _div_table, .parent_name = "clkxtal", \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ + _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg) \ + PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _rst_bar_mask, \ + _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, _pcw_chg_reg, NULL) + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_NETSYSPLL, "netsyspll", 0x0104, 0x0110, 0x00000001, 0, + 0, 32, 0x0104, 4, 0, 0, 0, 0x0108, 0, 0x0104), + PLL(CLK_APMIXED_MPLL, "mpll", 0x0114, 0x0120, 0xff000001, HAVE_RST_BAR, + 23, 32, 0x0114, 4, 0, 0, 0, 0x0118, 0, 0x0114), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0124, 0x0130, 0xff000001, + HAVE_RST_BAR, 23, 32, 0x0124, 4, 0, 0, 0, 0x0128, 0, 0x0124), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0134, 0x0140, 0x00000001, 0, 0, 32, + 0x0134, 4, 0x0704, 0x0700, 1, 0x0138, 0, 0x0134), + PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0144, 0x0150, 0xff000001, + HAVE_RST_BAR, 23, 32, 0x0144, 4, 0, 0, 0, 0x0148, 0, 0x0144), + PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0154, 0x0160, 0xff000001, + (HAVE_RST_BAR | PLL_AO), 23, 32, 0x0154, 4, 0, 0, 0, 0x0158, 0, + 0x0154), + PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0164, 0x0170, 0x00000001, 0, + 0, 32, 0x0164, 4, 0, 0, 0, 0x0168, 0, 0x0164), + PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0174, 0x0180, 0x00000001, 0, 0, 32, + 0x0174, 4, 0, 0, 0, 0x0178, 0, 0x0174), + PLL(CLK_APMIXED_ARM_B, "arm_b", 0x0204, 0x0210, 0xff000001, + (HAVE_RST_BAR | PLL_AO), 23, 32, 0x0204, 4, 0, 0, 0, 0x0208, 0, + 0x0204), + PLL(CLK_APMIXED_CCIPLL2_B, "ccipll2_b", 0x0214, 0x0220, 0xff000001, + HAVE_RST_BAR, 23, 32, 0x0214, 4, 0, 0, 0, 0x0218, 0, 0x0214), + PLL(CLK_APMIXED_USXGMIIPLL, "usxgmiipll", 0x0304, 0x0310, 0xff000001, + HAVE_RST_BAR, 23, 32, 0x0304, 4, 0, 0, 0, 0x0308, 0, 0x0304), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0314, 0x0320, 0x00000001, 0, 0, + 32, 0x0314, 4, 0, 0, 0, 0x0318, 0, 0x0314), +}; + +static const struct of_device_id of_match_clk_mt7988_apmixed[] = { + { + .compatible = "mediatek,mt7988-apmixedsys", + }, + {} +}; + +static int clk_mt7988_apmixed_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_apmixed_data; + } + return r; + +free_apmixed_data: + mtk_free_clk_data(clk_data); + return r; +} + +static struct platform_driver clk_mt7988_apmixed_drv = { + .probe = clk_mt7988_apmixed_probe, + .driver = { + .name = "clk-mt7988-apmixed", + .of_match_table = of_match_clk_mt7988_apmixed, + }, +}; +builtin_platform_driver(clk_mt7988_apmixed_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c new file mode 100644 index 00000000000..341d0f73fd3 --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-eth.c @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Sam Shih + * Author: Xiufeng Li + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include + +static const struct mtk_gate_regs ethdma_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +#define GATE_ETHDMA(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = ðdma_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate ethdma_clks[] = { + GATE_ETHDMA(CLK_ETHDMA_XGP1_EN, "ethdma_xgp1_en", "top_xtal", 0), + GATE_ETHDMA(CLK_ETHDMA_XGP2_EN, "ethdma_xgp2_en", "top_xtal", 1), + GATE_ETHDMA(CLK_ETHDMA_XGP3_EN, "ethdma_xgp3_en", "top_xtal", 2), + GATE_ETHDMA(CLK_ETHDMA_FE_EN, "ethdma_fe_en", "netsys_2x_sel", 6), + GATE_ETHDMA(CLK_ETHDMA_GP2_EN, "ethdma_gp2_en", "top_xtal", 7), + GATE_ETHDMA(CLK_ETHDMA_GP1_EN, "ethdma_gp1_en", "top_xtal", 8), + GATE_ETHDMA(CLK_ETHDMA_GP3_EN, "ethdma_gp3_en", "top_xtal", 10), + GATE_ETHDMA(CLK_ETHDMA_ESW_EN, "ethdma_esw_en", "netsys_gsw_sel", 16), + GATE_ETHDMA(CLK_ETHDMA_CRYPT0_EN, "ethdma_crypt0_en", "eip197_sel", + 29), +}; + +static int clk_mt7988_ethsys_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(ethdma_clks)); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, ethdma_clks, ARRAY_SIZE(ethdma_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_data; + } + return r; + +free_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct mtk_gate_regs sgmii0_cg_regs = { + .set_ofs = 0xe4, + .clr_ofs = 0xe4, + .sta_ofs = 0xe4, +}; + +#define GATE_SGMII0(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &sgmii0_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate sgmii0_clks[] = { + GATE_SGMII0(CLK_SGM0_TX_EN, "sgm0_tx_en", "top_xtal", 2), + GATE_SGMII0(CLK_SGM0_RX_EN, "sgm0_rx_en", "top_xtal", 3), +}; + +static int clk_mt7988_sgmii0_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_data; + } + return r; + +free_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct mtk_gate_regs sgmii1_cg_regs = { + .set_ofs = 0xe4, + .clr_ofs = 0xe4, + .sta_ofs = 0xe4, +}; + +#define GATE_SGMII1(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &sgmii1_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate sgmii1_clks[] = { + GATE_SGMII1(CLK_SGM1_TX_EN, "sgm1_tx_en", "top_xtal", 2), + GATE_SGMII1(CLK_SGM1_RX_EN, "sgm1_rx_en", "top_xtal", 3), +}; + +static int clk_mt7988_sgmii1_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_data; + } + return r; + +free_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct mtk_gate_regs ethwarp_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +#define GATE_ETHWARP(_id, _name, _parent, _shift) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = ðwarp_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr_inv, \ + } + +static const struct mtk_gate ethwarp_clks[] = { + GATE_ETHWARP(CLK_ETHWARP_WOCPU2_EN, "ethwarp_wocpu2_en", + "netsys_mcu_sel", 13), + GATE_ETHWARP(CLK_ETHWARP_WOCPU1_EN, "ethwarp_wocpu1_en", + "netsys_mcu_sel", 14), + GATE_ETHWARP(CLK_ETHWARP_WOCPU0_EN, "ethwarp_wocpu0_en", + "netsys_mcu_sel", 15), +}; + +static int clk_mt7988_ethwarp_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(ethwarp_clks)); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, ethwarp_clks, ARRAY_SIZE(ethwarp_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_data; + } + return r; + +free_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct of_device_id of_match_clk_mt7988_ethsys[] = { + { + .compatible = "mediatek,mt7988-ethsys", + }, + {} +}; + +static struct platform_driver clk_mt7988_ethsys_drv = { + .probe = clk_mt7988_ethsys_probe, + .driver = { + .name = "clk-mt7988-ethsys", + .of_match_table = of_match_clk_mt7988_ethsys, + }, +}; +builtin_platform_driver(clk_mt7988_ethsys_drv); + +static const struct of_device_id of_match_clk_mt7988_sgmii0[] = { + { + .compatible = "mediatek,mt7988-sgmiisys_0", + }, + {} +}; + +static struct platform_driver clk_mt7988_sgmii0_drv = { + .probe = clk_mt7988_sgmii0_probe, + .driver = { + .name = "clk-mt7988-sgmiisys_0", + .of_match_table = of_match_clk_mt7988_sgmii0, + }, +}; +builtin_platform_driver(clk_mt7988_sgmii0_drv); + +static const struct of_device_id of_match_clk_mt7988_sgmii1[] = { + { + .compatible = "mediatek,mt7988-sgmiisys_1", + }, + {} +}; + +static struct platform_driver clk_mt7988_sgmii1_drv = { + .probe = clk_mt7988_sgmii1_probe, + .driver = { + .name = "clk-mt7988-sgmiisys_1", + .of_match_table = of_match_clk_mt7988_sgmii1, + }, +}; +builtin_platform_driver(clk_mt7988_sgmii1_drv); + +static const struct of_device_id of_match_clk_mt7988_ethwarp[] = { + { + .compatible = "mediatek,mt7988-ethwarp", + }, + {} +}; + +static struct platform_driver clk_mt7988_ethwarp_drv = { + .probe = clk_mt7988_ethwarp_probe, + .driver = { + .name = "clk-mt7988-ethwarp", + .of_match_table = of_match_clk_mt7988_ethwarp, + }, +}; +builtin_platform_driver(clk_mt7988_ethwarp_drv); \ No newline at end of file diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c new file mode 100644 index 00000000000..77e25383b6e --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-infracfg.c @@ -0,0 +1,399 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Sam Shih + * Author: Xiufeng Li + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" +#include + +static DEFINE_SPINLOCK(mt7988_clk_lock); + +static const char *const infra_mux_uart0_parents[] __initconst = { + "csw_infra_f26m_sel", "uart_sel" +}; + +static const char *const infra_mux_uart1_parents[] __initconst = { + "csw_infra_f26m_sel", "uart_sel" +}; + +static const char *const infra_mux_uart2_parents[] __initconst = { + "csw_infra_f26m_sel", "uart_sel" +}; + +static const char *const infra_mux_spi0_parents[] __initconst = { "i2c_sel", + "spi_sel" }; + +static const char *const infra_mux_spi1_parents[] __initconst = { + "i2c_sel", "spim_mst_sel" +}; + +static const char *const infra_pwm_bck_parents[] __initconst = { + "top_rtc_32p7k", "csw_infra_f26m_sel", "sysaxi_sel", "pwm_sel" +}; + +static const char *const infra_pcie_gfmux_tl_ck_o_p0_parents[] __initconst = { + "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", + "pextp_tl_sel" +}; + +static const char *const infra_pcie_gfmux_tl_ck_o_p1_parents[] __initconst = { + "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", + "pextp_tl_p1_sel" +}; + +static const char *const infra_pcie_gfmux_tl_ck_o_p2_parents[] __initconst = { + "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", + "pextp_tl_p2_sel" +}; + +static const char *const infra_pcie_gfmux_tl_ck_o_p3_parents[] __initconst = { + "top_rtc_32p7k", "csw_infra_f26m_sel", "csw_infra_f26m_sel", + "pextp_tl_p3_sel" +}; + +static const struct mtk_mux infra_muxes[] = { + /* MODULE_CLK_SEL_0 */ + MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART0_SEL, "infra_mux_uart0_sel", + infra_mux_uart0_parents, 0x0018, 0x0010, 0x0014, + 0, 1, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART1_SEL, "infra_mux_uart1_sel", + infra_mux_uart1_parents, 0x0018, 0x0010, 0x0014, + 1, 1, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_UART2_SEL, "infra_mux_uart2_sel", + infra_mux_uart2_parents, 0x0018, 0x0010, 0x0014, + 2, 1, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI0_SEL, "infra_mux_spi0_sel", + infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 4, + 1, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI1_SEL, "infra_mux_spi1_sel", + infra_mux_spi1_parents, 0x0018, 0x0010, 0x0014, 5, + 1, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_MUX_SPI2_SEL, "infra_mux_spi2_sel", + infra_mux_spi0_parents, 0x0018, 0x0010, 0x0014, 6, + 1, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_SEL, "infra_pwm_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 14, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK1_SEL, "infra_pwm_ck1_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 16, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK2_SEL, "infra_pwm_ck2_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 18, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK3_SEL, "infra_pwm_ck3_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 20, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK4_SEL, "infra_pwm_ck4_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 22, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK5_SEL, "infra_pwm_ck5_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 24, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK6_SEL, "infra_pwm_ck6_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 26, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK7_SEL, "infra_pwm_ck7_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 28, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_CK8_SEL, "infra_pwm_ck8_sel", + infra_pwm_bck_parents, 0x0018, 0x0010, 0x0014, 30, + 2, -1, -1, -1), + /* MODULE_CLK_SEL_1 */ + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL, + "infra_pcie_gfmux_tl_o_p0_sel", + infra_pcie_gfmux_tl_ck_o_p0_parents, 0x0028, + 0x0020, 0x0024, 0, 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL, + "infra_pcie_gfmux_tl_o_p1_sel", + infra_pcie_gfmux_tl_ck_o_p1_parents, 0x0028, + 0x0020, 0x0024, 2, 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL, + "infra_pcie_gfmux_tl_o_p2_sel", + infra_pcie_gfmux_tl_ck_o_p2_parents, 0x0028, + 0x0020, 0x0024, 4, 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL, + "infra_pcie_gfmux_tl_o_p3_sel", + infra_pcie_gfmux_tl_ck_o_p3_parents, 0x0028, + 0x0020, 0x0024, 6, 2, -1, -1, -1), +}; + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x14, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0x50, + .clr_ofs = 0x54, + .sta_ofs = 0x58, +}; + +static const struct mtk_gate_regs infra3_cg_regs = { + .set_ofs = 0x60, + .clr_ofs = 0x64, + .sta_ofs = 0x68, +}; + +#define GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, _flags) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra0_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ + } + +#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flags) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra1_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ + } + +#define GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, _flags) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra2_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ + } + +#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flags) \ + { \ + .id = _id, .name = _name, .parent_name = _parent, \ + .regs = &infra3_cg_regs, .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, .flags = _flags, \ + } + +#define GATE_INFRA0(_id, _name, _parent, _shift) \ + GATE_INFRA0_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA1(_id, _name, _parent, _shift) \ + GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA2(_id, _name, _parent, _shift) \ + GATE_INFRA2_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA3(_id, _name, _parent, _shift) \ + GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, 0) + +static const struct mtk_gate infra_clks[] = { + /* INFRA0 */ + GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P0, + "infra_pcie_peri_ck_26m_ck_p0", "csw_infra_f26m_sel", 7), + GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, + "infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8), + GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, + "infra_pcie_peri_ck_26m_ck_p2", "csw_infra_f26m_sel", 9), + GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, + "infra_pcie_peri_ck_26m_ck_p3", "csw_infra_f26m_sel", 10), + /* INFRA1 */ + GATE_INFRA1(CLK_INFRA_66M_GPT_BCK, "infra_hf_66m_gpt_bck", + "sysaxi_sel", 0), + GATE_INFRA1(CLK_INFRA_66M_PWM_HCK, "infra_hf_66m_pwm_hck", + "sysaxi_sel", 1), + GATE_INFRA1(CLK_INFRA_66M_PWM_BCK, "infra_hf_66m_pwm_bck", + "infra_pwm_sel", 2), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK1, "infra_hf_66m_pwm_ck1", + "infra_pwm_ck1_sel", 3), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK2, "infra_hf_66m_pwm_ck2", + "infra_pwm_ck2_sel", 4), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK3, "infra_hf_66m_pwm_ck3", + "infra_pwm_ck3_sel", 5), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK4, "infra_hf_66m_pwm_ck4", + "infra_pwm_ck4_sel", 6), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK5, "infra_hf_66m_pwm_ck5", + "infra_pwm_ck5_sel", 7), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK6, "infra_hf_66m_pwm_ck6", + "infra_pwm_ck6_sel", 8), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK7, "infra_hf_66m_pwm_ck7", + "infra_pwm_ck7_sel", 9), + GATE_INFRA1(CLK_INFRA_66M_PWM_CK8, "infra_hf_66m_pwm_ck8", + "infra_pwm_ck8_sel", 10), + GATE_INFRA1(CLK_INFRA_133M_CQDMA_BCK, "infra_hf_133m_cqdma_bck", + "sysaxi_sel", 12), + GATE_INFRA1(CLK_INFRA_66M_AUD_SLV_BCK, "infra_66m_aud_slv_bck", + "sysaxi_sel", 13), + GATE_INFRA1(CLK_INFRA_AUD_26M, "infra_f_faud_26m", + "csw_infra_f26m_sel", 14), + GATE_INFRA1(CLK_INFRA_AUD_L, "infra_f_faud_l", "aud_l_sel", 15), + GATE_INFRA1(CLK_INFRA_AUD_AUD, "infra_f_aud_aud", "a1sys_sel", 16), + GATE_INFRA1(CLK_INFRA_AUD_EG2, "infra_f_faud_eg2", "a_tuner_sel", 18), + GATE_INFRA1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", + "csw_infra_f26m_sel", 19, CLK_IS_CRITICAL), + // JTAG + GATE_INFRA1_FLAGS(CLK_INFRA_133M_DBG_ACKM, "infra_hf_133m_dbg_ackm", + "sysaxi_sel", 20, CLK_IS_CRITICAL), + GATE_INFRA1(CLK_INFRA_66M_AP_DMA_BCK, "infra_66m_ap_dma_bck", + "sysaxi_sel", 21), + GATE_INFRA1(CLK_INFRA_66M_SEJ_BCK, "infra_hf_66m_sej_bck", + "sysaxi_sel", 29), + GATE_INFRA1(CLK_INFRA_PRE_CK_SEJ_F13M, "infra_pre_ck_sej_f13m", + "csw_infra_f26m_sel", 30), + /* INFRA2 */ + GATE_INFRA2(CLK_INFRA_26M_THERM_SYSTEM, "infra_hf_26m_therm_system", + "csw_infra_f26m_sel", 0), + GATE_INFRA2(CLK_INFRA_I2C_BCK, "infra_i2c_bck", "i2c_sel", 1), + GATE_INFRA2(CLK_INFRA_52M_UART0_CK, "infra_f_52m_uart0", + "infra_mux_uart0_sel", 3), + GATE_INFRA2(CLK_INFRA_52M_UART1_CK, "infra_f_52m_uart1", + "infra_mux_uart1_sel", 4), + GATE_INFRA2(CLK_INFRA_52M_UART2_CK, "infra_f_52m_uart2", + "infra_mux_uart2_sel", 5), + GATE_INFRA2(CLK_INFRA_NFI, "infra_f_fnfi", "nfi1x_sel", 9), + GATE_INFRA2(CLK_INFRA_SPINFI, "infra_f_fspinfi", "spinfi_sel", 10), + GATE_INFRA2_FLAGS(CLK_INFRA_66M_NFI_HCK, "infra_hf_66m_nfi_hck", + "sysaxi_sel", 11, CLK_IS_CRITICAL), + GATE_INFRA2_FLAGS(CLK_INFRA_104M_SPI0, "infra_hf_104m_spi0", + "infra_mux_spi0_sel", 12, CLK_IS_CRITICAL), + GATE_INFRA2(CLK_INFRA_104M_SPI1, "infra_hf_104m_spi1", + "infra_mux_spi1_sel", 13), + GATE_INFRA2(CLK_INFRA_104M_SPI2_BCK, "infra_hf_104m_spi2_bck", + "infra_mux_spi2_sel", 14), + GATE_INFRA2_FLAGS(CLK_INFRA_66M_SPI0_HCK, "infra_hf_66m_spi0_hck", + "sysaxi_sel", 15, CLK_IS_CRITICAL), + GATE_INFRA2(CLK_INFRA_66M_SPI1_HCK, "infra_hf_66m_spi1_hck", + "sysaxi_sel", 16), + GATE_INFRA2(CLK_INFRA_66M_SPI2_HCK, "infra_hf_66m_spi2_hck", + "sysaxi_sel", 17), + GATE_INFRA2(CLK_INFRA_66M_FLASHIF_AXI, "infra_hf_66m_flashif_axi", + "sysaxi_sel", 18), + GATE_INFRA2(CLK_INFRA_RTC, "infra_f_frtc", "top_rtc_32k", 19), + GATE_INFRA2(CLK_INFRA_26M_ADC_BCK, "infra_f_26m_adc_bck", + "csw_infra_f26m_sel", 20), + GATE_INFRA2(CLK_INFRA_RC_ADC, "infra_f_frc_adc", "infra_f_26m_adc_bck", + 21), + GATE_INFRA2(CLK_INFRA_MSDC400, "infra_f_fmsdc400", "emmc_400m_sel", + 22), + GATE_INFRA2(CLK_INFRA_MSDC2_HCK, "infra_f_fmsdc2_hck", "emmc_250m_sel", + 23), + GATE_INFRA2(CLK_INFRA_133M_MSDC_0_HCK, "infra_hf_133m_msdc_0_hck", + "sysaxi_sel", 24), + GATE_INFRA2(CLK_INFRA_66M_MSDC_0_HCK, "infra_66m_msdc_0_hck", + "sysaxi_sel", 25), + GATE_INFRA2(CLK_INFRA_133M_CPUM_BCK, "infra_hf_133m_cpum_bck", + "sysaxi_sel", 26), + GATE_INFRA2(CLK_INFRA_BIST2FPC, "infra_hf_fbist2fpc", "nfi1x_sel", 27), + GATE_INFRA2(CLK_INFRA_I2C_X16W_MCK_CK_P1, + "infra_hf_i2c_x16w_mck_ck_p1", "sysaxi_sel", 29), + GATE_INFRA2(CLK_INFRA_I2C_X16W_PCK_CK_P1, + "infra_hf_i2c_x16w_pck_ck_p1", "sysaxi_sel", 31), + /* INFRA3 */ + GATE_INFRA3(CLK_INFRA_133M_USB_HCK, "infra_133m_usb_hck", "sysaxi_sel", + 0), + GATE_INFRA3(CLK_INFRA_133M_USB_HCK_CK_P1, "infra_133m_usb_hck_ck_p1", + "sysaxi_sel", 1), + GATE_INFRA3(CLK_INFRA_66M_USB_HCK, "infra_66m_usb_hck", "sysaxi_sel", + 2), + GATE_INFRA3(CLK_INFRA_66M_USB_HCK_CK_P1, "infra_66m_usb_hck_ck_p1", + "sysaxi_sel", 3), + GATE_INFRA3(CLK_INFRA_USB_SYS, "infra_usb_sys", "usb_sys_sel", 4), + GATE_INFRA3(CLK_INFRA_USB_SYS_CK_P1, "infra_usb_sys_ck_p1", + "usb_sys_p1_sel", 5), + GATE_INFRA3(CLK_INFRA_USB_REF, "infra_usb_ref", "top_xtal", 6), + GATE_INFRA3(CLK_INFRA_USB_CK_P1, "infra_usb_ck_p1", "top_xtal", 7), + GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT, "infra_usb_frmcnt", + "usb_frmcnt_sel", 8, CLK_IS_CRITICAL), + GATE_INFRA3_FLAGS(CLK_INFRA_USB_FRMCNT_CK_P1, "infra_usb_frmcnt_ck_p1", + "usb_frmcnt_p1_sel", 9, CLK_IS_CRITICAL), + GATE_INFRA3(CLK_INFRA_USB_PIPE, "infra_usb_pipe", "sspxtp_sel", 10), + GATE_INFRA3(CLK_INFRA_USB_PIPE_CK_P1, "infra_usb_pipe_ck_p1", + "usb_phy_sel", 11), + GATE_INFRA3(CLK_INFRA_USB_UTMI, "infra_usb_utmi", "top_xtal", 12), + GATE_INFRA3(CLK_INFRA_USB_UTMI_CK_P1, "infra_usb_utmi_ck_p1", + "top_xtal", 13), + GATE_INFRA3(CLK_INFRA_USB_XHCI, "infra_usb_xhci", "usb_xhci_sel", 14), + GATE_INFRA3(CLK_INFRA_USB_XHCI_CK_P1, "infra_usb_xhci_ck_p1", + "usb_xhci_p1_sel", 15), + GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P0, "infra_pcie_gfmux_tl_ck_p0", + "infra_pcie_gfmux_tl_o_p0_sel", 20), + GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P1, "infra_pcie_gfmux_tl_ck_p1", + "infra_pcie_gfmux_tl_o_p1_sel", 21), + GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P2, "infra_pcie_gfmux_tl_ck_p2", + "infra_pcie_gfmux_tl_o_p2_sel", 22), + GATE_INFRA3(CLK_INFRA_PCIE_GFMUX_TL_P3, "infra_pcie_gfmux_tl_ck_p3", + "infra_pcie_gfmux_tl_o_p3_sel", 23), + GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P0, "infra_pcie_pipe_ck_p0", + "top_xtal", 24), + GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P1, "infra_pcie_pipe_ck_p1", + "top_xtal", 25), + GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P2, "infra_pcie_pipe_ck_p2", + "top_xtal", 26), + GATE_INFRA3(CLK_INFRA_PCIE_PIPE_P3, "infra_pcie_pipe_ck_p3", + "top_xtal", 27), + GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P0, "infra_133m_pcie_ck_p0", + "sysaxi_sel", 28), + GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P1, "infra_133m_pcie_ck_p1", + "sysaxi_sel", 29), + GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P2, "infra_133m_pcie_ck_p2", + "sysaxi_sel", 30), + GATE_INFRA3(CLK_INFRA_133M_PCIE_CK_P3, "infra_133m_pcie_ck_p3", + "sysaxi_sel", 31), +}; + +static int clk_mt7988_infracfg_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(infra_muxes) + ARRAY_SIZE(infra_clks); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, + &mt7988_clk_lock, clk_data); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_infracfg_data; + } + return r; + +free_infracfg_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct of_device_id of_match_clk_mt7988_infracfg[] = { + { + .compatible = "mediatek,mt7988-infracfg", + }, + {} +}; + +static struct platform_driver clk_mt7988_infracfg_drv = { + .probe = clk_mt7988_infracfg_probe, + .driver = { + .name = "clk-mt7988-infracfg", + .of_match_table = of_match_clk_mt7988_infracfg, + }, +}; +builtin_platform_driver(clk_mt7988_infracfg_drv); diff --git a/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c new file mode 100644 index 00000000000..917302b6df6 --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/clk/mediatek/clk-mt7988-topckgen.c @@ -0,0 +1,522 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Sam Shih + * Author: Xiufeng Li + */ + +#include +#include +#include +#include +#include +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" +#include + +static DEFINE_SPINLOCK(mt7988_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2), + FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250), + FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220), + FACTOR(CLK_TOP_MPLL_D2, "mpll_d2", "mpll", 1, 2), + FACTOR(CLK_TOP_MPLL_D3_D2, "mpll_d3_d2", "mpll", 1, 2), + FACTOR(CLK_TOP_MPLL_D4, "mpll_d4", "mpll", 1, 4), + FACTOR(CLK_TOP_MPLL_D8, "mpll_d8", "mpll", 1, 8), + FACTOR(CLK_TOP_MPLL_D8_D2, "mpll_d8_d2", "mpll", 1, 16), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_D3_D5, "mmpll_d3_d5", "mmpll", 1, 15), + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4), + FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll", 1, 12), + FACTOR(CLK_TOP_MMPLL_D8, "mmpll_d8", "mmpll", 1, 8), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), + FACTOR(CLK_TOP_NET1PLL_D4, "net1pll_d4", "net1pll", 1, 4), + FACTOR(CLK_TOP_NET1PLL_D5, "net1pll_d5", "net1pll", 1, 5), + FACTOR(CLK_TOP_NET1PLL_D5_D2, "net1pll_d5_d2", "net1pll", 1, 10), + FACTOR(CLK_TOP_NET1PLL_D5_D4, "net1pll_d5_d4", "net1pll", 1, 20), + FACTOR(CLK_TOP_NET1PLL_D8, "net1pll_d8", "net1pll", 1, 8), + FACTOR(CLK_TOP_NET1PLL_D8_D2, "net1pll_d8_d2", "net1pll", 1, 16), + FACTOR(CLK_TOP_NET1PLL_D8_D4, "net1pll_d8_d4", "net1pll", 1, 32), + FACTOR(CLK_TOP_NET1PLL_D8_D8, "net1pll_d8_d8", "net1pll", 1, 64), + FACTOR(CLK_TOP_NET1PLL_D8_D16, "net1pll_d8_d16", "net1pll", 1, 128), + FACTOR(CLK_TOP_NET2PLL_D2, "net2pll_d2", "net2pll", 1, 2), + FACTOR(CLK_TOP_NET2PLL_D4, "net2pll_d4", "net2pll", 1, 4), + FACTOR(CLK_TOP_NET2PLL_D4_D4, "net2pll_d4_d4", "net2pll", 1, 16), + FACTOR(CLK_TOP_NET2PLL_D4_D8, "net2pll_d4_d8", "net2pll", 1, 32), + FACTOR(CLK_TOP_NET2PLL_D6, "net2pll_d6", "net2pll", 1, 6), + FACTOR(CLK_TOP_NET2PLL_D8, "net2pll_d8", "net2pll", 1, 8), +}; + +static const char *const netsys_parents[] = { "top_xtal", "net2pll_d2", + "mmpll_d2" }; + +static const char *const netsys_500m_parents[] = { "top_xtal", "net1pll_d5", + "net1pll_d5_d2" }; + +static const char *const netsys_2x_parents[] = { "top_xtal", "net2pll", + "mmpll" }; + +static const char *const netsys_gsw_parents[] = { "top_xtal", "net1pll_d4", + "net1pll_d5" }; + +static const char *const eth_gmii_parents[] = { "top_xtal", "net1pll_d5_d4" }; + +static const char *const netsys_mcu_parents[] = { "top_xtal", "net2pll", + "mmpll", "net1pll_d4", + "net1pll_d5", "mpll" }; + +static const char *const eip197_parents[] = { "top_xtal", "netsyspll", + "net2pll", "mmpll", + "net1pll_d4", "net1pll_d5" }; + +static const char *const axi_infra_parents[] = { "top_xtal", "net1pll_d8_d2" }; + +static const char *const uart_parents[] = { "top_xtal", "mpll_d8", + "mpll_d8_d2" }; + +static const char *const emmc_250m_parents[] = { "top_xtal", "net1pll_d5_d2", + "mmpll_d4" }; + +static const char *const emmc_400m_parents[] = { "top_xtal", "msdcpll", + "mmpll_d2", "mpll_d2", + "mmpll_d4", "net1pll_d8_d2" }; + +static const char *const spi_parents[] = { "top_xtal", "mpll_d2", + "mmpll_d4", "net1pll_d8_d2", + "net2pll_d6", "net1pll_d5_d4", + "mpll_d4", "net1pll_d8_d4" }; + +static const char *const nfi1x_parents[] = { "top_xtal", "mmpll_d4", + "net1pll_d8_d2", "net2pll_d6", + "mpll_d4", "mmpll_d8", + "net1pll_d8_d4", "mpll_d8" }; + +static const char *const spinfi_parents[] = { "top_xtal_d2", "top_xtal", + "net1pll_d5_d4", "mpll_d4", + "mmpll_d8", "net1pll_d8_d4", + "mmpll_d6_d2", "mpll_d8" }; + +static const char *const pwm_parents[] = { "top_xtal", "net1pll_d8_d2", + "net1pll_d5_d4", "mpll_d4", + "mpll_d8_d2", "top_rtc_32k" }; + +static const char *const i2c_parents[] = { "top_xtal", "net1pll_d5_d4", + "mpll_d4", "net1pll_d8_d4" }; + +static const char *const pcie_mbist_250m_parents[] = { "top_xtal", + "net1pll_d5_d2" }; + +static const char *const pextp_tl_ck_parents[] = { "top_xtal", "net2pll_d6", + "mmpll_d8", "mpll_d8_d2", + "top_rtc_32k" }; + +static const char *const usb_frmcnt_parents[] = { "top_xtal", "mmpll_d3_d5" }; + +static const char *const aud_parents[] = { "top_xtal", "apll2" }; + +static const char *const a1sys_parents[] = { "top_xtal", "apll2_d4" }; + +static const char *const aud_l_parents[] = { "top_xtal", "apll2", + "mpll_d8_d2" }; + +static const char *const sspxtp_parents[] = { "top_xtal_d2", "mpll_d8_d2" }; + +static const char *const usxgmii_sbus_0_parents[] = { "top_xtal", + "net1pll_d8_d4" }; + +static const char *const sgm_0_parents[] = { "top_xtal", "sgmpll" }; + +static const char *const sysapb_parents[] = { "top_xtal", "mpll_d3_d2" }; + +static const char *const eth_refck_50m_parents[] = { "top_xtal", + "net2pll_d4_d4" }; + +static const char *const eth_sys_200m_parents[] = { "top_xtal", "net2pll_d4" }; + +static const char *const eth_xgmii_parents[] = { "top_xtal_d2", + "net1pll_d8_d8", + "net1pll_d8_d16" }; + +static const char *const bus_tops_parents[] = { "top_xtal", "net1pll_d5", + "net2pll_d2" }; + +static const char *const npu_tops_parents[] = { "top_xtal", "net2pll" }; + +static const char *const dramc_md32_parents[] = { "top_xtal", "mpll_d2", + "wedmcupll" }; + +static const char *const da_xtp_glb_p0_parents[] = { "top_xtal", + "net2pll_d8" }; + +static const char *const mcusys_backup_625m_parents[] = { "top_xtal", + "net1pll_d4" }; + +static const char *const macsec_parents[] = { "top_xtal", "sgmpll", + "net1pll_d8" }; + +static const char *const netsys_tops_400m_parents[] = { "top_xtal", + "net2pll_d2" }; + +static const char *const eth_mii_parents[] = { "top_xtal_d2", + "net2pll_d4_d8" }; + +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, + 0x000, 0x004, 0x008, 0, 2, 7, 0x1c0, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", + netsys_500m_parents, 0x000, 0x004, 0x008, 8, 2, + 15, 0x1C0, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", + netsys_2x_parents, 0x000, 0x004, 0x008, 16, 2, 23, + 0x1C0, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_GSW_SEL, "netsys_gsw_sel", + netsys_gsw_parents, 0x000, 0x004, 0x008, 24, 2, + 31, 0x1C0, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_GMII_SEL, "eth_gmii_sel", + eth_gmii_parents, 0x010, 0x014, 0x018, 0, 1, 7, + 0x1C0, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", + netsys_mcu_parents, 0x010, 0x014, 0x018, 8, 3, 15, + 0x1C0, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PAO_2X_SEL, "netsys_pao_2x_sel", + netsys_mcu_parents, 0x010, 0x014, 0x018, 16, 3, + 23, 0x1C0, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP197_SEL, "eip197_sel", eip197_parents, + 0x010, 0x014, 0x018, 24, 3, 31, 0x1c0, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_INFRA_SEL, "axi_infra_sel", + axi_infra_parents, 0x020, 0x024, 0x028, 0, + 1, 7, 0x1C0, 8, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x020, + 0x024, 0x028, 8, 2, 15, 0x1c0, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", + emmc_250m_parents, 0x020, 0x024, 0x028, 16, 2, 23, + 0x1C0, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_400M_SEL, "emmc_400m_sel", + emmc_400m_parents, 0x020, 0x024, 0x028, 24, 3, 31, + 0x1C0, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x030, + 0x034, 0x038, 0, 3, 7, 0x1c0, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, + 0x030, 0x034, 0x038, 8, 3, 15, 0x1c0, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, + 0x030, 0x034, 0x038, 16, 3, 23, 0x1c0, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, + 0x030, 0x034, 0x038, 24, 3, 31, 0x1c0, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x040, + 0x044, 0x048, 0, 3, 7, 0x1c0, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x040, + 0x044, 0x048, 8, 2, 15, 0x1c0, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_MBIST_250M_SEL, + "pcie_mbist_250m_sel", pcie_mbist_250m_parents, + 0x040, 0x044, 0x048, 16, 1, 23, 0x1C0, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_sel", + pextp_tl_ck_parents, 0x040, 0x044, 0x048, 24, 3, + 31, 0x1C0, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P1_SEL, "pextp_tl_p1_sel", + pextp_tl_ck_parents, 0x050, 0x054, 0x058, 0, 3, 7, + 0x1C0, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P2_SEL, "pextp_tl_p2_sel", + pextp_tl_ck_parents, 0x050, 0x054, 0x058, 8, 3, + 15, 0x1C0, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_P3_SEL, "pextp_tl_p3_sel", + pextp_tl_ck_parents, 0x050, 0x054, 0x058, 16, 3, + 23, 0x1C0, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_SEL, "usb_sys_sel", + eth_gmii_parents, 0x050, 0x054, 0x058, 24, 1, 31, + 0x1C0, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_SYS_P1_SEL, "usb_sys_p1_sel", + eth_gmii_parents, 0x060, 0x064, 0x068, 0, 1, 7, + 0x1C0, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_SEL, "usb_xhci_sel", + eth_gmii_parents, 0x060, 0x064, 0x068, 8, 1, 15, + 0x1C0, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_XHCI_P1_SEL, "usb_xhci_p1_sel", + eth_gmii_parents, 0x060, 0x064, 0x068, 16, 1, 23, + 0x1C0, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_SEL, "usb_frmcnt_sel", + usb_frmcnt_parents, 0x060, 0x064, 0x068, 24, 1, + 31, 0x1C0, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_FRMCNT_P1_SEL, "usb_frmcnt_p1_sel", + usb_frmcnt_parents, 0x070, 0x074, 0x078, 0, 1, 7, + 0x1C0, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SEL, "aud_sel", aud_parents, 0x070, + 0x074, 0x078, 8, 1, 15, 0x1c0, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, + 0x070, 0x074, 0x078, 16, 1, 23, 0x1c0, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, + 0x070, 0x074, 0x078, 24, 2, 31, 0x1c4, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", a1sys_parents, + 0x080, 0x084, 0x088, 0, 1, 7, 0x1c4, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPXTP_SEL, "sspxtp_sel", sspxtp_parents, + 0x080, 0x084, 0x088, 8, 1, 15, 0x1c4, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_PHY_SEL, "usb_phy_sel", + sspxtp_parents, 0x080, 0x084, 0x088, 16, 1, 23, + 0x1c4, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_0_SEL, "usxgmii_sbus_0_sel", + usxgmii_sbus_0_parents, 0x080, 0x084, 0x088, 24, + 1, 31, 0x1C4, 4), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USXGMII_SBUS_1_SEL, "usxgmii_sbus_1_sel", + usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, 0, 1, + 7, 0x1C4, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_0_SEL, "sgm_0_sel", sgm_0_parents, + 0x090, 0x094, 0x098, 8, 1, 15, 0x1c4, 6), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_0_SEL, "sgm_sbus_0_sel", + usxgmii_sbus_0_parents, 0x090, 0x094, 0x098, + 16, 1, 23, 0x1C4, 7, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_1_SEL, "sgm_1_sel", sgm_0_parents, + 0x090, 0x094, 0x098, 24, 1, 31, 0x1c4, 8), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_SBUS_1_SEL, "sgm_sbus_1_sel", + usxgmii_sbus_0_parents, 0x0a0, 0x0a4, 0x0a8, + 0, 1, 7, 0x1C4, 9, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_0_XTAL_SEL, "xfi_phy_0_xtal_sel", + sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 8, 1, 15, + 0x1C4, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_XFI_PHY_1_XTAL_SEL, "xfi_phy_1_xtal_sel", + sspxtp_parents, 0x0a0, 0x0a4, 0x0a8, 16, 1, 23, + 0x1C4, 11), + /* CLK_CFG_11 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", + axi_infra_parents, 0x0a0, 0x0a4, 0x0a8, 24, + 1, 31, 0x1C4, 12, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SYSAPB_SEL, "sysapb_sel", + sysapb_parents, 0x0b0, 0x0b4, 0x0b8, 0, 1, + 7, 0x1c4, 13, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_REFCK_50M_SEL, "eth_refck_50m_sel", + eth_refck_50m_parents, 0x0b0, 0x0b4, 0x0b8, 8, 1, + 15, 0x1C4, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_200M_SEL, "eth_sys_200m_sel", + eth_sys_200m_parents, 0x0b0, 0x0b4, 0x0b8, 16, 1, + 23, 0x1C4, 15), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SYS_SEL, "eth_sys_sel", + pcie_mbist_250m_parents, 0x0b0, 0x0b4, 0x0b8, 24, + 1, 31, 0x1C4, 16), + /* CLK_CFG_12 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_XGMII_SEL, "eth_xgmii_sel", + eth_xgmii_parents, 0x0c0, 0x0c4, 0x0c8, 0, 2, 7, + 0x1C4, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_BUS_TOPS_SEL, "bus_tops_sel", + bus_tops_parents, 0x0c0, 0x0c4, 0x0c8, 8, 2, 15, + 0x1C4, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_TOPS_SEL, "npu_tops_sel", + npu_tops_parents, 0x0c0, 0x0c4, 0x0c8, 16, 1, 23, + 0x1C4, 19), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_SEL, "dramc_sel", + sspxtp_parents, 0x0c0, 0x0c4, 0x0c8, 24, 1, + 31, 0x1C4, 20, CLK_IS_CRITICAL), + /* CLK_CFG_13 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", + dramc_md32_parents, 0x0d0, 0x0d4, 0x0d8, 0, + 2, 7, 0x1C4, 21, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS( + CLK_TOP_INFRA_F26M_SEL, "csw_infra_f26m_sel", sspxtp_parents, + 0x0d0, 0x0d4, 0x0d8, 8, 1, 15, 0x1C4, 22, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P0_SEL, "pextp_p0_sel", + sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 16, 1, 23, + 0x1C4, 23), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P1_SEL, "pextp_p1_sel", + sspxtp_parents, 0x0d0, 0x0d4, 0x0d8, 24, 1, 31, + 0x1C4, 24), + /* CLK_CFG_14 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P2_SEL, "pextp_p2_sel", + sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 0, 1, 7, + 0x1C4, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_P3_SEL, "pextp_p3_sel", + sspxtp_parents, 0x0e0, 0x0e4, 0x0e8, 8, 1, 15, + 0x1C4, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P0_SEL, "da_xtp_glb_p0_sel", + da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 16, 1, + 23, 0x1C4, 27), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P1_SEL, "da_xtp_glb_p1_sel", + da_xtp_glb_p0_parents, 0x0e0, 0x0e4, 0x0e8, 24, 1, + 31, 0x1C4, 28), + /* CLK_CFG_15 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P2_SEL, "da_xtp_glb_p2_sel", + da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 0, 1, + 7, 0x1C4, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_XTP_GLB_P3_SEL, "da_xtp_glb_p3_sel", + da_xtp_glb_p0_parents, 0x0f0, 0x0f4, 0x0f8, 8, 1, + 15, 0x1C4, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CKM_SEL, "ckm_sel", sspxtp_parents, 0x0F0, + 0x0f4, 0x0f8, 16, 1, 23, 0x1c8, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_SEL, "da_sel", sspxtp_parents, 0x0f0, + 0x0f4, 0x0f8, 24, 1, 31, 0x1C8, 1), + /* CLK_CFG_16 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_SEL, "pextp_sel", sspxtp_parents, + 0x0100, 0x104, 0x108, 0, 1, 7, 0x1c8, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_TOPS_P2_26M_SEL, "tops_p2_26m_sel", + sspxtp_parents, 0x0100, 0x104, 0x108, 8, 1, 15, + 0x1C8, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MCUSYS_BACKUP_625M_SEL, + "mcusys_backup_625m_sel", + mcusys_backup_625m_parents, 0x0100, 0x104, 0x108, + 16, 1, 23, 0x1C8, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SYNC_250M_SEL, + "netsys_sync_250m_sel", pcie_mbist_250m_parents, + 0x0100, 0x104, 0x108, 24, 1, 31, 0x1c8, 5), + /* CLK_CFG_17 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MACSEC_SEL, "macsec_sel", macsec_parents, + 0x0110, 0x114, 0x118, 0, 2, 7, 0x1c8, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_TOPS_400M_SEL, + "netsys_tops_400m_sel", netsys_tops_400m_parents, + 0x0110, 0x114, 0x118, 8, 1, 15, 0x1c8, 7), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_PPEFB_250M_SEL, + "netsys_ppefb_250m_sel", pcie_mbist_250m_parents, + 0x0110, 0x114, 0x118, 16, 1, 23, 0x1c8, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_WARP_SEL, "netsys_warp_sel", + netsys_parents, 0x0110, 0x114, 0x118, 24, 2, 31, + 0x1C8, 9), + /* CLK_CFG_18 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_MII_SEL, "eth_mii_sel", + eth_mii_parents, 0x0120, 0x124, 0x128, 0, 1, 7, + 0x1c8, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NPU_SEL, "ck_npu_sel", netsys_2x_parents, + 0x0120, 0x124, 0x128, 8, 2, 15, 0x1c8, 11), +}; + +static const struct mtk_composite top_aud_divs[] = { + DIV_GATE(CLK_TOP_AUD_I2S_M, "aud_i2s_m", "aud_sel", 0x0420, 0, 0x0420, + 8, 8), +}; + +static int clk_mt7988_topckgen_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) + + ARRAY_SIZE(top_muxes) + ARRAY_SIZE(top_aud_divs); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + + mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, + &mt7988_clk_lock, clk_data); + + mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), + base, &mt7988_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_topckgen_data; + } + return r; + +free_topckgen_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const char *const mcu_bus_div_parents[] = { "top_xtal", "ccipll2_b", + "net1pll_d4" }; + +static const char *const mcu_arm_div_parents[] = { "top_xtal", "arm_b", + "net1pll_d4" }; + +static struct mtk_composite mcu_muxes[] = { + /* bus_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_BUS_DIV_SEL, "mcu_bus_div_sel", + mcu_bus_div_parents, 0x7C0, 9, 2, -1, CLK_IS_CRITICAL), + /* mp2_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_ARM_DIV_SEL, "mcu_arm_div_sel", + mcu_arm_div_parents, 0x7A8, 9, 2, -1, CLK_IS_CRITICAL), +}; + +static int clk_mt7988_mcusys_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(mcu_muxes); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + &mt7988_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_mcusys_data; + } + return r; + +free_mcusys_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct of_device_id of_match_clk_mt7988_topckgen[] = { + { + .compatible = "mediatek,mt7988-topckgen", + }, + {} +}; + +static struct platform_driver clk_mt7988_topckgen_drv = { + .probe = clk_mt7988_topckgen_probe, + .driver = { + .name = "clk-mt7988-topckgen", + .of_match_table = of_match_clk_mt7988_topckgen, + }, +}; +builtin_platform_driver(clk_mt7988_topckgen_drv); + +static const struct of_device_id of_match_clk_mt7988_mcusys[] = { + { + .compatible = "mediatek,mt7988-mcusys", + }, + {} +}; + +static struct platform_driver clk_mt7988_mcusys_drv = { + .probe = clk_mt7988_mcusys_probe, + .driver = { + .name = "clk-mt7988-mcusys", + .of_match_table = of_match_clk_mt7988_mcusys, + }, +}; +builtin_platform_driver(clk_mt7988_mcusys_drv); \ No newline at end of file diff --git a/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h new file mode 100644 index 00000000000..77cfea4a8ea --- /dev/null +++ b/target/linux/mediatek/files-5.15/include/dt-bindings/clock/mediatek,mt7988-clk.h @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (c) 2023 MediaTek Inc. + * Author: Sam Shih + * Author: Xiufeng Li + */ + +#ifndef _DT_BINDINGS_CLK_MT7988_H +#define _DT_BINDINGS_CLK_MT7988_H + +/* APMIXEDSYS */ + +#define CLK_APMIXED_NETSYSPLL 0 +#define CLK_APMIXED_MPLL 1 +#define CLK_APMIXED_MMPLL 2 +#define CLK_APMIXED_APLL2 3 +#define CLK_APMIXED_NET1PLL 4 +#define CLK_APMIXED_NET2PLL 5 +#define CLK_APMIXED_WEDMCUPLL 6 +#define CLK_APMIXED_SGMPLL 7 +#define CLK_APMIXED_ARM_B 8 +#define CLK_APMIXED_CCIPLL2_B 9 +#define CLK_APMIXED_USXGMIIPLL 10 +#define CLK_APMIXED_MSDCPLL 11 + +/* TOPCKGEN */ + +#define CLK_TOP_XTAL 0 +#define CLK_TOP_XTAL_D2 1 +#define CLK_TOP_RTC_32K 2 +#define CLK_TOP_RTC_32P7K 3 +#define CLK_TOP_MPLL_D2 4 +#define CLK_TOP_MPLL_D3_D2 5 +#define CLK_TOP_MPLL_D4 6 +#define CLK_TOP_MPLL_D8 7 +#define CLK_TOP_MPLL_D8_D2 8 +#define CLK_TOP_MMPLL_D2 9 +#define CLK_TOP_MMPLL_D3_D5 10 +#define CLK_TOP_MMPLL_D4 11 +#define CLK_TOP_MMPLL_D6_D2 12 +#define CLK_TOP_MMPLL_D8 13 +#define CLK_TOP_APLL2_D4 14 +#define CLK_TOP_NET1PLL_D4 15 +#define CLK_TOP_NET1PLL_D5 16 +#define CLK_TOP_NET1PLL_D5_D2 17 +#define CLK_TOP_NET1PLL_D5_D4 18 +#define CLK_TOP_NET1PLL_D8 19 +#define CLK_TOP_NET1PLL_D8_D2 20 +#define CLK_TOP_NET1PLL_D8_D4 21 +#define CLK_TOP_NET1PLL_D8_D8 22 +#define CLK_TOP_NET1PLL_D8_D16 23 +#define CLK_TOP_NET2PLL_D2 24 +#define CLK_TOP_NET2PLL_D4 25 +#define CLK_TOP_NET2PLL_D4_D4 26 +#define CLK_TOP_NET2PLL_D4_D8 27 +#define CLK_TOP_NET2PLL_D6 28 +#define CLK_TOP_NET2PLL_D8 29 +#define CLK_TOP_NETSYS_SEL 30 +#define CLK_TOP_NETSYS_500M_SEL 31 +#define CLK_TOP_NETSYS_2X_SEL 32 +#define CLK_TOP_NETSYS_GSW_SEL 33 +#define CLK_TOP_ETH_GMII_SEL 34 +#define CLK_TOP_NETSYS_MCU_SEL 35 +#define CLK_TOP_NETSYS_PAO_2X_SEL 36 +#define CLK_TOP_EIP197_SEL 37 +#define CLK_TOP_AXI_INFRA_SEL 38 +#define CLK_TOP_UART_SEL 39 +#define CLK_TOP_EMMC_250M_SEL 40 +#define CLK_TOP_EMMC_400M_SEL 41 +#define CLK_TOP_SPI_SEL 42 +#define CLK_TOP_SPIM_MST_SEL 43 +#define CLK_TOP_NFI1X_SEL 44 +#define CLK_TOP_SPINFI_SEL 45 +#define CLK_TOP_PWM_SEL 46 +#define CLK_TOP_I2C_SEL 47 +#define CLK_TOP_PCIE_MBIST_250M_SEL 48 +#define CLK_TOP_PEXTP_TL_SEL 49 +#define CLK_TOP_PEXTP_TL_P1_SEL 50 +#define CLK_TOP_PEXTP_TL_P2_SEL 51 +#define CLK_TOP_PEXTP_TL_P3_SEL 52 +#define CLK_TOP_USB_SYS_SEL 53 +#define CLK_TOP_USB_SYS_P1_SEL 54 +#define CLK_TOP_USB_XHCI_SEL 55 +#define CLK_TOP_USB_XHCI_P1_SEL 56 +#define CLK_TOP_USB_FRMCNT_SEL 57 +#define CLK_TOP_USB_FRMCNT_P1_SEL 58 +#define CLK_TOP_AUD_SEL 59 +#define CLK_TOP_A1SYS_SEL 60 +#define CLK_TOP_AUD_L_SEL 61 +#define CLK_TOP_A_TUNER_SEL 62 +#define CLK_TOP_SSPXTP_SEL 63 +#define CLK_TOP_USB_PHY_SEL 64 +#define CLK_TOP_USXGMII_SBUS_0_SEL 65 +#define CLK_TOP_USXGMII_SBUS_1_SEL 66 +#define CLK_TOP_SGM_0_SEL 67 +#define CLK_TOP_SGM_SBUS_0_SEL 68 +#define CLK_TOP_SGM_1_SEL 69 +#define CLK_TOP_SGM_SBUS_1_SEL 70 +#define CLK_TOP_XFI_PHY_0_XTAL_SEL 71 +#define CLK_TOP_XFI_PHY_1_XTAL_SEL 72 +#define CLK_TOP_SYSAXI_SEL 73 +#define CLK_TOP_SYSAPB_SEL 74 +#define CLK_TOP_ETH_REFCK_50M_SEL 75 +#define CLK_TOP_ETH_SYS_200M_SEL 76 +#define CLK_TOP_ETH_SYS_SEL 77 +#define CLK_TOP_ETH_XGMII_SEL 78 +#define CLK_TOP_BUS_TOPS_SEL 79 +#define CLK_TOP_NPU_TOPS_SEL 80 +#define CLK_TOP_DRAMC_SEL 81 +#define CLK_TOP_DRAMC_MD32_SEL 82 +#define CLK_TOP_INFRA_F26M_SEL 83 +#define CLK_TOP_PEXTP_P0_SEL 84 +#define CLK_TOP_PEXTP_P1_SEL 85 +#define CLK_TOP_PEXTP_P2_SEL 86 +#define CLK_TOP_PEXTP_P3_SEL 87 +#define CLK_TOP_DA_XTP_GLB_P0_SEL 88 +#define CLK_TOP_DA_XTP_GLB_P1_SEL 89 +#define CLK_TOP_DA_XTP_GLB_P2_SEL 90 +#define CLK_TOP_DA_XTP_GLB_P3_SEL 91 +#define CLK_TOP_CKM_SEL 92 +#define CLK_TOP_DA_SEL 93 +#define CLK_TOP_PEXTP_SEL 94 +#define CLK_TOP_TOPS_P2_26M_SEL 95 +#define CLK_TOP_MCUSYS_BACKUP_625M_SEL 96 +#define CLK_TOP_NETSYS_SYNC_250M_SEL 97 +#define CLK_TOP_MACSEC_SEL 98 +#define CLK_TOP_NETSYS_TOPS_400M_SEL 99 +#define CLK_TOP_NETSYS_PPEFB_250M_SEL 100 +#define CLK_TOP_NETSYS_WARP_SEL 101 +#define CLK_TOP_ETH_MII_SEL 102 +#define CLK_TOP_NPU_SEL 103 +#define CLK_TOP_AUD_I2S_M 104 + +/* MCUSYS */ + +#define CLK_MCU_BUS_DIV_SEL 0 +#define CLK_MCU_ARM_DIV_SEL 1 + +/* INFRACFG_AO */ + +#define CLK_INFRA_MUX_UART0_SEL 0 +#define CLK_INFRA_MUX_UART1_SEL 1 +#define CLK_INFRA_MUX_UART2_SEL 2 +#define CLK_INFRA_MUX_SPI0_SEL 3 +#define CLK_INFRA_MUX_SPI1_SEL 4 +#define CLK_INFRA_MUX_SPI2_SEL 5 +#define CLK_INFRA_PWM_SEL 6 +#define CLK_INFRA_PWM_CK1_SEL 7 +#define CLK_INFRA_PWM_CK2_SEL 8 +#define CLK_INFRA_PWM_CK3_SEL 9 +#define CLK_INFRA_PWM_CK4_SEL 10 +#define CLK_INFRA_PWM_CK5_SEL 11 +#define CLK_INFRA_PWM_CK6_SEL 12 +#define CLK_INFRA_PWM_CK7_SEL 13 +#define CLK_INFRA_PWM_CK8_SEL 14 +#define CLK_INFRA_PCIE_GFMUX_TL_O_P0_SEL 15 +#define CLK_INFRA_PCIE_GFMUX_TL_O_P1_SEL 16 +#define CLK_INFRA_PCIE_GFMUX_TL_O_P2_SEL 17 +#define CLK_INFRA_PCIE_GFMUX_TL_O_P3_SEL 18 + +/* INFRACFG */ + +#define CLK_INFRA_PCIE_PERI_26M_CK_P0 19 +#define CLK_INFRA_PCIE_PERI_26M_CK_P1 20 +#define CLK_INFRA_PCIE_PERI_26M_CK_P2 21 +#define CLK_INFRA_PCIE_PERI_26M_CK_P3 22 +#define CLK_INFRA_66M_GPT_BCK 23 +#define CLK_INFRA_66M_PWM_HCK 24 +#define CLK_INFRA_66M_PWM_BCK 25 +#define CLK_INFRA_66M_PWM_CK1 26 +#define CLK_INFRA_66M_PWM_CK2 27 +#define CLK_INFRA_66M_PWM_CK3 28 +#define CLK_INFRA_66M_PWM_CK4 29 +#define CLK_INFRA_66M_PWM_CK5 30 +#define CLK_INFRA_66M_PWM_CK6 31 +#define CLK_INFRA_66M_PWM_CK7 32 +#define CLK_INFRA_66M_PWM_CK8 33 +#define CLK_INFRA_133M_CQDMA_BCK 34 +#define CLK_INFRA_66M_AUD_SLV_BCK 35 +#define CLK_INFRA_AUD_26M 36 +#define CLK_INFRA_AUD_L 37 +#define CLK_INFRA_AUD_AUD 38 +#define CLK_INFRA_AUD_EG2 39 +#define CLK_INFRA_DRAMC_F26M 40 +#define CLK_INFRA_133M_DBG_ACKM 41 +#define CLK_INFRA_66M_AP_DMA_BCK 42 +#define CLK_INFRA_66M_SEJ_BCK 43 +#define CLK_INFRA_PRE_CK_SEJ_F13M 44 +#define CLK_INFRA_26M_THERM_SYSTEM 45 +#define CLK_INFRA_I2C_BCK 46 +#define CLK_INFRA_52M_UART0_CK 47 +#define CLK_INFRA_52M_UART1_CK 48 +#define CLK_INFRA_52M_UART2_CK 49 +#define CLK_INFRA_NFI 50 +#define CLK_INFRA_SPINFI 51 +#define CLK_INFRA_66M_NFI_HCK 52 +#define CLK_INFRA_104M_SPI0 53 +#define CLK_INFRA_104M_SPI1 54 +#define CLK_INFRA_104M_SPI2_BCK 55 +#define CLK_INFRA_66M_SPI0_HCK 56 +#define CLK_INFRA_66M_SPI1_HCK 57 +#define CLK_INFRA_66M_SPI2_HCK 58 +#define CLK_INFRA_66M_FLASHIF_AXI 59 +#define CLK_INFRA_RTC 60 +#define CLK_INFRA_26M_ADC_BCK 61 +#define CLK_INFRA_RC_ADC 62 +#define CLK_INFRA_MSDC400 63 +#define CLK_INFRA_MSDC2_HCK 64 +#define CLK_INFRA_133M_MSDC_0_HCK 65 +#define CLK_INFRA_66M_MSDC_0_HCK 66 +#define CLK_INFRA_133M_CPUM_BCK 67 +#define CLK_INFRA_BIST2FPC 68 +#define CLK_INFRA_I2C_X16W_MCK_CK_P1 69 +#define CLK_INFRA_I2C_X16W_PCK_CK_P1 70 +#define CLK_INFRA_133M_USB_HCK 71 +#define CLK_INFRA_133M_USB_HCK_CK_P1 72 +#define CLK_INFRA_66M_USB_HCK 73 +#define CLK_INFRA_66M_USB_HCK_CK_P1 74 +#define CLK_INFRA_USB_SYS 75 +#define CLK_INFRA_USB_SYS_CK_P1 76 +#define CLK_INFRA_USB_REF 77 +#define CLK_INFRA_USB_CK_P1 78 +#define CLK_INFRA_USB_FRMCNT 79 +#define CLK_INFRA_USB_FRMCNT_CK_P1 80 +#define CLK_INFRA_USB_PIPE 81 +#define CLK_INFRA_USB_PIPE_CK_P1 82 +#define CLK_INFRA_USB_UTMI 83 +#define CLK_INFRA_USB_UTMI_CK_P1 84 +#define CLK_INFRA_USB_XHCI 85 +#define CLK_INFRA_USB_XHCI_CK_P1 86 +#define CLK_INFRA_PCIE_GFMUX_TL_P0 87 +#define CLK_INFRA_PCIE_GFMUX_TL_P1 88 +#define CLK_INFRA_PCIE_GFMUX_TL_P2 89 +#define CLK_INFRA_PCIE_GFMUX_TL_P3 90 +#define CLK_INFRA_PCIE_PIPE_P0 91 +#define CLK_INFRA_PCIE_PIPE_P1 92 +#define CLK_INFRA_PCIE_PIPE_P2 93 +#define CLK_INFRA_PCIE_PIPE_P3 94 +#define CLK_INFRA_133M_PCIE_CK_P0 95 +#define CLK_INFRA_133M_PCIE_CK_P1 96 +#define CLK_INFRA_133M_PCIE_CK_P2 97 +#define CLK_INFRA_133M_PCIE_CK_P3 98 + +/* ETHDMA */ + +#define CLK_ETHDMA_XGP1_EN 0 +#define CLK_ETHDMA_XGP2_EN 1 +#define CLK_ETHDMA_XGP3_EN 2 +#define CLK_ETHDMA_FE_EN 3 +#define CLK_ETHDMA_GP2_EN 4 +#define CLK_ETHDMA_GP1_EN 5 +#define CLK_ETHDMA_GP3_EN 6 +#define CLK_ETHDMA_ESW_EN 7 +#define CLK_ETHDMA_CRYPT0_EN 8 +#define CLK_ETHDMA_NR_CLK 9 + +/* SGMIISYS_0 */ + +#define CLK_SGM0_TX_EN 0 +#define CLK_SGM0_RX_EN 1 +#define CLK_SGMII0_NR_CLK 2 + +/* SGMIISYS_1 */ + +#define CLK_SGM1_TX_EN 0 +#define CLK_SGM1_RX_EN 1 +#define CLK_SGMII1_NR_CLK 2 + +/* ETHWARP */ + +#define CLK_ETHWARP_WOCPU2_EN 0 +#define CLK_ETHWARP_WOCPU1_EN 1 +#define CLK_ETHWARP_WOCPU0_EN 2 +#define CLK_ETHWARP_NR_CLK 3 + +#endif /* _DT_BINDINGS_CLK_MT7988_H */ diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 9df1494ca09..9f1c6f69395 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -60,6 +60,7 @@ CONFIG_COMMON_CLK_MT7981=y CONFIG_COMMON_CLK_MT7981_ETHSYS=y CONFIG_COMMON_CLK_MT7986=y CONFIG_COMMON_CLK_MT7986_ETHSYS=y +CONFIG_COMMON_CLK_MT7988=y # CONFIG_COMMON_CLK_MT8173 is not set # CONFIG_COMMON_CLK_MT8183 is not set # CONFIG_COMMON_CLK_MT8516 is not set diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index ac09c8a9c47..56e855c5590 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -71,6 +71,7 @@ CONFIG_COMMON_CLK_MT7622_ETHSYS=y CONFIG_COMMON_CLK_MT7622_HIFSYS=y # CONFIG_COMMON_CLK_MT7981 is not set # CONFIG_COMMON_CLK_MT7986 is not set +# CONFIG_COMMON_CLK_MT7988 is not set # CONFIG_COMMON_CLK_MT8173 is not set # CONFIG_COMMON_CLK_MT8183 is not set # CONFIG_COMMON_CLK_MT8183_AUDIOSYS is not set diff --git a/target/linux/mediatek/mt7623/config-5.15 b/target/linux/mediatek/mt7623/config-5.15 index fb9588ee4f7..77d20a3bdba 100644 --- a/target/linux/mediatek/mt7623/config-5.15 +++ b/target/linux/mediatek/mt7623/config-5.15 @@ -71,6 +71,7 @@ CONFIG_COMMON_CLK_MT2701_VDECSYS=y # CONFIG_COMMON_CLK_MT7629 is not set # CONFIG_COMMON_CLK_MT7981 is not set # CONFIG_COMMON_CLK_MT7986 is not set +# CONFIG_COMMON_CLK_MT7988 is not set # CONFIG_COMMON_CLK_MT8135 is not set # CONFIG_COMMON_CLK_MT8173 is not set CONFIG_COMMON_CLK_MT8516=y diff --git a/target/linux/mediatek/mt7629/config-5.15 b/target/linux/mediatek/mt7629/config-5.15 index 709be00c744..46b444108bc 100644 --- a/target/linux/mediatek/mt7629/config-5.15 +++ b/target/linux/mediatek/mt7629/config-5.15 @@ -53,6 +53,7 @@ CONFIG_COMMON_CLK_MT7629_ETHSYS=y CONFIG_COMMON_CLK_MT7629_HIFSYS=y # CONFIG_COMMON_CLK_MT7981 is not set # CONFIG_COMMON_CLK_MT7986 is not set +# CONFIG_COMMON_CLK_MT7988 is not set # CONFIG_COMMON_CLK_MT8135 is not set # CONFIG_COMMON_CLK_MT8173 is not set CONFIG_COMMON_CLK_MT8516=y diff --git a/target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch b/target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch new file mode 100644 index 00000000000..23a5b7c911a --- /dev/null +++ b/target/linux/mediatek/patches-5.15/241-clk-mediatek-Add-pcw-chg-shift-control.patch @@ -0,0 +1,24 @@ +--- a/drivers/clk/mediatek/clk-mtk.h ++++ b/drivers/clk/mediatek/clk-mtk.h +@@ -233,6 +233,7 @@ struct mtk_pll_data { + u32 pcw_reg; + int pcw_shift; + u32 pcw_chg_reg; ++ int pcw_chg_shift; + const struct mtk_pll_div_table *div_table; + const char *parent_name; + u32 en_reg; +--- a/drivers/clk/mediatek/clk-pll.c ++++ b/drivers/clk/mediatek/clk-pll.c +@@ -137,7 +137,10 @@ static void mtk_pll_set_rate_regs(struct + pll->data->pcw_shift); + val |= pcw << pll->data->pcw_shift; + writel(val, pll->pcw_addr); +- chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; ++ if (pll->data->pcw_chg_shift) ++ chg = readl(pll->pcw_chg_addr) | BIT(pll->data->pcw_chg_shift); ++ else ++ chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; + writel(chg, pll->pcw_chg_addr); + if (pll->tuner_addr) + writel(val + 1, pll->tuner_addr); diff --git a/target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch b/target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch new file mode 100644 index 00000000000..bf9146352a6 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/242-clk-mediatek-add-mt7988-clock-support.patch @@ -0,0 +1,31 @@ +--- a/drivers/clk/mediatek/Kconfig ++++ b/drivers/clk/mediatek/Kconfig +@@ -378,6 +378,15 @@ config COMMON_CLK_MT7986_ETHSYS + This driver add support for clocks for Ethernet and SGMII + required on MediaTek MT7986 SoC. + ++config COMMON_CLK_MT7988 ++ bool "Clock driver for MediaTek MT7988" ++ depends on ARCH_MEDIATEK || COMPILE_TEST ++ select COMMON_CLK_MEDIATEK ++ default ARCH_MEDIATEK ++ help ++ This driver supports MediaTek MT7988 basic clocks and clocks ++ required for various periperals found on MediaTek. ++ + config COMMON_CLK_MT8135 + bool "Clock driver for MediaTek MT8135" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST +--- a/drivers/clk/mediatek/Makefile ++++ b/drivers/clk/mediatek/Makefile +@@ -54,6 +54,10 @@ obj-$(CONFIG_COMMON_CLK_MT7986) += clk-m + obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o + obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o + obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o ++obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-apmixed.o ++obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-topckgen.o ++obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-infracfg.o ++obj-$(CONFIG_COMMON_CLK_MT7988) += clk-mt7988-eth.o + obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o + obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o + obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o From 9e6a7e808f2e9dd02733ccc41827940fb421091d Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Sun, 19 Feb 2023 10:15:10 +0800 Subject: [PATCH 10/43] mediatek: add mt7988 pinctrl driver support This adds provisional pinctrl driver support for the MediaTek MT7988 SoC. Signed-off-by: Sam Shih Signed-off-by: Daniel Golle --- .../drivers/pinctrl/mediatek/pinctrl-mt7988.c | 1281 +++++++++++++++++ target/linux/mediatek/filogic/config-5.15 | 1 + target/linux/mediatek/mt7622/config-5.15 | 1 + ...-mediatek-add-support-for-MT7988-SoC.patch | 26 + 4 files changed, 1309 insertions(+) create mode 100644 target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c create mode 100644 target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch diff --git a/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c new file mode 100644 index 00000000000..80a7e19f7a2 --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/pinctrl/mediatek/pinctrl-mt7988.c @@ -0,0 +1,1281 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * The MT7988 driver based on Linux generic pinctrl binding. + * + * Copyright (C) 2020 MediaTek Inc. + * Author: Sam Shih + */ + +#include "pinctrl-moore.h" + +enum MT7988_PINCTRL_REG_PAGE { + GPIO_BASE, + IOCFG_TR_BASE, + IOCFG_BR_BASE, + IOCFG_RB_BASE, + IOCFG_LB_BASE, + IOCFG_TL_BASE, +}; + +#define MT7988_PIN(_number, _name) MTK_PIN(_number, _name, 0, _number, DRV_GRP4) + +#define PIN_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ + _x_bits) \ + PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 32, 0) + +#define PINS_FIELD_BASE(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ + _x_bits) \ + PIN_FIELD_CALC(_s_pin, _e_pin, _i_base, _s_addr, _x_addrs, _s_bit, \ + _x_bits, 32, 1) + +static const struct mtk_pin_field_calc mt7988_pin_mode_range[] = { + PIN_FIELD(0, 83, 0x300, 0x10, 0, 4), +}; + +static const struct mtk_pin_field_calc mt7988_pin_dir_range[] = { + PIN_FIELD(0, 83, 0x0, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_di_range[] = { + PIN_FIELD(0, 83, 0x200, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_do_range[] = { + PIN_FIELD(0, 83, 0x100, 0x10, 0, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_ies_range[] = { + PIN_FIELD_BASE(0, 1, 5, 0x30, 0x10, 13, 1), + PIN_FIELD_BASE(2, 3, 5, 0x30, 0x10, 11, 1), + PIN_FIELD_BASE(4, 4, 5, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, 5, 0x30, 0x10, 9, 1), + PIN_FIELD_BASE(7, 7, 4, 0x30, 0x10, 8, 1), + PIN_FIELD_BASE(8, 8, 4, 0x30, 0x10, 6, 1), + PIN_FIELD_BASE(9, 9, 4, 0x30, 0x10, 5, 1), + PIN_FIELD_BASE(10, 10, 4, 0x30, 0x10, 3, 1), + PIN_FIELD_BASE(11, 11, 1, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(12, 12, 1, 0x40, 0x10, 21, 1), + PIN_FIELD_BASE(13, 14, 1, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(15, 16, 5, 0x30, 0x10, 7, 1), + PIN_FIELD_BASE(17, 18, 5, 0x30, 0x10, 3, 1), + PIN_FIELD_BASE(19, 19, 4, 0x30, 0x10, 7, 1), + PIN_FIELD_BASE(20, 20, 4, 0x30, 0x10, 4, 1), + PIN_FIELD_BASE(21, 21, 3, 0x50, 0x10, 17, 1), + PIN_FIELD_BASE(22, 22, 3, 0x50, 0x10, 23, 1), + PIN_FIELD_BASE(23, 23, 3, 0x50, 0x10, 20, 1), + PIN_FIELD_BASE(24, 24, 3, 0x50, 0x10, 19, 1), + PIN_FIELD_BASE(25, 26, 3, 0x50, 0x10, 21, 1), + PIN_FIELD_BASE(27, 27, 3, 0x50, 0x10, 18, 1), + PIN_FIELD_BASE(28, 30, 3, 0x50, 0x10, 25, 1), + PIN_FIELD_BASE(31, 31, 3, 0x50, 0x10, 24, 1), + PIN_FIELD_BASE(32, 32, 3, 0x50, 0x10, 28, 1), + PIN_FIELD_BASE(33, 33, 3, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 3, 0x50, 0x10, 31, 1), + PIN_FIELD_BASE(35, 36, 3, 0x50, 0x10, 29, 1), + PIN_FIELD_BASE(37, 37, 3, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 3, 0x50, 0x10, 11, 1), + PIN_FIELD_BASE(39, 39, 3, 0x50, 0x10, 10, 1), + PIN_FIELD_BASE(40, 41, 3, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(42, 42, 3, 0x50, 0x10, 9, 1), + PIN_FIELD_BASE(43, 43, 3, 0x50, 0x10, 8, 1), + PIN_FIELD_BASE(44, 44, 3, 0x50, 0x10, 7, 1), + PIN_FIELD_BASE(45, 45, 3, 0x50, 0x10, 6, 1), + PIN_FIELD_BASE(46, 46, 3, 0x50, 0x10, 5, 1), + PIN_FIELD_BASE(47, 47, 3, 0x50, 0x10, 4, 1), + PIN_FIELD_BASE(48, 48, 3, 0x50, 0x10, 3, 1), + PIN_FIELD_BASE(49, 49, 3, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(50, 50, 3, 0x50, 0x10, 15, 1), + PIN_FIELD_BASE(51, 53, 3, 0x50, 0x10, 12, 1), + PIN_FIELD_BASE(54, 54, 3, 0x50, 0x10, 16, 1), + PIN_FIELD_BASE(55, 56, 1, 0x40, 0x10, 14, 1), + PIN_FIELD_BASE(57, 57, 1, 0x40, 0x10, 13, 1), + PIN_FIELD_BASE(58, 60, 1, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(61, 61, 1, 0x40, 0x10, 3, 1), + PIN_FIELD_BASE(62, 62, 1, 0x40, 0x10, 7, 1), + PIN_FIELD_BASE(63, 63, 1, 0x40, 0x10, 20, 1), + PIN_FIELD_BASE(64, 68, 1, 0x40, 0x10, 8, 1), + PIN_FIELD_BASE(69, 70, 5, 0x30, 0x10, 1, 1), + PIN_FIELD_BASE(71, 72, 5, 0x30, 0x10, 5, 1), + PIN_FIELD_BASE(73, 73, 4, 0x30, 0x10, 10, 1), + PIN_FIELD_BASE(74, 74, 4, 0x30, 0x10, 1, 1), + PIN_FIELD_BASE(75, 75, 4, 0x30, 0x10, 11, 1), + PIN_FIELD_BASE(76, 76, 4, 0x30, 0x10, 9, 1), + PIN_FIELD_BASE(77, 77, 4, 0x30, 0x10, 2, 1), + PIN_FIELD_BASE(78, 78, 4, 0x30, 0x10, 0, 1), + PIN_FIELD_BASE(79, 79, 4, 0x30, 0x10, 12, 1), + PIN_FIELD_BASE(80, 81, 1, 0x40, 0x10, 18, 1), + PIN_FIELD_BASE(82, 83, 1, 0x40, 0x10, 16, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_smt_range[] = { + PIN_FIELD_BASE(0, 1, 5, 0xc0, 0x10, 13, 1), + PIN_FIELD_BASE(2, 3, 5, 0xc0, 0x10, 11, 1), + PIN_FIELD_BASE(4, 4, 5, 0xc0, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, 5, 0xc0, 0x10, 9, 1), + PIN_FIELD_BASE(7, 7, 4, 0xb0, 0x10, 8, 1), + PIN_FIELD_BASE(8, 8, 4, 0xb0, 0x10, 6, 1), + PIN_FIELD_BASE(9, 9, 4, 0xb0, 0x10, 5, 1), + PIN_FIELD_BASE(10, 10, 4, 0xb0, 0x10, 3, 1), + PIN_FIELD_BASE(11, 11, 1, 0xe0, 0x10, 0, 1), + PIN_FIELD_BASE(12, 12, 1, 0xe0, 0x10, 21, 1), + PIN_FIELD_BASE(13, 14, 1, 0xe0, 0x10, 1, 1), + PIN_FIELD_BASE(15, 16, 5, 0xc0, 0x10, 7, 1), + PIN_FIELD_BASE(17, 18, 5, 0xc0, 0x10, 3, 1), + PIN_FIELD_BASE(19, 19, 4, 0xb0, 0x10, 7, 1), + PIN_FIELD_BASE(20, 20, 4, 0xb0, 0x10, 4, 1), + PIN_FIELD_BASE(21, 21, 3, 0x140, 0x10, 17, 1), + PIN_FIELD_BASE(22, 22, 3, 0x140, 0x10, 23, 1), + PIN_FIELD_BASE(23, 23, 3, 0x140, 0x10, 20, 1), + PIN_FIELD_BASE(24, 24, 3, 0x140, 0x10, 19, 1), + PIN_FIELD_BASE(25, 26, 3, 0x140, 0x10, 21, 1), + PIN_FIELD_BASE(27, 27, 3, 0x140, 0x10, 18, 1), + PIN_FIELD_BASE(28, 30, 3, 0x140, 0x10, 25, 1), + PIN_FIELD_BASE(31, 31, 3, 0x140, 0x10, 24, 1), + PIN_FIELD_BASE(32, 32, 3, 0x140, 0x10, 28, 1), + PIN_FIELD_BASE(33, 33, 3, 0x150, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 3, 0x140, 0x10, 31, 1), + PIN_FIELD_BASE(35, 36, 3, 0x140, 0x10, 29, 1), + PIN_FIELD_BASE(37, 37, 3, 0x150, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 3, 0x140, 0x10, 11, 1), + PIN_FIELD_BASE(39, 39, 3, 0x140, 0x10, 10, 1), + PIN_FIELD_BASE(40, 41, 3, 0x140, 0x10, 0, 1), + PIN_FIELD_BASE(42, 42, 3, 0x140, 0x10, 9, 1), + PIN_FIELD_BASE(43, 43, 3, 0x140, 0x10, 8, 1), + PIN_FIELD_BASE(44, 44, 3, 0x140, 0x10, 7, 1), + PIN_FIELD_BASE(45, 45, 3, 0x140, 0x10, 6, 1), + PIN_FIELD_BASE(46, 46, 3, 0x140, 0x10, 5, 1), + PIN_FIELD_BASE(47, 47, 3, 0x140, 0x10, 4, 1), + PIN_FIELD_BASE(48, 48, 3, 0x140, 0x10, 3, 1), + PIN_FIELD_BASE(49, 49, 3, 0x140, 0x10, 2, 1), + PIN_FIELD_BASE(50, 50, 3, 0x140, 0x10, 15, 1), + PIN_FIELD_BASE(51, 53, 3, 0x140, 0x10, 12, 1), + PIN_FIELD_BASE(54, 54, 3, 0x140, 0x10, 16, 1), + PIN_FIELD_BASE(55, 56, 1, 0xe0, 0x10, 14, 1), + PIN_FIELD_BASE(57, 57, 1, 0xe0, 0x10, 13, 1), + PIN_FIELD_BASE(58, 60, 1, 0xe0, 0x10, 4, 1), + PIN_FIELD_BASE(61, 61, 1, 0xe0, 0x10, 3, 1), + PIN_FIELD_BASE(62, 62, 1, 0xe0, 0x10, 7, 1), + PIN_FIELD_BASE(63, 63, 1, 0xe0, 0x10, 20, 1), + PIN_FIELD_BASE(64, 68, 1, 0xe0, 0x10, 8, 1), + PIN_FIELD_BASE(69, 70, 5, 0xc0, 0x10, 1, 1), + PIN_FIELD_BASE(71, 72, 5, 0xc0, 0x10, 5, 1), + PIN_FIELD_BASE(73, 73, 4, 0xb0, 0x10, 10, 1), + PIN_FIELD_BASE(74, 74, 4, 0xb0, 0x10, 1, 1), + PIN_FIELD_BASE(75, 75, 4, 0xb0, 0x10, 11, 1), + PIN_FIELD_BASE(76, 76, 4, 0xb0, 0x10, 9, 1), + PIN_FIELD_BASE(77, 77, 4, 0xb0, 0x10, 2, 1), + PIN_FIELD_BASE(78, 78, 4, 0xb0, 0x10, 0, 1), + PIN_FIELD_BASE(79, 79, 4, 0xb0, 0x10, 12, 1), + PIN_FIELD_BASE(80, 81, 1, 0xe0, 0x10, 18, 1), + PIN_FIELD_BASE(82, 83, 1, 0xe0, 0x10, 16, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_pu_range[] = { + PIN_FIELD_BASE(7, 7, 4, 0x60, 0x10, 5, 1), + PIN_FIELD_BASE(8, 8, 4, 0x60, 0x10, 4, 1), + PIN_FIELD_BASE(9, 9, 4, 0x60, 0x10, 3, 1), + PIN_FIELD_BASE(10, 10, 4, 0x60, 0x10, 2, 1), + PIN_FIELD_BASE(13, 14, 1, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(63, 63, 1, 0x70, 0x10, 2, 1), + PIN_FIELD_BASE(75, 75, 4, 0x60, 0x10, 7, 1), + PIN_FIELD_BASE(76, 76, 4, 0x60, 0x10, 6, 1), + PIN_FIELD_BASE(77, 77, 4, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(78, 78, 4, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(79, 79, 4, 0x60, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_pd_range[] = { + PIN_FIELD_BASE(7, 7, 4, 0x40, 0x10, 5, 1), + PIN_FIELD_BASE(8, 8, 4, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(9, 9, 4, 0x40, 0x10, 3, 1), + PIN_FIELD_BASE(10, 10, 4, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(13, 14, 1, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(15, 16, 5, 0x40, 0x10, 4, 1), + PIN_FIELD_BASE(17, 18, 5, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(63, 63, 1, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(71, 72, 5, 0x40, 0x10, 2, 1), + PIN_FIELD_BASE(75, 75, 4, 0x40, 0x10, 7, 1), + PIN_FIELD_BASE(76, 76, 4, 0x40, 0x10, 6, 1), + PIN_FIELD_BASE(77, 77, 4, 0x40, 0x10, 1, 1), + PIN_FIELD_BASE(78, 78, 4, 0x40, 0x10, 0, 1), + PIN_FIELD_BASE(79, 79, 4, 0x40, 0x10, 8, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_drv_range[] = { + PIN_FIELD_BASE(0, 1, 5, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(2, 3, 5, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(4, 4, 5, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(5, 6, 5, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(7, 7, 4, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(8, 8, 4, 0x00, 0x10, 28, 3), + PIN_FIELD_BASE(9, 9, 4, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(10, 10, 4, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(11, 11, 1, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(12, 12, 1, 0x20, 0x10, 3, 3), + PIN_FIELD_BASE(13, 14, 1, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(19, 19, 4, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(20, 20, 4, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(21, 21, 3, 0x10, 0x10, 21, 3), + PIN_FIELD_BASE(22, 22, 3, 0x20, 0x10, 9, 3), + PIN_FIELD_BASE(23, 23, 3, 0x20, 0x10, 0, 3), + PIN_FIELD_BASE(24, 24, 3, 0x10, 0x10, 27, 3), + PIN_FIELD_BASE(25, 26, 3, 0x20, 0x10, 3, 3), + PIN_FIELD_BASE(27, 27, 3, 0x10, 0x10, 24, 3), + PIN_FIELD_BASE(28, 30, 3, 0x20, 0x10, 15, 3), + PIN_FIELD_BASE(31, 31, 3, 0x20, 0x10, 12, 3), + PIN_FIELD_BASE(32, 32, 3, 0x20, 0x10, 24, 3), + PIN_FIELD_BASE(33, 33, 3, 0x30, 0x10, 6, 3), + PIN_FIELD_BASE(34, 34, 3, 0x30, 0x10, 3, 3), + PIN_FIELD_BASE(35, 35, 3, 0x20, 0x10, 27, 3), + PIN_FIELD_BASE(36, 36, 3, 0x30, 0x10, 0, 3), + PIN_FIELD_BASE(37, 37, 3, 0x30, 0x10, 9, 3), + PIN_FIELD_BASE(38, 38, 3, 0x10, 0x10, 3, 3), + PIN_FIELD_BASE(39, 39, 3, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(40, 41, 3, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(42, 42, 3, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(43, 43, 3, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(44, 44, 3, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(45, 45, 3, 0x00, 0x10, 18, 3), + PIN_FIELD_BASE(46, 46, 3, 0x00, 0x10, 15, 3), + PIN_FIELD_BASE(47, 47, 3, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(48, 48, 3, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(49, 49, 3, 0x00, 0x10, 6, 3), + PIN_FIELD_BASE(50, 50, 3, 0x10, 0x10, 15, 3), + PIN_FIELD_BASE(51, 53, 3, 0x10, 0x10, 6, 3), + PIN_FIELD_BASE(54, 54, 3, 0x10, 0x10, 18, 3), + PIN_FIELD_BASE(55, 56, 1, 0x10, 0x10, 12, 3), + PIN_FIELD_BASE(57, 57, 1, 0x10, 0x10, 9, 3), + PIN_FIELD_BASE(58, 60, 1, 0x00, 0x10, 12, 3), + PIN_FIELD_BASE(61, 61, 1, 0x00, 0x10, 9, 3), + PIN_FIELD_BASE(62, 62, 1, 0x00, 0x10, 21, 3), + PIN_FIELD_BASE(63, 63, 1, 0x20, 0x10, 0, 3), + PIN_FIELD_BASE(64, 65, 1, 0x00, 0x10, 24, 3), + PIN_FIELD_BASE(66, 68, 1, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(69, 70, 5, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(73, 73, 4, 0x10, 0x10, 0, 3), + PIN_FIELD_BASE(74, 74, 4, 0x00, 0x10, 3, 3), + PIN_FIELD_BASE(75, 75, 4, 0x10, 0x10, 3, 3), + PIN_FIELD_BASE(76, 76, 4, 0x00, 0x10, 27, 3), + PIN_FIELD_BASE(77, 77, 4, 0x00, 0x10, 6, 3), + PIN_FIELD_BASE(78, 78, 4, 0x00, 0x10, 0, 3), + PIN_FIELD_BASE(79, 79, 4, 0x10, 0x10, 6, 3), + PIN_FIELD_BASE(80, 81, 1, 0x10, 0x10, 24, 3), + PIN_FIELD_BASE(82, 83, 1, 0x10, 0x10, 18, 3), +}; + +static const struct mtk_pin_field_calc mt7988_pin_pupd_range[] = { + PIN_FIELD_BASE(0, 1, 5, 0x50, 0x10, 7, 1), + PIN_FIELD_BASE(2, 3, 5, 0x50, 0x10, 5, 1), + PIN_FIELD_BASE(4, 4, 5, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, 5, 0x50, 0x10, 3, 1), + PIN_FIELD_BASE(11, 11, 1, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(12, 12, 1, 0x60, 0x10, 18, 1), + PIN_FIELD_BASE(19, 19, 4, 0x50, 0x10, 2, 1), + PIN_FIELD_BASE(20, 20, 4, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0x70, 0x10, 17, 1), + PIN_FIELD_BASE(22, 22, 3, 0x70, 0x10, 23, 1), + PIN_FIELD_BASE(23, 23, 3, 0x70, 0x10, 20, 1), + PIN_FIELD_BASE(24, 24, 3, 0x70, 0x10, 19, 1), + PIN_FIELD_BASE(25, 26, 3, 0x70, 0x10, 21, 1), + PIN_FIELD_BASE(27, 27, 3, 0x70, 0x10, 18, 1), + PIN_FIELD_BASE(28, 30, 3, 0x70, 0x10, 25, 1), + PIN_FIELD_BASE(31, 31, 3, 0x70, 0x10, 24, 1), + PIN_FIELD_BASE(32, 32, 3, 0x70, 0x10, 28, 1), + PIN_FIELD_BASE(33, 33, 3, 0x80, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 3, 0x70, 0x10, 31, 1), + PIN_FIELD_BASE(35, 36, 3, 0x70, 0x10, 29, 1), + PIN_FIELD_BASE(37, 37, 3, 0x80, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 3, 0x70, 0x10, 11, 1), + PIN_FIELD_BASE(39, 39, 3, 0x70, 0x10, 10, 1), + PIN_FIELD_BASE(40, 41, 3, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(42, 42, 3, 0x70, 0x10, 9, 1), + PIN_FIELD_BASE(43, 43, 3, 0x70, 0x10, 8, 1), + PIN_FIELD_BASE(44, 44, 3, 0x70, 0x10, 7, 1), + PIN_FIELD_BASE(45, 45, 3, 0x70, 0x10, 6, 1), + PIN_FIELD_BASE(46, 46, 3, 0x70, 0x10, 5, 1), + PIN_FIELD_BASE(47, 47, 3, 0x70, 0x10, 4, 1), + PIN_FIELD_BASE(48, 48, 3, 0x70, 0x10, 3, 1), + PIN_FIELD_BASE(49, 49, 3, 0x70, 0x10, 2, 1), + PIN_FIELD_BASE(50, 50, 3, 0x70, 0x10, 15, 1), + PIN_FIELD_BASE(51, 53, 3, 0x70, 0x10, 12, 1), + PIN_FIELD_BASE(54, 54, 3, 0x70, 0x10, 16, 1), + PIN_FIELD_BASE(55, 56, 1, 0x60, 0x10, 12, 1), + PIN_FIELD_BASE(57, 57, 1, 0x60, 0x10, 11, 1), + PIN_FIELD_BASE(58, 60, 1, 0x60, 0x10, 2, 1), + PIN_FIELD_BASE(61, 61, 1, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(62, 62, 1, 0x60, 0x10, 5, 1), + PIN_FIELD_BASE(64, 68, 1, 0x60, 0x10, 6, 1), + PIN_FIELD_BASE(69, 70, 5, 0x50, 0x10, 1, 1), + PIN_FIELD_BASE(73, 73, 4, 0x50, 0x10, 3, 1), + PIN_FIELD_BASE(74, 74, 4, 0x50, 0x10, 0, 1), + PIN_FIELD_BASE(80, 81, 1, 0x60, 0x10, 16, 1), + PIN_FIELD_BASE(82, 83, 1, 0x60, 0x10, 14, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_r0_range[] = { + PIN_FIELD_BASE(0, 1, 5, 0x60, 0x10, 7, 1), + PIN_FIELD_BASE(2, 3, 5, 0x60, 0x10, 5, 1), + PIN_FIELD_BASE(4, 4, 5, 0x60, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, 5, 0x60, 0x10, 3, 1), + PIN_FIELD_BASE(11, 11, 1, 0x80, 0x10, 0, 1), + PIN_FIELD_BASE(12, 12, 1, 0x80, 0x10, 18, 1), + PIN_FIELD_BASE(19, 19, 4, 0x70, 0x10, 2, 1), + PIN_FIELD_BASE(20, 20, 4, 0x70, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0x90, 0x10, 17, 1), + PIN_FIELD_BASE(22, 22, 3, 0x90, 0x10, 23, 1), + PIN_FIELD_BASE(23, 23, 3, 0x90, 0x10, 20, 1), + PIN_FIELD_BASE(24, 24, 3, 0x90, 0x10, 19, 1), + PIN_FIELD_BASE(25, 26, 3, 0x90, 0x10, 21, 1), + PIN_FIELD_BASE(27, 27, 3, 0x90, 0x10, 18, 1), + PIN_FIELD_BASE(28, 30, 3, 0x90, 0x10, 25, 1), + PIN_FIELD_BASE(31, 31, 3, 0x90, 0x10, 24, 1), + PIN_FIELD_BASE(32, 32, 3, 0x90, 0x10, 28, 1), + PIN_FIELD_BASE(33, 33, 3, 0xa0, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 3, 0x90, 0x10, 31, 1), + PIN_FIELD_BASE(35, 36, 3, 0x90, 0x10, 29, 1), + PIN_FIELD_BASE(37, 37, 3, 0xa0, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 3, 0x90, 0x10, 11, 1), + PIN_FIELD_BASE(39, 39, 3, 0x90, 0x10, 10, 1), + PIN_FIELD_BASE(40, 41, 3, 0x90, 0x10, 0, 1), + PIN_FIELD_BASE(42, 42, 3, 0x90, 0x10, 9, 1), + PIN_FIELD_BASE(43, 43, 3, 0x90, 0x10, 8, 1), + PIN_FIELD_BASE(44, 44, 3, 0x90, 0x10, 7, 1), + PIN_FIELD_BASE(45, 45, 3, 0x90, 0x10, 6, 1), + PIN_FIELD_BASE(46, 46, 3, 0x90, 0x10, 5, 1), + PIN_FIELD_BASE(47, 47, 3, 0x90, 0x10, 4, 1), + PIN_FIELD_BASE(48, 48, 3, 0x90, 0x10, 3, 1), + PIN_FIELD_BASE(49, 49, 3, 0x90, 0x10, 2, 1), + PIN_FIELD_BASE(50, 50, 3, 0x90, 0x10, 15, 1), + PIN_FIELD_BASE(51, 53, 3, 0x90, 0x10, 12, 1), + PIN_FIELD_BASE(54, 54, 3, 0x90, 0x10, 16, 1), + PIN_FIELD_BASE(55, 56, 1, 0x80, 0x10, 12, 1), + PIN_FIELD_BASE(57, 57, 1, 0x80, 0x10, 11, 1), + PIN_FIELD_BASE(58, 60, 1, 0x80, 0x10, 2, 1), + PIN_FIELD_BASE(61, 61, 1, 0x80, 0x10, 1, 1), + PIN_FIELD_BASE(62, 62, 1, 0x80, 0x10, 5, 1), + PIN_FIELD_BASE(64, 68, 1, 0x80, 0x10, 6, 1), + PIN_FIELD_BASE(69, 70, 5, 0x60, 0x10, 1, 1), + PIN_FIELD_BASE(73, 73, 4, 0x70, 0x10, 3, 1), + PIN_FIELD_BASE(74, 74, 4, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(80, 81, 1, 0x80, 0x10, 16, 1), + PIN_FIELD_BASE(82, 83, 1, 0x80, 0x10, 14, 1), +}; + +static const struct mtk_pin_field_calc mt7988_pin_r1_range[] = { + PIN_FIELD_BASE(0, 1, 5, 0x70, 0x10, 7, 1), + PIN_FIELD_BASE(2, 3, 5, 0x70, 0x10, 5, 1), + PIN_FIELD_BASE(4, 4, 5, 0x70, 0x10, 0, 1), + PIN_FIELD_BASE(5, 6, 5, 0x70, 0x10, 3, 1), + PIN_FIELD_BASE(11, 11, 1, 0x90, 0x10, 0, 1), + PIN_FIELD_BASE(12, 12, 1, 0x90, 0x10, 18, 1), + PIN_FIELD_BASE(19, 19, 4, 0x80, 0x10, 2, 1), + PIN_FIELD_BASE(20, 20, 4, 0x80, 0x10, 1, 1), + PIN_FIELD_BASE(21, 21, 3, 0xb0, 0x10, 17, 1), + PIN_FIELD_BASE(22, 22, 3, 0xb0, 0x10, 23, 1), + PIN_FIELD_BASE(23, 23, 3, 0xb0, 0x10, 20, 1), + PIN_FIELD_BASE(24, 24, 3, 0xb0, 0x10, 19, 1), + PIN_FIELD_BASE(25, 26, 3, 0xb0, 0x10, 21, 1), + PIN_FIELD_BASE(27, 27, 3, 0xb0, 0x10, 18, 1), + PIN_FIELD_BASE(28, 30, 3, 0xb0, 0x10, 25, 1), + PIN_FIELD_BASE(31, 31, 3, 0xb0, 0x10, 24, 1), + PIN_FIELD_BASE(32, 32, 3, 0xb0, 0x10, 28, 1), + PIN_FIELD_BASE(33, 33, 3, 0xc0, 0x10, 0, 1), + PIN_FIELD_BASE(34, 34, 3, 0xb0, 0x10, 31, 1), + PIN_FIELD_BASE(35, 36, 3, 0xb0, 0x10, 29, 1), + PIN_FIELD_BASE(37, 37, 3, 0xc0, 0x10, 1, 1), + PIN_FIELD_BASE(38, 38, 3, 0xb0, 0x10, 11, 1), + PIN_FIELD_BASE(39, 39, 3, 0xb0, 0x10, 10, 1), + PIN_FIELD_BASE(40, 41, 3, 0xb0, 0x10, 0, 1), + PIN_FIELD_BASE(42, 42, 3, 0xb0, 0x10, 9, 1), + PIN_FIELD_BASE(43, 43, 3, 0xb0, 0x10, 8, 1), + PIN_FIELD_BASE(44, 44, 3, 0xb0, 0x10, 7, 1), + PIN_FIELD_BASE(45, 45, 3, 0xb0, 0x10, 6, 1), + PIN_FIELD_BASE(46, 46, 3, 0xb0, 0x10, 5, 1), + PIN_FIELD_BASE(47, 47, 3, 0xb0, 0x10, 4, 1), + PIN_FIELD_BASE(48, 48, 3, 0xb0, 0x10, 3, 1), + PIN_FIELD_BASE(49, 49, 3, 0xb0, 0x10, 2, 1), + PIN_FIELD_BASE(50, 50, 3, 0xb0, 0x10, 15, 1), + PIN_FIELD_BASE(51, 53, 3, 0xb0, 0x10, 12, 1), + PIN_FIELD_BASE(54, 54, 3, 0xb0, 0x10, 16, 1), + PIN_FIELD_BASE(55, 56, 1, 0x90, 0x10, 12, 1), + PIN_FIELD_BASE(57, 57, 1, 0x90, 0x10, 11, 1), + PIN_FIELD_BASE(58, 60, 1, 0x90, 0x10, 2, 1), + PIN_FIELD_BASE(61, 61, 1, 0x90, 0x10, 1, 1), + PIN_FIELD_BASE(62, 62, 1, 0x90, 0x10, 5, 1), + PIN_FIELD_BASE(64, 68, 1, 0x90, 0x10, 6, 1), + PIN_FIELD_BASE(69, 70, 5, 0x70, 0x10, 1, 1), + PIN_FIELD_BASE(73, 73, 4, 0x80, 0x10, 3, 1), + PIN_FIELD_BASE(74, 74, 4, 0x80, 0x10, 0, 1), + PIN_FIELD_BASE(80, 81, 1, 0x90, 0x10, 16, 1), + PIN_FIELD_BASE(82, 83, 1, 0x90, 0x10, 14, 1), +}; + +static const struct mtk_pin_reg_calc mt7988_reg_cals[] = { + [PINCTRL_PIN_REG_MODE] = MTK_RANGE(mt7988_pin_mode_range), + [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt7988_pin_dir_range), + [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt7988_pin_di_range), + [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt7988_pin_do_range), + [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt7988_pin_smt_range), + [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt7988_pin_ies_range), + [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt7988_pin_pu_range), + [PINCTRL_PIN_REG_PD] = MTK_RANGE(mt7988_pin_pd_range), + [PINCTRL_PIN_REG_DRV] = MTK_RANGE(mt7988_pin_drv_range), + [PINCTRL_PIN_REG_PUPD] = MTK_RANGE(mt7988_pin_pupd_range), + [PINCTRL_PIN_REG_R0] = MTK_RANGE(mt7988_pin_r0_range), + [PINCTRL_PIN_REG_R1] = MTK_RANGE(mt7988_pin_r1_range), +}; + +static const struct mtk_pin_desc mt7988_pins[] = { + MT7988_PIN(0, "UART2_RXD"), + MT7988_PIN(1, "UART2_TXD"), + MT7988_PIN(2, "UART2_CTS"), + MT7988_PIN(3, "UART2_RTS"), + MT7988_PIN(4, "GPIO_A"), + MT7988_PIN(5, "SMI_0_MDC"), + MT7988_PIN(6, "SMI_0_MDIO"), + MT7988_PIN(7, "PCIE30_2L_0_WAKE_N"), + MT7988_PIN(8, "PCIE30_2L_0_CLKREQ_N"), + MT7988_PIN(9, "PCIE30_1L_1_WAKE_N"), + MT7988_PIN(10, "PCIE30_1L_1_CLKREQ_N"), + MT7988_PIN(11, "GPIO_P"), + MT7988_PIN(12, "WATCHDOG"), + MT7988_PIN(13, "GPIO_RESET"), + MT7988_PIN(14, "GPIO_WPS"), + MT7988_PIN(15, "PMIC_I2C_SCL"), + MT7988_PIN(16, "PMIC_I2C_SDA"), + MT7988_PIN(17, "I2C_1_SCL"), + MT7988_PIN(18, "I2C_1_SDA"), + MT7988_PIN(19, "PCIE30_2L_0_PRESET_N"), + MT7988_PIN(20, "PCIE30_1L_1_PRESET_N"), + MT7988_PIN(21, "PWMD1"), + MT7988_PIN(22, "SPI0_WP"), + MT7988_PIN(23, "SPI0_HOLD"), + MT7988_PIN(24, "SPI0_CSB"), + MT7988_PIN(25, "SPI0_MISO"), + MT7988_PIN(26, "SPI0_MOSI"), + MT7988_PIN(27, "SPI0_CLK"), + MT7988_PIN(28, "SPI1_CSB"), + MT7988_PIN(29, "SPI1_MISO"), + MT7988_PIN(30, "SPI1_MOSI"), + MT7988_PIN(31, "SPI1_CLK"), + MT7988_PIN(32, "SPI2_CLK"), + MT7988_PIN(33, "SPI2_MOSI"), + MT7988_PIN(34, "SPI2_MISO"), + MT7988_PIN(35, "SPI2_CSB"), + MT7988_PIN(36, "SPI2_HOLD"), + MT7988_PIN(37, "SPI2_WP"), + MT7988_PIN(38, "EMMC_RSTB"), + MT7988_PIN(39, "EMMC_DSL"), + MT7988_PIN(40, "EMMC_CK"), + MT7988_PIN(41, "EMMC_CMD"), + MT7988_PIN(42, "EMMC_DATA_7"), + MT7988_PIN(43, "EMMC_DATA_6"), + MT7988_PIN(44, "EMMC_DATA_5"), + MT7988_PIN(45, "EMMC_DATA_4"), + MT7988_PIN(46, "EMMC_DATA_3"), + MT7988_PIN(47, "EMMC_DATA_2"), + MT7988_PIN(48, "EMMC_DATA_1"), + MT7988_PIN(49, "EMMC_DATA_0"), + MT7988_PIN(50, "PCM_FS_I2S_LRCK"), + MT7988_PIN(51, "PCM_CLK_I2S_BCLK"), + MT7988_PIN(52, "PCM_DRX_I2S_DIN"), + MT7988_PIN(53, "PCM_DTX_I2S_DOUT"), + MT7988_PIN(54, "PCM_MCK_I2S_MCLK"), + MT7988_PIN(55, "UART0_RXD"), + MT7988_PIN(56, "UART0_TXD"), + MT7988_PIN(57, "PWMD0"), + MT7988_PIN(58, "JTAG_JTDI"), + MT7988_PIN(59, "JTAG_JTDO"), + MT7988_PIN(60, "JTAG_JTMS"), + MT7988_PIN(61, "JTAG_JTCLK"), + MT7988_PIN(62, "JTAG_JTRST_N"), + MT7988_PIN(63, "USB_DRV_VBUS_P1"), + MT7988_PIN(64, "LED_A"), + MT7988_PIN(65, "LED_B"), + MT7988_PIN(66, "LED_C"), + MT7988_PIN(67, "LED_D"), + MT7988_PIN(68, "LED_E"), + MT7988_PIN(69, "GPIO_B"), + MT7988_PIN(70, "GPIO_C"), + MT7988_PIN(71, "I2C_2_SCL"), + MT7988_PIN(72, "I2C_2_SDA"), + MT7988_PIN(73, "PCIE30_2L_1_PRESET_N"), + MT7988_PIN(74, "PCIE30_1L_0_PRESET_N"), + MT7988_PIN(75, "PCIE30_2L_1_WAKE_N"), + MT7988_PIN(76, "PCIE30_2L_1_CLKREQ_N"), + MT7988_PIN(77, "PCIE30_1L_0_WAKE_N"), + MT7988_PIN(78, "PCIE30_1L_0_CLKREQ_N"), + MT7988_PIN(79, "USB_DRV_VBUS_P0"), + MT7988_PIN(80, "UART1_RXD"), + MT7988_PIN(81, "UART1_TXD"), + MT7988_PIN(82, "UART1_CTS"), + MT7988_PIN(83, "UART1_RTS"), +}; + +/* jtag */ +static int mt7988_tops_jtag0_0_pins[] = { 0, 1, 2, 3, 4 }; +static int mt7988_tops_jtag0_0_funcs[] = { 2, 2, 2, 2, 2 }; + +static int mt7988_wo0_jtag_pins[] = { 50, 51, 52, 53, 54 }; +static int mt7988_wo0_jtag_funcs[] = { 3, 3, 3, 3, 3 }; + +static int mt7988_wo1_jtag_pins[] = { 50, 51, 52, 53, 54 }; +static int mt7988_wo1_jtag_funcs[] = { 4, 4, 4, 4, 4 }; + +static int mt7988_wo2_jtag_pins[] = { 50, 51, 52, 53, 54 }; +static int mt7988_wo2_jtag_funcs[] = { 5, 5, 5, 5, 5 }; + +static int mt7988_jtag_pins[] = { 58, 59, 60, 61, 62 }; +static int mt7988_jtag_funcs[] = { 1, 1, 1, 1, 1 }; + +static int mt7988_tops_jtag0_1_pins[] = { 58, 59, 60, 61, 62 }; +static int mt7988_tops_jtag0_1_funcs[] = { 4, 4, 4, 4, 4 }; + +/* int_usxgmii */ +static int mt7988_int_usxgmii_pins[] = { 2, 3 }; +static int mt7988_int_usxgmii_funcs[] = { 3, 3 }; + +/* pwm */ +static int mt7988_pwm0_pins[] = { 57 }; +static int mt7988_pwm0_funcs[] = { 1 }; + +static int mt7988_pwm1_pins[] = { 21 }; +static int mt7988_pwm1_funcs[] = { 1 }; + +static int mt7988_pwm2_pins[] = { 80 }; +static int mt7988_pwm2_funcs[] = { 2 }; + +static int mt7988_pwm3_pins[] = { 81 }; +static int mt7988_pwm3_funcs[] = { 2 }; + +static int mt7988_pwm4_pins[] = { 82 }; +static int mt7988_pwm4_funcs[] = { 2 }; + +static int mt7988_pwm5_pins[] = { 83 }; +static int mt7988_pwm5_funcs[] = { 2 }; + +static int mt7988_pwm6_pins[] = { 69 }; +static int mt7988_pwm6_funcs[] = { 3 }; + +static int mt7988_pwm7_pins[] = { 70 }; +static int mt7988_pwm7_funcs[] = { 3 }; + +/* dfd */ +static int mt7988_dfd_pins[] = { 0, 1, 2, 3, 4 }; +static int mt7988_dfd_funcs[] = { 4, 4, 4, 4, 4 }; + +/* i2c */ +static int mt7988_xfi_phy0_i2c0_pins[] = { 0, 1 }; +static int mt7988_xfi_phy0_i2c0_funcs[] = { 5, 5 }; + +static int mt7988_xfi_phy1_i2c0_pins[] = { 0, 1 }; +static int mt7988_xfi_phy1_i2c0_funcs[] = { 6, 6 }; + +static int mt7988_xfi_phy_pll_i2c0_pins[] = { 3, 4 }; +static int mt7988_xfi_phy_pll_i2c0_funcs[] = { 5, 5 }; + +static int mt7988_xfi_phy_pll_i2c1_pins[] = { 3, 4 }; +static int mt7988_xfi_phy_pll_i2c1_funcs[] = { 6, 6 }; + +static int mt7988_i2c0_0_pins[] = { 5, 6 }; +static int mt7988_i2c0_0_funcs[] = { 2, 2 }; + +static int mt7988_i2c1_sfp_pins[] = { 5, 6 }; +static int mt7988_i2c1_sfp_funcs[] = { 4, 4 }; + +static int mt7988_xfi_pextp_phy0_i2c_pins[] = { 5, 6 }; +static int mt7988_xfi_pextp_phy0_i2c_funcs[] = { 5, 5 }; + +static int mt7988_xfi_pextp_phy1_i2c_pins[] = { 5, 6 }; +static int mt7988_xfi_pextp_phy1_i2c_funcs[] = { 6, 6 }; + +static int mt7988_i2c0_1_pins[] = { 15, 16 }; +static int mt7988_i2c0_1_funcs[] = { 1, 1 }; + +static int mt7988_u30_phy_i2c0_pins[] = { 15, 16 }; +static int mt7988_u30_phy_i2c0_funcs[] = { 2, 2 }; + +static int mt7988_u32_phy_i2c0_pins[] = { 15, 16 }; +static int mt7988_u32_phy_i2c0_funcs[] = { 3, 3 }; + +static int mt7988_xfi_phy0_i2c1_pins[] = { 15, 16 }; +static int mt7988_xfi_phy0_i2c1_funcs[] = { 5, 5 }; + +static int mt7988_xfi_phy1_i2c1_pins[] = { 15, 16 }; +static int mt7988_xfi_phy1_i2c1_funcs[] = { 6, 6 }; + +static int mt7988_xfi_phy_pll_i2c2_pins[] = { 15, 16 }; +static int mt7988_xfi_phy_pll_i2c2_funcs[] = { 7, 7 }; + +static int mt7988_i2c1_0_pins[] = { 17, 18 }; +static int mt7988_i2c1_0_funcs[] = { 1, 1 }; + +static int mt7988_u30_phy_i2c1_pins[] = { 17, 18 }; +static int mt7988_u30_phy_i2c1_funcs[] = { 2, 2 }; + +static int mt7988_u32_phy_i2c1_pins[] = { 17, 18 }; +static int mt7988_u32_phy_i2c1_funcs[] = { 3, 3 }; + +static int mt7988_xfi_phy_pll_i2c3_pins[] = { 17, 18 }; +static int mt7988_xfi_phy_pll_i2c3_funcs[] = { 4, 4 }; + +static int mt7988_sgmii0_i2c_pins[] = { 17, 18 }; +static int mt7988_sgmii0_i2c_funcs[] = { 5, 5 }; + +static int mt7988_sgmii1_i2c_pins[] = { 17, 18 }; +static int mt7988_sgmii1_i2c_funcs[] = { 6, 6 }; + +static int mt7988_i2c1_2_pins[] = { 69, 70 }; +static int mt7988_i2c1_2_funcs[] = { 2, 2 }; + +static int mt7988_i2c2_0_pins[] = { 69, 70 }; +static int mt7988_i2c2_0_funcs[] = { 4, 4 }; + +static int mt7988_i2c2_1_pins[] = { 71, 72 }; +static int mt7988_i2c2_1_funcs[] = { 1, 1 }; + +/* eth */ +static int mt7988_mdc_mdio0_pins[] = { 5, 6 }; +static int mt7988_mdc_mdio0_funcs[] = { 1, 1 }; + +static int mt7988_2p5g_ext_mdio_pins[] = { 28, 29 }; +static int mt7988_2p5g_ext_mdio_funcs[] = { 6, 6 }; + +static int mt7988_gbe_ext_mdio_pins[] = { 30, 31 }; +static int mt7988_gbe_ext_mdio_funcs[] = { 6, 6 }; + +static int mt7988_mdc_mdio1_pins[] = { 69, 70 }; +static int mt7988_mdc_mdio1_funcs[] = { 1, 1 }; + +/* pcie */ +static int mt7988_pcie_wake_n0_0_pins[] = { 7 }; +static int mt7988_pcie_wake_n0_0_funcs[] = { 1 }; + +static int mt7988_pcie_clk_req_n0_0_pins[] = { 8 }; +static int mt7988_pcie_clk_req_n0_0_funcs[] = { 1 }; + +static int mt7988_pcie_wake_n3_0_pins[] = { 9 }; +static int mt7988_pcie_wake_n3_0_funcs[] = { 1 }; + +static int mt7988_pcie_clk_req_n3_pins[] = { 10 }; +static int mt7988_pcie_clk_req_n3_funcs[] = { 1 }; + +static int mt7988_pcie_clk_req_n0_1_pins[] = { 10 }; +static int mt7988_pcie_clk_req_n0_1_funcs[] = { 2 }; + +static int mt7988_pcie_p0_phy_i2c_pins[] = { 7, 8 }; +static int mt7988_pcie_p0_phy_i2c_funcs[] = { 3, 3 }; + +static int mt7988_pcie_p1_phy_i2c_pins[] = { 7, 8 }; +static int mt7988_pcie_p1_phy_i2c_funcs[] = { 4, 4 }; + +static int mt7988_pcie_p3_phy_i2c_pins[] = { 9, 10 }; +static int mt7988_pcie_p3_phy_i2c_funcs[] = { 4, 4 }; + +static int mt7988_pcie_p2_phy_i2c_pins[] = { 7, 8 }; +static int mt7988_pcie_p2_phy_i2c_funcs[] = { 5, 5 }; + +static int mt7988_ckm_phy_i2c_pins[] = { 9, 10 }; +static int mt7988_ckm_phy_i2c_funcs[] = { 5, 5 }; + +static int mt7988_pcie_wake_n0_1_pins[] = { 13 }; +static int mt7988_pcie_wake_n0_1_funcs[] = { 2 }; + +static int mt7988_pcie_wake_n3_1_pins[] = { 14 }; +static int mt7988_pcie_wake_n3_1_funcs[] = { 2 }; + +static int mt7988_pcie_2l_0_pereset_pins[] = { 19 }; +static int mt7988_pcie_2l_0_pereset_funcs[] = { 1 }; + +static int mt7988_pcie_1l_1_pereset_pins[] = { 20 }; +static int mt7988_pcie_1l_1_pereset_funcs[] = { 1 }; + +static int mt7988_pcie_clk_req_n2_1_pins[] = { 63 }; +static int mt7988_pcie_clk_req_n2_1_funcs[] = { 2 }; + +static int mt7988_pcie_2l_1_pereset_pins[] = { 73 }; +static int mt7988_pcie_2l_1_pereset_funcs[] = { 1 }; + +static int mt7988_pcie_1l_0_pereset_pins[] = { 74 }; +static int mt7988_pcie_1l_0_pereset_funcs[] = { 1 }; + +static int mt7988_pcie_wake_n1_0_pins[] = { 75 }; +static int mt7988_pcie_wake_n1_0_funcs[] = { 1 }; + +static int mt7988_pcie_clk_req_n1_pins[] = { 76 }; +static int mt7988_pcie_clk_req_n1_funcs[] = { 1 }; + +static int mt7988_pcie_wake_n2_0_pins[] = { 77 }; +static int mt7988_pcie_wake_n2_0_funcs[] = { 1 }; + +static int mt7988_pcie_clk_req_n2_0_pins[] = { 78 }; +static int mt7988_pcie_clk_req_n2_0_funcs[] = { 1 }; + +static int mt7988_pcie_wake_n2_1_pins[] = { 79 }; +static int mt7988_pcie_wake_n2_1_funcs[] = { 2 }; + +/* pmic */ +static int mt7988_pmic_pins[] = { 11 }; +static int mt7988_pmic_funcs[] = { 1 }; + +/* watchdog */ +static int mt7988_watchdog_pins[] = { 12 }; +static int mt7988_watchdog_funcs[] = { 1 }; + +/* spi */ +static int mt7988_spi0_wp_hold_pins[] = { 22, 23 }; +static int mt7988_spi0_wp_hold_funcs[] = { 1, 1 }; + +static int mt7988_spi0_pins[] = { 24, 25, 26, 27 }; +static int mt7988_spi0_funcs[] = { 1, 1, 1, 1 }; + +static int mt7988_spi1_pins[] = { 28, 29, 30, 31 }; +static int mt7988_spi1_funcs[] = { 1, 1, 1, 1 }; + +static int mt7988_spi2_pins[] = { 32, 33, 34, 35 }; +static int mt7988_spi2_funcs[] = { 1, 1, 1, 1 }; + +static int mt7988_spi2_wp_hold_pins[] = { 36, 37 }; +static int mt7988_spi2_wp_hold_funcs[] = { 1, 1 }; + +/* flash */ +static int mt7988_snfi_pins[] = { 22, 23, 24, 25, 26, 27 }; +static int mt7988_snfi_funcs[] = { 2, 2, 2, 2, 2, 2 }; + +static int mt7988_emmc_45_pins[] = { + 21, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 +}; +static int mt7988_emmc_45_funcs[] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }; + +static int mt7988_sdcard_pins[] = { 32, 33, 34, 35, 36, 37 }; +static int mt7988_sdcard_funcs[] = { 5, 5, 5, 5, 5, 5 }; + +static int mt7988_emmc_51_pins[] = { 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49 }; +static int mt7988_emmc_51_funcs[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + +/* uart */ +static int mt7988_uart2_pins[] = { 0, 1, 2, 3 }; +static int mt7988_uart2_funcs[] = { 1, 1, 1, 1 }; + +static int mt7988_tops_uart0_0_pins[] = { 22, 23 }; +static int mt7988_tops_uart0_0_funcs[] = { 3, 3 }; + +static int mt7988_uart2_0_pins[] = { 28, 29, 30, 31 }; +static int mt7988_uart2_0_funcs[] = { 2, 2, 2, 2 }; + +static int mt7988_uart1_0_pins[] = { 32, 33, 34, 35 }; +static int mt7988_uart1_0_funcs[] = { 2, 2, 2, 2 }; + +static int mt7988_uart2_1_pins[] = { 32, 33, 34, 35 }; +static int mt7988_uart2_1_funcs[] = { 3, 3, 3, 3 }; + +static int mt7988_net_wo0_uart_txd_0_pins[] = { 28 }; +static int mt7988_net_wo0_uart_txd_0_funcs[] = { 3 }; + +static int mt7988_net_wo1_uart_txd_0_pins[] = { 29 }; +static int mt7988_net_wo1_uart_txd_0_funcs[] = { 3 }; + +static int mt7988_net_wo2_uart_txd_0_pins[] = { 30 }; +static int mt7988_net_wo2_uart_txd_0_funcs[] = { 3 }; + +static int mt7988_tops_uart1_0_pins[] = { 28, 29 }; +static int mt7988_tops_uart1_0_funcs[] = { 4, 4 }; + +static int mt7988_tops_uart0_1_pins[] = { 30, 31 }; +static int mt7988_tops_uart0_1_funcs[] = { 4, 4 }; + +static int mt7988_tops_uart1_1_pins[] = { 36, 37 }; +static int mt7988_tops_uart1_1_funcs[] = { 3, 3 }; + +static int mt7988_uart0_pins[] = { 55, 56 }; +static int mt7988_uart0_funcs[] = { 1, 1 }; + +static int mt7988_tops_uart0_2_pins[] = { 55, 56 }; +static int mt7988_tops_uart0_2_funcs[] = { 2, 2 }; + +static int mt7988_uart2_2_pins[] = { 50, 51, 52, 53 }; +static int mt7988_uart2_2_funcs[] = { 2, 2, 2, 2 }; + +static int mt7988_uart1_1_pins[] = { 58, 59, 60, 61 }; +static int mt7988_uart1_1_funcs[] = { 2, 2, 2, 2 }; + +static int mt7988_uart2_3_pins[] = { 58, 59, 60, 61 }; +static int mt7988_uart2_3_funcs[] = { 3, 3, 3, 3 }; + +static int mt7988_uart1_2_pins[] = { 80, 81, 82, 83 }; +static int mt7988_uart1_2_funcs[] = { 1, 1, 1, 1 }; + +static int mt7988_tops_uart1_2_pins[] = { 80, 81 }; +static int mt7988_tops_uart1_2_funcs[] = { + 4, + 4, +}; + +static int mt7988_net_wo0_uart_txd_1_pins[] = { 80 }; +static int mt7988_net_wo0_uart_txd_1_funcs[] = { 3 }; + +static int mt7988_net_wo1_uart_txd_1_pins[] = { 81 }; +static int mt7988_net_wo1_uart_txd_1_funcs[] = { 3 }; + +static int mt7988_net_wo2_uart_txd_1_pins[] = { 82 }; +static int mt7988_net_wo2_uart_txd_1_funcs[] = { 3 }; + +/* udi */ +static int mt7988_udi_pins[] = { 32, 33, 34, 35, 36 }; +static int mt7988_udi_funcs[] = { 4, 4, 4, 4, 4 }; + +/* i2s */ +static int mt7988_i2s_pins[] = { 50, 51, 52, 53, 54 }; +static int mt7988_i2s_funcs[] = { 1, 1, 1, 1, 1 }; + +/* pcm */ +static int mt7988_pcm_pins[] = { 50, 51, 52, 53 }; +static int mt7988_pcm_funcs[] = { 1, 1, 1, 1 }; + +/* led */ +static int mt7988_gbe0_led1_pins[] = { 58 }; +static int mt7988_gbe0_led1_funcs[] = { 6 }; +static int mt7988_gbe1_led1_pins[] = { 59 }; +static int mt7988_gbe1_led1_funcs[] = { 6 }; +static int mt7988_gbe2_led1_pins[] = { 60 }; +static int mt7988_gbe2_led1_funcs[] = { 6 }; +static int mt7988_gbe3_led1_pins[] = { 61 }; +static int mt7988_gbe3_led1_funcs[] = { 6 }; + +static int mt7988_2p5gbe_led1_pins[] = { 62 }; +static int mt7988_2p5gbe_led1_funcs[] = { 6 }; + +static int mt7988_gbe0_led0_pins[] = { 64 }; +static int mt7988_gbe0_led0_funcs[] = { 1 }; +static int mt7988_gbe1_led0_pins[] = { 65 }; +static int mt7988_gbe1_led0_funcs[] = { 1 }; +static int mt7988_gbe2_led0_pins[] = { 66 }; +static int mt7988_gbe2_led0_funcs[] = { 1 }; +static int mt7988_gbe3_led0_pins[] = { 67 }; +static int mt7988_gbe3_led0_funcs[] = { 1 }; + +static int mt7988_2p5gbe_led0_pins[] = { 68 }; +static int mt7988_2p5gbe_led0_funcs[] = { 1 }; + +/* usb */ +static int mt7988_drv_vbus_p1_pins[] = { 63 }; +static int mt7988_drv_vbus_p1_funcs[] = { 1 }; + +static int mt7988_drv_vbus_pins[] = { 79 }; +static int mt7988_drv_vbus_funcs[] = { 1 }; + +static const struct group_desc mt7988_groups[] = { + /* @GPIO(0,1,2,3): uart2 */ + PINCTRL_PIN_GROUP("uart2", mt7988_uart2), + /* @GPIO(0,1,2,3,4): tops_jtag0_0 */ + PINCTRL_PIN_GROUP("tops_jtag0_0", mt7988_tops_jtag0_0), + /* @GPIO(2,3): int_usxgmii */ + PINCTRL_PIN_GROUP("int_usxgmii", mt7988_int_usxgmii), + /* @GPIO(0,1,2,3,4): dfd */ + PINCTRL_PIN_GROUP("dfd", mt7988_dfd), + /* @GPIO(0,1): xfi_phy0_i2c0 */ + PINCTRL_PIN_GROUP("xfi_phy0_i2c0", mt7988_xfi_phy0_i2c0), + /* @GPIO(0,1): xfi_phy1_i2c0 */ + PINCTRL_PIN_GROUP("xfi_phy1_i2c0", mt7988_xfi_phy1_i2c0), + /* @GPIO(3,4): xfi_phy_pll_i2c0 */ + PINCTRL_PIN_GROUP("xfi_phy_pll_i2c0", mt7988_xfi_phy_pll_i2c0), + /* @GPIO(3,4): xfi_phy_pll_i2c1 */ + PINCTRL_PIN_GROUP("xfi_phy_pll_i2c1", mt7988_xfi_phy_pll_i2c1), + /* @GPIO(5,6) i2c0_0 */ + PINCTRL_PIN_GROUP("i2c0_0", mt7988_i2c0_0), + /* @GPIO(5,6) i2c1_sfp */ + PINCTRL_PIN_GROUP("i2c1_sfp", mt7988_i2c1_sfp), + /* @GPIO(5,6) xfi_pextp_phy0_i2c */ + PINCTRL_PIN_GROUP("xfi_pextp_phy0_i2c", mt7988_xfi_pextp_phy0_i2c), + /* @GPIO(5,6) xfi_pextp_phy1_i2c */ + PINCTRL_PIN_GROUP("xfi_pextp_phy1_i2c", mt7988_xfi_pextp_phy1_i2c), + /* @GPIO(5,6) mdc_mdio0 */ + PINCTRL_PIN_GROUP("mdc_mdio0", mt7988_mdc_mdio0), + /* @GPIO(7): pcie_wake_n0_0 */ + PINCTRL_PIN_GROUP("pcie_wake_n0_0", mt7988_pcie_wake_n0_0), + /* @GPIO(8): pcie_clk_req_n0_0 */ + PINCTRL_PIN_GROUP("pcie_clk_req_n0_0", mt7988_pcie_clk_req_n0_0), + /* @GPIO(9): pcie_wake_n3_0 */ + PINCTRL_PIN_GROUP("pcie_wake_n3_0", mt7988_pcie_wake_n3_0), + /* @GPIO(10): pcie_clk_req_n3 */ + PINCTRL_PIN_GROUP("pcie_clk_req_n3", mt7988_pcie_clk_req_n3), + /* @GPIO(10): pcie_clk_req_n0_1 */ + PINCTRL_PIN_GROUP("pcie_clk_req_n0_1", mt7988_pcie_clk_req_n0_1), + /* @GPIO(7,8) pcie_p0_phy_i2c */ + PINCTRL_PIN_GROUP("pcie_p0_phy_i2c", mt7988_pcie_p0_phy_i2c), + /* @GPIO(7,8) pcie_p1_phy_i2c */ + PINCTRL_PIN_GROUP("pcie_p1_phy_i2c", mt7988_pcie_p1_phy_i2c), + /* @GPIO(7,8) pcie_p2_phy_i2c */ + PINCTRL_PIN_GROUP("pcie_p2_phy_i2c", mt7988_pcie_p2_phy_i2c), + /* @GPIO(9,10) pcie_p3_phy_i2c */ + PINCTRL_PIN_GROUP("pcie_p3_phy_i2c", mt7988_pcie_p3_phy_i2c), + /* @GPIO(9,10) ckm_phy_i2c */ + PINCTRL_PIN_GROUP("ckm_phy_i2c", mt7988_ckm_phy_i2c), + /* @GPIO(11): pmic */ + PINCTRL_PIN_GROUP("pcie_pmic", mt7988_pmic), + /* @GPIO(12): watchdog */ + PINCTRL_PIN_GROUP("watchdog", mt7988_watchdog), + /* @GPIO(13): pcie_wake_n0_1 */ + PINCTRL_PIN_GROUP("pcie_wake_n0_1", mt7988_pcie_wake_n0_1), + /* @GPIO(14): pcie_wake_n3_1 */ + PINCTRL_PIN_GROUP("pcie_wake_n3_1", mt7988_pcie_wake_n3_1), + /* @GPIO(15,16) i2c0_1 */ + PINCTRL_PIN_GROUP("i2c0_1", mt7988_i2c0_1), + /* @GPIO(15,16) u30_phy_i2c0 */ + PINCTRL_PIN_GROUP("u30_phy_i2c0", mt7988_u30_phy_i2c0), + /* @GPIO(15,16) u32_phy_i2c0 */ + PINCTRL_PIN_GROUP("u32_phy_i2c0", mt7988_u32_phy_i2c0), + /* @GPIO(15,16) xfi_phy0_i2c1 */ + PINCTRL_PIN_GROUP("xfi_phy0_i2c1", mt7988_xfi_phy0_i2c1), + /* @GPIO(15,16) xfi_phy1_i2c1 */ + PINCTRL_PIN_GROUP("xfi_phy1_i2c1", mt7988_xfi_phy1_i2c1), + /* @GPIO(15,16) xfi_phy_pll_i2c2 */ + PINCTRL_PIN_GROUP("xfi_phy_pll_i2c2", mt7988_xfi_phy_pll_i2c2), + /* @GPIO(17,18) i2c1_0 */ + PINCTRL_PIN_GROUP("i2c1_0", mt7988_i2c1_0), + /* @GPIO(17,18) u30_phy_i2c1 */ + PINCTRL_PIN_GROUP("u30_phy_i2c1", mt7988_u30_phy_i2c1), + /* @GPIO(17,18) u32_phy_i2c1 */ + PINCTRL_PIN_GROUP("u32_phy_i2c1", mt7988_u32_phy_i2c1), + /* @GPIO(17,18) xfi_phy_pll_i2c3 */ + PINCTRL_PIN_GROUP("xfi_phy_pll_i2c3", mt7988_xfi_phy_pll_i2c3), + /* @GPIO(17,18) sgmii0_i2c */ + PINCTRL_PIN_GROUP("sgmii0_i2c", mt7988_sgmii0_i2c), + /* @GPIO(17,18) sgmii1_i2c */ + PINCTRL_PIN_GROUP("sgmii1_i2c", mt7988_sgmii1_i2c), + /* @GPIO(19): pcie_2l_0_pereset */ + PINCTRL_PIN_GROUP("pcie_2l_0_pereset", mt7988_pcie_2l_0_pereset), + /* @GPIO(20): pcie_1l_1_pereset */ + PINCTRL_PIN_GROUP("pcie_1l_1_pereset", mt7988_pcie_1l_1_pereset), + /* @GPIO(21): pwm1 */ + PINCTRL_PIN_GROUP("pwm1", mt7988_pwm1), + /* @GPIO(22,23) spi0_wp_hold */ + PINCTRL_PIN_GROUP("spi0_wp_hold", mt7988_spi0_wp_hold), + /* @GPIO(24,25,26,27) spi0 */ + PINCTRL_PIN_GROUP("spi0", mt7988_spi0), + /* @GPIO(28,29,30,31) spi1 */ + PINCTRL_PIN_GROUP("spi1", mt7988_spi1), + /* @GPIO(32,33,34,35) spi2 */ + PINCTRL_PIN_GROUP("spi2", mt7988_spi2), + /* @GPIO(36,37) spi2_wp_hold */ + PINCTRL_PIN_GROUP("spi2_wp_hold", mt7988_spi2_wp_hold), + /* @GPIO(22,23,24,25,26,27) snfi */ + PINCTRL_PIN_GROUP("snfi", mt7988_snfi), + /* @GPIO(22,23) tops_uart0_0 */ + PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart0_0), + /* @GPIO(28,29,30,31) uart2_0 */ + PINCTRL_PIN_GROUP("uart2_0", mt7988_uart2_0), + /* @GPIO(32,33,34,35) uart1_0 */ + PINCTRL_PIN_GROUP("uart1_0", mt7988_uart1_0), + /* @GPIO(32,33,34,35) uart2_1 */ + PINCTRL_PIN_GROUP("uart2_1", mt7988_uart2_1), + /* @GPIO(28) net_wo0_uart_txd_0 */ + PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0), + /* @GPIO(29) net_wo1_uart_txd_0 */ + PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0), + /* @GPIO(30) net_wo2_uart_txd_0 */ + PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0), + /* @GPIO(28,29) tops_uart1_0 */ + PINCTRL_PIN_GROUP("tops_uart0_0", mt7988_tops_uart1_0), + /* @GPIO(30,31) tops_uart0_1 */ + PINCTRL_PIN_GROUP("tops_uart0_1", mt7988_tops_uart0_1), + /* @GPIO(36,37) tops_uart1_1 */ + PINCTRL_PIN_GROUP("tops_uart1_1", mt7988_tops_uart1_1), + /* @GPIO(32,33,34,35,36) udi */ + PINCTRL_PIN_GROUP("udi", mt7988_udi), + /* @GPIO(21,28,29,30,31,32,33,34,35,36,37) emmc_45 */ + PINCTRL_PIN_GROUP("emmc_45", mt7988_emmc_45), + /* @GPIO(32,33,34,35,36,37) sdcard */ + PINCTRL_PIN_GROUP("sdcard", mt7988_sdcard), + /* @GPIO(38,39,40,41,42,43,44,45,46,47,48,49) emmc_51 */ + PINCTRL_PIN_GROUP("emmc_51", mt7988_emmc_51), + /* @GPIO(28,29) 2p5g_ext_mdio */ + PINCTRL_PIN_GROUP("2p5g_ext_mdio", mt7988_2p5g_ext_mdio), + /* @GPIO(30,31) gbe_ext_mdio */ + PINCTRL_PIN_GROUP("gbe_ext_mdio", mt7988_gbe_ext_mdio), + /* @GPIO(50,51,52,53,54) i2s */ + PINCTRL_PIN_GROUP("i2s", mt7988_i2s), + /* @GPIO(50,51,52,53) pcm */ + PINCTRL_PIN_GROUP("pcm", mt7988_pcm), + /* @GPIO(55,56) uart0 */ + PINCTRL_PIN_GROUP("uart0", mt7988_uart0), + /* @GPIO(55,56) tops_uart0_2 */ + PINCTRL_PIN_GROUP("tops_uart0_2", mt7988_tops_uart0_2), + /* @GPIO(50,51,52,53) uart2_2 */ + PINCTRL_PIN_GROUP("uart2_2", mt7988_uart2_2), + /* @GPIO(50,51,52,53,54) wo0_jtag */ + PINCTRL_PIN_GROUP("wo0_jtag", mt7988_wo0_jtag), + /* @GPIO(50,51,52,53,54) wo1-wo1_jtag */ + PINCTRL_PIN_GROUP("wo1_jtag", mt7988_wo1_jtag), + /* @GPIO(50,51,52,53,54) wo2_jtag */ + PINCTRL_PIN_GROUP("wo2_jtag", mt7988_wo2_jtag), + /* @GPIO(57) pwm0 */ + PINCTRL_PIN_GROUP("pwm0", mt7988_pwm0), + /* @GPIO(58,59,60,61,62) jtag */ + PINCTRL_PIN_GROUP("jtag", mt7988_jtag), + /* @GPIO(58,59,60,61,62) tops_jtag0_1 */ + PINCTRL_PIN_GROUP("tops_jtag0_1", mt7988_tops_jtag0_1), + /* @GPIO(58,59,60,61) uart2_3 */ + PINCTRL_PIN_GROUP("uart2_3", mt7988_uart2_3), + /* @GPIO(58,59,60,61) uart1_1 */ + PINCTRL_PIN_GROUP("uart1_1", mt7988_uart1_1), + /* @GPIO(58,59,60,61) gbe_led1 */ + PINCTRL_PIN_GROUP("gbe0_led1", mt7988_gbe0_led1), + PINCTRL_PIN_GROUP("gbe1_led1", mt7988_gbe1_led1), + PINCTRL_PIN_GROUP("gbe2_led1", mt7988_gbe2_led1), + PINCTRL_PIN_GROUP("gbe3_led1", mt7988_gbe3_led1), + /* @GPIO(62) 2p5gbe_led1 */ + PINCTRL_PIN_GROUP("2p5gbe_led1", mt7988_2p5gbe_led1), + /* @GPIO(64,65,66,67) gbe_led0 */ + PINCTRL_PIN_GROUP("gbe0_led0", mt7988_gbe0_led0), + PINCTRL_PIN_GROUP("gbe1_led0", mt7988_gbe1_led0), + PINCTRL_PIN_GROUP("gbe2_led0", mt7988_gbe2_led0), + PINCTRL_PIN_GROUP("gbe3_led0", mt7988_gbe3_led0), + /* @GPIO(68) 2p5gbe_led0 */ + PINCTRL_PIN_GROUP("2p5gbe_led0", mt7988_2p5gbe_led0), + /* @GPIO(63) drv_vbus_p1 */ + PINCTRL_PIN_GROUP("drv_vbus_p1", mt7988_drv_vbus_p1), + /* @GPIO(63) pcie_clk_req_n2_1 */ + PINCTRL_PIN_GROUP("pcie_clk_req_n2_1", mt7988_pcie_clk_req_n2_1), + /* @GPIO(69, 70) mdc_mdio1 */ + PINCTRL_PIN_GROUP("mdc_mdio1", mt7988_mdc_mdio1), + /* @GPIO(69, 70) i2c1_2 */ + PINCTRL_PIN_GROUP("i2c1_2", mt7988_i2c1_2), + /* @GPIO(69) pwm6 */ + PINCTRL_PIN_GROUP("pwm6", mt7988_pwm6), + /* @GPIO(70) pwm7 */ + PINCTRL_PIN_GROUP("pwm7", mt7988_pwm7), + /* @GPIO(69,70) i2c2_0 */ + PINCTRL_PIN_GROUP("i2c2_0", mt7988_i2c2_0), + /* @GPIO(71,72) i2c2_1 */ + PINCTRL_PIN_GROUP("i2c2_1", mt7988_i2c2_1), + /* @GPIO(73) pcie_2l_1_pereset */ + PINCTRL_PIN_GROUP("pcie_2l_1_pereset", mt7988_pcie_2l_1_pereset), + /* @GPIO(74) pcie_1l_0_pereset */ + PINCTRL_PIN_GROUP("pcie_1l_0_pereset", mt7988_pcie_1l_0_pereset), + /* @GPIO(75) pcie_wake_n1_0 */ + PINCTRL_PIN_GROUP("pcie_wake_n1_0", mt7988_pcie_wake_n1_0), + /* @GPIO(76) pcie_clk_req_n1 */ + PINCTRL_PIN_GROUP("pcie_clk_req_n1", mt7988_pcie_clk_req_n1), + /* @GPIO(77) pcie_wake_n2_0 */ + PINCTRL_PIN_GROUP("pcie_wake_n2_0", mt7988_pcie_wake_n2_0), + /* @GPIO(78) pcie_clk_req_n2_0 */ + PINCTRL_PIN_GROUP("pcie_clk_req_n2_0", mt7988_pcie_clk_req_n2_0), + /* @GPIO(79) drv_vbus */ + PINCTRL_PIN_GROUP("drv_vbus", mt7988_drv_vbus), + /* @GPIO(79) pcie_wake_n2_1 */ + PINCTRL_PIN_GROUP("pcie_wake_n2_1", mt7988_pcie_wake_n2_1), + /* @GPIO(80,81,82,83) uart1_2 */ + PINCTRL_PIN_GROUP("uart1_2", mt7988_uart1_2), + /* @GPIO(80) pwm2 */ + PINCTRL_PIN_GROUP("pwm2", mt7988_pwm2), + /* @GPIO(81) pwm3 */ + PINCTRL_PIN_GROUP("pwm3", mt7988_pwm3), + /* @GPIO(82) pwm4 */ + PINCTRL_PIN_GROUP("pwm4", mt7988_pwm4), + /* @GPIO(83) pwm5 */ + PINCTRL_PIN_GROUP("pwm5", mt7988_pwm5), + /* @GPIO(80) net_wo0_uart_txd_0 */ + PINCTRL_PIN_GROUP("net_wo0_uart_txd_0", mt7988_net_wo0_uart_txd_0), + /* @GPIO(81) net_wo1_uart_txd_0 */ + PINCTRL_PIN_GROUP("net_wo1_uart_txd_0", mt7988_net_wo1_uart_txd_0), + /* @GPIO(82) net_wo2_uart_txd_0 */ + PINCTRL_PIN_GROUP("net_wo2_uart_txd_0", mt7988_net_wo2_uart_txd_0), + /* @GPIO(80,81) tops_uart1_2 */ + PINCTRL_PIN_GROUP("tops_uart1_2", mt7988_tops_uart1_2), + /* @GPIO(80) net_wo0_uart_txd_1 */ + PINCTRL_PIN_GROUP("net_wo0_uart_txd_1", mt7988_net_wo0_uart_txd_1), + /* @GPIO(81) net_wo1_uart_txd_1 */ + PINCTRL_PIN_GROUP("net_wo1_uart_txd_1", mt7988_net_wo1_uart_txd_1), + /* @GPIO(82) net_wo2_uart_txd_1 */ + PINCTRL_PIN_GROUP("net_wo2_uart_txd_1", mt7988_net_wo2_uart_txd_1), +}; + +/* Joint those groups owning the same capability in user point of view which + * allows that people tend to use through the device tree. + */ +static const char *mt7988_jtag_groups[] = { + "tops_jtag0_0", "wo0_jtag", "wo1_jtag", + "wo2_jtag", "jtag", "tops_jtag0_1", +}; +static const char *mt7988_int_usxgmii_groups[] = { + "int_usxgmii", +}; +static const char *mt7988_pwm_groups[] = { + "pwm0", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5", "pwm6", "pwm7" +}; +static const char *mt7988_dfd_groups[] = { + "dfd", +}; +static const char *mt7988_i2c_groups[] = { + "xfi_phy0_i2c0", + "xfi_phy1_i2c0", + "xfi_phy_pll_i2c0", + "xfi_phy_pll_i2c1", + "i2c0_0", + "i2c1_sfp", + "xfi_pextp_phy0_i2c", + "xfi_pextp_phy1_i2c", + "i2c0_1", + "u30_phy_i2c0", + "u32_phy_i2c0", + "xfi_phy0_i2c1", + "xfi_phy1_i2c1", + "xfi_phy_pll_i2c2", + "i2c1_0", + "u30_phy_i2c1", + "u32_phy_i2c1", + "xfi_phy_pll_i2c3", + "sgmii0_i2c", + "sgmii1_i2c", + "i2c1_2", + "i2c2_0", + "i2c2_1", +}; +static const char *mt7988_ethernet_groups[] = { + "mdc_mdio0", + "2p5g_ext_mdio", + "gbe_ext_mdio", + "mdc_mdio1", +}; +static const char *mt7988_pcie_groups[] = { + "pcie_wake_n0_0", "pcie_clk_req_n0_0", "pcie_wake_n3_0", + "pcie_clk_req_n3", "pcie_p0_phy_i2c", "pcie_p1_phy_i2c", + "pcie_p3_phy_i2c", "pcie_p2_phy_i2c", "ckm_phy_i2c", + "pcie_wake_n0_1", "pcie_wake_n3_1", "pcie_2l_0_pereset", + "pcie_1l_1_pereset", "pcie_clk_req_n2_1", "pcie_2l_1_pereset", + "pcie_1l_0_pereset", "pcie_wake_n1_0", "pcie_clk_req_n1", + "pcie_wake_n2_0", "pcie_clk_req_n2_0", "pcie_wake_n2_1", + "pcie_clk_req_n0_1" +}; +static const char *mt7988_pmic_groups[] = { + "pmic", +}; +static const char *mt7988_wdt_groups[] = { + "watchdog", +}; +static const char *mt7988_spi_groups[] = { + "spi0", "spi0_wp_hold", "spi1", "spi2", "spi2_wp_hold", +}; +static const char *mt7988_flash_groups[] = { "emmc_45", "sdcard", "snfi", + "emmc_51" }; +static const char *mt7988_uart_groups[] = { + "uart2", + "tops_uart0_0", + "uart2_0", + "uart1_0", + "uart2_1", + "net_wo0_uart_txd_0", + "net_wo1_uart_txd_0", + "net_wo2_uart_txd_0", + "tops_uart1_0", + "ops_uart0_1", + "ops_uart1_1", + "uart0", + "tops_uart0_2", + "uart1_1", + "uart2_3", + "uart1_2", + "tops_uart1_2", + "net_wo0_uart_txd_1", + "net_wo1_uart_txd_1", + "net_wo2_uart_txd_1", +}; +static const char *mt7988_udi_groups[] = { + "udi", +}; +static const char *mt7988_audio_groups[] = { + "i2s", "pcm", +}; +static const char *mt7988_led_groups[] = { + "gbe0_led1", "gbe1_led1", "gbe2_led1", "gbe3_led1", "2p5gbe_led1", + "gbe0_led0", "gbe1_led0", "gbe2_led0", "gbe3_led0", "2p5gbe_led0", + "wf5g_led0", "wf5g_led1", +}; +static const char *mt7988_usb_groups[] = { + "drv_vbus", + "drv_vbus_p1", +}; + +static const struct function_desc mt7988_functions[] = { + { "audio", mt7988_audio_groups, ARRAY_SIZE(mt7988_audio_groups) }, + { "jtag", mt7988_jtag_groups, ARRAY_SIZE(mt7988_jtag_groups) }, + { "int_usxgmii", mt7988_int_usxgmii_groups, + ARRAY_SIZE(mt7988_int_usxgmii_groups) }, + { "pwm", mt7988_pwm_groups, ARRAY_SIZE(mt7988_pwm_groups) }, + { "dfd", mt7988_dfd_groups, ARRAY_SIZE(mt7988_dfd_groups) }, + { "i2c", mt7988_i2c_groups, ARRAY_SIZE(mt7988_i2c_groups) }, + { "eth", mt7988_ethernet_groups, ARRAY_SIZE(mt7988_ethernet_groups) }, + { "pcie", mt7988_pcie_groups, ARRAY_SIZE(mt7988_pcie_groups) }, + { "pmic", mt7988_pmic_groups, ARRAY_SIZE(mt7988_pmic_groups) }, + { "watchdog", mt7988_wdt_groups, ARRAY_SIZE(mt7988_wdt_groups) }, + { "spi", mt7988_spi_groups, ARRAY_SIZE(mt7988_spi_groups) }, + { "flash", mt7988_flash_groups, ARRAY_SIZE(mt7988_flash_groups) }, + { "uart", mt7988_uart_groups, ARRAY_SIZE(mt7988_uart_groups) }, + { "udi", mt7988_udi_groups, ARRAY_SIZE(mt7988_udi_groups) }, + { "usb", mt7988_usb_groups, ARRAY_SIZE(mt7988_usb_groups) }, + { "led", mt7988_led_groups, ARRAY_SIZE(mt7988_led_groups) }, +}; + +static const struct mtk_eint_hw mt7988_eint_hw = { + .port_mask = 7, + .ports = 7, + .ap_num = ARRAY_SIZE(mt7988_pins), + .db_cnt = 16, +}; + +static const char *mt7988_pinctrl_register_base_names[] = { + "gpio_base", "iocfg_tr_base", "iocfg_br_base", + "iocfg_rb_base", "iocfg_lb_base", "iocfg_tl_base", +}; + +static struct mtk_pin_soc mt7988_data = { + .reg_cal = mt7988_reg_cals, + .pins = mt7988_pins, + .npins = ARRAY_SIZE(mt7988_pins), + .grps = mt7988_groups, + .ngrps = ARRAY_SIZE(mt7988_groups), + .funcs = mt7988_functions, + .nfuncs = ARRAY_SIZE(mt7988_functions), + .eint_hw = &mt7988_eint_hw, + .gpio_m = 0, + .ies_present = false, + .base_names = mt7988_pinctrl_register_base_names, + .nbase_names = ARRAY_SIZE(mt7988_pinctrl_register_base_names), + .bias_disable_set = mtk_pinconf_bias_disable_set, + .bias_disable_get = mtk_pinconf_bias_disable_get, + .bias_set = mtk_pinconf_bias_set, + .bias_get = mtk_pinconf_bias_get, + .drive_set = mtk_pinconf_drive_set_rev1, + .drive_get = mtk_pinconf_drive_get_rev1, + .adv_pull_get = mtk_pinconf_adv_pull_get, + .adv_pull_set = mtk_pinconf_adv_pull_set, +}; + +static const struct of_device_id mt7988_pinctrl_of_match[] = { + { + .compatible = "mediatek,mt7988-pinctrl", + }, + {} +}; + +static int mt7988_pinctrl_probe(struct platform_device *pdev) +{ + return mtk_moore_pinctrl_probe(pdev, &mt7988_data); +} + +static struct platform_driver mt7988_pinctrl_driver = { + .driver = { + .name = "mt7988-pinctrl", + .of_match_table = mt7988_pinctrl_of_match, + }, + .probe = mt7988_pinctrl_probe, +}; + +static int __init mt7988_pinctrl_init(void) +{ + return platform_driver_register(&mt7988_pinctrl_driver); +} +arch_initcall(mt7988_pinctrl_init); diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 9f1c6f69395..5170dfdf980 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -311,6 +311,7 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_MT7622 is not set CONFIG_PINCTRL_MT7981=y CONFIG_PINCTRL_MT7986=y +CONFIG_PINCTRL_MT7988=y # CONFIG_PINCTRL_MT8173 is not set # CONFIG_PINCTRL_MT8183 is not set CONFIG_PINCTRL_MT8516=y diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 56e855c5590..be51e02f4d7 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -330,6 +330,7 @@ CONFIG_PINCTRL=y CONFIG_PINCTRL_MT7622=y # CONFIG_PINCTRL_MT7981 is not set # CONFIG_PINCTRL_MT7986 is not set +# CONFIG_PINCTRL_MT7988 is not set # CONFIG_PINCTRL_MT8173 is not set # CONFIG_PINCTRL_MT8183 is not set CONFIG_PINCTRL_MT8516=y diff --git a/target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch b/target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch new file mode 100644 index 00000000000..cbee45bc1f8 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/240-pinctrl-mediatek-add-support-for-MT7988-SoC.patch @@ -0,0 +1,26 @@ +--- a/drivers/pinctrl/mediatek/Kconfig ++++ b/drivers/pinctrl/mediatek/Kconfig +@@ -134,6 +134,13 @@ config PINCTRL_MT7986 + default ARM64 && ARCH_MEDIATEK + select PINCTRL_MTK_MOORE + ++config PINCTRL_MT7988 ++ bool "Mediatek MT7988 pin control" ++ depends on OF ++ depends on ARM64 || COMPILE_TEST ++ default ARCH_MEDIATEK ++ select PINCTRL_MTK_MOORE ++ + config PINCTRL_MT8167 + bool "Mediatek MT8167 pin control" + depends on OF +--- a/drivers/pinctrl/mediatek/Makefile ++++ b/drivers/pinctrl/mediatek/Makefile +@@ -19,6 +19,7 @@ obj-$(CONFIG_PINCTRL_MT7623) += pinctrl- + obj-$(CONFIG_PINCTRL_MT7629) += pinctrl-mt7629.o + obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7981.o + obj-$(CONFIG_PINCTRL_MT7986) += pinctrl-mt7986.o ++obj-$(CONFIG_PINCTRL_MT7988) += pinctrl-mt7988.o + obj-$(CONFIG_PINCTRL_MT8167) += pinctrl-mt8167.o + obj-$(CONFIG_PINCTRL_MT8173) += pinctrl-mt8173.o + obj-$(CONFIG_PINCTRL_MT8183) += pinctrl-mt8183.o From 6983a215d9d1966f95bc5b1c0045c200948b2079 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 17:16:12 +0100 Subject: [PATCH 11/43] generic: add support for MediaTek NETSYS v3 In order to support Ethernet on the MT7988 SoC add support for NETSYS v3 as well as new paths and USXGMII SerDes to the mtk_eth_soc driver. Signed-off-by: Daniel Golle --- ..._eth_soc-add-MTK_NETSYS_V1-capabilit.patch | 223 +++ ..._eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch | 181 ++ ..._eth_soc-rely-on-num_devs-and-remove.patch | 153 ++ ..._eth_soc-add-MTK_NETSYS_V3-capabilit.patch | 292 +++ ..._eth_soc-convert-caps-in-mtk_soc_dat.patch | 197 ++ ...k_eth_soc-add-support-for-MT7988-SoC.patch | 495 +++++ ..._eth_soc-add-paths-and-SerDes-modes-.patch | 1671 +++++++++++++++++ target/linux/mediatek/filogic/config-5.15 | 1 + target/linux/mediatek/mt7622/config-5.15 | 1 + ..._eth_soc-implement-Clause-45-MDIO-ac.patch | 8 +- ...ethernet-mediatek-support-net-labels.patch | 4 +- 11 files changed, 3220 insertions(+), 6 deletions(-) create mode 100644 target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch create mode 100644 target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch create mode 100644 target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch create mode 100644 target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch create mode 100644 target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch create mode 100644 target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch create mode 100644 target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch diff --git a/target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch b/target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch new file mode 100644 index 00000000000..621a7b0fcf0 --- /dev/null +++ b/target/linux/generic/pending-5.15/737-01-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V1-capabilit.patch @@ -0,0 +1,223 @@ +From 663fa1b7e0cb2c929008482014a70c6625caad75 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 7 Mar 2023 15:55:13 +0000 +Subject: [PATCH 1/7] net: ethernet: mtk_eth_soc: add MTK_NETSYS_V1 capability + bit + +Introduce MTK_NETSYS_V1 bit in the device capabilities for +MT7621/MT7622/MT7623/MT7628/MT7629 SoCs. +Use !MTK_NETSYS_V1 instead of MTK_NETSYS_V2 in the driver codebase. +This is a preliminary patch to introduce support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 +++++++------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 45 ++++++++++++--------- + 2 files changed, 41 insertions(+), 34 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -597,7 +597,7 @@ static void mtk_set_queue_speed(struct m + FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | + FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | + MTK_QTX_SCH_LEAKY_BUCKET_SIZE; +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) + val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; + + if (IS_ENABLED(CONFIG_SOC_MT7621)) { +@@ -974,7 +974,7 @@ static bool mtk_rx_get_desc(struct mtk_e + rxd->rxd1 = READ_ONCE(dma_rxd->rxd1); + rxd->rxd3 = READ_ONCE(dma_rxd->rxd3); + rxd->rxd4 = READ_ONCE(dma_rxd->rxd4); +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { + rxd->rxd5 = READ_ONCE(dma_rxd->rxd5); + rxd->rxd6 = READ_ONCE(dma_rxd->rxd6); + } +@@ -1032,7 +1032,7 @@ static int mtk_init_fq_dma(struct mtk_et + + txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE); + txd->txd4 = 0; +- if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V1)) { + txd->txd5 = 0; + txd->txd6 = 0; + txd->txd7 = 0; +@@ -1221,7 +1221,7 @@ static void mtk_tx_set_dma_desc(struct n + struct mtk_mac *mac = netdev_priv(dev); + struct mtk_eth *eth = mac->hw; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) + mtk_tx_set_dma_desc_v2(dev, txd, info); + else + mtk_tx_set_dma_desc_v1(dev, txd, info); +@@ -1902,7 +1902,7 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) + mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; + else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && + !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) +@@ -1998,7 +1998,7 @@ static int mtk_poll_rx(struct napi_struc + skb->dev = netdev; + bytes += skb->len; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { + reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5); + hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY; + if (hash != MTK_RXD5_FOE_ENTRY) +@@ -2023,7 +2023,7 @@ static int mtk_poll_rx(struct napi_struc + /* When using VLAN untagging in combination with DSA, the + * hardware treats the MTK special tag as a VLAN and untags it. + */ +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) && ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1) && + (trxd.rxd2 & RX_DMA_VTAG) && netdev_uses_dsa(netdev)) { + unsigned int port = RX_DMA_VPID(trxd.rxd3) & GENMASK(2, 0); + +@@ -2328,7 +2328,7 @@ static int mtk_tx_alloc(struct mtk_eth * + txd->txd2 = next_ptr; + txd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU; + txd->txd4 = 0; +- if (MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(soc->caps, MTK_NETSYS_V1)) { + txd->txd5 = 0; + txd->txd6 = 0; + txd->txd7 = 0; +@@ -2381,7 +2381,7 @@ static int mtk_tx_alloc(struct mtk_eth * + FIELD_PREP(MTK_QTX_SCH_MIN_RATE_MAN, 1) | + FIELD_PREP(MTK_QTX_SCH_MIN_RATE_EXP, 4) | + MTK_QTX_SCH_LEAKY_BUCKET_SIZE; +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) + val |= MTK_QTX_SCH_LEAKY_BUCKET_EN; + mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); + ofs += MTK_QTX_OFFSET; +@@ -2515,7 +2515,7 @@ static int mtk_rx_alloc(struct mtk_eth * + + rxd->rxd3 = 0; + rxd->rxd4 = 0; +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { + rxd->rxd5 = 0; + rxd->rxd6 = 0; + rxd->rxd7 = 0; +@@ -3063,7 +3063,7 @@ static int mtk_start_dma(struct mtk_eth + MTK_TX_BT_32DWORDS | MTK_NDP_CO_PRO | + MTK_RX_2B_OFFSET | MTK_TX_WB_DDONE; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) + val |= MTK_MUTLI_CNT | MTK_RESV_BUF | + MTK_WCOMP_EN | MTK_DMAD_WR_WDONE | + MTK_CHK_DDONE_EN | MTK_LEAKY_BUCKET_EN; +@@ -3475,7 +3475,7 @@ static void mtk_hw_reset(struct mtk_eth + { + u32 val; + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, 0); + val = RSTCTRL_PPE0_V2; + } else { +@@ -3487,7 +3487,7 @@ static void mtk_hw_reset(struct mtk_eth + + ethsys_reset(eth, RSTCTRL_ETH | RSTCTRL_FE | val); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) + regmap_write(eth->ethsys, ETHSYS_FE_RST_CHK_IDLE_EN, + 0x3ffffff); + } +@@ -3683,7 +3683,7 @@ static int mtk_hw_init(struct mtk_eth *e + else + mtk_hw_reset(eth); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { + /* Set FE to PDMAv2 if necessary */ + val = mtk_r32(eth, MTK_FE_GLO_MISC); + mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC); +@@ -3720,7 +3720,7 @@ static int mtk_hw_init(struct mtk_eth *e + */ + val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); + mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL); +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { + val = mtk_r32(eth, MTK_CDMP_IG_CTRL); + mtk_w32(eth, val | MTK_CDMP_STAG_EN, MTK_CDMP_IG_CTRL); + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -816,6 +816,7 @@ enum mkt_eth_capabilities { + MTK_SHARED_INT_BIT, + MTK_TRGMII_MT7621_CLK_BIT, + MTK_QDMA_BIT, ++ MTK_NETSYS_V1_BIT, + MTK_NETSYS_V2_BIT, + MTK_SOC_MT7628_BIT, + MTK_RSTCTRL_PPE1_BIT, +@@ -851,6 +852,7 @@ enum mkt_eth_capabilities { + #define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT) + #define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) + #define MTK_QDMA BIT(MTK_QDMA_BIT) ++#define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT) + #define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) + #define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) + #define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) +@@ -913,25 +915,30 @@ enum mkt_eth_capabilities { + + #define MTK_HAS_CAPS(caps, _x) (((caps) & (_x) & ~(MTK_CAP_MASK)) == (_x)) + +-#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ +- MTK_GMAC2_RGMII | MTK_SHARED_INT | \ +- MTK_TRGMII_MT7621_CLK | MTK_QDMA) +- +-#define MT7622_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | MTK_GMAC2_RGMII | \ +- MTK_GMAC2_SGMII | MTK_GDM1_ESW | \ +- MTK_MUX_GDM1_TO_GMAC1_ESW | \ +- MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_QDMA) +- +-#define MT7623_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | MTK_GMAC2_RGMII | \ +- MTK_QDMA) +- +-#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628) +- +-#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ +- MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW | \ +- MTK_MUX_GMAC2_GMAC0_TO_GEPHY | \ +- MTK_MUX_U3_GMAC2_TO_QPHY | \ +- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA) ++#define MT7621_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ ++ MTK_GMAC2_RGMII | MTK_SHARED_INT | \ ++ MTK_TRGMII_MT7621_CLK | MTK_QDMA | \ ++ MTK_NETSYS_V1) ++ ++#define MT7622_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_SGMII | \ ++ MTK_GMAC2_RGMII | MTK_GMAC2_SGMII | \ ++ MTK_GDM1_ESW | MTK_MUX_GDM1_TO_GMAC1_ESW |\ ++ MTK_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | \ ++ MTK_QDMA | MTK_NETSYS_V1) ++ ++#define MT7623_CAPS (MTK_GMAC1_RGMII | MTK_GMAC1_TRGMII | \ ++ MTK_GMAC2_RGMII | MTK_QDMA | \ ++ MTK_NETSYS_V1) ++ ++#define MT7628_CAPS (MTK_SHARED_INT | MTK_SOC_MT7628 | \ ++ MTK_NETSYS_V1) ++ ++#define MT7629_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ ++ MTK_GMAC2_GEPHY | MTK_GDM1_ESW | \ ++ MTK_MUX_GMAC2_GMAC0_TO_GEPHY | MTK_QDMA | \ ++ MTK_MUX_U3_GMAC2_TO_QPHY | MTK_NETSYS_V1 |\ ++ MTK_MUX_GDM1_TO_GMAC1_ESW | \ ++ MTK_MUX_GMAC12_TO_GEPHY_SGMII) + + #define MT7981_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | MTK_GMAC2_GEPHY | \ + MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ diff --git a/target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch b/target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch new file mode 100644 index 00000000000..a8debc41bfb --- /dev/null +++ b/target/linux/generic/pending-5.15/737-02-net-ethernet-mtk_eth_soc-move-MAX_DEVS-in-mtk_soc_da.patch @@ -0,0 +1,181 @@ +From 5af2b2dc4d6ba0ff7696e79f18e5b2bf862194eb Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 7 Mar 2023 15:55:24 +0000 +Subject: [PATCH 2/7] net: ethernet: mtk_eth_soc: move MAX_DEVS in mtk_soc_data + +This is a preliminary patch to add MT7988 SoC support since it runs 3 +macs instead of 2. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 +++++++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 11 +++---- + 2 files changed, 36 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -3989,7 +3989,10 @@ static void mtk_sgmii_destroy(struct mtk + { + int i; + +- for (i = 0; i < MTK_MAX_DEVS; i++) ++ if (!eth->sgmii_pcs) ++ return; ++ ++ for (i = 0; i < eth->soc->num_devs; i++) + mtk_pcs_lynxi_destroy(eth->sgmii_pcs[i]); + } + +@@ -4432,7 +4435,12 @@ static int mtk_sgmii_init(struct mtk_eth + u32 flags; + int i; + +- for (i = 0; i < MTK_MAX_DEVS; i++) { ++ eth->sgmii_pcs = devm_kzalloc(eth->dev, ++ sizeof(*eth->sgmii_pcs) * ++ eth->soc->num_devs, ++ GFP_KERNEL); ++ ++ for (i = 0; i < eth->soc->num_devs; i++) { + np = of_parse_phandle(eth->dev->of_node, "mediatek,sgmiisys", i); + if (!np) + break; +@@ -4477,6 +4485,18 @@ static int mtk_probe(struct platform_dev + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) + eth->ip_align = NET_IP_ALIGN; + ++ eth->netdev = devm_kzalloc(eth->dev, ++ sizeof(*eth->netdev) * eth->soc->num_devs, ++ GFP_KERNEL); ++ if (!eth->netdev) ++ return -ENOMEM; ++ ++ eth->mac = devm_kzalloc(eth->dev, ++ sizeof(*eth->mac) * eth->soc->num_devs, ++ GFP_KERNEL); ++ if (!eth->mac) ++ return -ENOMEM; ++ + spin_lock_init(ð->page_lock); + spin_lock_init(ð->tx_irq_lock); + spin_lock_init(ð->rx_irq_lock); +@@ -4662,7 +4682,7 @@ static int mtk_probe(struct platform_dev + goto err_free_dev; + } + +- for (i = 0; i < MTK_MAX_DEVS; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->netdev[i]) + continue; + +@@ -4739,6 +4759,7 @@ static const struct mtk_soc_data mt2701_ + .hw_features = MTK_HW_FEATURES, + .required_clks = MT7623_CLKS_BITMAP, + .required_pctl = true, ++ .num_devs = 2, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4757,6 +4778,7 @@ static const struct mtk_soc_data mt7621_ + .required_pctl = false, + .offload_version = 1, + .hash_offset = 2, ++ .num_devs = 2, + .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), +@@ -4778,6 +4800,7 @@ static const struct mtk_soc_data mt7622_ + .offload_version = 2, + .hash_offset = 2, + .has_accounting = true, ++ .num_devs = 2, + .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), +@@ -4797,6 +4820,7 @@ static const struct mtk_soc_data mt7623_ + .required_pctl = true, + .offload_version = 1, + .hash_offset = 2, ++ .num_devs = 2, + .foe_entry_size = sizeof(struct mtk_foe_entry) - 16, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), +@@ -4816,6 +4840,7 @@ static const struct mtk_soc_data mt7629_ + .required_clks = MT7629_CLKS_BITMAP, + .required_pctl = false, + .has_accounting = true, ++ .num_devs = 2, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +@@ -4837,6 +4862,7 @@ static const struct mtk_soc_data mt7981_ + .hash_offset = 4, + .foe_entry_size = sizeof(struct mtk_foe_entry), + .has_accounting = true, ++ .num_devs = 2, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma_v2), + .rxd_size = sizeof(struct mtk_rx_dma_v2), +@@ -4856,6 +4882,7 @@ static const struct mtk_soc_data mt7986_ + .required_pctl = false, + .offload_version = 2, + .hash_offset = 4, ++ .num_devs = 2, + .foe_entry_size = sizeof(struct mtk_foe_entry), + .has_accounting = true, + .txrx = { +@@ -4874,6 +4901,7 @@ static const struct mtk_soc_data rt5350_ + .hw_features = MTK_HW_FEATURES_MT7628, + .required_clks = MT7628_CLKS_BITMAP, + .required_pctl = false, ++ .num_devs = 2, + .txrx = { + .txd_size = sizeof(struct mtk_tx_dma), + .rxd_size = sizeof(struct mtk_rx_dma), +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -1018,6 +1018,7 @@ struct mtk_reg_map { + * @required_pctl A bool value to show whether the SoC requires + * the extra setup for those pins used by GMAC. + * @hash_offset Flow table hash offset. ++ * @num_devs SoC number of macs. + * @foe_entry_size Foe table entry size. + * @has_accounting Bool indicating support for accounting of + * offloaded flows. +@@ -1036,6 +1037,7 @@ struct mtk_soc_data { + bool required_pctl; + u8 offload_version; + u8 hash_offset; ++ u8 num_devs; + u16 foe_entry_size; + netdev_features_t hw_features; + bool has_accounting; +@@ -1051,9 +1053,6 @@ struct mtk_soc_data { + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) + +-/* currently no SoC has more than 2 macs */ +-#define MTK_MAX_DEVS 2 +- + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver + * @dev: The device pointer +@@ -1108,14 +1107,14 @@ struct mtk_eth { + spinlock_t tx_irq_lock; + spinlock_t rx_irq_lock; + struct net_device dummy_dev; +- struct net_device *netdev[MTK_MAX_DEVS]; +- struct mtk_mac *mac[MTK_MAX_DEVS]; ++ struct net_device **netdev; ++ struct mtk_mac **mac; + int irq[3]; + u32 msg_enable; + unsigned long sysclk; + struct regmap *ethsys; + struct regmap *infra; +- struct phylink_pcs *sgmii_pcs[MTK_MAX_DEVS]; ++ struct phylink_pcs **sgmii_pcs; + struct regmap *pctl; + bool hwlro; + refcount_t dma_refcnt; diff --git a/target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch b/target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch new file mode 100644 index 00000000000..d6b36bf6368 --- /dev/null +++ b/target/linux/generic/pending-5.15/737-03-net-ethernet-mtk_eth_soc-rely-on-num_devs-and-remove.patch @@ -0,0 +1,153 @@ +From 4e35e80750b33727e606be9e7ce447bde2e0deb7 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 7 Mar 2023 15:55:35 +0000 +Subject: [PATCH 3/7] net: ethernet: mtk_eth_soc: rely on num_devs and remove + MTK_MAC_COUNT + +Get rid of MTK_MAC_COUNT since it is a duplicated of eth->soc->num_devs. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 30 ++++++++++----------- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 - + 2 files changed, 15 insertions(+), 16 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -900,7 +900,7 @@ static void mtk_stats_update(struct mtk_ + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->mac[i] || !eth->mac[i]->hw_stats) + continue; + if (spin_trylock(ð->mac[i]->hw_stats->stats_lock)) { +@@ -1403,7 +1403,7 @@ static int mtk_queue_stopped(struct mtk_ + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->netdev[i]) + continue; + if (netif_queue_stopped(eth->netdev[i])) +@@ -1417,7 +1417,7 @@ static void mtk_wake_queue(struct mtk_et + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->netdev[i]) + continue; + netif_tx_wake_all_queues(eth->netdev[i]); +@@ -1908,7 +1908,7 @@ static int mtk_poll_rx(struct napi_struc + !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) + mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; + +- if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT || ++ if (unlikely(mac < 0 || mac >= eth->soc->num_devs || + !eth->netdev[mac])) + goto release_desc; + +@@ -2937,7 +2937,7 @@ static void mtk_dma_free(struct mtk_eth + const struct mtk_soc_data *soc = eth->soc; + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) ++ for (i = 0; i < soc->num_devs; i++) + if (eth->netdev[i]) + netdev_reset_queue(eth->netdev[i]); + if (eth->scratch_ring) { +@@ -3091,7 +3091,7 @@ static void mtk_gdm_config(struct mtk_et + if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) + return; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + u32 val = mtk_r32(eth, MTK_GDMA_FWD_CFG(i)); + + /* default setup the forward port to send frame to PDMA */ +@@ -3704,7 +3704,7 @@ static int mtk_hw_init(struct mtk_eth *e + * up with the more appropriate value when mtk_mac_config call is being + * invoked. + */ +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + struct net_device *dev = eth->netdev[i]; + + mtk_w32(eth, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(i)); +@@ -3909,7 +3909,7 @@ static void mtk_pending_work(struct work + mtk_prepare_for_reset(eth); + + /* stop all devices to make sure that dma is properly shut down */ +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->netdev[i] || !netif_running(eth->netdev[i])) + continue; + +@@ -3925,7 +3925,7 @@ static void mtk_pending_work(struct work + mtk_hw_init(eth, true); + + /* restart DMA and enable IRQs */ +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!test_bit(i, &restart)) + continue; + +@@ -3953,7 +3953,7 @@ static int mtk_free_dev(struct mtk_eth * + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->netdev[i]) + continue; + free_netdev(eth->netdev[i]); +@@ -3972,7 +3972,7 @@ static int mtk_unreg_dev(struct mtk_eth + { + int i; + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + struct mtk_mac *mac; + if (!eth->netdev[i]) + continue; +@@ -4277,7 +4277,7 @@ static int mtk_add_mac(struct mtk_eth *e + } + + id = be32_to_cpup(_id); +- if (id >= MTK_MAC_COUNT) { ++ if (id >= eth->soc->num_devs) { + dev_err(eth->dev, "%d is not a valid mac id\n", id); + return -EINVAL; + } +@@ -4407,7 +4407,7 @@ void mtk_eth_set_dma_device(struct mtk_e + + rtnl_lock(); + +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + dev = eth->netdev[i]; + + if (!dev || !(dev->flags & IFF_UP)) +@@ -4734,7 +4734,7 @@ static int mtk_remove(struct platform_de + int i; + + /* stop all devices to make sure that dma is properly shut down */ +- for (i = 0; i < MTK_MAC_COUNT; i++) { ++ for (i = 0; i < eth->soc->num_devs; i++) { + if (!eth->netdev[i]) + continue; + mtk_stop(eth->netdev[i]); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -33,7 +33,6 @@ + #define MTK_TX_DMA_BUF_LEN_V2 0xffff + #define MTK_QDMA_RING_SIZE 2048 + #define MTK_DMA_SIZE 512 +-#define MTK_MAC_COUNT 2 + #define MTK_RX_ETH_HLEN (VLAN_ETH_HLEN + ETH_FCS_LEN) + #define MTK_RX_HLEN (NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN) + #define MTK_DMA_DUMMY_DESC 0xffffffff diff --git a/target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch b/target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch new file mode 100644 index 00000000000..80d729db17f --- /dev/null +++ b/target/linux/generic/pending-5.15/737-04-net-ethernet-mtk_eth_soc-add-MTK_NETSYS_V3-capabilit.patch @@ -0,0 +1,292 @@ +From ab817f559d505329d8a413c7d29250f6d87d77a0 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 7 Mar 2023 15:55:47 +0000 +Subject: [PATCH 4/7] net: ethernet: mtk_eth_soc: add MTK_NETSYS_V3 capability + bit + +Introduce MTK_NETSYS_V3 bit in the device capabilities. +This is a preliminary patch to introduce support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 115 ++++++++++++++++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 44 +++++++- + 2 files changed, 134 insertions(+), 25 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -880,17 +880,32 @@ void mtk_stats_update_mac(struct mtk_mac + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x20 + offs); + hw_stats->rx_flow_control_packets += + mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x24 + offs); +- hw_stats->tx_skip += +- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs); +- hw_stats->tx_collisions += +- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs); +- hw_stats->tx_bytes += +- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs); +- stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs); +- if (stats) +- hw_stats->tx_bytes += (stats << 32); +- hw_stats->tx_packets += +- mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ hw_stats->tx_skip += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x50 + offs); ++ hw_stats->tx_collisions += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x54 + offs); ++ hw_stats->tx_bytes += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x40 + offs); ++ stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x44 + offs); ++ if (stats) ++ hw_stats->tx_bytes += (stats << 32); ++ hw_stats->tx_packets += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x48 + offs); ++ } else { ++ hw_stats->tx_skip += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x28 + offs); ++ hw_stats->tx_collisions += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x2c + offs); ++ hw_stats->tx_bytes += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x30 + offs); ++ stats = mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x34 + offs); ++ if (stats) ++ hw_stats->tx_bytes += (stats << 32); ++ hw_stats->tx_packets += ++ mtk_r32(mac->hw, reg_map->gdm1_cnt + 0x38 + offs); ++ } + } + + u64_stats_update_end(&hw_stats->syncp); +@@ -1192,7 +1207,10 @@ static void mtk_tx_set_dma_desc_v2(struc + data |= TX_DMA_LS0; + WRITE_ONCE(desc->txd3, data); + +- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ ++ if (mac->id == MTK_GMAC3_ID) ++ data = PSE_GDM3_PORT; ++ else ++ data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ + data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); + WRITE_ONCE(desc->txd4, data); + +@@ -1203,6 +1221,9 @@ static void mtk_tx_set_dma_desc_v2(struc + /* tx checksum offload */ + if (info->csum) + data |= TX_DMA_CHKSUM_V2; ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) && ++ netdev_uses_dsa(dev)) ++ data |= TX_DMA_SPTAG_V3; + } + WRITE_ONCE(desc->txd5, data); + +@@ -1268,8 +1289,13 @@ static int mtk_tx_map(struct sk_buff *sk + mtk_tx_set_dma_desc(dev, itxd, &txd_info); + + itx_buf->flags |= MTK_TX_FLAGS_SINGLE0; +- itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : +- MTK_TX_FLAGS_FPORT1; ++ if (mac->id == MTK_GMAC1_ID) ++ itx_buf->flags |= MTK_TX_FLAGS_FPORT0; ++ else if (mac->id == MTK_GMAC2_ID) ++ itx_buf->flags |= MTK_TX_FLAGS_FPORT1; ++ else ++ itx_buf->flags |= MTK_TX_FLAGS_FPORT2; ++ + setup_tx_buf(eth, itx_buf, itxd_pdma, txd_info.addr, txd_info.size, + k++); + +@@ -1317,8 +1343,13 @@ static int mtk_tx_map(struct sk_buff *sk + memset(tx_buf, 0, sizeof(*tx_buf)); + tx_buf->data = (void *)MTK_DMA_DUMMY_DESC; + tx_buf->flags |= MTK_TX_FLAGS_PAGE0; +- tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 : +- MTK_TX_FLAGS_FPORT1; ++ ++ if (mac->id == MTK_GMAC1_ID) ++ tx_buf->flags |= MTK_TX_FLAGS_FPORT0; ++ else if (mac->id == MTK_GMAC2_ID) ++ tx_buf->flags |= MTK_TX_FLAGS_FPORT1; ++ else ++ tx_buf->flags |= MTK_TX_FLAGS_FPORT2; + + setup_tx_buf(eth, tx_buf, txd_pdma, txd_info.addr, + txd_info.size, k++); +@@ -1902,11 +1933,24 @@ static int mtk_poll_rx(struct napi_struc + break; + + /* find out which mac the packet come from. values start at 1 */ +- if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) +- mac = RX_DMA_GET_SPORT_V2(trxd.rxd5) - 1; +- else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && +- !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V1)) { ++ u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5); ++ ++ switch (val) { ++ case PSE_GDM1_PORT: ++ case PSE_GDM2_PORT: ++ mac = val - 1; ++ break; ++ case PSE_GDM3_PORT: ++ mac = MTK_GMAC3_ID; ++ break; ++ default: ++ break; ++ } ++ } else if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) && ++ !(trxd.rxd4 & RX_DMA_SPECIAL_TAG)) { + mac = RX_DMA_GET_SPORT(trxd.rxd4) - 1; ++ } + + if (unlikely(mac < 0 || mac >= eth->soc->num_devs || + !eth->netdev[mac])) +@@ -2135,7 +2179,9 @@ static int mtk_poll_tx_qdma(struct mtk_e + tx_buf = mtk_desc_to_tx_buf(ring, desc, + eth->soc->txrx.txd_size); + if (tx_buf->flags & MTK_TX_FLAGS_FPORT1) +- mac = 1; ++ mac = MTK_GMAC2_ID; ++ else if (tx_buf->flags & MTK_TX_FLAGS_FPORT2) ++ mac = MTK_GMAC3_ID; + + if (!tx_buf->data) + break; +@@ -3742,7 +3788,26 @@ static int mtk_hw_init(struct mtk_eth *e + mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4); + mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP); + +- if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ /* PSE should not drop port1, port8 and port9 packets */ ++ mtk_w32(eth, 0x00000302, PSE_DROP_CFG); ++ ++ /* GDM and CDM Threshold */ ++ mtk_w32(eth, 0x00000707, MTK_CDMW0_THRES); ++ mtk_w32(eth, 0x00000077, MTK_CDMW1_THRES); ++ ++ /* Disable GDM1 RX CRC stripping */ ++ val = mtk_r32(eth, MTK_GDMA_FWD_CFG(0)); ++ val &= ~MTK_GDMA_STRP_CRC; ++ mtk_w32(eth, val, MTK_GDMA_FWD_CFG(0)); ++ ++ /* PSE GDM3 MIB counter has incorrect hw default values, ++ * so the driver ought to read clear the values beforehand ++ * in case ethtool retrieve wrong mib values. ++ */ ++ for (i = 0; i < 0x80; i += 0x4) ++ mtk_r32(eth, reg_map->gdm1_cnt + 0x100 + i); ++ } else if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { + /* PSE should not drop port8 and port9 packets from WDMA Tx */ + mtk_w32(eth, 0x00000300, PSE_DROP_CFG); + +@@ -4314,7 +4379,11 @@ static int mtk_add_mac(struct mtk_eth *e + } + spin_lock_init(&mac->hw_stats->stats_lock); + u64_stats_init(&mac->hw_stats->syncp); +- mac->hw_stats->reg_offset = id * MTK_STAT_OFFSET; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) ++ mac->hw_stats->reg_offset = id * 0x80; ++ else ++ mac->hw_stats->reg_offset = id * 0x40; + + /* phylink create */ + err = of_get_phy_mode(np, &phy_mode); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -121,6 +121,7 @@ + #define MTK_GDMA_ICS_EN BIT(22) + #define MTK_GDMA_TCS_EN BIT(21) + #define MTK_GDMA_UCS_EN BIT(20) ++#define MTK_GDMA_STRP_CRC BIT(16) + #define MTK_GDMA_TO_PDMA 0x0 + #define MTK_GDMA_DROP_ALL 0x7777 + +@@ -286,8 +287,6 @@ + /* QDMA Interrupt grouping registers */ + #define MTK_RLS_DONE_INT BIT(0) + +-#define MTK_STAT_OFFSET 0x40 +- + /* QDMA TX NUM */ + #define QID_BITS_V2(x) (((x) & 0x3f) << 16) + #define MTK_QDMA_GMAC2_QID 8 +@@ -300,6 +299,8 @@ + #define TX_DMA_CHKSUM_V2 (0x7 << 28) + #define TX_DMA_TSO_V2 BIT(31) + ++#define TX_DMA_SPTAG_V3 BIT(27) ++ + /* QDMA V2 descriptor txd4 */ + #define TX_DMA_FPORT_SHIFT_V2 8 + #define TX_DMA_FPORT_MASK_V2 0xf +@@ -636,6 +637,7 @@ enum mtk_tx_flags { + */ + MTK_TX_FLAGS_FPORT0 = 0x04, + MTK_TX_FLAGS_FPORT1 = 0x08, ++ MTK_TX_FLAGS_FPORT2 = 0x10, + }; + + /* This enum allows us to identify how the clock is defined on the array of the +@@ -721,6 +723,42 @@ enum mtk_dev_state { + MTK_RESETTING + }; + ++/* PSE Port Definition */ ++enum mtk_pse_port { ++ PSE_ADMA_PORT = 0, ++ PSE_GDM1_PORT, ++ PSE_GDM2_PORT, ++ PSE_PPE0_PORT, ++ PSE_PPE1_PORT, ++ PSE_QDMA_TX_PORT, ++ PSE_QDMA_RX_PORT, ++ PSE_DROP_PORT, ++ PSE_WDMA0_PORT, ++ PSE_WDMA1_PORT, ++ PSE_TDMA_PORT, ++ PSE_NONE_PORT, ++ PSE_PPE2_PORT, ++ PSE_WDMA2_PORT, ++ PSE_EIP197_PORT, ++ PSE_GDM3_PORT, ++ PSE_PORT_MAX ++}; ++ ++/* GMAC Identifier */ ++enum mtk_gmac_id { ++ MTK_GMAC1_ID = 0, ++ MTK_GMAC2_ID, ++ MTK_GMAC3_ID, ++ MTK_GMAC_ID_MAX ++}; ++ ++/* GDM Type */ ++enum mtk_gdm_type { ++ MTK_GDM_TYPE = 0, ++ MTK_XGDM_TYPE, ++ MTK_GDM_TYPE_MAX ++}; ++ + enum mtk_tx_buf_type { + MTK_TYPE_SKB, + MTK_TYPE_XDP_TX, +@@ -817,6 +855,7 @@ enum mkt_eth_capabilities { + MTK_QDMA_BIT, + MTK_NETSYS_V1_BIT, + MTK_NETSYS_V2_BIT, ++ MTK_NETSYS_V3_BIT, + MTK_SOC_MT7628_BIT, + MTK_RSTCTRL_PPE1_BIT, + MTK_U3_COPHY_V2_BIT, +@@ -853,6 +892,7 @@ enum mkt_eth_capabilities { + #define MTK_QDMA BIT(MTK_QDMA_BIT) + #define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT) + #define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) ++#define MTK_NETSYS_V3 BIT(MTK_NETSYS_V3_BIT) + #define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) + #define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) + #define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) diff --git a/target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch b/target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch new file mode 100644 index 00000000000..bd26cca305d --- /dev/null +++ b/target/linux/generic/pending-5.15/737-05-net-ethernet-mtk_eth_soc-convert-caps-in-mtk_soc_dat.patch @@ -0,0 +1,197 @@ +From 45b575fd9e6a455090820248bf1b98b1f2c7b6c8 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Tue, 7 Mar 2023 15:56:00 +0000 +Subject: [PATCH 5/7] net: ethernet: mtk_eth_soc: convert caps in mtk_soc_data + struct to u64 + +This is a preliminary patch to introduce support for MT7988 SoC. + +Signed-off-by: Lorenzo Bianconi +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 22 +++---- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 62 ++++++++++---------- + 2 files changed, 42 insertions(+), 42 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c +@@ -15,10 +15,10 @@ + struct mtk_eth_muxc { + const char *name; + int cap_bit; +- int (*set_path)(struct mtk_eth *eth, int path); ++ int (*set_path)(struct mtk_eth *eth, u64 path); + }; + +-static const char *mtk_eth_path_name(int path) ++static const char *mtk_eth_path_name(u64 path) + { + switch (path) { + case MTK_ETH_PATH_GMAC1_RGMII: +@@ -40,7 +40,7 @@ static const char *mtk_eth_path_name(int + } + } + +-static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path) ++static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) + { + bool updated = true; + u32 val, mask, set; +@@ -71,7 +71,7 @@ static int set_mux_gdm1_to_gmac1_esw(str + return 0; + } + +-static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path) ++static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; + bool updated = true; +@@ -94,7 +94,7 @@ static int set_mux_gmac2_gmac0_to_gephy( + return 0; + } + +-static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) ++static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0, mask = 0, reg = 0; + bool updated = true; +@@ -125,7 +125,7 @@ static int set_mux_u3_gmac2_to_qphy(stru + return 0; + } + +-static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path) ++static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; + bool updated = true; +@@ -163,7 +163,7 @@ static int set_mux_gmac1_gmac2_to_sgmii_ + return 0; + } + +-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path) ++static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; + bool updated = true; +@@ -218,7 +218,7 @@ static const struct mtk_eth_muxc mtk_eth + }, + }; + +-static int mtk_eth_mux_setup(struct mtk_eth *eth, int path) ++static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path) + { + int i, err = 0; + +@@ -249,7 +249,7 @@ out: + + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) + { +- int path; ++ u64 path; + + path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : + MTK_ETH_PATH_GMAC2_SGMII; +@@ -260,7 +260,7 @@ int mtk_gmac_sgmii_path_setup(struct mtk + + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) + { +- int path = 0; ++ u64 path = 0; + + if (mac_id == 1) + path = MTK_ETH_PATH_GMAC2_GEPHY; +@@ -274,7 +274,7 @@ int mtk_gmac_gephy_path_setup(struct mtk + + int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id) + { +- int path; ++ u64 path; + + path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII : + MTK_ETH_PATH_GMAC2_RGMII; +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -878,44 +878,44 @@ enum mkt_eth_capabilities { + }; + + /* Supported hardware group on SoCs */ +-#define MTK_RGMII BIT(MTK_RGMII_BIT) +-#define MTK_TRGMII BIT(MTK_TRGMII_BIT) +-#define MTK_SGMII BIT(MTK_SGMII_BIT) +-#define MTK_ESW BIT(MTK_ESW_BIT) +-#define MTK_GEPHY BIT(MTK_GEPHY_BIT) +-#define MTK_MUX BIT(MTK_MUX_BIT) +-#define MTK_INFRA BIT(MTK_INFRA_BIT) +-#define MTK_SHARED_SGMII BIT(MTK_SHARED_SGMII_BIT) +-#define MTK_HWLRO BIT(MTK_HWLRO_BIT) +-#define MTK_SHARED_INT BIT(MTK_SHARED_INT_BIT) +-#define MTK_TRGMII_MT7621_CLK BIT(MTK_TRGMII_MT7621_CLK_BIT) +-#define MTK_QDMA BIT(MTK_QDMA_BIT) +-#define MTK_NETSYS_V1 BIT(MTK_NETSYS_V1_BIT) +-#define MTK_NETSYS_V2 BIT(MTK_NETSYS_V2_BIT) +-#define MTK_NETSYS_V3 BIT(MTK_NETSYS_V3_BIT) +-#define MTK_SOC_MT7628 BIT(MTK_SOC_MT7628_BIT) +-#define MTK_RSTCTRL_PPE1 BIT(MTK_RSTCTRL_PPE1_BIT) +-#define MTK_U3_COPHY_V2 BIT(MTK_U3_COPHY_V2_BIT) ++#define MTK_RGMII BIT_ULL(MTK_RGMII_BIT) ++#define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) ++#define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) ++#define MTK_ESW BIT_ULL(MTK_ESW_BIT) ++#define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) ++#define MTK_MUX BIT_ULL(MTK_MUX_BIT) ++#define MTK_INFRA BIT_ULL(MTK_INFRA_BIT) ++#define MTK_SHARED_SGMII BIT_ULL(MTK_SHARED_SGMII_BIT) ++#define MTK_HWLRO BIT_ULL(MTK_HWLRO_BIT) ++#define MTK_SHARED_INT BIT_ULL(MTK_SHARED_INT_BIT) ++#define MTK_TRGMII_MT7621_CLK BIT_ULL(MTK_TRGMII_MT7621_CLK_BIT) ++#define MTK_QDMA BIT_ULL(MTK_QDMA_BIT) ++#define MTK_NETSYS_V1 BIT_ULL(MTK_NETSYS_V1_BIT) ++#define MTK_NETSYS_V2 BIT_ULL(MTK_NETSYS_V2_BIT) ++#define MTK_NETSYS_V3 BIT_ULL(MTK_NETSYS_V3_BIT) ++#define MTK_SOC_MT7628 BIT_ULL(MTK_SOC_MT7628_BIT) ++#define MTK_RSTCTRL_PPE1 BIT_ULL(MTK_RSTCTRL_PPE1_BIT) ++#define MTK_U3_COPHY_V2 BIT_ULL(MTK_U3_COPHY_V2_BIT) + + #define MTK_ETH_MUX_GDM1_TO_GMAC1_ESW \ +- BIT(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) ++ BIT_ULL(MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT) + #define MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY \ +- BIT(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) ++ BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) + #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \ +- BIT(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) ++ BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) + #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \ +- BIT(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) ++ BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) + #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ +- BIT(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) ++ BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) + + /* Supported path present on SoCs */ +-#define MTK_ETH_PATH_GMAC1_RGMII BIT(MTK_ETH_PATH_GMAC1_RGMII_BIT) +-#define MTK_ETH_PATH_GMAC1_TRGMII BIT(MTK_ETH_PATH_GMAC1_TRGMII_BIT) +-#define MTK_ETH_PATH_GMAC1_SGMII BIT(MTK_ETH_PATH_GMAC1_SGMII_BIT) +-#define MTK_ETH_PATH_GMAC2_RGMII BIT(MTK_ETH_PATH_GMAC2_RGMII_BIT) +-#define MTK_ETH_PATH_GMAC2_SGMII BIT(MTK_ETH_PATH_GMAC2_SGMII_BIT) +-#define MTK_ETH_PATH_GMAC2_GEPHY BIT(MTK_ETH_PATH_GMAC2_GEPHY_BIT) +-#define MTK_ETH_PATH_GDM1_ESW BIT(MTK_ETH_PATH_GDM1_ESW_BIT) ++#define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) ++#define MTK_ETH_PATH_GMAC1_TRGMII BIT_ULL(MTK_ETH_PATH_GMAC1_TRGMII_BIT) ++#define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT) ++#define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) ++#define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) ++#define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) ++#define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) + + #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) + #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) +@@ -1071,7 +1071,7 @@ struct mtk_reg_map { + struct mtk_soc_data { + const struct mtk_reg_map *reg_map; + u32 ana_rgc3; +- u32 caps; ++ u64 caps; + u32 required_clks; + bool required_pctl; + u8 offload_version; diff --git a/target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch b/target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch new file mode 100644 index 00000000000..504d2ea2266 --- /dev/null +++ b/target/linux/generic/pending-5.15/737-06-net-ethernet-mtk_eth_soc-add-support-for-MT7988-SoC.patch @@ -0,0 +1,495 @@ +From 661bacf4363ca68939c15e20056b5f72fbd034e7 Mon Sep 17 00:00:00 2001 +From: Lorenzo Bianconi +Date: Sat, 25 Feb 2023 00:08:24 +0100 +Subject: [PATCH 6/7] net: ethernet: mtk_eth_soc: add support for MT7988 SoC + +Introduce support for ethernet chip available in MT7988 SoC to +mtk_eth_soc driver. +--- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 153 ++++++++++++++-- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 193 ++++++++++++++------ + 2 files changed, 279 insertions(+), 67 deletions(-) + +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -152,6 +152,54 @@ static const struct mtk_reg_map mt7986_r + .pse_oq_sta = 0x01a0, + }; + ++static const struct mtk_reg_map mt7988_reg_map = { ++ .tx_irq_mask = 0x461c, ++ .tx_irq_status = 0x4618, ++ .pdma = { ++ .rx_ptr = 0x6900, ++ .rx_cnt_cfg = 0x6904, ++ .pcrx_ptr = 0x6908, ++ .glo_cfg = 0x6a04, ++ .rst_idx = 0x6a08, ++ .delay_irq = 0x6a0c, ++ .irq_status = 0x6a20, ++ .irq_mask = 0x6a28, ++ .adma_rx_dbg0 = 0x6a38, ++ .int_grp = 0x6a50, ++ }, ++ .qdma = { ++ .qtx_cfg = 0x4400, ++ .qtx_sch = 0x4404, ++ .rx_ptr = 0x4500, ++ .rx_cnt_cfg = 0x4504, ++ .qcrx_ptr = 0x4508, ++ .glo_cfg = 0x4604, ++ .rst_idx = 0x4608, ++ .delay_irq = 0x460c, ++ .fc_th = 0x4610, ++ .int_grp = 0x4620, ++ .hred = 0x4644, ++ .ctx_ptr = 0x4700, ++ .dtx_ptr = 0x4704, ++ .crx_ptr = 0x4710, ++ .drx_ptr = 0x4714, ++ .fq_head = 0x4720, ++ .fq_tail = 0x4724, ++ .fq_count = 0x4728, ++ .fq_blen = 0x472c, ++ .tx_sch_rate = 0x4798, ++ }, ++ .gdm1_cnt = 0x1c00, ++ .gdma_to_ppe0 = 0x3333, ++ .ppe_base = 0x2200, ++ .wdma_base = { ++ [0] = 0x4800, ++ [1] = 0x4c00, ++ }, ++ .pse_iq_sta = 0x0180, ++ .pse_oq_sta = 0x01a0, ++}; ++ + /* strings used by ethtool */ + static const struct mtk_ethtool_stats { + char str[ETH_GSTRING_LEN]; +@@ -179,10 +227,54 @@ static const struct mtk_ethtool_stats { + }; + + static const char * const mtk_clks_source_name[] = { +- "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", "fe", "trgpll", +- "sgmii_tx250m", "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", +- "sgmii2_tx250m", "sgmii2_rx250m", "sgmii2_cdr_ref", "sgmii2_cdr_fb", +- "sgmii_ck", "eth2pll", "wocpu0", "wocpu1", "netsys0", "netsys1" ++ "ethif", ++ "sgmiitop", ++ "esw", ++ "gp0", ++ "gp1", ++ "gp2", ++ "gp3", ++ "xgp1", ++ "xgp2", ++ "xgp3", ++ "crypto", ++ "fe", ++ "trgpll", ++ "sgmii_tx250m", ++ "sgmii_rx250m", ++ "sgmii_cdr_ref", ++ "sgmii_cdr_fb", ++ "sgmii2_tx250m", ++ "sgmii2_rx250m", ++ "sgmii2_cdr_ref", ++ "sgmii2_cdr_fb", ++ "sgmii_ck", ++ "eth2pll", ++ "wocpu0", ++ "wocpu1", ++ "netsys0", ++ "netsys1", ++ "ethwarp_wocpu2", ++ "ethwarp_wocpu1", ++ "ethwarp_wocpu0", ++ "top_usxgmii0_sel", ++ "top_usxgmii1_sel", ++ "top_sgm0_sel", ++ "top_sgm1_sel", ++ "top_xfi_phy0_xtal_sel", ++ "top_xfi_phy1_xtal_sel", ++ "top_eth_gmii_sel", ++ "top_eth_refck_50m_sel", ++ "top_eth_sys_200m_sel", ++ "top_eth_sys_sel", ++ "top_eth_xgmii_sel", ++ "top_eth_mii_sel", ++ "top_netsys_sel", ++ "top_netsys_500m_sel", ++ "top_netsys_pao_2x_sel", ++ "top_netsys_sync_250m_sel", ++ "top_netsys_ppefb_250m_sel", ++ "top_netsys_warp_sel", + }; + + void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg) +@@ -1207,10 +1299,19 @@ static void mtk_tx_set_dma_desc_v2(struc + data |= TX_DMA_LS0; + WRITE_ONCE(desc->txd3, data); + +- if (mac->id == MTK_GMAC3_ID) +- data = PSE_GDM3_PORT; +- else +- data = (mac->id + 1) << TX_DMA_FPORT_SHIFT_V2; /* forward port */ ++ /* set forward port */ ++ switch (mac->id) { ++ case MTK_GMAC1_ID: ++ data = PSE_GDM1_PORT << TX_DMA_FPORT_SHIFT_V2; ++ break; ++ case MTK_GMAC2_ID: ++ data = PSE_GDM2_PORT << TX_DMA_FPORT_SHIFT_V2; ++ break; ++ case MTK_GMAC3_ID: ++ data = PSE_GDM3_PORT << TX_DMA_FPORT_SHIFT_V2; ++ break; ++ } ++ + data |= TX_DMA_SWC_V2 | QID_BITS_V2(info->qid); + WRITE_ONCE(desc->txd4, data); + +@@ -4964,6 +5065,25 @@ static const struct mtk_soc_data mt7986_ + }, + }; + ++static const struct mtk_soc_data mt7988_data = { ++ .reg_map = &mt7988_reg_map, ++ .ana_rgc3 = 0x128, ++ .caps = MT7988_CAPS, ++ .hw_features = MTK_HW_FEATURES, ++ .required_clks = MT7988_CLKS_BITMAP, ++ .required_pctl = false, ++ .num_devs = 3, ++ .txrx = { ++ .txd_size = sizeof(struct mtk_tx_dma_v2), ++ .rxd_size = sizeof(struct mtk_rx_dma_v2), ++ .rx_irq_done_mask = MTK_RX_DONE_INT_V2, ++ .rx_dma_l4_valid = RX_DMA_L4_VALID_V2, ++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2, ++ .dma_len_offset = 8, ++ }, ++}; ++ ++ + static const struct mtk_soc_data rt5350_data = { + .reg_map = &mt7628_reg_map, + .caps = MT7628_CAPS, +@@ -4982,14 +5102,15 @@ static const struct mtk_soc_data rt5350_ + }; + + const struct of_device_id of_mtk_match[] = { +- { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data}, +- { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data}, +- { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data}, +- { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data}, +- { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data}, +- { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data}, +- { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data}, +- { .compatible = "ralink,rt5350-eth", .data = &rt5350_data}, ++ { .compatible = "mediatek,mt2701-eth", .data = &mt2701_data }, ++ { .compatible = "mediatek,mt7621-eth", .data = &mt7621_data }, ++ { .compatible = "mediatek,mt7622-eth", .data = &mt7622_data }, ++ { .compatible = "mediatek,mt7623-eth", .data = &mt7623_data }, ++ { .compatible = "mediatek,mt7629-eth", .data = &mt7629_data }, ++ { .compatible = "mediatek,mt7981-eth", .data = &mt7981_data }, ++ { .compatible = "mediatek,mt7986-eth", .data = &mt7986_data }, ++ { .compatible = "mediatek,mt7988-eth", .data = &mt7988_data }, ++ { .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, + {}, + }; + MODULE_DEVICE_TABLE(of, of_mtk_match); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -116,7 +116,8 @@ + #define MTK_CDMP_EG_CTRL 0x404 + + /* GDM Exgress Control Register */ +-#define MTK_GDMA_FWD_CFG(x) (0x500 + (x * 0x1000)) ++#define MTK_GDMA_FWD_CFG(x) ((x == MTK_GMAC3_ID) ? \ ++ 0x540 : 0x500 + (x * 0x1000)) + #define MTK_GDMA_SPECIAL_TAG BIT(24) + #define MTK_GDMA_ICS_EN BIT(22) + #define MTK_GDMA_TCS_EN BIT(21) +@@ -650,6 +651,11 @@ enum mtk_clks_map { + MTK_CLK_GP0, + MTK_CLK_GP1, + MTK_CLK_GP2, ++ MTK_CLK_GP3, ++ MTK_CLK_XGP1, ++ MTK_CLK_XGP2, ++ MTK_CLK_XGP3, ++ MTK_CLK_CRYPTO, + MTK_CLK_FE, + MTK_CLK_TRGPLL, + MTK_CLK_SGMII_TX_250M, +@@ -666,57 +672,108 @@ enum mtk_clks_map { + MTK_CLK_WOCPU1, + MTK_CLK_NETSYS0, + MTK_CLK_NETSYS1, ++ MTK_CLK_ETHWARP_WOCPU2, ++ MTK_CLK_ETHWARP_WOCPU1, ++ MTK_CLK_ETHWARP_WOCPU0, ++ MTK_CLK_TOP_USXGMII_SBUS_0_SEL, ++ MTK_CLK_TOP_USXGMII_SBUS_1_SEL, ++ MTK_CLK_TOP_SGM_0_SEL, ++ MTK_CLK_TOP_SGM_1_SEL, ++ MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL, ++ MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL, ++ MTK_CLK_TOP_ETH_GMII_SEL, ++ MTK_CLK_TOP_ETH_REFCK_50M_SEL, ++ MTK_CLK_TOP_ETH_SYS_200M_SEL, ++ MTK_CLK_TOP_ETH_SYS_SEL, ++ MTK_CLK_TOP_ETH_XGMII_SEL, ++ MTK_CLK_TOP_ETH_MII_SEL, ++ MTK_CLK_TOP_NETSYS_SEL, ++ MTK_CLK_TOP_NETSYS_500M_SEL, ++ MTK_CLK_TOP_NETSYS_PAO_2X_SEL, ++ MTK_CLK_TOP_NETSYS_SYNC_250M_SEL, ++ MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL, ++ MTK_CLK_TOP_NETSYS_WARP_SEL, + MTK_CLK_MAX + }; + +-#define MT7623_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ +- BIT(MTK_CLK_GP1) | BIT(MTK_CLK_GP2) | \ +- BIT(MTK_CLK_TRGPLL)) +-#define MT7622_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ +- BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \ +- BIT(MTK_CLK_GP2) | \ +- BIT(MTK_CLK_SGMII_TX_250M) | \ +- BIT(MTK_CLK_SGMII_RX_250M) | \ +- BIT(MTK_CLK_SGMII_CDR_REF) | \ +- BIT(MTK_CLK_SGMII_CDR_FB) | \ +- BIT(MTK_CLK_SGMII_CK) | \ +- BIT(MTK_CLK_ETH2PLL)) ++#define MT7623_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ ++ BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \ ++ BIT_ULL(MTK_CLK_TRGPLL)) ++#define MT7622_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ ++ BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \ ++ BIT_ULL(MTK_CLK_GP2) | \ ++ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ ++ BIT_ULL(MTK_CLK_SGMII_CK) | \ ++ BIT_ULL(MTK_CLK_ETH2PLL)) + #define MT7621_CLKS_BITMAP (0) + #define MT7628_CLKS_BITMAP (0) +-#define MT7629_CLKS_BITMAP (BIT(MTK_CLK_ETHIF) | BIT(MTK_CLK_ESW) | \ +- BIT(MTK_CLK_GP0) | BIT(MTK_CLK_GP1) | \ +- BIT(MTK_CLK_GP2) | BIT(MTK_CLK_FE) | \ +- BIT(MTK_CLK_SGMII_TX_250M) | \ +- BIT(MTK_CLK_SGMII_RX_250M) | \ +- BIT(MTK_CLK_SGMII_CDR_REF) | \ +- BIT(MTK_CLK_SGMII_CDR_FB) | \ +- BIT(MTK_CLK_SGMII2_TX_250M) | \ +- BIT(MTK_CLK_SGMII2_RX_250M) | \ +- BIT(MTK_CLK_SGMII2_CDR_REF) | \ +- BIT(MTK_CLK_SGMII2_CDR_FB) | \ +- BIT(MTK_CLK_SGMII_CK) | \ +- BIT(MTK_CLK_ETH2PLL) | BIT(MTK_CLK_SGMIITOP)) +-#define MT7981_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ +- BIT(MTK_CLK_WOCPU0) | \ +- BIT(MTK_CLK_SGMII_TX_250M) | \ +- BIT(MTK_CLK_SGMII_RX_250M) | \ +- BIT(MTK_CLK_SGMII_CDR_REF) | \ +- BIT(MTK_CLK_SGMII_CDR_FB) | \ +- BIT(MTK_CLK_SGMII2_TX_250M) | \ +- BIT(MTK_CLK_SGMII2_RX_250M) | \ +- BIT(MTK_CLK_SGMII2_CDR_REF) | \ +- BIT(MTK_CLK_SGMII2_CDR_FB) | \ +- BIT(MTK_CLK_SGMII_CK)) +-#define MT7986_CLKS_BITMAP (BIT(MTK_CLK_FE) | BIT(MTK_CLK_GP2) | BIT(MTK_CLK_GP1) | \ +- BIT(MTK_CLK_WOCPU1) | BIT(MTK_CLK_WOCPU0) | \ +- BIT(MTK_CLK_SGMII_TX_250M) | \ +- BIT(MTK_CLK_SGMII_RX_250M) | \ +- BIT(MTK_CLK_SGMII_CDR_REF) | \ +- BIT(MTK_CLK_SGMII_CDR_FB) | \ +- BIT(MTK_CLK_SGMII2_TX_250M) | \ +- BIT(MTK_CLK_SGMII2_RX_250M) | \ +- BIT(MTK_CLK_SGMII2_CDR_REF) | \ +- BIT(MTK_CLK_SGMII2_CDR_FB)) ++#define MT7629_CLKS_BITMAP (BIT_ULL(MTK_CLK_ETHIF) | BIT_ULL(MTK_CLK_ESW) | \ ++ BIT_ULL(MTK_CLK_GP0) | BIT_ULL(MTK_CLK_GP1) | \ ++ BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_FE) | \ ++ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ ++ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \ ++ BIT_ULL(MTK_CLK_SGMII_CK) | \ ++ BIT_ULL(MTK_CLK_ETH2PLL) | BIT_ULL(MTK_CLK_SGMIITOP)) ++#define MT7981_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP1) | \ ++ BIT_ULL(MTK_CLK_WOCPU0) | \ ++ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ ++ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII2_CDR_FB) | \ ++ BIT_ULL(MTK_CLK_SGMII_CK)) ++#define MT7986_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_GP2) | BIT_ULL(MTK_CLK_GP1) | \ ++ BIT_ULL(MTK_CLK_WOCPU1) | BIT_ULL(MTK_CLK_WOCPU0) | \ ++ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII_CDR_FB) | \ ++ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_CDR_REF) | \ ++ BIT_ULL(MTK_CLK_SGMII2_CDR_FB)) ++#define MT7988_CLKS_BITMAP (BIT_ULL(MTK_CLK_FE) | BIT_ULL(MTK_CLK_ESW) | \ ++ BIT_ULL(MTK_CLK_GP1) | BIT_ULL(MTK_CLK_GP2) | \ ++ BIT_ULL(MTK_CLK_GP3) | BIT_ULL(MTK_CLK_XGP1) | \ ++ BIT_ULL(MTK_CLK_XGP2) | BIT_ULL(MTK_CLK_XGP3) | \ ++ BIT_ULL(MTK_CLK_CRYPTO) | \ ++ BIT_ULL(MTK_CLK_SGMII_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII_RX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_TX_250M) | \ ++ BIT_ULL(MTK_CLK_SGMII2_RX_250M) | \ ++ BIT_ULL(MTK_CLK_ETHWARP_WOCPU2) | \ ++ BIT_ULL(MTK_CLK_ETHWARP_WOCPU1) | \ ++ BIT_ULL(MTK_CLK_ETHWARP_WOCPU0) | \ ++ BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_0_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_USXGMII_SBUS_1_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_SGM_0_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_SGM_1_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_XFI_PHY_0_XTAL_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_XFI_PHY_1_XTAL_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_ETH_GMII_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_ETH_REFCK_50M_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_ETH_SYS_200M_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_ETH_SYS_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_ETH_XGMII_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_ETH_MII_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_NETSYS_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_NETSYS_500M_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_NETSYS_PAO_2X_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_NETSYS_SYNC_250M_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_NETSYS_PPEFB_250M_SEL) | \ ++ BIT_ULL(MTK_CLK_TOP_NETSYS_WARP_SEL)) + + enum mtk_dev_state { + MTK_HW_INIT, +@@ -844,6 +901,7 @@ enum mkt_eth_capabilities { + MTK_RGMII_BIT = 0, + MTK_TRGMII_BIT, + MTK_SGMII_BIT, ++ MTK_USXGMII_BIT, + MTK_ESW_BIT, + MTK_GEPHY_BIT, + MTK_MUX_BIT, +@@ -866,6 +924,8 @@ enum mkt_eth_capabilities { + MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT, + MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT, + MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT, ++ MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT, ++ MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT, + + /* PATH BITS */ + MTK_ETH_PATH_GMAC1_RGMII_BIT, +@@ -874,13 +934,18 @@ enum mkt_eth_capabilities { + MTK_ETH_PATH_GMAC2_RGMII_BIT, + MTK_ETH_PATH_GMAC2_SGMII_BIT, + MTK_ETH_PATH_GMAC2_GEPHY_BIT, ++ MTK_ETH_PATH_GMAC3_SGMII_BIT, + MTK_ETH_PATH_GDM1_ESW_BIT, ++ MTK_ETH_PATH_GMAC1_USXGMII_BIT, ++ MTK_ETH_PATH_GMAC2_USXGMII_BIT, ++ MTK_ETH_PATH_GMAC3_USXGMII_BIT, + }; + + /* Supported hardware group on SoCs */ + #define MTK_RGMII BIT_ULL(MTK_RGMII_BIT) + #define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) + #define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) ++#define MTK_USXGMII BIT_ULL(MTK_USXGMII_BIT) + #define MTK_ESW BIT_ULL(MTK_ESW_BIT) + #define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) + #define MTK_MUX BIT_ULL(MTK_MUX_BIT) +@@ -907,6 +972,10 @@ enum mkt_eth_capabilities { + BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) + #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ + BIT_ULL(MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT) ++#define MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII \ ++ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT) ++#define MTK_ETH_MUX_GMAC123_TO_USXGMII \ ++ BIT_ULL(MTK_ETH_MUX_GMAC123_TO_USXGMII_BIT) + + /* Supported path present on SoCs */ + #define MTK_ETH_PATH_GMAC1_RGMII BIT_ULL(MTK_ETH_PATH_GMAC1_RGMII_BIT) +@@ -915,7 +984,11 @@ enum mkt_eth_capabilities { + #define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) + #define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) + #define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) ++#define MTK_ETH_PATH_GMAC3_SGMII BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT) + #define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) ++#define MTK_ETH_PATH_GMAC1_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC1_USXGMII_BIT) ++#define MTK_ETH_PATH_GMAC2_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC2_USXGMII_BIT) ++#define MTK_ETH_PATH_GMAC3_USXGMII BIT_ULL(MTK_ETH_PATH_GMAC3_USXGMII_BIT) + + #define MTK_GMAC1_RGMII (MTK_ETH_PATH_GMAC1_RGMII | MTK_RGMII) + #define MTK_GMAC1_TRGMII (MTK_ETH_PATH_GMAC1_TRGMII | MTK_TRGMII) +@@ -923,7 +996,11 @@ enum mkt_eth_capabilities { + #define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII) + #define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII) + #define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY) ++#define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII) + #define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW) ++#define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII) ++#define MTK_GMAC2_USXGMII (MTK_ETH_PATH_GMAC2_USXGMII | MTK_USXGMII) ++#define MTK_GMAC3_USXGMII (MTK_ETH_PATH_GMAC3_USXGMII | MTK_USXGMII) + + /* MUXes present on SoCs */ + /* 0: GDM1 -> GMAC1, 1: GDM1 -> ESW */ +@@ -946,6 +1023,12 @@ enum mkt_eth_capabilities { + #define MTK_MUX_GMAC12_TO_GEPHY_SGMII \ + (MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX) + ++#define MTK_MUX_GMAC123_TO_GEPHY_SGMII \ ++ (MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII | MTK_MUX) ++ ++#define MTK_MUX_GMAC123_TO_USXGMII \ ++ (MTK_ETH_MUX_GMAC123_TO_USXGMII | MTK_MUX | MTK_INFRA) ++ + #ifdef CONFIG_SOC_MT7621 + #define MTK_CAP_MASK MTK_NETSYS_V2 + #else +@@ -984,9 +1067,17 @@ enum mkt_eth_capabilities { + MTK_MUX_U3_GMAC2_TO_QPHY | MTK_U3_COPHY_V2 | \ + MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) + +-#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ +- MTK_MUX_GMAC12_TO_GEPHY_SGMII | MTK_QDMA | \ +- MTK_NETSYS_V2 | MTK_RSTCTRL_PPE1) ++#define MT7986_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ ++ MTK_MUX_GMAC12_TO_GEPHY_SGMII | \ ++ MTK_QDMA | MTK_NETSYS_V2 | \ ++ MTK_RSTCTRL_PPE1) ++ ++#define MT7988_CAPS (MTK_GMAC1_SGMII | MTK_GMAC2_SGMII | \ ++ MTK_GMAC3_SGMII | MTK_QDMA | \ ++ MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ ++ MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | \ ++ MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \ ++ MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1072,7 +1163,7 @@ struct mtk_soc_data { + const struct mtk_reg_map *reg_map; + u32 ana_rgc3; + u64 caps; +- u32 required_clks; ++ u64 required_clks; + bool required_pctl; + u8 offload_version; + u8 hash_offset; diff --git a/target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch b/target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch new file mode 100644 index 00000000000..68170b6614b --- /dev/null +++ b/target/linux/generic/pending-5.15/737-07-net-ethernet-mtk_eth_soc-add-paths-and-SerDes-modes-.patch @@ -0,0 +1,1671 @@ +From 20ac14fedba025b6b336a821ea60660afe2d46cd Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Wed, 1 Mar 2023 11:56:04 +0000 +Subject: [PATCH 7/7] net: ethernet: mtk_eth_soc: add paths and SerDes modes + for MT7988 + +MT7988 comes with a built-in 2.5G PHY as well as USXGMII or 10Base-KR +compatible SerDes lanes for external PHYs. +Add support for configuring the MAC and SerDes parts for the new paths. + +Signed-off-by: Daniel Golle +--- + drivers/net/ethernet/mediatek/Makefile | 2 +- + drivers/net/ethernet/mediatek/mtk_eth_path.c | 154 ++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 291 +++++++- + drivers/net/ethernet/mediatek/mtk_eth_soc.h | 162 ++++- + drivers/net/ethernet/mediatek/mtk_usxgmii.c | 659 +++++++++++++++++++ + 5 files changed, 1236 insertions(+), 32 deletions(-) + create mode 100644 drivers/net/ethernet/mediatek/mtk_usxgmii.c + +--- a/drivers/net/ethernet/mediatek/Makefile ++++ b/drivers/net/ethernet/mediatek/Makefile +@@ -5,6 +5,7 @@ + + obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o + mtk_eth-y := mtk_eth_soc.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_ppe_offload.o ++mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_USXGMII) += mtk_usxgmii.o + mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed.o mtk_wed_mcu.o mtk_wed_wo.o + ifdef CONFIG_DEBUG_FS + mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o +--- a/drivers/net/ethernet/mediatek/mtk_eth_path.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_path.c +@@ -31,10 +31,20 @@ static const char *mtk_eth_path_name(u64 + return "gmac2_rgmii"; + case MTK_ETH_PATH_GMAC2_SGMII: + return "gmac2_sgmii"; ++ case MTK_ETH_PATH_GMAC2_2P5GPHY: ++ return "gmac2_2p5gphy"; + case MTK_ETH_PATH_GMAC2_GEPHY: + return "gmac2_gephy"; ++ case MTK_ETH_PATH_GMAC3_SGMII: ++ return "gmac3_sgmii"; + case MTK_ETH_PATH_GDM1_ESW: + return "gdm1_esw"; ++ case MTK_ETH_PATH_GMAC1_USXGMII: ++ return "gmac1_usxgmii"; ++ case MTK_ETH_PATH_GMAC2_USXGMII: ++ return "gmac2_usxgmii"; ++ case MTK_ETH_PATH_GMAC3_USXGMII: ++ return "gmac3_usxgmii"; + default: + return "unknown path"; + } +@@ -42,8 +52,8 @@ static const char *mtk_eth_path_name(u64 + + static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path) + { ++ u32 val, mask, set, reg; + bool updated = true; +- u32 val, mask, set; + + switch (path) { + case MTK_ETH_PATH_GMAC1_SGMII: +@@ -59,10 +69,15 @@ static int set_mux_gdm1_to_gmac1_esw(str + break; + } + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) ++ reg = MTK_MAC_MISC_V3; ++ else ++ reg = MTK_MAC_MISC; ++ + if (updated) { +- val = mtk_r32(eth, MTK_MAC_MISC); ++ val = mtk_r32(eth, reg); + val = (val & mask) | set; +- mtk_w32(eth, val, MTK_MAC_MISC); ++ mtk_w32(eth, val, reg); + } + + dev_dbg(eth->dev, "path %s in %s updated = %d\n", +@@ -125,6 +140,31 @@ static int set_mux_u3_gmac2_to_qphy(stru + return 0; + } + ++static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path) ++{ ++ unsigned int val = 0; ++ bool updated = true; ++ int mac_id = 0; ++ ++ regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); ++ ++ switch (path) { ++ case MTK_ETH_PATH_GMAC2_2P5GPHY: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2; ++ mac_id = MTK_GMAC2_ID; ++ break; ++ default: ++ updated = false; ++ break; ++ }; ++ ++ if (updated) ++ regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, ++ SYSCFG0_SGMII_MASK, val); ++ ++ return 0; ++} ++ + static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; +@@ -163,7 +203,61 @@ static int set_mux_gmac1_gmac2_to_sgmii_ + return 0; + } + +-static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path) ++static int set_mux_gmac123_to_usxgmii(struct mtk_eth *eth, u64 path) ++{ ++ unsigned int val = 0; ++ bool updated = true; ++ int mac_id = 0; ++ ++ dev_dbg(eth->dev, "path %s in %s updated = %d\n", ++ mtk_eth_path_name(path), __func__, updated); ++ ++ /* Disable SYSCFG1 SGMII */ ++ regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); ++ ++ switch (path) { ++ case MTK_ETH_PATH_GMAC1_USXGMII: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC1_V2; ++ mac_id = MTK_GMAC1_ID; ++ break; ++ case MTK_ETH_PATH_GMAC2_USXGMII: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2; ++ mac_id = MTK_GMAC2_ID; ++ break; ++ case MTK_ETH_PATH_GMAC3_USXGMII: ++ val &= ~(u32)SYSCFG0_SGMII_GMAC3_V2; ++ mac_id = MTK_GMAC3_ID; ++ break; ++ default: ++ updated = false; ++ }; ++ ++ if (updated) { ++ regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, ++ SYSCFG0_SGMII_MASK, val); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) && ++ mac_id == MTK_GMAC2_ID) { ++ regmap_update_bits(eth->infra, ++ TOP_MISC_NETSYS_PCS_MUX, ++ NETSYS_PCS_MUX_MASK, ++ MUX_G2_USXGMII_SEL); ++ } ++ } ++ ++ /* Enable XGDM Path */ ++ val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac_id)); ++ val |= MTK_GDMA_XGDM_SEL; ++ mtk_w32(eth, val, MTK_GDMA_EG_CTRL(mac_id)); ++ ++ dev_dbg(eth->dev, "path %s in %s updated = %d\n", ++ mtk_eth_path_name(path), __func__, updated); ++ ++ ++ return 0; ++} ++ ++static int set_mux_gmac123_to_gephy_sgmii(struct mtk_eth *eth, u64 path) + { + unsigned int val = 0; + bool updated = true; +@@ -180,6 +274,9 @@ static int set_mux_gmac12_to_gephy_sgmii + case MTK_ETH_PATH_GMAC2_SGMII: + val |= SYSCFG0_SGMII_GMAC2_V2; + break; ++ case MTK_ETH_PATH_GMAC3_SGMII: ++ val |= SYSCFG0_SGMII_GMAC3_V2; ++ break; + default: + updated = false; + } +@@ -208,13 +305,25 @@ static const struct mtk_eth_muxc mtk_eth + .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY, + .set_path = set_mux_u3_gmac2_to_qphy, + }, { ++ .name = "mux_gmac2_to_2p5gphy", ++ .cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY, ++ .set_path = set_mux_gmac2_to_2p5gphy, ++ }, { + .name = "mux_gmac1_gmac2_to_sgmii_rgmii", + .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII, + .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii, + }, { + .name = "mux_gmac12_to_gephy_sgmii", + .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII, +- .set_path = set_mux_gmac12_to_gephy_sgmii, ++ .set_path = set_mux_gmac123_to_gephy_sgmii, ++ }, { ++ .name = "mux_gmac123_to_gephy_sgmii", ++ .cap_bit = MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII, ++ .set_path = set_mux_gmac123_to_gephy_sgmii, ++ }, { ++ .name = "mux_gmac123_to_usxgmii", ++ .cap_bit = MTK_ETH_MUX_GMAC123_TO_USXGMII, ++ .set_path = set_mux_gmac123_to_usxgmii, + }, + }; + +@@ -243,16 +352,46 @@ static int mtk_eth_mux_setup(struct mtk_ + } + } + ++ dev_dbg(eth->dev, "leaving mux_setup %s\n", ++ mtk_eth_path_name(path)); ++ + out: + return err; + } + ++int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id) ++{ ++ u64 path; ++ ++ path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_USXGMII : ++ (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_USXGMII : ++ MTK_ETH_PATH_GMAC3_USXGMII; ++ ++ /* Setup proper MUXes along the path */ ++ return mtk_eth_mux_setup(eth, path); ++} ++ + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) + { + u64 path; + +- path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : +- MTK_ETH_PATH_GMAC2_SGMII; ++ path = (mac_id == MTK_GMAC1_ID) ? MTK_ETH_PATH_GMAC1_SGMII : ++ (mac_id == MTK_GMAC2_ID) ? MTK_ETH_PATH_GMAC2_SGMII : ++ MTK_ETH_PATH_GMAC3_SGMII; ++ ++ /* Setup proper MUXes along the path */ ++ return mtk_eth_mux_setup(eth, path); ++} ++ ++int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id) ++{ ++ u64 path = 0; ++ ++ if (mac_id == MTK_GMAC2_ID) ++ path = MTK_ETH_PATH_GMAC2_2P5GPHY; ++ ++ if (!path) ++ return -EINVAL; + + /* Setup proper MUXes along the path */ + return mtk_eth_mux_setup(eth, path); +@@ -282,4 +421,3 @@ int mtk_gmac_rgmii_path_setup(struct mtk + /* Setup proper MUXes along the path */ + return mtk_eth_mux_setup(eth, path); + } +- +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c +@@ -437,6 +437,23 @@ static void mtk_gmac0_rgmii_adjust(struc + mtk_w32(eth, val, TRGMII_TCK_CTRL); + } + ++static void mtk_setup_bridge_switch(struct mtk_eth *eth) ++{ ++ int val; ++ ++ /* Force Port1 XGMAC Link Up */ ++ val = mtk_r32(eth, MTK_XGMAC_STS(MTK_GMAC1_ID)); ++ mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK(MTK_GMAC1_ID), ++ MTK_XGMAC_STS(MTK_GMAC1_ID)); ++ ++ /* Adjust GSW bridge IPG to 11*/ ++ val = mtk_r32(eth, MTK_GSW_CFG); ++ val &= ~(GSWTX_IPG_MASK | GSWRX_IPG_MASK); ++ val |= (GSW_IPG_11 << GSWTX_IPG_SHIFT) | ++ (GSW_IPG_11 << GSWRX_IPG_SHIFT); ++ mtk_w32(eth, val, MTK_GSW_CFG); ++} ++ + static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +@@ -462,7 +479,7 @@ static void mtk_mac_config(struct phylin + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); + struct mtk_eth *eth = mac->hw; +- int val, ge_mode, err = 0; ++ int val, ge_mode, force_link, err = 0; + u32 i; + + /* MT76x8 has no hardware settings between for the MAC */ +@@ -506,6 +523,23 @@ static void mtk_mac_config(struct phylin + goto init_err; + } + break; ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GKR: ++ case PHY_INTERFACE_MODE_5GBASER: ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) { ++ err = mtk_gmac_usxgmii_path_setup(eth, mac->id); ++ if (err) ++ goto init_err; ++ } ++ break; ++ case PHY_INTERFACE_MODE_INTERNAL: ++ if (mac->id == MTK_GMAC2_ID && ++ MTK_HAS_CAPS(eth->soc->caps, MTK_2P5GPHY)) { ++ err = mtk_gmac_2p5gphy_path_setup(eth, mac->id); ++ if (err) ++ goto init_err; ++ } ++ break; + default: + goto err_phy; + } +@@ -584,14 +618,92 @@ static void mtk_mac_config(struct phylin + SYSCFG0_SGMII_MASK, + ~(u32)SYSCFG0_SGMII_MASK); + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ mtk_xfi_pll_enable(eth); ++ mtk_sgmii_reset(eth, mac->id); ++ if (phylink_autoneg_inband(mode)) ++ mtk_sgmii_setup_phya_gen1(eth, mac->id); ++ else ++ mtk_sgmii_setup_phya_gen2(eth, mac->id); ++ } + /* Save the syscfg0 value for mac_finish */ + mac->syscfg0 = val; ++ } else if (state->interface == PHY_INTERFACE_MODE_USXGMII || ++ state->interface == PHY_INTERFACE_MODE_10GKR || ++ state->interface == PHY_INTERFACE_MODE_5GBASER) { ++ ++ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ err = -EINVAL; ++ goto init_err; ++ } ++ if (phylink_autoneg_inband(mode)) ++ err = mtk_usxgmii_setup_mode_force(eth, mac->id, ++ state); ++ else ++ err = mtk_usxgmii_setup_mode_an(eth, mac->id, ++ SPEED_10000); ++ ++ if (err) ++ goto init_err; + } else if (phylink_autoneg_inband(mode)) { + dev_err(eth->dev, + "In-band mode not supported in non SGMII mode!\n"); + return; + } + ++ /* Setup gmac */ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3) && ++ (mtk_interface_mode_is_xgmii(state->interface) || ++ mac->interface == PHY_INTERFACE_MODE_INTERNAL)) { ++ mtk_w32(mac->hw, MTK_GDMA_XGDM_SEL, MTK_GDMA_EG_CTRL(mac->id)); ++ mtk_w32(mac->hw, MAC_MCR_FORCE_LINK_DOWN, MTK_MAC_MCR(mac->id)); ++ ++ switch (mac->id) { ++ case MTK_GMAC1_ID: ++ mtk_setup_bridge_switch(eth); ++ break; ++ case MTK_GMAC2_ID: ++ force_link = (mac->interface == ++ PHY_INTERFACE_MODE_INTERNAL) ? ++ MTK_XGMAC_FORCE_LINK(mac->id) : 0; ++ val = mtk_r32(eth, MTK_XGMAC_STS(mac->id)); ++ mtk_w32(eth, val | force_link, ++ MTK_XGMAC_STS(mac->id)); ++ break; ++ case MTK_GMAC3_ID: ++ val = mtk_r32(eth, MTK_XGMAC_STS(mac->id)); ++ mtk_w32(eth, val | MTK_XGMAC_FORCE_LINK(mac->id), ++ MTK_XGMAC_STS(mac->id)); ++ break; ++ } ++ } else { ++ val = mtk_r32(eth, MTK_GDMA_EG_CTRL(mac->id)); ++ mtk_w32(eth, val & ~MTK_GDMA_XGDM_SEL, ++ MTK_GDMA_EG_CTRL(mac->id)); ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ switch (mac->id) { ++ case MTK_GMAC2_ID: ++ case MTK_GMAC3_ID: ++ val = mtk_r32(eth, MTK_XGMAC_STS(mac->id)); ++ mtk_w32(eth, ++ val & ~MTK_XGMAC_FORCE_LINK(mac->id), ++ MTK_XGMAC_STS(mac->id)); ++ break; ++ } ++ } ++ ++/* ++ if (mac->type != mac_type) { ++ if (atomic_read(&reset_pending) == 0) { ++ atomic_inc(&force); ++ schedule_work(ð->pending_work); ++ atomic_inc(&reset_pending); ++ } else ++ atomic_dec(&reset_pending); ++ } ++*/ ++ } + return; + + err_phy: +@@ -632,11 +744,37 @@ static int mtk_mac_finish(struct phylink + return 0; + } + +-static void mtk_mac_pcs_get_state(struct phylink_config *config, ++static void mtk_xgdm_pcs_get_state(struct mtk_mac *mac, ++ struct phylink_link_state *state) ++{ ++ u32 sts = mtk_r32(mac->hw, MTK_XGMAC_STS(mac->id)); ++ ++ if (mac->id == MTK_GMAC2_ID) ++ sts = sts >> 16; ++ ++ state->duplex = 1; ++ ++ switch (FIELD_GET(MTK_USXGMII_PCS_MODE, sts)) { ++ case 0: ++ state->speed = SPEED_10000; ++ break; ++ case 1: ++ state->speed = SPEED_5000; ++ break; ++ case 2: ++ state->speed = SPEED_2500; ++ break; ++ case 3: ++ state->speed = SPEED_1000; ++ break; ++ } ++ ++ state->link = FIELD_GET(MTK_USXGMII_PCS_LINK, sts); ++} ++ ++static void mtk_gdm_pcs_get_state(struct mtk_mac *mac, + struct phylink_link_state *state) + { +- struct mtk_mac *mac = container_of(config, struct mtk_mac, +- phylink_config); + u32 pmsr = mtk_r32(mac->hw, MTK_MAC_MSR(mac->id)); + + state->link = (pmsr & MAC_MSR_LINK); +@@ -664,15 +802,35 @@ static void mtk_mac_pcs_get_state(struct + state->pause |= MLO_PAUSE_TX; + } + ++static void mtk_mac_pcs_get_state(struct phylink_config *config, ++ struct phylink_link_state *state) ++{ ++ struct mtk_mac *mac = container_of(config, struct mtk_mac, ++ phylink_config); ++ ++ if (mtk_interface_mode_is_xgmii(state->interface)) ++ mtk_xgdm_pcs_get_state(mac, state); ++ else ++ mtk_gdm_pcs_get_state(mac, state); ++} ++ + static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode, + phy_interface_t interface) + { + struct mtk_mac *mac = container_of(config, struct mtk_mac, + phylink_config); +- u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); ++ u32 mcr; + +- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); +- mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); ++ if (!mtk_interface_mode_is_xgmii(interface)) { ++ mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); ++ mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN); ++ mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); ++ } else if (mac->id != MTK_GMAC1_ID) { ++ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id)); ++ mcr &= 0xfffffff0; ++ mcr |= XMAC_MCR_TRX_DISABLE; ++ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id)); ++ } + } + + static void mtk_set_queue_speed(struct mtk_eth *eth, unsigned int idx, +@@ -744,13 +902,11 @@ static void mtk_set_queue_speed(struct m + mtk_w32(eth, val, soc->reg_map->qdma.qtx_sch + ofs); + } + +-static void mtk_mac_link_up(struct phylink_config *config, +- struct phy_device *phy, +- unsigned int mode, phy_interface_t interface, +- int speed, int duplex, bool tx_pause, bool rx_pause) ++static void mtk_gdm_mac_link_up(struct mtk_mac *mac, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) + { +- struct mtk_mac *mac = container_of(config, struct mtk_mac, +- phylink_config); + u32 mcr; + + mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id)); +@@ -784,6 +940,47 @@ static void mtk_mac_link_up(struct phyli + mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id)); + } + ++static void mtk_xgdm_mac_link_up(struct mtk_mac *mac, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ u32 mcr; ++ ++ if (mac->id == MTK_GMAC1_ID) ++ return; ++ ++ mcr = mtk_r32(mac->hw, MTK_XMAC_MCR(mac->id)); ++ ++ mcr &= ~(XMAC_MCR_FORCE_TX_FC | XMAC_MCR_FORCE_RX_FC); ++ /* Configure pause modes - ++ * phylink will avoid these for half duplex ++ */ ++ if (tx_pause) ++ mcr |= XMAC_MCR_FORCE_TX_FC; ++ if (rx_pause) ++ mcr |= XMAC_MCR_FORCE_RX_FC; ++ ++ mcr &= ~(XMAC_MCR_TRX_DISABLE); ++ mtk_w32(mac->hw, mcr, MTK_XMAC_MCR(mac->id)); ++} ++ ++static void mtk_mac_link_up(struct phylink_config *config, ++ struct phy_device *phy, ++ unsigned int mode, phy_interface_t interface, ++ int speed, int duplex, bool tx_pause, bool rx_pause) ++{ ++ struct mtk_mac *mac = container_of(config, struct mtk_mac, ++ phylink_config); ++ ++ if (mtk_interface_mode_is_xgmii(interface)) ++ mtk_xgdm_mac_link_up(mac, phy, mode, interface, speed, duplex, ++ tx_pause, rx_pause); ++ else ++ mtk_gdm_mac_link_up(mac, phy, mode, interface, speed, duplex, ++ tx_pause, rx_pause); ++} ++ + static const struct phylink_mac_ops mtk_phylink_ops = { + .validate = phylink_generic_validate, + .mac_select_pcs = mtk_mac_select_pcs, +@@ -836,10 +1033,21 @@ static int mtk_mdio_init(struct mtk_eth + } + divider = min_t(unsigned int, DIV_ROUND_UP(MDC_MAX_FREQ, max_clk), 63); + ++ /* Configure MDC Turbo Mode */ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ val = mtk_r32(eth, MTK_MAC_MISC_V3); ++ val |= MISC_MDC_TURBO; ++ mtk_w32(eth, val, MTK_MAC_MISC_V3); ++ } else { ++ val = mtk_r32(eth, MTK_PPSC); ++ val |= PPSC_MDC_TURBO; ++ mtk_w32(eth, val, MTK_PPSC); ++ } ++ + /* Configure MDC Divider */ + val = mtk_r32(eth, MTK_PPSC); + val &= ~PPSC_MDC_CFG; +- val |= FIELD_PREP(PPSC_MDC_CFG, divider) | PPSC_MDC_TURBO; ++ val |= FIELD_PREP(PPSC_MDC_CFG, divider); + mtk_w32(eth, val, MTK_PPSC); + + dev_dbg(eth->dev, "MDC is running on %d Hz\n", MDC_MAX_FREQ / divider); +@@ -4433,8 +4641,8 @@ static int mtk_add_mac(struct mtk_eth *e + const __be32 *_id = of_get_property(np, "reg", NULL); + phy_interface_t phy_mode; + struct phylink *phylink; +- struct mtk_mac *mac; + int id, err; ++ struct mtk_mac *mac; + int txqs = 1; + + if (!_id) { +@@ -4525,6 +4733,32 @@ static int mtk_add_mac(struct mtk_eth *e + mac->phylink_config.supported_interfaces); + } + ++ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_USXGMII)) { ++ if (id == MTK_GMAC1_ID) { ++ mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | ++ MAC_SYM_PAUSE | ++ MAC_10000FD; ++ phy_interface_zero( ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ mac->phylink_config.supported_interfaces); ++ } else { ++ mac->phylink_config.mac_capabilities |= MAC_5000FD | MAC_10000FD; ++ __set_bit(PHY_INTERFACE_MODE_5GBASER, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_10GKR, ++ mac->phylink_config.supported_interfaces); ++ __set_bit(PHY_INTERFACE_MODE_USXGMII, ++ mac->phylink_config.supported_interfaces); ++ } ++ } ++ ++ if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_2P5GPHY)) { ++ if (id == MTK_GMAC2_ID) ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ mac->phylink_config.supported_interfaces); ++ } ++ + phylink = phylink_create(&mac->phylink_config, + of_fwnode_handle(mac->of_node), + phy_mode, &mtk_phylink_ops); +@@ -4714,6 +4948,33 @@ static int mtk_probe(struct platform_dev + return err; + } + ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_USXGMII)) { ++ eth->xgmii = devm_kzalloc(eth->dev, sizeof(*eth->xgmii), GFP_KERNEL); ++ err = mtk_usxgmii_init(eth); ++ if (err) { ++ dev_err(&pdev->dev, "usxgmii init failed\n"); ++ return err; ++ } ++ ++ err = mtk_xfi_pextp_init(eth); ++ if (err) { ++ dev_err(&pdev->dev, "pextp init failed\n"); ++ return err; ++ } ++ ++ err = mtk_xfi_pll_init(eth); ++ if (err) { ++ dev_err(&pdev->dev, "xfi pll init failed\n"); ++ return err; ++ } ++ ++ err = mtk_toprgu_init(eth); ++ if (err) { ++ dev_err(&pdev->dev, "toprgu init failed\n"); ++ return err; ++ } ++ } ++ + if (eth->soc->required_pctl) { + eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, + "mediatek,pctl"); +--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h ++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h +@@ -126,6 +126,11 @@ + #define MTK_GDMA_TO_PDMA 0x0 + #define MTK_GDMA_DROP_ALL 0x7777 + ++/* GDM Egress Control Register */ ++#define MTK_GDMA_EG_CTRL(x) ((x == MTK_GMAC3_ID) ? \ ++ 0x544 : 0x504 + (x * 0x1000)) ++#define MTK_GDMA_XGDM_SEL BIT(31) ++ + /* Unicast Filter MAC Address Register - Low */ + #define MTK_GDMA_MAC_ADRL(x) (0x508 + (x * 0x1000)) + +@@ -386,7 +391,26 @@ + #define PHY_IAC_TIMEOUT HZ + + #define MTK_MAC_MISC 0x1000c ++#define MTK_MAC_MISC_V3 0x10010 + #define MTK_MUX_TO_ESW BIT(0) ++#define MISC_MDC_TURBO BIT(4) ++ ++/* XMAC status registers */ ++#define MTK_XGMAC_STS(x) ((x == MTK_GMAC3_ID) ? 0x1001C : 0x1000C) ++#define MTK_XGMAC_FORCE_LINK(x) ((x == MTK_GMAC2_ID) ? BIT(31) : BIT(15)) ++#define MTK_USXGMII_PCS_LINK BIT(8) ++#define MTK_XGMAC_RX_FC BIT(5) ++#define MTK_XGMAC_TX_FC BIT(4) ++#define MTK_USXGMII_PCS_MODE GENMASK(3, 1) ++#define MTK_XGMAC_LINK_STS BIT(0) ++ ++/* GSW bridge registers */ ++#define MTK_GSW_CFG (0x10080) ++#define GSWTX_IPG_MASK GENMASK(19, 16) ++#define GSWTX_IPG_SHIFT 16 ++#define GSWRX_IPG_MASK GENMASK(3, 0) ++#define GSWRX_IPG_SHIFT 0 ++#define GSW_IPG_11 11 + + /* Mac control registers */ + #define MTK_MAC_MCR(x) (0x10100 + (x * 0x100)) +@@ -411,6 +435,17 @@ + #define MAC_MCR_FORCE_LINK BIT(0) + #define MAC_MCR_FORCE_LINK_DOWN (MAC_MCR_FORCE_MODE) + ++/* Mac EEE control registers */ ++#define MTK_MAC_EEE(x) (0x10104 + (x * 0x100)) ++#define MAC_EEE_WAKEUP_TIME_1000 GENMASK(31, 24) ++#define MAC_EEE_WAKEUP_TIME_100 GENMASK(23, 16) ++#define MAC_EEE_LPI_TXIDLE_THD GENMASK(15, 8) ++#define MAC_EEE_RESV0 GENMASK(7, 4) ++#define MAC_EEE_CKG_TXILDE BIT(3) ++#define MAC_EEE_CKG_RXLPI BIT(2) ++#define MAC_EEE_TX_DOWN_REQ BIT(1) ++#define MAC_EEE_LPI_MODE BIT(0) ++ + /* Mac status registers */ + #define MTK_MAC_MSR(x) (0x10108 + (x * 0x100)) + #define MAC_MSR_EEE1G BIT(7) +@@ -455,6 +490,12 @@ + #define INTF_MODE_RGMII_1000 (TRGMII_MODE | TRGMII_CENTRAL_ALIGNED) + #define INTF_MODE_RGMII_10_100 0 + ++/* XFI Mac control registers */ ++#define MTK_XMAC_MCR(x) (0x12000 + ((x - 1) * 0x1000)) ++#define XMAC_MCR_TRX_DISABLE 0xf ++#define XMAC_MCR_FORCE_TX_FC BIT(5) ++#define XMAC_MCR_FORCE_RX_FC BIT(4) ++ + /* GPIO port control registers for GMAC 2*/ + #define GPIO_OD33_CTRL8 0x4c0 + #define GPIO_BIAS_CTRL 0xed0 +@@ -480,6 +521,7 @@ + #define SYSCFG0_SGMII_GMAC2 ((3 << 8) & SYSCFG0_SGMII_MASK) + #define SYSCFG0_SGMII_GMAC1_V2 BIT(9) + #define SYSCFG0_SGMII_GMAC2_V2 BIT(8) ++#define SYSCFG0_SGMII_GMAC3_V2 BIT(7) + + + /* ethernet subsystem clock register */ +@@ -506,16 +548,69 @@ + #define ETHSYS_DMA_AG_MAP_QDMA BIT(1) + #define ETHSYS_DMA_AG_MAP_PPE BIT(2) + ++/* USXGMII subsystem config registers */ ++/* Register to control speed */ ++#define RG_PHY_TOP_SPEED_CTRL1 0x80C ++#define RG_USXGMII_RATE_UPDATE_MODE BIT(31) ++#define RG_MAC_CK_GATED BIT(29) ++#define RG_IF_FORCE_EN BIT(28) ++#define RG_RATE_ADAPT_MODE GENMASK(10, 8) ++#define RG_RATE_ADAPT_MODE_X1 0 ++#define RG_RATE_ADAPT_MODE_X2 1 ++#define RG_RATE_ADAPT_MODE_X4 2 ++#define RG_RATE_ADAPT_MODE_X10 3 ++#define RG_RATE_ADAPT_MODE_X100 4 ++#define RG_RATE_ADAPT_MODE_X5 5 ++#define RG_RATE_ADAPT_MODE_X50 6 ++#define RG_XFI_RX_MODE GENMASK(6, 4) ++#define RG_XFI_RX_MODE_10G 0 ++#define RG_XFI_RX_MODE_5G 1 ++#define RG_XFI_TX_MODE GENMASK(2, 0) ++#define RG_XFI_TX_MODE_10G 0 ++#define RG_XFI_TX_MODE_5G 1 ++ ++/* Register to control PCS AN */ ++#define RG_PCS_AN_CTRL0 0x810 ++#define RG_AN_ENABLE BIT(0) ++ ++/* Register to control USXGMII XFI PLL digital */ ++#define XFI_PLL_DIG_GLB8 0x08 ++#define RG_XFI_PLL_EN BIT(31) ++ ++/* Register to control USXGMII XFI PLL analog */ ++#define XFI_PLL_ANA_GLB8 0x108 ++#define RG_XFI_PLL_ANA_SWWA 0x02283248 ++ + /* Infrasys subsystem config registers */ + #define INFRA_MISC2 0x70c + #define CO_QPHY_SEL BIT(0) + #define GEPHY_MAC_SEL BIT(1) + ++/* Toprgu subsystem config registers */ ++#define TOPRGU_SWSYSRST 0x18 ++#define SWSYSRST_UNLOCK_KEY GENMASK(31, 24) ++#define SWSYSRST_XFI_PLL_GRST BIT(16) ++#define SWSYSRST_XFI_PEXPT1_GRST BIT(15) ++#define SWSYSRST_XFI_PEXPT0_GRST BIT(14) ++#define SWSYSRST_SGMII1_GRST BIT(2) ++#define SWSYSRST_SGMII0_GRST BIT(1) ++#define TOPRGU_SWSYSRST_EN 0xFC ++ + /* Top misc registers */ ++#define TOP_MISC_NETSYS_PCS_MUX 0x84 ++#define NETSYS_PCS_MUX_MASK GENMASK(1, 0) ++#define MUX_G2_USXGMII_SEL BIT(1) ++#define MUX_HSGMII1_G1_SEL BIT(0) ++ + #define USB_PHY_SWITCH_REG 0x218 + #define QPHY_SEL_MASK GENMASK(1, 0) + #define SGMII_QPHY_SEL 0x2 + ++/* MDIO control */ ++#define MII_MMD_ACC_CTL_REG 0x0d ++#define MII_MMD_ADDR_DATA_REG 0x0e ++#define MMD_OP_MODE_DATA BIT(14) ++ + /* MT7628/88 specific stuff */ + #define MT7628_PDMA_OFFSET 0x0800 + #define MT7628_SDM_OFFSET 0x0c00 +@@ -809,13 +904,6 @@ enum mtk_gmac_id { + MTK_GMAC_ID_MAX + }; + +-/* GDM Type */ +-enum mtk_gdm_type { +- MTK_GDM_TYPE = 0, +- MTK_XGDM_TYPE, +- MTK_GDM_TYPE_MAX +-}; +- + enum mtk_tx_buf_type { + MTK_TYPE_SKB, + MTK_TYPE_XDP_TX, +@@ -902,6 +990,7 @@ enum mkt_eth_capabilities { + MTK_TRGMII_BIT, + MTK_SGMII_BIT, + MTK_USXGMII_BIT, ++ MTK_2P5GPHY_BIT, + MTK_ESW_BIT, + MTK_GEPHY_BIT, + MTK_MUX_BIT, +@@ -922,6 +1011,7 @@ enum mkt_eth_capabilities { + MTK_ETH_MUX_GDM1_TO_GMAC1_ESW_BIT, + MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT, + MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT, ++ MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT, + MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT, + MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII_BIT, + MTK_ETH_MUX_GMAC123_TO_GEPHY_SGMII_BIT, +@@ -933,6 +1023,7 @@ enum mkt_eth_capabilities { + MTK_ETH_PATH_GMAC1_SGMII_BIT, + MTK_ETH_PATH_GMAC2_RGMII_BIT, + MTK_ETH_PATH_GMAC2_SGMII_BIT, ++ MTK_ETH_PATH_GMAC2_2P5GPHY_BIT, + MTK_ETH_PATH_GMAC2_GEPHY_BIT, + MTK_ETH_PATH_GMAC3_SGMII_BIT, + MTK_ETH_PATH_GDM1_ESW_BIT, +@@ -946,6 +1037,7 @@ enum mkt_eth_capabilities { + #define MTK_TRGMII BIT_ULL(MTK_TRGMII_BIT) + #define MTK_SGMII BIT_ULL(MTK_SGMII_BIT) + #define MTK_USXGMII BIT_ULL(MTK_USXGMII_BIT) ++#define MTK_2P5GPHY BIT_ULL(MTK_2P5GPHY_BIT) + #define MTK_ESW BIT_ULL(MTK_ESW_BIT) + #define MTK_GEPHY BIT_ULL(MTK_GEPHY_BIT) + #define MTK_MUX BIT_ULL(MTK_MUX_BIT) +@@ -968,6 +1060,8 @@ enum mkt_eth_capabilities { + BIT_ULL(MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY_BIT) + #define MTK_ETH_MUX_U3_GMAC2_TO_QPHY \ + BIT_ULL(MTK_ETH_MUX_U3_GMAC2_TO_QPHY_BIT) ++#define MTK_ETH_MUX_GMAC2_TO_2P5GPHY \ ++ BIT_ULL(MTK_ETH_MUX_GMAC2_TO_2P5GPHY_BIT) + #define MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII \ + BIT_ULL(MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII_BIT) + #define MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII \ +@@ -983,6 +1077,7 @@ enum mkt_eth_capabilities { + #define MTK_ETH_PATH_GMAC1_SGMII BIT_ULL(MTK_ETH_PATH_GMAC1_SGMII_BIT) + #define MTK_ETH_PATH_GMAC2_RGMII BIT_ULL(MTK_ETH_PATH_GMAC2_RGMII_BIT) + #define MTK_ETH_PATH_GMAC2_SGMII BIT_ULL(MTK_ETH_PATH_GMAC2_SGMII_BIT) ++#define MTK_ETH_PATH_GMAC2_2P5GPHY BIT_ULL(MTK_ETH_PATH_GMAC2_2P5GPHY_BIT) + #define MTK_ETH_PATH_GMAC2_GEPHY BIT_ULL(MTK_ETH_PATH_GMAC2_GEPHY_BIT) + #define MTK_ETH_PATH_GMAC3_SGMII BIT_ULL(MTK_ETH_PATH_GMAC3_SGMII_BIT) + #define MTK_ETH_PATH_GDM1_ESW BIT_ULL(MTK_ETH_PATH_GDM1_ESW_BIT) +@@ -996,6 +1091,7 @@ enum mkt_eth_capabilities { + #define MTK_GMAC2_RGMII (MTK_ETH_PATH_GMAC2_RGMII | MTK_RGMII) + #define MTK_GMAC2_SGMII (MTK_ETH_PATH_GMAC2_SGMII | MTK_SGMII) + #define MTK_GMAC2_GEPHY (MTK_ETH_PATH_GMAC2_GEPHY | MTK_GEPHY) ++#define MTK_GMAC2_2P5GPHY (MTK_ETH_PATH_GMAC2_2P5GPHY | MTK_2P5GPHY) + #define MTK_GMAC3_SGMII (MTK_ETH_PATH_GMAC3_SGMII | MTK_SGMII) + #define MTK_GDM1_ESW (MTK_ETH_PATH_GDM1_ESW | MTK_ESW) + #define MTK_GMAC1_USXGMII (MTK_ETH_PATH_GMAC1_USXGMII | MTK_USXGMII) +@@ -1019,6 +1115,10 @@ enum mkt_eth_capabilities { + (MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII | MTK_MUX | \ + MTK_SHARED_SGMII) + ++/* 2: GMAC2 -> XGMII */ ++#define MTK_MUX_GMAC2_TO_2P5GPHY \ ++ (MTK_ETH_MUX_GMAC2_TO_2P5GPHY | MTK_MUX | MTK_INFRA) ++ + /* 0: GMACx -> GEPHY, 1: GMACx -> SGMII where x is 1 or 2 */ + #define MTK_MUX_GMAC12_TO_GEPHY_SGMII \ + (MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII | MTK_MUX) +@@ -1077,7 +1177,8 @@ enum mkt_eth_capabilities { + MTK_MUX_GMAC123_TO_GEPHY_SGMII | \ + MTK_NETSYS_V3 | MTK_RSTCTRL_PPE1 | \ + MTK_GMAC1_USXGMII | MTK_GMAC2_USXGMII | \ +- MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII) ++ MTK_GMAC3_USXGMII | MTK_MUX_GMAC123_TO_USXGMII | \ ++ MTK_GMAC2_2P5GPHY | MTK_MUX_GMAC2_TO_2P5GPHY) + + struct mtk_tx_dma_desc_info { + dma_addr_t addr; +@@ -1183,6 +1284,19 @@ struct mtk_soc_data { + + #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000) + ++/* struct mtk_xgmii - This is the structure holding sgmii/usxgmii regmap and ++ * its characteristics ++ * @regmap: The register map pointing at the range used to setup ++ * SGMII/USXGMII modes ++ * @flags: The enum refers to which mode the sgmii wants to run on ++ * @ana_rgc3: The offset refers to register ANA_RGC3 related to regmap ++ */ ++struct mtk_xgmii { ++ struct regmap **regmap_usxgmii; ++ struct regmap **regmap_pextp; ++ struct regmap *regmap_pll; ++}; ++ + /* struct mtk_eth - This is the main datasructure for holding the state + * of the driver + * @dev: The device pointer +@@ -1244,7 +1358,9 @@ struct mtk_eth { + unsigned long sysclk; + struct regmap *ethsys; + struct regmap *infra; ++ struct regmap *toprgu; + struct phylink_pcs **sgmii_pcs; ++ struct mtk_xgmii *xgmii; + struct regmap *pctl; + bool hwlro; + refcount_t dma_refcnt; +@@ -1400,6 +1516,19 @@ static inline u32 mtk_get_ib2_multicast_ + return MTK_FOE_IB2_MULTICAST; + } + ++static inline bool mtk_interface_mode_is_xgmii(phy_interface_t interface) ++{ ++ switch (interface) { ++ case PHY_INTERFACE_MODE_USXGMII: ++ case PHY_INTERFACE_MODE_10GKR: ++ case PHY_INTERFACE_MODE_5GBASER: ++ return true; ++ break; ++ default: ++ return false; ++ } ++} ++ + /* read the hardware status register */ + void mtk_stats_update_mac(struct mtk_mac *mac); + +@@ -1407,8 +1536,10 @@ void mtk_w32(struct mtk_eth *eth, u32 va + u32 mtk_r32(struct mtk_eth *eth, unsigned reg); + + int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id); ++int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id); + int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id); ++int mtk_gmac_usxgmii_path_setup(struct mtk_eth *eth, int mac_id); + + int mtk_eth_offload_init(struct mtk_eth *eth); + int mtk_eth_setup_tc(struct net_device *dev, enum tc_setup_type type, +@@ -1418,5 +1549,36 @@ int mtk_flow_offload_cmd(struct mtk_eth + void mtk_flow_offload_cleanup(struct mtk_eth *eth, struct list_head *list); + void mtk_eth_set_dma_device(struct mtk_eth *eth, struct device *dma_dev); + ++#ifdef CONFIG_NET_MEDIATEK_SOC_USXGMII ++int mtk_usxgmii_init(struct mtk_eth *eth); ++int mtk_xfi_pextp_init(struct mtk_eth *eth); ++int mtk_xfi_pll_init(struct mtk_eth *eth); ++int mtk_toprgu_init(struct mtk_eth *eth); ++int mtk_xfi_pll_enable(struct mtk_eth *eth); ++int mtk_usxgmii_setup_mode_an(struct mtk_eth *eth, int mac_id, ++ int max_speed); ++int mtk_usxgmii_setup_mode_force(struct mtk_eth *eth, int mac_id, ++ const struct phylink_link_state *state); ++void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth *eth, int mac_id); ++void mtk_usxgmii_reset(struct mtk_eth *eth, int mac_id); ++void mtk_sgmii_setup_phya_gen1(struct mtk_eth *eth, int mac_id); ++void mtk_sgmii_setup_phya_gen2(struct mtk_eth *eth, int mac_id); ++void mtk_sgmii_reset(struct mtk_eth *eth, int mac_id); ++#else ++static inline int mtk_usxgmii_init(struct mtk_eth *eth) { return 0; }; ++static inline int mtk_xfi_pextp_init(struct mtk_eth *eth) { return 0; }; ++static inline int mtk_xfi_pll_init(struct mtk_eth *eth) { return 0; }; ++static inline int mtk_toprgu_init(struct mtk_eth *eth) { return 0; }; ++static inline int mtk_xfi_pll_enable(struct mtk_eth *eth) { return 0; }; ++static inline int mtk_usxgmii_setup_mode_an(struct mtk_eth *eth, int mac_id, ++ int max_speed) { return 0; }; ++static inline int mtk_usxgmii_setup_mode_force(struct mtk_eth *eth, int mac_id, ++ const struct phylink_link_state *state) { return 0; }; ++static inline void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth *eth, int mac_id) { }; ++static inline void mtk_usxgmii_reset(struct mtk_eth *eth, int mac_id) { }; ++static inline void mtk_sgmii_setup_phya_gen1(struct mtk_eth *eth, int mac_id) { }; ++static inline void mtk_sgmii_setup_phya_gen2(struct mtk_eth *eth, int mac_id) { }; ++static inline void mtk_sgmii_reset(struct mtk_eth *eth, int mac_id) { }; ++#endif + + #endif /* MTK_ETH_H */ +--- /dev/null ++++ b/drivers/net/ethernet/mediatek/mtk_usxgmii.c +@@ -0,0 +1,646 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (c) 2022 MediaTek Inc. ++ * Author: Henry Yen ++ */ ++ ++#include ++#include ++#include ++#include "mtk_eth_soc.h" ++ ++int mtk_usxgmii_init(struct mtk_eth *eth) ++{ ++ struct device_node *r = eth->dev->of_node; ++ struct mtk_xgmii *xs = eth->xgmii; ++ struct device *dev = eth->dev; ++ struct device_node *np; ++ int i; ++ ++ xs->regmap_usxgmii = devm_kzalloc(dev, sizeof(*xs->regmap_usxgmii) * ++ eth->soc->num_devs, GFP_KERNEL); ++ if (!xs->regmap_usxgmii) ++ return -ENOMEM; ++ ++ for (i = 0; i < eth->soc->num_devs; i++) { ++ np = of_parse_phandle(r, "mediatek,usxgmiisys", i); ++ if (!np) ++ break; ++ ++ xs->regmap_usxgmii[i] = syscon_node_to_regmap(np); ++ if (IS_ERR(xs->regmap_usxgmii[i])) ++ return PTR_ERR(xs->regmap_usxgmii[i]); ++ } ++ ++ return 0; ++} ++ ++int mtk_xfi_pextp_init(struct mtk_eth *eth) ++{ ++ struct device *dev = eth->dev; ++ struct device_node *r = dev->of_node; ++ struct mtk_xgmii *xs = eth->xgmii; ++ struct device_node *np; ++ int i; ++ ++ xs->regmap_pextp = devm_kzalloc(dev, sizeof(*xs->regmap_pextp) * ++ eth->soc->num_devs, GFP_KERNEL); ++ if (!xs->regmap_pextp) ++ return -ENOMEM; ++ ++ for (i = 0; i < eth->soc->num_devs; i++) { ++ np = of_parse_phandle(r, "mediatek,xfi_pextp", i); ++ if (!np) ++ break; ++ ++ xs->regmap_pextp[i] = syscon_node_to_regmap(np); ++ if (IS_ERR(xs->regmap_pextp[i])) ++ return PTR_ERR(xs->regmap_pextp[i]); ++ } ++ ++ return 0; ++} ++ ++int mtk_xfi_pll_init(struct mtk_eth *eth) ++{ ++ struct device_node *r = eth->dev->of_node; ++ struct mtk_xgmii *xs = eth->xgmii; ++ struct device_node *np; ++ ++ np = of_parse_phandle(r, "mediatek,xfi_pll", 0); ++ if (!np) ++ return -1; ++ ++ xs->regmap_pll = syscon_node_to_regmap(np); ++ if (IS_ERR(xs->regmap_pll)) ++ return PTR_ERR(xs->regmap_pll); ++ ++ return 0; ++} ++ ++int mtk_toprgu_init(struct mtk_eth *eth) ++{ ++ struct device_node *r = eth->dev->of_node; ++ struct device_node *np; ++ ++ np = of_parse_phandle(r, "mediatek,toprgu", 0); ++ if (!np) ++ return -1; ++ ++ eth->toprgu = syscon_node_to_regmap(np); ++ if (IS_ERR(eth->toprgu)) ++ return PTR_ERR(eth->toprgu); ++ ++ return 0; ++} ++ ++int mtk_xfi_pll_enable(struct mtk_eth *eth) ++{ ++ struct mtk_xgmii *xs = eth->xgmii; ++ u32 val = 0; ++ ++ if (!xs->regmap_pll) ++ return -EINVAL; ++ ++ /* Add software workaround for USXGMII PLL TCL issue */ ++ regmap_write(xs->regmap_pll, XFI_PLL_ANA_GLB8, RG_XFI_PLL_ANA_SWWA); ++ ++ regmap_read(xs->regmap_pll, XFI_PLL_DIG_GLB8, &val); ++ val |= RG_XFI_PLL_EN; ++ regmap_write(xs->regmap_pll, XFI_PLL_DIG_GLB8, val); ++ ++ return 0; ++} ++ ++static int mtk_mac2xgmii_id(struct mtk_eth *eth, int mac_id) ++{ ++ int xgmii_id = mac_id; ++ ++ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) { ++ switch (mac_id) { ++ case MTK_GMAC1_ID: ++ case MTK_GMAC2_ID: ++ xgmii_id = 1; ++ break; ++ case MTK_GMAC3_ID: ++ xgmii_id = 0; ++ break; ++ default: ++ xgmii_id = -1; ++ } ++ } ++ ++ return xgmii_id; ++} ++ ++void mtk_usxgmii_setup_phya_an_10000(struct mtk_eth *eth, int mac_id) ++{ ++ struct mtk_xgmii *xs = eth->xgmii; ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ ++ if (id >= eth->soc->num_devs || ++ !xs->regmap_usxgmii[id] || !xs->regmap_pextp[id]) ++ return; ++ ++ regmap_write(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, 0x000FFE6D); ++ regmap_write(xs->regmap_usxgmii[id], 0x818, 0x07B1EC7B); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, 0x30000000); ++ ndelay(1020); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, 0x10000000); ++ ndelay(1020); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, 0x00000000); ++ ++ regmap_write(xs->regmap_pextp[id], 0x9024, 0x00C9071C); ++ regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA); ++ regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707); ++ regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F); ++ regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032); ++ regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014AA); ++ regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B); ++ regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF); ++ regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA); ++ regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F); ++ regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68); ++ regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166); ++ regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000AAF); ++ regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080D0D); ++ regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030909); ++ regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000); ++ regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000); ++ regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06); ++ regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C); ++ regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000); ++ regmap_write(xs->regmap_pextp[id], 0x00F8, 0x01423342); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F20); ++ regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020); ++ regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01); ++ regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884); ++ regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002); ++ regmap_write(xs->regmap_pextp[id], 0x3010, 0x00022220); ++ regmap_write(xs->regmap_pextp[id], 0x5064, 0x0F020A01); ++ regmap_write(xs->regmap_pextp[id], 0x50B4, 0x06100600); ++ regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000); ++ regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000); ++ regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA); ++ regmap_write(xs->regmap_pextp[id], 0x306C, 0x00000F00); ++ regmap_write(xs->regmap_pextp[id], 0xA060, 0x00040000); ++ regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000001); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800); ++ udelay(150); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101); ++ udelay(15); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C101); ++ udelay(100); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F00); ++ regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000); ++ udelay(400); ++} ++ ++void mtk_usxgmii_setup_phya_force_5000(struct mtk_eth *eth, int mac_id) ++{ ++ unsigned int val; ++ struct mtk_xgmii *xs = eth->xgmii; ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ ++ if (id >= eth->soc->num_devs || ++ !xs->regmap_usxgmii[id] || !xs->regmap_pextp[id]) ++ return; ++ ++ /* Setup USXGMII speed */ ++ val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_5G) | ++ FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_5G); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ /* Disable USXGMII AN mode */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, &val); ++ val &= ~RG_AN_ENABLE; ++ regmap_write(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, val); ++ ++ /* Gated USXGMII */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val); ++ val |= RG_MAC_CK_GATED; ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ ndelay(1020); ++ ++ /* USXGMII force mode setting */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val); ++ val |= RG_USXGMII_RATE_UPDATE_MODE; ++ val |= RG_IF_FORCE_EN; ++ val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ /* Un-gated USXGMII */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val); ++ val &= ~RG_MAC_CK_GATED; ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ ndelay(1020); ++ ++ regmap_write(xs->regmap_pextp[id], 0x9024, 0x00D9071C); ++ regmap_write(xs->regmap_pextp[id], 0x2020, 0xAAA5A5AA); ++ regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707); ++ regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F); ++ regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032); ++ regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C018AA); ++ regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777812B); ++ regmap_write(xs->regmap_pextp[id], 0x506C, 0x005C9CFF); ++ regmap_write(xs->regmap_pextp[id], 0x5070, 0x9DFAFAFA); ++ regmap_write(xs->regmap_pextp[id], 0x5074, 0x273F3F3F); ++ regmap_write(xs->regmap_pextp[id], 0x5078, 0xA8883868); ++ regmap_write(xs->regmap_pextp[id], 0x507C, 0x14661466); ++ regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E001ABF); ++ regmap_write(xs->regmap_pextp[id], 0x5084, 0x080B0D0D); ++ regmap_write(xs->regmap_pextp[id], 0x5088, 0x02050909); ++ regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C000000); ++ regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04000000); ++ regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06); ++ regmap_write(xs->regmap_pextp[id], 0x50A8, 0x50808C8C); ++ regmap_write(xs->regmap_pextp[id], 0x6004, 0x18000000); ++ regmap_write(xs->regmap_pextp[id], 0x00F8, 0x00A132A1); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F20); ++ regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020); ++ regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01); ++ regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884); ++ regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002); ++ regmap_write(xs->regmap_pextp[id], 0x3010, 0x00022220); ++ regmap_write(xs->regmap_pextp[id], 0x5064, 0x0F020A01); ++ regmap_write(xs->regmap_pextp[id], 0x50B4, 0x06100600); ++ regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000); ++ regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000); ++ regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA); ++ regmap_write(xs->regmap_pextp[id], 0x306C, 0x00000F00); ++ regmap_write(xs->regmap_pextp[id], 0xA060, 0x00040000); ++ regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000003); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800); ++ udelay(150); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101); ++ udelay(15); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C101); ++ udelay(100); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F00); ++ regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000); ++ udelay(400); ++} ++ ++void mtk_usxgmii_setup_phya_force_10000(struct mtk_eth *eth, int mac_id) ++{ ++ struct mtk_xgmii *xs = eth->xgmii; ++ unsigned int val; ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ ++ if (id >= eth->soc->num_devs || ++ !xs->regmap_usxgmii[id] || !xs->regmap_pextp[id]) ++ return; ++ ++ /* Setup USXGMII speed */ ++ val = FIELD_PREP(RG_XFI_RX_MODE, RG_XFI_RX_MODE_10G) | ++ FIELD_PREP(RG_XFI_TX_MODE, RG_XFI_TX_MODE_10G); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ /* Disable USXGMII AN mode */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, &val); ++ val &= ~RG_AN_ENABLE; ++ regmap_write(xs->regmap_usxgmii[id], RG_PCS_AN_CTRL0, val); ++ ++ /* Gated USXGMII */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val); ++ val |= RG_MAC_CK_GATED; ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ ndelay(1020); ++ ++ /* USXGMII force mode setting */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val); ++ val |= RG_USXGMII_RATE_UPDATE_MODE; ++ val |= RG_IF_FORCE_EN; ++ val |= FIELD_PREP(RG_RATE_ADAPT_MODE, RG_RATE_ADAPT_MODE_X1); ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ /* Un-gated USXGMII */ ++ regmap_read(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, &val); ++ val &= ~RG_MAC_CK_GATED; ++ regmap_write(xs->regmap_usxgmii[id], RG_PHY_TOP_SPEED_CTRL1, val); ++ ++ ndelay(1020); ++ ++ regmap_write(xs->regmap_pextp[id], 0x9024, 0x00C9071C); ++ regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA); ++ regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707); ++ regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F); ++ regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032); ++ regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014AA); ++ regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B); ++ regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF); ++ regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA); ++ regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F); ++ regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68); ++ regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166); ++ regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000AAF); ++ regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080D0D); ++ regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030909); ++ regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000); ++ regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000); ++ regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06); ++ regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C); ++ regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000); ++ regmap_write(xs->regmap_pextp[id], 0x00F8, 0x01423342); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F20); ++ regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020); ++ regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01); ++ regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884); ++ regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002); ++ regmap_write(xs->regmap_pextp[id], 0x3010, 0x00022220); ++ regmap_write(xs->regmap_pextp[id], 0x5064, 0x0F020A01); ++ regmap_write(xs->regmap_pextp[id], 0x50B4, 0x06100600); ++ regmap_write(xs->regmap_pextp[id], 0x3048, 0x49664100); ++ regmap_write(xs->regmap_pextp[id], 0x3050, 0x00000000); ++ regmap_write(xs->regmap_pextp[id], 0x3054, 0x00000000); ++ regmap_write(xs->regmap_pextp[id], 0x306C, 0x00000F00); ++ regmap_write(xs->regmap_pextp[id], 0xA060, 0x00040000); ++ regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000001); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800); ++ udelay(150); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101); ++ udelay(15); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0202C101); ++ udelay(100); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F00); ++ regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000); ++ udelay(400); ++} ++ ++void mtk_usxgmii_reset(struct mtk_eth *eth, int mac_id) ++{ ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ ++ if (id >= eth->soc->num_devs || !eth->toprgu) ++ return; ++ ++ switch (mac_id) { ++ case MTK_GMAC2_ID: ++ regmap_write(eth->toprgu, 0xFC, 0x0000A004); ++ regmap_write(eth->toprgu, 0x18, 0x88F0A004); ++ regmap_write(eth->toprgu, 0xFC, 0x00000000); ++ regmap_write(eth->toprgu, 0x18, 0x88F00000); ++ regmap_write(eth->toprgu, 0x18, 0x00F00000); ++ break; ++ case MTK_GMAC3_ID: ++ regmap_write(eth->toprgu, 0xFC, 0x00005002); ++ regmap_write(eth->toprgu, 0x18, 0x88F05002); ++ regmap_write(eth->toprgu, 0xFC, 0x00000000); ++ regmap_write(eth->toprgu, 0x18, 0x88F00000); ++ regmap_write(eth->toprgu, 0x18, 0x00F00000); ++ break; ++ } ++ ++ mdelay(10); ++} ++ ++int mtk_usxgmii_setup_mode_an(struct mtk_eth *eth, int mac_id, int max_speed) ++{ ++ if (mac_id < 0 || mac_id >= eth->soc->num_devs) ++ return -EINVAL; ++ ++ if ((max_speed != SPEED_10000) && (max_speed != SPEED_5000)) ++ return -EINVAL; ++ ++ mtk_xfi_pll_enable(eth); ++ mtk_usxgmii_reset(eth, mac_id); ++ mtk_usxgmii_setup_phya_an_10000(eth, mac_id); ++ ++ return 0; ++} ++ ++int mtk_usxgmii_setup_mode_force(struct mtk_eth *eth, int mac_id, ++ const struct phylink_link_state *state) ++{ ++ if (mac_id < 0 || mac_id >= eth->soc->num_devs) ++ return -EINVAL; ++ ++ mtk_xfi_pll_enable(eth); ++ mtk_usxgmii_reset(eth, mac_id); ++ if (state->interface == PHY_INTERFACE_MODE_5GBASER) ++ mtk_usxgmii_setup_phya_force_5000(eth, mac_id); ++ else ++ mtk_usxgmii_setup_phya_force_10000(eth, mac_id); ++ ++ return 0; ++} ++ ++void mtk_sgmii_setup_phya_gen1(struct mtk_eth *eth, int mac_id) ++{ ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ struct mtk_xgmii *xs = eth->xgmii; ++ ++ if (id >= eth->soc->num_devs || !xs->regmap_pextp[id]) ++ return; ++ ++ regmap_write(xs->regmap_pextp[id], 0x9024, 0x00D9071C); ++ regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA); ++ regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020207); ++ regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E05050F); ++ regmap_write(xs->regmap_pextp[id], 0x2040, 0x00200032); ++ regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014BA); ++ regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B); ++ regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF); ++ regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA); ++ regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F); ++ regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68); ++ regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166); ++ regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000EAF); ++ regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080E0D); ++ regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030B09); ++ regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000); ++ regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000); ++ regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0606); ++ regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C); ++ regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000); ++ regmap_write(xs->regmap_pextp[id], 0x00F8, 0x00FA32FA); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F21); ++ regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020); ++ regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01); ++ regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884); ++ regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002); ++ regmap_write(xs->regmap_pextp[id], 0x3010, 0x00011110); ++ regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000); ++ regmap_write(xs->regmap_pextp[id], 0x3064, 0x0000C000); ++ regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000); ++ regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA); ++ regmap_write(xs->regmap_pextp[id], 0x306C, 0x20200F00); ++ regmap_write(xs->regmap_pextp[id], 0xA060, 0x00050000); ++ regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000007); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800); ++ udelay(150); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101); ++ udelay(15); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C101); ++ udelay(100); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F01); ++ regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000); ++ udelay(400); ++} ++ ++void mtk_sgmii_setup_phya_gen2(struct mtk_eth *eth, int mac_id) ++{ ++ struct mtk_xgmii *xs = eth->xgmii; ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ ++ if (id >= eth->soc->num_devs || !xs->regmap_pextp[id]) ++ return; ++ ++ regmap_write(xs->regmap_pextp[id], 0x9024, 0x00D9071C); ++ regmap_write(xs->regmap_pextp[id], 0x2020, 0xAA8585AA); ++ regmap_write(xs->regmap_pextp[id], 0x2030, 0x0C020707); ++ regmap_write(xs->regmap_pextp[id], 0x2034, 0x0E050F0F); ++ regmap_write(xs->regmap_pextp[id], 0x2040, 0x00140032); ++ regmap_write(xs->regmap_pextp[id], 0x50F0, 0x00C014AA); ++ regmap_write(xs->regmap_pextp[id], 0x50E0, 0x3777C12B); ++ regmap_write(xs->regmap_pextp[id], 0x506C, 0x005F9CFF); ++ regmap_write(xs->regmap_pextp[id], 0x5070, 0x9D9DFAFA); ++ regmap_write(xs->regmap_pextp[id], 0x5074, 0x27273F3F); ++ regmap_write(xs->regmap_pextp[id], 0x5078, 0xA7883C68); ++ regmap_write(xs->regmap_pextp[id], 0x507C, 0x11661166); ++ regmap_write(xs->regmap_pextp[id], 0x5080, 0x0E000AAF); ++ regmap_write(xs->regmap_pextp[id], 0x5084, 0x08080D0D); ++ regmap_write(xs->regmap_pextp[id], 0x5088, 0x02030909); ++ regmap_write(xs->regmap_pextp[id], 0x50E4, 0x0C0C0000); ++ regmap_write(xs->regmap_pextp[id], 0x50E8, 0x04040000); ++ regmap_write(xs->regmap_pextp[id], 0x50EC, 0x0F0F0C06); ++ regmap_write(xs->regmap_pextp[id], 0x50A8, 0x506E8C8C); ++ regmap_write(xs->regmap_pextp[id], 0x6004, 0x18190000); ++ regmap_write(xs->regmap_pextp[id], 0x00F8, 0x009C329C); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F21); ++ regmap_write(xs->regmap_pextp[id], 0x0030, 0x00050C00); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x02002800); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000020); ++ regmap_write(xs->regmap_pextp[id], 0x3028, 0x00008A01); ++ regmap_write(xs->regmap_pextp[id], 0x302C, 0x0000A884); ++ regmap_write(xs->regmap_pextp[id], 0x3024, 0x00083002); ++ regmap_write(xs->regmap_pextp[id], 0x3010, 0x00011110); ++ regmap_write(xs->regmap_pextp[id], 0x3048, 0x40704000); ++ regmap_write(xs->regmap_pextp[id], 0x3050, 0xA8000000); ++ regmap_write(xs->regmap_pextp[id], 0x3054, 0x000000AA); ++ regmap_write(xs->regmap_pextp[id], 0x306C, 0x22000F00); ++ regmap_write(xs->regmap_pextp[id], 0xA060, 0x00050000); ++ regmap_write(xs->regmap_pextp[id], 0x90D0, 0x00000005); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200E800); ++ udelay(150); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0200C101); ++ udelay(15); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C111); ++ ndelay(1020); ++ regmap_write(xs->regmap_pextp[id], 0x0070, 0x0201C101); ++ udelay(100); ++ regmap_write(xs->regmap_pextp[id], 0x30B0, 0x00000030); ++ regmap_write(xs->regmap_pextp[id], 0x00F4, 0x80201F01); ++ regmap_write(xs->regmap_pextp[id], 0x3040, 0x30000000); ++ udelay(400); ++} ++ ++void mtk_sgmii_reset(struct mtk_eth *eth, int mac_id) ++{ ++ u32 id = mtk_mac2xgmii_id(eth, mac_id); ++ u32 val = 0; ++ ++ if (id >= eth->soc->num_devs || !eth->toprgu) ++ return; ++ ++ switch (mac_id) { ++ case MTK_GMAC2_ID: ++ /* Enable software reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val); ++ val |= SWSYSRST_XFI_PEXPT1_GRST | ++ SWSYSRST_SGMII1_GRST; ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val); ++ ++ /* Assert SGMII reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val); ++ val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) | ++ SWSYSRST_XFI_PEXPT1_GRST | ++ SWSYSRST_SGMII1_GRST; ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val); ++ ++ udelay(100); ++ ++ /* De-assert SGMII reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val); ++ val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88); ++ val &= ~(SWSYSRST_XFI_PEXPT1_GRST | ++ SWSYSRST_SGMII1_GRST); ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val); ++ ++ /* Disable software reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val); ++ val &= ~(SWSYSRST_XFI_PEXPT1_GRST | ++ SWSYSRST_SGMII1_GRST); ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val); ++ break; ++ case MTK_GMAC3_ID: ++ /* Enable Software reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val); ++ val |= SWSYSRST_XFI_PEXPT0_GRST | ++ SWSYSRST_SGMII0_GRST; ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val); ++ ++ /* Assert SGMII reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val); ++ val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88) | ++ SWSYSRST_XFI_PEXPT0_GRST | ++ SWSYSRST_SGMII0_GRST; ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val); ++ ++ udelay(100); ++ ++ /* De-assert SGMII reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST, &val); ++ val |= FIELD_PREP(SWSYSRST_UNLOCK_KEY, 0x88); ++ val &= ~(SWSYSRST_XFI_PEXPT0_GRST | ++ SWSYSRST_SGMII0_GRST); ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST, val); ++ ++ /* Disable software reset */ ++ regmap_read(eth->toprgu, TOPRGU_SWSYSRST_EN, &val); ++ val &= ~(SWSYSRST_XFI_PEXPT0_GRST | ++ SWSYSRST_SGMII0_GRST); ++ regmap_write(eth->toprgu, TOPRGU_SWSYSRST_EN, val); ++ break; ++ } ++ ++ mdelay(1); ++} +--- a/drivers/net/ethernet/mediatek/Kconfig ++++ b/drivers/net/ethernet/mediatek/Kconfig +@@ -11,6 +11,14 @@ config NET_MEDIATEK_SOC_WED + depends on ARCH_MEDIATEK || COMPILE_TEST + def_bool NET_MEDIATEK_SOC != n + ++config NET_MEDIATEK_SOC_USXGMII ++ bool "Support USXGMII SerDes on MT7988" ++ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST ++ def_bool NET_MEDIATEK_SOC != n ++ help ++ Include support for 10G USXGMII SerDes unit which can ++ be found on MT7988. ++ + config NET_MEDIATEK_SOC + tristate "MediaTek SoC Gigabit Ethernet support" + depends on NET_DSA || !NET_DSA diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 5170dfdf980..7268b693895 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -253,6 +253,7 @@ CONFIG_NET_DSA_MT7530=y CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y +CONFIG_NET_MEDIATEK_SOC_USXGMII=y CONFIG_NET_MEDIATEK_SOC_WED=y CONFIG_NET_SELFTESTS=y CONFIG_NET_SWITCHDEV=y diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index be51e02f4d7..88ca94472cd 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -275,6 +275,7 @@ CONFIG_NET_DSA_MT7530=y CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y +# CONFIG_NET_MEDIATEK_SOC_USXGMII is not set CONFIG_NET_MEDIATEK_SOC_WED=y CONFIG_NET_SELFTESTS=y CONFIG_NET_SWITCHDEV=y diff --git a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch index 4187557b781..04ca80c213d 100644 --- a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch +++ b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch @@ -20,7 +20,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -231,13 +231,35 @@ static int _mtk_mdio_write(struct mtk_et +@@ -323,13 +323,35 @@ static int _mtk_mdio_write(struct mtk_et if (ret < 0) return ret; @@ -63,7 +63,7 @@ Signed-off-by: David S. Miller ret = mtk_mdio_busy_wait(eth); if (ret < 0) -@@ -254,12 +276,33 @@ static int _mtk_mdio_read(struct mtk_eth +@@ -346,12 +368,33 @@ static int _mtk_mdio_read(struct mtk_eth if (ret < 0) return ret; @@ -103,7 +103,7 @@ Signed-off-by: David S. Miller ret = mtk_mdio_busy_wait(eth); if (ret < 0) -@@ -729,6 +772,7 @@ static int mtk_mdio_init(struct mtk_eth +@@ -1018,6 +1061,7 @@ static int mtk_mdio_init(struct mtk_eth eth->mii_bus->name = "mdio"; eth->mii_bus->read = mtk_mdio_read; eth->mii_bus->write = mtk_mdio_write; @@ -113,7 +113,7 @@ Signed-off-by: David S. Miller --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h -@@ -376,9 +376,12 @@ +@@ -382,9 +382,12 @@ #define PHY_IAC_ADDR_MASK GENMASK(24, 20) #define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x)) #define PHY_IAC_CMD_MASK GENMASK(19, 18) diff --git a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch index 285e24429a4..a613803ee6d 100644 --- a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch +++ b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch @@ -14,7 +14,7 @@ Signed-off-by: René van Dorst --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c -@@ -4261,6 +4261,7 @@ static const struct net_device_ops mtk_n +@@ -4638,6 +4638,7 @@ static const struct net_device_ops mtk_n static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) { @@ -22,7 +22,7 @@ Signed-off-by: René van Dorst const __be32 *_id = of_get_property(np, "reg", NULL); phy_interface_t phy_mode; struct phylink *phylink; -@@ -4389,6 +4390,9 @@ static int mtk_add_mac(struct mtk_eth *e +@@ -4796,6 +4797,9 @@ static int mtk_add_mac(struct mtk_eth *e register_netdevice_notifier(&mac->device_notifier); } From 958fdf36e35c814eb83faf2c39db4ca379c921b5 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 14:32:03 +0100 Subject: [PATCH 12/43] generic: mt7530: backport support for the MT7988 built-in switch Backport commits adding support for the MT7988 built-in switch to the mt7530 driver. This change results in the Kconfig symbol NET_DSA_MT7530 to be extended by NET_DSA_MT7530_MDIO (everything formally covered by NET_DSA_MT7530) and NET_DSA_MT7530_MMIO (a new driver for the MMIO-connected built-in switch of the MT7988 SoC). Select NET_DSA_MT7530_MDIO for all targets previously selecting NET_DSA_MT7530, with the exception of mediatek/filogic which also selects NET_DSA_MT7530_MMIO. Signed-off-by: Daniel Golle --- ...ake-some-noise-if-register-read-fail.patch | 32 + ...a-mt7530-refactor-SGMII-PCS-creation.patch | 111 +++ ...mt7530-use-unlocked-regmap-accessors.patch | 74 ++ ...se-regmap-to-access-switch-register-.patch | 224 ++++++ ...ove-SGMII-PCS-creation-to-mt7530_pro.patch | 54 ++ ...t-dsa-mt7530-introduce-mutex-helpers.patch | 273 +++++++ ...ove-p5_intf_modes-function-to-mt7530.patch | 75 ++ ...ntroduce-mt7530_probe_common-helper-.patch | 155 ++++ ...ntroduce-mt7530_remove_common-helper.patch | 55 ++ ...plit-off-common-parts-from-mt7531_se.patch | 143 ++++ ...t7530-introduce-separate-MDIO-driver.patch | 692 ++++++++++++++++++ ...kip-locking-if-MDIO-bus-isn-t-presen.patch | 47 ++ ...ntroduce-driver-for-MT7988-built-in-.patch | 421 +++++++++++ ...-dsa-mt7530-fix-support-for-MT7531BE.patch | 118 +++ ...or-Motorcomm-yt8521-gigabit-ethernet.patch | 2 +- ...d-driver-for-OCOTP-in-Sunplus-SP7021.patch | 2 +- ...001-nvmem-microchip-otpc-add-support.patch | 2 +- ...e-all-MACs-are-powered-down-before-r.patch | 2 +- ...gister-OF-node-for-internal-MDIO-bus.patch | 4 +- target/linux/mediatek/filogic/config-5.15 | 2 + target/linux/mediatek/mt7622/config-5.15 | 2 + target/linux/mediatek/mt7623/config-5.15 | 2 + target/linux/mediatek/mt7629/config-5.15 | 2 + target/linux/ramips/mt7621/config-5.15 | 2 + ...hdog-add-realtek-otto-watchdog-timer.patch | 2 +- ...t-dsa-add-support-for-rtl838x-switch.patch | 4 +- 26 files changed, 2493 insertions(+), 9 deletions(-) create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0010-net-dsa-mt7530-split-off-common-parts-from-mt7531_se.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0011-net-dsa-mt7530-introduce-separate-MDIO-driver.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0012-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0013-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch create mode 100644 target/linux/generic/backport-5.15/790-v6.4-0014-net-dsa-mt7530-fix-support-for-MT7531BE.patch diff --git a/target/linux/generic/backport-5.15/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch b/target/linux/generic/backport-5.15/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch new file mode 100644 index 00000000000..ffbdde5a577 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0001-net-dsa-mt7530-make-some-noise-if-register-read-fail.patch @@ -0,0 +1,32 @@ +From b6f56cddb5f57a0b8da0ce582232a2f1933558c6 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:19 +0100 +Subject: [PATCH 04/16] net: dsa: mt7530: make some noise if register read + fails + +Simply returning the negative error value instead of the read value +doesn't seem like a good idea. Return 0 instead and add WARN_ON_ONCE(1) +so this kind of error will not go unnoticed. + +Suggested-by: Andrew Lunn +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -224,9 +224,10 @@ mt7530_mii_read(struct mt7530_priv *priv + /* MT7530 uses 31 as the pseudo port */ + ret = bus->write(bus, 0x1f, 0x1f, page); + if (ret < 0) { ++ WARN_ON_ONCE(1); + dev_err(&bus->dev, + "failed to read mt7530 register\n"); +- return ret; ++ return 0; + } + + lo = bus->read(bus, 0x1f, r); diff --git a/target/linux/generic/backport-5.15/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch b/target/linux/generic/backport-5.15/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch new file mode 100644 index 00000000000..8963d93d107 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0002-net-dsa-mt7530-refactor-SGMII-PCS-creation.patch @@ -0,0 +1,111 @@ +From 9ecc00164dc2300dfcd40afe549a8ee951dfea9f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:30 +0100 +Subject: [PATCH 05/16] net: dsa: mt7530: refactor SGMII PCS creation + +Instead of macro templates use a dedidated function and allocated +regmap_config when creating the regmaps for the pcs-mtk-lynxi +instances. +This is in preparation to switching to use unlocked regmap accessors +and have regmap's locking API handle locking for us. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 74 +++++++++++++++++++++++++++------------- + 1 file changed, 50 insertions(+), 24 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2926,26 +2926,56 @@ static const struct regmap_bus mt7531_re + .reg_update_bits = mt7530_regmap_update_bits, + }; + +-#define MT7531_PCS_REGMAP_CONFIG(_name, _reg_base) \ +- { \ +- .name = _name, \ +- .reg_bits = 16, \ +- .val_bits = 32, \ +- .reg_stride = 4, \ +- .reg_base = _reg_base, \ +- .max_register = 0x17c, \ ++static int ++mt7531_create_sgmii(struct mt7530_priv *priv) ++{ ++ struct regmap_config *mt7531_pcs_config[2]; ++ struct phylink_pcs *pcs; ++ struct regmap *regmap; ++ int i, ret = 0; ++ ++ for (i = 0; i < 2; i++) { ++ mt7531_pcs_config[i] = devm_kzalloc(priv->dev, ++ sizeof(struct regmap_config), ++ GFP_KERNEL); ++ if (!mt7531_pcs_config[i]) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ mt7531_pcs_config[i]->name = i ? "port6" : "port5"; ++ mt7531_pcs_config[i]->reg_bits = 16; ++ mt7531_pcs_config[i]->val_bits = 32; ++ mt7531_pcs_config[i]->reg_stride = 4; ++ mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); ++ mt7531_pcs_config[i]->max_register = 0x17c; ++ ++ regmap = devm_regmap_init(priv->dev, ++ &mt7531_regmap_bus, priv, ++ mt7531_pcs_config[i]); ++ if (IS_ERR(regmap)) { ++ ret = PTR_ERR(regmap); ++ break; ++ } ++ pcs = mtk_pcs_lynxi_create(priv->dev, regmap, ++ MT7531_PHYA_CTRL_SIGNAL3, 0); ++ if (!pcs) { ++ ret = -ENXIO; ++ break; ++ } ++ priv->ports[5 + i].sgmii_pcs = pcs; + } + +-static const struct regmap_config mt7531_pcs_config[] = { +- MT7531_PCS_REGMAP_CONFIG("port5", MT7531_SGMII_REG_BASE(5)), +- MT7531_PCS_REGMAP_CONFIG("port6", MT7531_SGMII_REG_BASE(6)), +-}; ++ if (ret && i) ++ mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); ++ ++ return ret; ++} + + static int + mt753x_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; +- struct regmap *regmap; + int i, ret; + + /* Initialise the PCS devices */ +@@ -2967,15 +2997,11 @@ mt753x_setup(struct dsa_switch *ds) + if (ret && priv->irq) + mt7530_free_irq_common(priv); + +- if (priv->id == ID_MT7531) +- for (i = 0; i < 2; i++) { +- regmap = devm_regmap_init(ds->dev, +- &mt7531_regmap_bus, priv, +- &mt7531_pcs_config[i]); +- priv->ports[5 + i].sgmii_pcs = +- mtk_pcs_lynxi_create(ds->dev, regmap, +- MT7531_PHYA_CTRL_SIGNAL3, 0); +- } ++ if (priv->id == ID_MT7531) { ++ ret = mt7531_create_sgmii(priv); ++ if (ret && priv->irq) ++ mt7530_free_irq_common(priv); ++ } + + return ret; + } diff --git a/target/linux/generic/backport-5.15/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch b/target/linux/generic/backport-5.15/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch new file mode 100644 index 00000000000..1b4a9561992 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0003-net-dsa-mt7530-use-unlocked-regmap-accessors.patch @@ -0,0 +1,74 @@ +From 1bd099c49f65ed923b9f19b8c4b3cd1ff0024091 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:40 +0100 +Subject: [PATCH 06/16] net: dsa: mt7530: use unlocked regmap accessors + +Instead of wrapping the locked register accessor functions, use the +unlocked variants and add locking wrapper functions to let regmap +handle the locking. + +This is a preparation towards being able to always use regmap to +access switch registers instead of open-coded accessor functions. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2899,7 +2899,7 @@ static int mt7530_regmap_read(void *cont + { + struct mt7530_priv *priv = context; + +- *val = mt7530_read(priv, reg); ++ *val = mt7530_mii_read(priv, reg); + return 0; + }; + +@@ -2907,23 +2907,25 @@ static int mt7530_regmap_write(void *con + { + struct mt7530_priv *priv = context; + +- mt7530_write(priv, reg, val); ++ mt7530_mii_write(priv, reg, val); + return 0; + }; + +-static int mt7530_regmap_update_bits(void *context, unsigned int reg, +- unsigned int mask, unsigned int val) ++static void ++mt7530_mdio_regmap_lock(void *mdio_lock) + { +- struct mt7530_priv *priv = context; ++ mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); ++} + +- mt7530_rmw(priv, reg, mask, val); +- return 0; +-}; ++static void ++mt7530_mdio_regmap_unlock(void *mdio_lock) ++{ ++ mutex_unlock(mdio_lock); ++} + + static const struct regmap_bus mt7531_regmap_bus = { + .reg_write = mt7530_regmap_write, + .reg_read = mt7530_regmap_read, +- .reg_update_bits = mt7530_regmap_update_bits, + }; + + static int +@@ -2949,6 +2951,9 @@ mt7531_create_sgmii(struct mt7530_priv * + mt7531_pcs_config[i]->reg_stride = 4; + mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); + mt7531_pcs_config[i]->max_register = 0x17c; ++ mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; ++ mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; ++ mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; + + regmap = devm_regmap_init(priv->dev, + &mt7531_regmap_bus, priv, diff --git a/target/linux/generic/backport-5.15/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch b/target/linux/generic/backport-5.15/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch new file mode 100644 index 00000000000..2d8bab9da63 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0004-net-dsa-mt7530-use-regmap-to-access-switch-register-.patch @@ -0,0 +1,224 @@ +From a08c045580e060a6886bbb656c50ae20b0c780b5 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:17:52 +0100 +Subject: [PATCH 07/16] net: dsa: mt7530: use regmap to access switch register + space + +Use regmap API to access the switch register space. + +Signed-off-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 99 ++++++++++++++++++++++++---------------- + drivers/net/dsa/mt7530.h | 2 + + 2 files changed, 62 insertions(+), 39 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -183,9 +183,9 @@ core_clear(struct mt7530_priv *priv, u32 + } + + static int +-mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) ++mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) + { +- struct mii_bus *bus = priv->bus; ++ struct mii_bus *bus = context; + u16 page, r, lo, hi; + int ret; + +@@ -197,24 +197,34 @@ mt7530_mii_write(struct mt7530_priv *pri + /* MT7530 uses 31 as the pseudo port */ + ret = bus->write(bus, 0x1f, 0x1f, page); + if (ret < 0) +- goto err; ++ return ret; + + ret = bus->write(bus, 0x1f, r, lo); + if (ret < 0) +- goto err; ++ return ret; + + ret = bus->write(bus, 0x1f, 0x10, hi); +-err: ++ return ret; ++} ++ ++static int ++mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) ++{ ++ int ret; ++ ++ ret = regmap_write(priv->regmap, reg, val); ++ + if (ret < 0) +- dev_err(&bus->dev, ++ dev_err(priv->dev, + "failed to write mt7530 register\n"); ++ + return ret; + } + +-static u32 +-mt7530_mii_read(struct mt7530_priv *priv, u32 reg) ++static int ++mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) + { +- struct mii_bus *bus = priv->bus; ++ struct mii_bus *bus = context; + u16 page, r, lo, hi; + int ret; + +@@ -223,17 +233,32 @@ mt7530_mii_read(struct mt7530_priv *priv + + /* MT7530 uses 31 as the pseudo port */ + ret = bus->write(bus, 0x1f, 0x1f, page); +- if (ret < 0) { ++ if (ret < 0) ++ return ret; ++ ++ lo = bus->read(bus, 0x1f, r); ++ hi = bus->read(bus, 0x1f, 0x10); ++ ++ *val = (hi << 16) | (lo & 0xffff); ++ ++ return 0; ++} ++ ++static u32 ++mt7530_mii_read(struct mt7530_priv *priv, u32 reg) ++{ ++ int ret; ++ u32 val; ++ ++ ret = regmap_read(priv->regmap, reg, &val); ++ if (ret) { + WARN_ON_ONCE(1); +- dev_err(&bus->dev, ++ dev_err(priv->dev, + "failed to read mt7530 register\n"); + return 0; + } + +- lo = bus->read(bus, 0x1f, r); +- hi = bus->read(bus, 0x1f, 0x10); +- +- return (hi << 16) | (lo & 0xffff); ++ return val; + } + + static void +@@ -283,14 +308,10 @@ mt7530_rmw(struct mt7530_priv *priv, u32 + u32 mask, u32 set) + { + struct mii_bus *bus = priv->bus; +- u32 val; + + mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); + +- val = mt7530_mii_read(priv, reg); +- val &= ~mask; +- val |= set; +- mt7530_mii_write(priv, reg, val); ++ regmap_update_bits(priv->regmap, reg, mask, set); + + mutex_unlock(&bus->mdio_lock); + } +@@ -298,7 +319,7 @@ mt7530_rmw(struct mt7530_priv *priv, u32 + static void + mt7530_set(struct mt7530_priv *priv, u32 reg, u32 val) + { +- mt7530_rmw(priv, reg, 0, val); ++ mt7530_rmw(priv, reg, val, val); + } + + static void +@@ -2895,22 +2916,6 @@ static const struct phylink_pcs_ops mt75 + .pcs_an_restart = mt7530_pcs_an_restart, + }; + +-static int mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) +-{ +- struct mt7530_priv *priv = context; +- +- *val = mt7530_mii_read(priv, reg); +- return 0; +-}; +- +-static int mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) +-{ +- struct mt7530_priv *priv = context; +- +- mt7530_mii_write(priv, reg, val); +- return 0; +-}; +- + static void + mt7530_mdio_regmap_lock(void *mdio_lock) + { +@@ -2923,7 +2928,7 @@ mt7530_mdio_regmap_unlock(void *mdio_loc + mutex_unlock(mdio_lock); + } + +-static const struct regmap_bus mt7531_regmap_bus = { ++static const struct regmap_bus mt7530_regmap_bus = { + .reg_write = mt7530_regmap_write, + .reg_read = mt7530_regmap_read, + }; +@@ -2956,7 +2961,7 @@ mt7531_create_sgmii(struct mt7530_priv * + mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; + + regmap = devm_regmap_init(priv->dev, +- &mt7531_regmap_bus, priv, ++ &mt7530_regmap_bus, priv->bus, + mt7531_pcs_config[i]); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); +@@ -3121,6 +3126,7 @@ MODULE_DEVICE_TABLE(of, mt7530_of_match) + static int + mt7530_probe(struct mdio_device *mdiodev) + { ++ static struct regmap_config *regmap_config; + struct mt7530_priv *priv; + struct device_node *dn; + +@@ -3200,6 +3206,21 @@ mt7530_probe(struct mdio_device *mdiodev + mutex_init(&priv->reg_mutex); + dev_set_drvdata(&mdiodev->dev, priv); + ++ regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), ++ GFP_KERNEL); ++ if (!regmap_config) ++ return -ENOMEM; ++ ++ regmap_config->reg_bits = 16; ++ regmap_config->val_bits = 32; ++ regmap_config->reg_stride = 4; ++ regmap_config->max_register = MT7530_CREV; ++ regmap_config->disable_locking = true; ++ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, ++ priv->bus, regmap_config); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ + return dsa_register_switch(priv->ds); + } + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -747,6 +747,7 @@ struct mt753x_info { + * @dev: The device pointer + * @ds: The pointer to the dsa core structure + * @bus: The bus used for the device and built-in PHY ++ * @regmap: The regmap instance representing all switch registers + * @rstc: The pointer to reset control used by MCM + * @core_pwr: The power supplied into the core + * @io_pwr: The power supplied into the I/O +@@ -767,6 +768,7 @@ struct mt7530_priv { + struct device *dev; + struct dsa_switch *ds; + struct mii_bus *bus; ++ struct regmap *regmap; + struct reset_control *rstc; + struct regulator *core_pwr; + struct regulator *io_pwr; diff --git a/target/linux/generic/backport-5.15/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch b/target/linux/generic/backport-5.15/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch new file mode 100644 index 00000000000..0bb64c3c5e9 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0005-net-dsa-mt7530-move-SGMII-PCS-creation-to-mt7530_pro.patch @@ -0,0 +1,54 @@ +From 6de2852297737171ba96b91e89bf302ca1fda869 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:04 +0100 +Subject: [PATCH 08/16] net: dsa: mt7530: move SGMII PCS creation to + mt7530_probe function + +Move creating the SGMII PCS from mt753x_setup() to the more appropriate +mt7530_probe() function. +This is done also in preparation of moving all functions related to +MDIO-connected MT753x switches to a separate module. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3007,12 +3007,6 @@ mt753x_setup(struct dsa_switch *ds) + if (ret && priv->irq) + mt7530_free_irq_common(priv); + +- if (priv->id == ID_MT7531) { +- ret = mt7531_create_sgmii(priv); +- if (ret && priv->irq) +- mt7530_free_irq_common(priv); +- } +- + return ret; + } + +@@ -3129,6 +3123,7 @@ mt7530_probe(struct mdio_device *mdiodev + static struct regmap_config *regmap_config; + struct mt7530_priv *priv; + struct device_node *dn; ++ int ret; + + dn = mdiodev->dev.of_node; + +@@ -3221,6 +3216,12 @@ mt7530_probe(struct mdio_device *mdiodev + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + ++ if (priv->id == ID_MT7531) { ++ ret = mt7531_create_sgmii(priv); ++ if (ret) ++ return ret; ++ } ++ + return dsa_register_switch(priv->ds); + } + diff --git a/target/linux/generic/backport-5.15/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch b/target/linux/generic/backport-5.15/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch new file mode 100644 index 00000000000..c23f96e7a66 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0006-net-dsa-mt7530-introduce-mutex-helpers.patch @@ -0,0 +1,273 @@ +From 1557c679f71c82a994eae0baadbaeb62b71e15bf Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:16 +0100 +Subject: [PATCH 09/16] net: dsa: mt7530: introduce mutex helpers + +As the MDIO bus lock only needs to be involved if actually operating +on an MDIO-connected switch we will need to skip locking for built-in +switches which are accessed via MMIO. +Create helper functions which simplify that upcoming change. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 73 ++++++++++++++++++++-------------------- + 1 file changed, 36 insertions(+), 37 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -143,31 +143,40 @@ err: + } + + static void +-core_write(struct mt7530_priv *priv, u32 reg, u32 val) ++mt7530_mutex_lock(struct mt7530_priv *priv) + { +- struct mii_bus *bus = priv->bus; ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++} + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++static void ++mt7530_mutex_unlock(struct mt7530_priv *priv) ++{ ++ mutex_unlock(&priv->bus->mdio_lock); ++} ++ ++static void ++core_write(struct mt7530_priv *priv, u32 reg, u32 val) ++{ ++ mt7530_mutex_lock(priv); + + core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); + +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + } + + static void + core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) + { +- struct mii_bus *bus = priv->bus; + u32 val; + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2); + val &= ~mask; + val |= set; + core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); + +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + } + + static void +@@ -264,13 +273,11 @@ mt7530_mii_read(struct mt7530_priv *priv + static void + mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val) + { +- struct mii_bus *bus = priv->bus; +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + mt7530_mii_write(priv, reg, val); + +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + } + + static u32 +@@ -282,14 +289,13 @@ _mt7530_unlocked_read(struct mt7530_dumm + static u32 + _mt7530_read(struct mt7530_dummy_poll *p) + { +- struct mii_bus *bus = p->priv->bus; + u32 val; + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(p->priv); + + val = mt7530_mii_read(p->priv, p->reg); + +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(p->priv); + + return val; + } +@@ -307,13 +313,11 @@ static void + mt7530_rmw(struct mt7530_priv *priv, u32 reg, + u32 mask, u32 set) + { +- struct mii_bus *bus = priv->bus; +- +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + regmap_update_bits(priv->regmap, reg, mask, set); + +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + } + + static void +@@ -645,14 +649,13 @@ static int + mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, + int regnum) + { +- struct mii_bus *bus = priv->bus; + struct mt7530_dummy_poll p; + u32 reg, val; + int ret; + + INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, + !(val & MT7531_PHY_ACS_ST), 20, 100000); +@@ -685,7 +688,7 @@ mt7531_ind_c45_phy_read(struct mt7530_pr + + ret = val & MT7531_MDIO_RW_DATA_MASK; + out: +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + + return ret; + } +@@ -694,14 +697,13 @@ static int + mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, + int regnum, u32 data) + { +- struct mii_bus *bus = priv->bus; + struct mt7530_dummy_poll p; + u32 val, reg; + int ret; + + INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, + !(val & MT7531_PHY_ACS_ST), 20, 100000); +@@ -733,7 +735,7 @@ mt7531_ind_c45_phy_write(struct mt7530_p + } + + out: +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + + return ret; + } +@@ -741,14 +743,13 @@ out: + static int + mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum) + { +- struct mii_bus *bus = priv->bus; + struct mt7530_dummy_poll p; + int ret; + u32 val; + + INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + ret = readx_poll_timeout(_mt7530_unlocked_read, &p, val, + !(val & MT7531_PHY_ACS_ST), 20, 100000); +@@ -771,7 +772,7 @@ mt7531_ind_c22_phy_read(struct mt7530_pr + + ret = val & MT7531_MDIO_RW_DATA_MASK; + out: +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + + return ret; + } +@@ -780,14 +781,13 @@ static int + mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, + u16 data) + { +- struct mii_bus *bus = priv->bus; + struct mt7530_dummy_poll p; + int ret; + u32 reg; + + INIT_MT7530_DUMMY_POLL(&p, priv, MT7531_PHY_IAC); + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + ret = readx_poll_timeout(_mt7530_unlocked_read, &p, reg, + !(reg & MT7531_PHY_ACS_ST), 20, 100000); +@@ -809,7 +809,7 @@ mt7531_ind_c22_phy_write(struct mt7530_p + } + + out: +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + + return ret; + } +@@ -1109,7 +1109,6 @@ static int + mt7530_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu) + { + struct mt7530_priv *priv = ds->priv; +- struct mii_bus *bus = priv->bus; + int length; + u32 val; + +@@ -1120,7 +1119,7 @@ mt7530_port_change_mtu(struct dsa_switch + if (!dsa_is_cpu_port(ds, port)) + return 0; + +- mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + + val = mt7530_mii_read(priv, MT7530_GMACCR); + val &= ~MAX_RX_PKT_LEN_MASK; +@@ -1141,7 +1140,7 @@ mt7530_port_change_mtu(struct dsa_switch + + mt7530_mii_write(priv, MT7530_GMACCR, val); + +- mutex_unlock(&bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + + return 0; + } +@@ -1937,10 +1936,10 @@ mt7530_irq_thread_fn(int irq, void *dev_ + u32 val; + int p; + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + val = mt7530_mii_read(priv, MT7530_SYS_INT_STS); + mt7530_mii_write(priv, MT7530_SYS_INT_STS, val); +- mutex_unlock(&priv->bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + + for (p = 0; p < MT7530_NUM_PHYS; p++) { + if (BIT(p) & val) { +@@ -1976,7 +1975,7 @@ mt7530_irq_bus_lock(struct irq_data *d) + { + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); + +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ mt7530_mutex_lock(priv); + } + + static void +@@ -1985,7 +1984,7 @@ mt7530_irq_bus_sync_unlock(struct irq_da + struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); + + mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); +- mutex_unlock(&priv->bus->mdio_lock); ++ mt7530_mutex_unlock(priv); + } + + static struct irq_chip mt7530_irq_chip = { diff --git a/target/linux/generic/backport-5.15/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch b/target/linux/generic/backport-5.15/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch new file mode 100644 index 00000000000..bd7ca33f6ed --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0007-net-dsa-mt7530-move-p5_intf_modes-function-to-mt7530.patch @@ -0,0 +1,75 @@ +From 25d15dee34a1a40d5fd71636a205e3211f09fd1d Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:28 +0100 +Subject: [PATCH 10/16] net: dsa: mt7530: move p5_intf_modes() function to + mt7530.c + +In preparation of splitting mt7530.c into a driver for MDIO-connected +as well as MDIO-accessed built-in switches on one hand and MMIO-accessed +built-in switches move the p5_inft_modes() function from mt7530.h to +mt7530.c. The function is only needed there and will trigger a compiler +warning about a defined but unused function otherwise when including +mt7530.h in the to-be-introduced bus-specific drivers. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 18 ++++++++++++++++++ + drivers/net/dsa/mt7530.h | 18 ------------------ + 2 files changed, 18 insertions(+), 18 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -950,6 +950,24 @@ mt7530_set_ageing_time(struct dsa_switch + return 0; + } + ++static const char *p5_intf_modes(unsigned int p5_interface) ++{ ++ switch (p5_interface) { ++ case P5_DISABLED: ++ return "DISABLED"; ++ case P5_INTF_SEL_PHY_P0: ++ return "PHY P0"; ++ case P5_INTF_SEL_PHY_P4: ++ return "PHY P4"; ++ case P5_INTF_SEL_GMAC5: ++ return "GMAC5"; ++ case P5_INTF_SEL_GMAC5_SGMII: ++ return "GMAC5_SGMII"; ++ default: ++ return "unknown"; ++ } ++} ++ + static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) + { + struct mt7530_priv *priv = ds->priv; +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -682,24 +682,6 @@ enum p5_interface_select { + P5_INTF_SEL_GMAC5_SGMII, + }; + +-static const char *p5_intf_modes(unsigned int p5_interface) +-{ +- switch (p5_interface) { +- case P5_DISABLED: +- return "DISABLED"; +- case P5_INTF_SEL_PHY_P0: +- return "PHY P0"; +- case P5_INTF_SEL_PHY_P4: +- return "PHY P4"; +- case P5_INTF_SEL_GMAC5: +- return "GMAC5"; +- case P5_INTF_SEL_GMAC5_SGMII: +- return "GMAC5_SGMII"; +- default: +- return "unknown"; +- } +-} +- + struct mt7530_priv; + + struct mt753x_pcs { diff --git a/target/linux/generic/backport-5.15/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch b/target/linux/generic/backport-5.15/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch new file mode 100644 index 00000000000..34a1bd7372d --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0008-net-dsa-mt7530-introduce-mt7530_probe_common-helper-.patch @@ -0,0 +1,155 @@ +From 37c9c0d8d0b2e24f8c9af72ecd4edd31537284d3 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:39 +0100 +Subject: [PATCH 11/16] net: dsa: mt7530: introduce mt7530_probe_common helper + function + +Move commonly used parts from mt7530_probe into new mt7530_probe_common +helper function which will be used by both, mt7530_probe and the +to-be-introduced mt7988_probe. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 98 ++++++++++++++++++++++------------------ + 1 file changed, 54 insertions(+), 44 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3135,44 +3135,21 @@ static const struct of_device_id mt7530_ + MODULE_DEVICE_TABLE(of, mt7530_of_match); + + static int +-mt7530_probe(struct mdio_device *mdiodev) ++mt7530_probe_common(struct mt7530_priv *priv) + { +- static struct regmap_config *regmap_config; +- struct mt7530_priv *priv; +- struct device_node *dn; +- int ret; ++ struct device *dev = priv->dev; + +- dn = mdiodev->dev.of_node; +- +- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL); ++ priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) + return -ENOMEM; + +- priv->ds->dev = &mdiodev->dev; ++ priv->ds->dev = dev; + priv->ds->num_ports = MT7530_NUM_PORTS; + +- /* Use medatek,mcm property to distinguish hardware type that would +- * casues a little bit differences on power-on sequence. +- */ +- priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); +- if (priv->mcm) { +- dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); +- +- priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); +- if (IS_ERR(priv->rstc)) { +- dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); +- return PTR_ERR(priv->rstc); +- } +- } +- + /* Get the hardware identifier from the devicetree node. + * We will need it for some of the clock and regulator setup. + */ +- priv->info = of_device_get_match_data(&mdiodev->dev); ++ priv->info = of_device_get_match_data(dev); + if (!priv->info) + return -EINVAL; + +@@ -3186,23 +3163,53 @@ mt7530_probe(struct mdio_device *mdiodev + return -EINVAL; + + priv->id = priv->info->id; ++ priv->dev = dev; ++ priv->ds->priv = priv; ++ priv->ds->ops = &mt7530_switch_ops; ++ mutex_init(&priv->reg_mutex); ++ dev_set_drvdata(dev, priv); + +- if (priv->id == ID_MT7530) { +- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); +- if (IS_ERR(priv->core_pwr)) +- return PTR_ERR(priv->core_pwr); ++ return 0; ++} + +- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); +- if (IS_ERR(priv->io_pwr)) +- return PTR_ERR(priv->io_pwr); +- } ++static int ++mt7530_probe(struct mdio_device *mdiodev) ++{ ++ static struct regmap_config *regmap_config; ++ struct mt7530_priv *priv; ++ struct device_node *dn; ++ int ret; ++ ++ dn = mdiodev->dev.of_node; ++ ++ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; + +- /* Not MCM that indicates switch works as the remote standalone ++ priv->bus = mdiodev->bus; ++ priv->dev = &mdiodev->dev; ++ ++ ret = mt7530_probe_common(priv); ++ if (ret) ++ return ret; ++ ++ /* Use medatek,mcm property to distinguish hardware type that would ++ * cause a little bit differences on power-on sequence. ++ * Not MCM that indicates switch works as the remote standalone + * integrated circuit so the GPIO pin would be used to complete + * the reset, otherwise memory-mapped register accessing used + * through syscon provides in the case of MCM. + */ +- if (!priv->mcm) { ++ priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); ++ if (priv->mcm) { ++ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); ++ ++ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); ++ if (IS_ERR(priv->rstc)) { ++ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); ++ return PTR_ERR(priv->rstc); ++ } ++ } else { + priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", + GPIOD_OUT_LOW); + if (IS_ERR(priv->reset)) { +@@ -3211,12 +3218,15 @@ mt7530_probe(struct mdio_device *mdiodev + } + } + +- priv->bus = mdiodev->bus; +- priv->dev = &mdiodev->dev; +- priv->ds->priv = priv; +- priv->ds->ops = &mt7530_switch_ops; +- mutex_init(&priv->reg_mutex); +- dev_set_drvdata(&mdiodev->dev, priv); ++ if (priv->id == ID_MT7530) { ++ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); ++ if (IS_ERR(priv->core_pwr)) ++ return PTR_ERR(priv->core_pwr); ++ ++ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); ++ if (IS_ERR(priv->io_pwr)) ++ return PTR_ERR(priv->io_pwr); ++ } + + regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), + GFP_KERNEL); diff --git a/target/linux/generic/backport-5.15/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch b/target/linux/generic/backport-5.15/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch new file mode 100644 index 00000000000..2881365ec77 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0009-net-dsa-mt7530-introduce-mt7530_remove_common-helper.patch @@ -0,0 +1,55 @@ +From 720d736351761574af02ed093658ab60de60576c Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:18:50 +0100 +Subject: [PATCH 12/16] net: dsa: mt7530: introduce mt7530_remove_common helper + function + +Move commonly used parts from mt7530_remove into new +mt7530_remove_common helper function which will be used by both, +mt7530_remove and the to-be-introduced mt7988_remove. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3253,6 +3253,17 @@ mt7530_probe(struct mdio_device *mdiodev + } + + static void ++mt7530_remove_common(struct mt7530_priv *priv) ++{ ++ if (priv->irq) ++ mt7530_free_irq(priv); ++ ++ dsa_unregister_switch(priv->ds); ++ ++ mutex_destroy(&priv->reg_mutex); ++} ++ ++static void + mt7530_remove(struct mdio_device *mdiodev) + { + struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); +@@ -3271,16 +3282,11 @@ mt7530_remove(struct mdio_device *mdiode + dev_err(priv->dev, "Failed to disable io pwr: %d\n", + ret); + +- if (priv->irq) +- mt7530_free_irq(priv); +- +- dsa_unregister_switch(priv->ds); ++ mt7530_remove_common(priv); + + for (i = 0; i < 2; ++i) + mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); + +- mutex_destroy(&priv->reg_mutex); +- + dev_set_drvdata(&mdiodev->dev, NULL); + } + diff --git a/target/linux/generic/backport-5.15/790-v6.4-0010-net-dsa-mt7530-split-off-common-parts-from-mt7531_se.patch b/target/linux/generic/backport-5.15/790-v6.4-0010-net-dsa-mt7530-split-off-common-parts-from-mt7531_se.patch new file mode 100644 index 00000000000..c8e7d93026d --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0010-net-dsa-mt7530-split-off-common-parts-from-mt7531_se.patch @@ -0,0 +1,143 @@ +From 7f54cc9772ced2d76ac11832f0ada43798443ac9 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:02 +0100 +Subject: [PATCH 13/16] net: dsa: mt7530: split-off common parts from + mt7531_setup + +MT7988 shares a significant part of the setup function with MT7531. +Split-off those parts into a shared function which is going to be used +also by mt7988_setup. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 99 ++++++++++++++++++++++------------------ + 1 file changed, 55 insertions(+), 44 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2348,11 +2348,64 @@ mt7530_setup(struct dsa_switch *ds) + } + + static int ++mt7531_setup_common(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *cpu_dp; ++ int ret, i; ++ ++ /* BPDU to CPU port */ ++ dsa_switch_for_each_cpu_port(cpu_dp, ds) { ++ mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, ++ BIT(cpu_dp->index)); ++ break; ++ } ++ mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, ++ MT753X_BPDU_CPU_ONLY); ++ ++ /* Enable and reset MIB counters */ ++ mt7530_mib_reset(ds); ++ ++ for (i = 0; i < MT7530_NUM_PORTS; i++) { ++ /* Disable forwarding by default on all ports */ ++ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, ++ PCR_MATRIX_CLR); ++ ++ /* Disable learning by default on all ports */ ++ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); ++ ++ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); ++ ++ if (dsa_is_cpu_port(ds, i)) { ++ ret = mt753x_cpu_port_enable(ds, i); ++ if (ret) ++ return ret; ++ } else { ++ mt7530_port_disable(ds, i); ++ ++ /* Set default PVID to 0 on all user ports */ ++ mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK, ++ G0_PORT_VID_DEF); ++ } ++ ++ /* Enable consistent egress tag */ ++ mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, ++ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); ++ } ++ ++ /* Flush the FDB table */ ++ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++ ++static int + mt7531_setup(struct dsa_switch *ds) + { + struct mt7530_priv *priv = ds->priv; + struct mt7530_dummy_poll p; +- struct dsa_port *cpu_dp; + u32 val, id; + int ret, i; + +@@ -2426,44 +2479,7 @@ mt7531_setup(struct dsa_switch *ds) + mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, + CORE_PLL_GROUP4, val); + +- /* BPDU to CPU port */ +- dsa_switch_for_each_cpu_port(cpu_dp, ds) { +- mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK, +- BIT(cpu_dp->index)); +- break; +- } +- mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK, +- MT753X_BPDU_CPU_ONLY); +- +- /* Enable and reset MIB counters */ +- mt7530_mib_reset(ds); +- +- for (i = 0; i < MT7530_NUM_PORTS; i++) { +- /* Disable forwarding by default on all ports */ +- mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK, +- PCR_MATRIX_CLR); +- +- /* Disable learning by default on all ports */ +- mt7530_set(priv, MT7530_PSC_P(i), SA_DIS); +- +- mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR); +- +- if (dsa_is_cpu_port(ds, i)) { +- ret = mt753x_cpu_port_enable(ds, i); +- if (ret) +- return ret; +- } else { +- mt7530_port_disable(ds, i); +- +- /* Set default PVID to 0 on all user ports */ +- mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK, +- G0_PORT_VID_DEF); +- } +- +- /* Enable consistent egress tag */ +- mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK, +- PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); +- } ++ mt7531_setup_common(ds); + + /* Setup VLAN ID 0 for VLAN-unaware bridges */ + ret = mt7530_setup_vlan0(priv); +@@ -2473,11 +2489,6 @@ mt7531_setup(struct dsa_switch *ds) + ds->assisted_learning_on_cpu_port = true; + ds->mtu_enforcement_ingress = true; + +- /* Flush the FDB table */ +- ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); +- if (ret < 0) +- return ret; +- + return 0; + } + diff --git a/target/linux/generic/backport-5.15/790-v6.4-0011-net-dsa-mt7530-introduce-separate-MDIO-driver.patch b/target/linux/generic/backport-5.15/790-v6.4-0011-net-dsa-mt7530-introduce-separate-MDIO-driver.patch new file mode 100644 index 00000000000..96afa041aad --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0011-net-dsa-mt7530-introduce-separate-MDIO-driver.patch @@ -0,0 +1,692 @@ +From cb675afcddbbeb2bfa6596e3bc236bc026cd425f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:13 +0100 +Subject: [PATCH 14/16] net: dsa: mt7530: introduce separate MDIO driver + +Split MT7530 switch driver into a common part and a part specific +for MDIO connected switches and multi-chip modules. +Move MDIO-specific functions to newly introduced mt7530-mdio.c while +keeping the common parts in mt7530.c. +Introduce new Kconfig symbol CONFIG_NET_DSA_MT7530_MDIO which is +implied by CONFIG_NET_DSA_MT7530. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + MAINTAINERS | 1 + + drivers/net/dsa/Kconfig | 15 +- + drivers/net/dsa/Makefile | 1 + + drivers/net/dsa/mt7530-mdio.c | 271 ++++++++++++++++++++++++++++++++++ + drivers/net/dsa/mt7530.c | 264 +-------------------------------- + drivers/net/dsa/mt7530.h | 6 + + 6 files changed, 300 insertions(+), 258 deletions(-) + create mode 100644 drivers/net/dsa/mt7530-mdio.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -11901,6 +11901,7 @@ M: Landen Chao + L: netdev@vger.kernel.org + S: Maintained ++F: drivers/net/dsa/mt7530-mdio.c + F: drivers/net/dsa/mt7530.* + F: net/dsa/tag_mtk.c + +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -37,10 +37,22 @@ config NET_DSA_MT7530 + tristate "MediaTek MT753x and MT7621 Ethernet switch support" + select NET_DSA_TAG_MTK + select MEDIATEK_GE_PHY ++ imply NET_DSA_MT7530_MDIO ++ help ++ This enables support for the MediaTek MT7530 and MT7531 Ethernet ++ switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT, ++ MT7621ST and MT7623AI SoCs, and built-in switch in MT7988 SoC are ++ supported as well. ++ ++config NET_DSA_MT7530_MDIO ++ tristate "MediaTek MT7530 MDIO interface driver" ++ depends on NET_DSA_MT7530 + select PCS_MTK_LYNXI + help +- This enables support for the MediaTek MT7530, MT7531, and MT7621 +- Ethernet switch chips. ++ This enables support for the MediaTek MT7530 and MT7531 switch ++ chips which are connected via MDIO, as well as multi-chip ++ module MT7530 which can be found in the MT7621AT, MT7621DAT, ++ MT7621ST and MT7623AI SoCs. + + config NET_DSA_MV88E6060 + tristate "Marvell 88E6060 ethernet switch chip support" +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -7,6 +7,7 @@ obj-$(CONFIG_FIXED_PHY) += dsa_loop_bdi + endif + obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o + obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o ++obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o + obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o + obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o + realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o +--- /dev/null ++++ b/drivers/net/dsa/mt7530-mdio.c +@@ -0,0 +1,271 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mt7530.h" ++ ++static int ++mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) ++{ ++ struct mii_bus *bus = context; ++ u16 page, r, lo, hi; ++ int ret; ++ ++ page = (reg >> 6) & 0x3ff; ++ r = (reg >> 2) & 0xf; ++ lo = val & 0xffff; ++ hi = val >> 16; ++ ++ /* MT7530 uses 31 as the pseudo port */ ++ ret = bus->write(bus, 0x1f, 0x1f, page); ++ if (ret < 0) ++ return ret; ++ ++ ret = bus->write(bus, 0x1f, r, lo); ++ if (ret < 0) ++ return ret; ++ ++ ret = bus->write(bus, 0x1f, 0x10, hi); ++ return ret; ++} ++ ++static int ++mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) ++{ ++ struct mii_bus *bus = context; ++ u16 page, r, lo, hi; ++ int ret; ++ ++ page = (reg >> 6) & 0x3ff; ++ r = (reg >> 2) & 0xf; ++ ++ /* MT7530 uses 31 as the pseudo port */ ++ ret = bus->write(bus, 0x1f, 0x1f, page); ++ if (ret < 0) ++ return ret; ++ ++ lo = bus->read(bus, 0x1f, r); ++ hi = bus->read(bus, 0x1f, 0x10); ++ ++ *val = (hi << 16) | (lo & 0xffff); ++ ++ return 0; ++} ++ ++static void ++mt7530_mdio_regmap_lock(void *mdio_lock) ++{ ++ mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); ++} ++ ++static void ++mt7530_mdio_regmap_unlock(void *mdio_lock) ++{ ++ mutex_unlock(mdio_lock); ++} ++ ++static const struct regmap_bus mt7530_regmap_bus = { ++ .reg_write = mt7530_regmap_write, ++ .reg_read = mt7530_regmap_read, ++}; ++ ++static int ++mt7531_create_sgmii(struct mt7530_priv *priv) ++{ ++ struct regmap_config *mt7531_pcs_config[2]; ++ struct phylink_pcs *pcs; ++ struct regmap *regmap; ++ int i, ret = 0; ++ ++ for (i = 0; i < 2; i++) { ++ mt7531_pcs_config[i] = devm_kzalloc(priv->dev, ++ sizeof(struct regmap_config), ++ GFP_KERNEL); ++ if (!mt7531_pcs_config[i]) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ mt7531_pcs_config[i]->name = i ? "port6" : "port5"; ++ mt7531_pcs_config[i]->reg_bits = 16; ++ mt7531_pcs_config[i]->val_bits = 32; ++ mt7531_pcs_config[i]->reg_stride = 4; ++ mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); ++ mt7531_pcs_config[i]->max_register = 0x17c; ++ mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; ++ mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; ++ mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; ++ ++ regmap = devm_regmap_init(priv->dev, ++ &mt7530_regmap_bus, priv->bus, ++ mt7531_pcs_config[i]); ++ if (IS_ERR(regmap)) { ++ ret = PTR_ERR(regmap); ++ break; ++ } ++ pcs = mtk_pcs_lynxi_create(priv->dev, regmap, ++ MT7531_PHYA_CTRL_SIGNAL3, 0); ++ if (!pcs) { ++ ret = -ENXIO; ++ break; ++ } ++ priv->ports[5 + i].sgmii_pcs = pcs; ++ } ++ ++ if (ret && i) ++ mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); ++ ++ return ret; ++} ++ ++static const struct of_device_id mt7530_of_match[] = { ++ { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, ++ { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, ++ { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mt7530_of_match); ++ ++static int ++mt7530_probe(struct mdio_device *mdiodev) ++{ ++ static struct regmap_config *regmap_config; ++ struct mt7530_priv *priv; ++ struct device_node *dn; ++ int ret; ++ ++ dn = mdiodev->dev.of_node; ++ ++ priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->bus = mdiodev->bus; ++ priv->dev = &mdiodev->dev; ++ ++ ret = mt7530_probe_common(priv); ++ if (ret) ++ return ret; ++ ++ /* Use medatek,mcm property to distinguish hardware type that would ++ * cause a little bit differences on power-on sequence. ++ * Not MCM that indicates switch works as the remote standalone ++ * integrated circuit so the GPIO pin would be used to complete ++ * the reset, otherwise memory-mapped register accessing used ++ * through syscon provides in the case of MCM. ++ */ ++ priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); ++ if (priv->mcm) { ++ dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); ++ ++ priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); ++ if (IS_ERR(priv->rstc)) { ++ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); ++ return PTR_ERR(priv->rstc); ++ } ++ } else { ++ priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", ++ GPIOD_OUT_LOW); ++ if (IS_ERR(priv->reset)) { ++ dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); ++ return PTR_ERR(priv->reset); ++ } ++ } ++ ++ if (priv->id == ID_MT7530) { ++ priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); ++ if (IS_ERR(priv->core_pwr)) ++ return PTR_ERR(priv->core_pwr); ++ ++ priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); ++ if (IS_ERR(priv->io_pwr)) ++ return PTR_ERR(priv->io_pwr); ++ } ++ ++ regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), ++ GFP_KERNEL); ++ if (!regmap_config) ++ return -ENOMEM; ++ ++ regmap_config->reg_bits = 16; ++ regmap_config->val_bits = 32; ++ regmap_config->reg_stride = 4; ++ regmap_config->max_register = MT7530_CREV; ++ regmap_config->disable_locking = true; ++ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, ++ priv->bus, regmap_config); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ ++ if (priv->id == ID_MT7531) { ++ ret = mt7531_create_sgmii(priv); ++ if (ret) ++ return ret; ++ } ++ ++ return dsa_register_switch(priv->ds); ++} ++ ++static void ++mt7530_remove(struct mdio_device *mdiodev) ++{ ++ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); ++ int ret = 0, i; ++ ++ if (!priv) ++ return; ++ ++ ret = regulator_disable(priv->core_pwr); ++ if (ret < 0) ++ dev_err(priv->dev, ++ "Failed to disable core power: %d\n", ret); ++ ++ ret = regulator_disable(priv->io_pwr); ++ if (ret < 0) ++ dev_err(priv->dev, "Failed to disable io pwr: %d\n", ++ ret); ++ ++ mt7530_remove_common(priv); ++ ++ for (i = 0; i < 2; ++i) ++ mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); ++} ++ ++static void mt7530_shutdown(struct mdio_device *mdiodev) ++{ ++ struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); ++ ++ if (!priv) ++ return; ++ ++ dsa_switch_shutdown(priv->ds); ++ ++ dev_set_drvdata(&mdiodev->dev, NULL); ++} ++ ++static struct mdio_driver mt7530_mdio_driver = { ++ .probe = mt7530_probe, ++ .remove = mt7530_remove, ++ .shutdown = mt7530_shutdown, ++ .mdiodrv.driver = { ++ .name = "mt7530-mdio", ++ .of_match_table = mt7530_of_match, ++ }, ++}; ++ ++mdio_module_driver(mt7530_mdio_driver); ++ ++MODULE_AUTHOR("Sean Wang "); ++MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MDIO)"); ++MODULE_LICENSE("GPL"); +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -14,7 +14,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -192,31 +191,6 @@ core_clear(struct mt7530_priv *priv, u32 + } + + static int +-mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) +-{ +- struct mii_bus *bus = context; +- u16 page, r, lo, hi; +- int ret; +- +- page = (reg >> 6) & 0x3ff; +- r = (reg >> 2) & 0xf; +- lo = val & 0xffff; +- hi = val >> 16; +- +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); +- if (ret < 0) +- return ret; +- +- ret = bus->write(bus, 0x1f, r, lo); +- if (ret < 0) +- return ret; +- +- ret = bus->write(bus, 0x1f, 0x10, hi); +- return ret; +-} +- +-static int + mt7530_mii_write(struct mt7530_priv *priv, u32 reg, u32 val) + { + int ret; +@@ -230,29 +204,6 @@ mt7530_mii_write(struct mt7530_priv *pri + return ret; + } + +-static int +-mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) +-{ +- struct mii_bus *bus = context; +- u16 page, r, lo, hi; +- int ret; +- +- page = (reg >> 6) & 0x3ff; +- r = (reg >> 2) & 0xf; +- +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); +- if (ret < 0) +- return ret; +- +- lo = bus->read(bus, 0x1f, r); +- hi = bus->read(bus, 0x1f, 0x10); +- +- *val = (hi << 16) | (lo & 0xffff); +- +- return 0; +-} +- + static u32 + mt7530_mii_read(struct mt7530_priv *priv, u32 reg) + { +@@ -2944,72 +2895,6 @@ static const struct phylink_pcs_ops mt75 + .pcs_an_restart = mt7530_pcs_an_restart, + }; + +-static void +-mt7530_mdio_regmap_lock(void *mdio_lock) +-{ +- mutex_lock_nested(mdio_lock, MDIO_MUTEX_NESTED); +-} +- +-static void +-mt7530_mdio_regmap_unlock(void *mdio_lock) +-{ +- mutex_unlock(mdio_lock); +-} +- +-static const struct regmap_bus mt7530_regmap_bus = { +- .reg_write = mt7530_regmap_write, +- .reg_read = mt7530_regmap_read, +-}; +- +-static int +-mt7531_create_sgmii(struct mt7530_priv *priv) +-{ +- struct regmap_config *mt7531_pcs_config[2]; +- struct phylink_pcs *pcs; +- struct regmap *regmap; +- int i, ret = 0; +- +- for (i = 0; i < 2; i++) { +- mt7531_pcs_config[i] = devm_kzalloc(priv->dev, +- sizeof(struct regmap_config), +- GFP_KERNEL); +- if (!mt7531_pcs_config[i]) { +- ret = -ENOMEM; +- break; +- } +- +- mt7531_pcs_config[i]->name = i ? "port6" : "port5"; +- mt7531_pcs_config[i]->reg_bits = 16; +- mt7531_pcs_config[i]->val_bits = 32; +- mt7531_pcs_config[i]->reg_stride = 4; +- mt7531_pcs_config[i]->reg_base = MT7531_SGMII_REG_BASE(5 + i); +- mt7531_pcs_config[i]->max_register = 0x17c; +- mt7531_pcs_config[i]->lock = mt7530_mdio_regmap_lock; +- mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; +- mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; +- +- regmap = devm_regmap_init(priv->dev, +- &mt7530_regmap_bus, priv->bus, +- mt7531_pcs_config[i]); +- if (IS_ERR(regmap)) { +- ret = PTR_ERR(regmap); +- break; +- } +- pcs = mtk_pcs_lynxi_create(priv->dev, regmap, +- MT7531_PHYA_CTRL_SIGNAL3, 0); +- if (!pcs) { +- ret = -ENXIO; +- break; +- } +- priv->ports[5 + i].sgmii_pcs = pcs; +- } +- +- if (ret && i) +- mtk_pcs_lynxi_destroy(priv->ports[5].sgmii_pcs); +- +- return ret; +-} +- + static int + mt753x_setup(struct dsa_switch *ds) + { +@@ -3068,7 +2953,7 @@ static int mt753x_set_mac_eee(struct dsa + return 0; + } + +-static const struct dsa_switch_ops mt7530_switch_ops = { ++const struct dsa_switch_ops mt7530_switch_ops = { + .get_tag_protocol = mtk_get_tag_protocol, + .setup = mt753x_setup, + .get_strings = mt7530_get_strings, +@@ -3102,8 +2987,9 @@ static const struct dsa_switch_ops mt753 + .get_mac_eee = mt753x_get_mac_eee, + .set_mac_eee = mt753x_set_mac_eee, + }; ++EXPORT_SYMBOL_GPL(mt7530_switch_ops); + +-static const struct mt753x_info mt753x_table[] = { ++const struct mt753x_info mt753x_table[] = { + [ID_MT7621] = { + .id = ID_MT7621, + .pcs_ops = &mt7530_pcs_ops, +@@ -3136,16 +3022,9 @@ static const struct mt753x_info mt753x_t + .mac_port_config = mt7531_mac_config, + }, + }; ++EXPORT_SYMBOL_GPL(mt753x_table); + +-static const struct of_device_id mt7530_of_match[] = { +- { .compatible = "mediatek,mt7621", .data = &mt753x_table[ID_MT7621], }, +- { .compatible = "mediatek,mt7530", .data = &mt753x_table[ID_MT7530], }, +- { .compatible = "mediatek,mt7531", .data = &mt753x_table[ID_MT7531], }, +- { /* sentinel */ }, +-}; +-MODULE_DEVICE_TABLE(of, mt7530_of_match); +- +-static int ++int + mt7530_probe_common(struct mt7530_priv *priv) + { + struct device *dev = priv->dev; +@@ -3182,88 +3061,9 @@ mt7530_probe_common(struct mt7530_priv * + + return 0; + } ++EXPORT_SYMBOL_GPL(mt7530_probe_common); + +-static int +-mt7530_probe(struct mdio_device *mdiodev) +-{ +- static struct regmap_config *regmap_config; +- struct mt7530_priv *priv; +- struct device_node *dn; +- int ret; +- +- dn = mdiodev->dev.of_node; +- +- priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); +- if (!priv) +- return -ENOMEM; +- +- priv->bus = mdiodev->bus; +- priv->dev = &mdiodev->dev; +- +- ret = mt7530_probe_common(priv); +- if (ret) +- return ret; +- +- /* Use medatek,mcm property to distinguish hardware type that would +- * cause a little bit differences on power-on sequence. +- * Not MCM that indicates switch works as the remote standalone +- * integrated circuit so the GPIO pin would be used to complete +- * the reset, otherwise memory-mapped register accessing used +- * through syscon provides in the case of MCM. +- */ +- priv->mcm = of_property_read_bool(dn, "mediatek,mcm"); +- if (priv->mcm) { +- dev_info(&mdiodev->dev, "MT7530 adapts as multi-chip module\n"); +- +- priv->rstc = devm_reset_control_get(&mdiodev->dev, "mcm"); +- if (IS_ERR(priv->rstc)) { +- dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); +- return PTR_ERR(priv->rstc); +- } +- } else { +- priv->reset = devm_gpiod_get_optional(&mdiodev->dev, "reset", +- GPIOD_OUT_LOW); +- if (IS_ERR(priv->reset)) { +- dev_err(&mdiodev->dev, "Couldn't get our reset line\n"); +- return PTR_ERR(priv->reset); +- } +- } +- +- if (priv->id == ID_MT7530) { +- priv->core_pwr = devm_regulator_get(&mdiodev->dev, "core"); +- if (IS_ERR(priv->core_pwr)) +- return PTR_ERR(priv->core_pwr); +- +- priv->io_pwr = devm_regulator_get(&mdiodev->dev, "io"); +- if (IS_ERR(priv->io_pwr)) +- return PTR_ERR(priv->io_pwr); +- } +- +- regmap_config = devm_kzalloc(&mdiodev->dev, sizeof(*regmap_config), +- GFP_KERNEL); +- if (!regmap_config) +- return -ENOMEM; +- +- regmap_config->reg_bits = 16; +- regmap_config->val_bits = 32; +- regmap_config->reg_stride = 4; +- regmap_config->max_register = MT7530_CREV; +- regmap_config->disable_locking = true; +- priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, +- priv->bus, regmap_config); +- if (IS_ERR(priv->regmap)) +- return PTR_ERR(priv->regmap); +- +- if (priv->id == ID_MT7531) { +- ret = mt7531_create_sgmii(priv); +- if (ret) +- return ret; +- } +- +- return dsa_register_switch(priv->ds); +-} +- +-static void ++void + mt7530_remove_common(struct mt7530_priv *priv) + { + if (priv->irq) +@@ -3274,57 +3074,6 @@ mt7530_remove_common(struct mt7530_priv + mutex_destroy(&priv->reg_mutex); + } + +-static void +-mt7530_remove(struct mdio_device *mdiodev) +-{ +- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); +- int ret = 0, i; +- +- if (!priv) +- return; +- +- ret = regulator_disable(priv->core_pwr); +- if (ret < 0) +- dev_err(priv->dev, +- "Failed to disable core power: %d\n", ret); +- +- ret = regulator_disable(priv->io_pwr); +- if (ret < 0) +- dev_err(priv->dev, "Failed to disable io pwr: %d\n", +- ret); +- +- mt7530_remove_common(priv); +- +- for (i = 0; i < 2; ++i) +- mtk_pcs_lynxi_destroy(priv->ports[5 + i].sgmii_pcs); +- +- dev_set_drvdata(&mdiodev->dev, NULL); +-} +- +-static void mt7530_shutdown(struct mdio_device *mdiodev) +-{ +- struct mt7530_priv *priv = dev_get_drvdata(&mdiodev->dev); +- +- if (!priv) +- return; +- +- dsa_switch_shutdown(priv->ds); +- +- dev_set_drvdata(&mdiodev->dev, NULL); +-} +- +-static struct mdio_driver mt7530_mdio_driver = { +- .probe = mt7530_probe, +- .remove = mt7530_remove, +- .shutdown = mt7530_shutdown, +- .mdiodrv.driver = { +- .name = "mt7530", +- .of_match_table = mt7530_of_match, +- }, +-}; +- +-mdio_module_driver(mt7530_mdio_driver); +- + MODULE_AUTHOR("Sean Wang "); + MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch"); + MODULE_LICENSE("GPL"); +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -807,4 +807,10 @@ static inline void INIT_MT7530_DUMMY_POL + p->reg = reg; + } + ++int mt7530_probe_common(struct mt7530_priv *priv); ++void mt7530_remove_common(struct mt7530_priv *priv); ++ ++extern const struct dsa_switch_ops mt7530_switch_ops; ++extern const struct mt753x_info mt753x_table[]; ++ + #endif /* __MT7530_H */ diff --git a/target/linux/generic/backport-5.15/790-v6.4-0012-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch b/target/linux/generic/backport-5.15/790-v6.4-0012-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch new file mode 100644 index 00000000000..95b7cc6afe5 --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0012-net-dsa-mt7530-skip-locking-if-MDIO-bus-isn-t-presen.patch @@ -0,0 +1,47 @@ +From 54d4147a121cec5004a673a58572da346e4458f8 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:28 +0100 +Subject: [PATCH 15/16] net: dsa: mt7530: skip locking if MDIO bus isn't + present + +As MT7530 and MT7531 internally use 32-bit wide registers, each access +to any register of the switch requires several operations on the MDIO +bus. Hence if there is congruent access, e.g. due to PCS or PHY +polling, this can mess up and interfere with another ongoing register +access sequence. + +However, the MDIO bus mutex is only relevant for MDIO-connected +switches. Prepare switches which have there registers directly mapped +into the SoCs register space via MMIO which do not require such +locking. There we can simply use regmap's default locking mechanism. + +Hence guard mutex operations to only be performed in case of MDIO +connected switches. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -144,13 +144,15 @@ err: + static void + mt7530_mutex_lock(struct mt7530_priv *priv) + { +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++ if (priv->bus) ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); + } + + static void + mt7530_mutex_unlock(struct mt7530_priv *priv) + { +- mutex_unlock(&priv->bus->mdio_lock); ++ if (priv->bus) ++ mutex_unlock(&priv->bus->mdio_lock); + } + + static void diff --git a/target/linux/generic/backport-5.15/790-v6.4-0013-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch b/target/linux/generic/backport-5.15/790-v6.4-0013-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch new file mode 100644 index 00000000000..8210aae27ce --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0013-net-dsa-mt7530-introduce-driver-for-MT7988-built-in-.patch @@ -0,0 +1,421 @@ +From 110c18bfed41421edd677935dd33be5e6507ba92 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 3 Apr 2023 02:19:40 +0100 +Subject: [PATCH 16/16] net: dsa: mt7530: introduce driver for MT7988 built-in + switch + +Add driver for the built-in Gigabit Ethernet switch which can be found +in the MediaTek MT7988 SoC. + +The switch shares most of its design with MT7530 and MT7531, but has +it's registers mapped into the SoCs register space rather than being +connected externally or internally via MDIO. + +Introduce a new platform driver to support that. + +Signed-off-by: Daniel Golle +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +--- + MAINTAINERS | 2 + + drivers/net/dsa/Kconfig | 12 +++ + drivers/net/dsa/Makefile | 1 + + drivers/net/dsa/mt7530-mmio.c | 101 +++++++++++++++++++++++++ + drivers/net/dsa/mt7530.c | 137 +++++++++++++++++++++++++++++++++- + drivers/net/dsa/mt7530.h | 12 +-- + 6 files changed, 255 insertions(+), 10 deletions(-) + create mode 100644 drivers/net/dsa/mt7530-mmio.c + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -11899,9 +11899,11 @@ MEDIATEK SWITCH DRIVER + M: Sean Wang + M: Landen Chao + M: DENG Qingfang ++M: Daniel Golle + L: netdev@vger.kernel.org + S: Maintained + F: drivers/net/dsa/mt7530-mdio.c ++F: drivers/net/dsa/mt7530-mmio.c + F: drivers/net/dsa/mt7530.* + F: net/dsa/tag_mtk.c + +--- a/drivers/net/dsa/Kconfig ++++ b/drivers/net/dsa/Kconfig +@@ -38,6 +38,7 @@ config NET_DSA_MT7530 + select NET_DSA_TAG_MTK + select MEDIATEK_GE_PHY + imply NET_DSA_MT7530_MDIO ++ imply NET_DSA_MT7530_MMIO + help + This enables support for the MediaTek MT7530 and MT7531 Ethernet + switch chips. Multi-chip module MT7530 in MT7621AT, MT7621DAT, +@@ -54,6 +55,17 @@ config NET_DSA_MT7530_MDIO + module MT7530 which can be found in the MT7621AT, MT7621DAT, + MT7621ST and MT7623AI SoCs. + ++config NET_DSA_MT7530_MMIO ++ tristate "MediaTek MT7530 MMIO interface driver" ++ depends on NET_DSA_MT7530 ++ depends on HAS_IOMEM ++ help ++ This enables support for the built-in Ethernet switch found ++ in the MediaTek MT7988 SoC. ++ The switch is a similar design as MT7531, but the switch registers ++ are directly mapped into the SoCs register space rather than being ++ accessible via MDIO. ++ + config NET_DSA_MV88E6060 + tristate "Marvell 88E6060 ethernet switch chip support" + select NET_DSA_TAG_TRAILER +--- a/drivers/net/dsa/Makefile ++++ b/drivers/net/dsa/Makefile +@@ -8,6 +8,7 @@ endif + obj-$(CONFIG_NET_DSA_LANTIQ_GSWIP) += lantiq_gswip.o + obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o + obj-$(CONFIG_NET_DSA_MT7530_MDIO) += mt7530-mdio.o ++obj-$(CONFIG_NET_DSA_MT7530_MMIO) += mt7530-mmio.o + obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o + obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o + realtek-smi-objs := realtek-smi-core.o rtl8366.o rtl8366rb.o +--- /dev/null ++++ b/drivers/net/dsa/mt7530-mmio.c +@@ -0,0 +1,101 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "mt7530.h" ++ ++static const struct of_device_id mt7988_of_match[] = { ++ { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(of, mt7988_of_match); ++ ++static int ++mt7988_probe(struct platform_device *pdev) ++{ ++ static struct regmap_config *sw_regmap_config; ++ struct mt7530_priv *priv; ++ void __iomem *base_addr; ++ int ret; ++ ++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->bus = NULL; ++ priv->dev = &pdev->dev; ++ ++ ret = mt7530_probe_common(priv); ++ if (ret) ++ return ret; ++ ++ priv->rstc = devm_reset_control_get(&pdev->dev, NULL); ++ if (IS_ERR(priv->rstc)) { ++ dev_err(&pdev->dev, "Couldn't get our reset line\n"); ++ return PTR_ERR(priv->rstc); ++ } ++ ++ base_addr = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(base_addr)) { ++ dev_err(&pdev->dev, "cannot request I/O memory space\n"); ++ return -ENXIO; ++ } ++ ++ sw_regmap_config = devm_kzalloc(&pdev->dev, sizeof(*sw_regmap_config), GFP_KERNEL); ++ if (!sw_regmap_config) ++ return -ENOMEM; ++ ++ sw_regmap_config->name = "switch"; ++ sw_regmap_config->reg_bits = 16; ++ sw_regmap_config->val_bits = 32; ++ sw_regmap_config->reg_stride = 4; ++ sw_regmap_config->max_register = MT7530_CREV; ++ priv->regmap = devm_regmap_init_mmio(&pdev->dev, base_addr, sw_regmap_config); ++ if (IS_ERR(priv->regmap)) ++ return PTR_ERR(priv->regmap); ++ ++ return dsa_register_switch(priv->ds); ++} ++ ++static int ++mt7988_remove(struct platform_device *pdev) ++{ ++ struct mt7530_priv *priv = platform_get_drvdata(pdev); ++ ++ if (priv) ++ mt7530_remove_common(priv); ++ ++ return 0; ++} ++ ++static void mt7988_shutdown(struct platform_device *pdev) ++{ ++ struct mt7530_priv *priv = platform_get_drvdata(pdev); ++ ++ if (!priv) ++ return; ++ ++ dsa_switch_shutdown(priv->ds); ++ ++ dev_set_drvdata(&pdev->dev, NULL); ++} ++ ++static struct platform_driver mt7988_platform_driver = { ++ .probe = mt7988_probe, ++ .remove = mt7988_remove, ++ .shutdown = mt7988_shutdown, ++ .driver = { ++ .name = "mt7530-mmio", ++ .of_match_table = mt7988_of_match, ++ }, ++}; ++module_platform_driver(mt7988_platform_driver); ++ ++MODULE_AUTHOR("Daniel Golle "); ++MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch (MMIO)"); ++MODULE_LICENSE("GPL"); +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1984,6 +1984,47 @@ static const struct irq_domain_ops mt753 + }; + + static void ++mt7988_irq_mask(struct irq_data *d) ++{ ++ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ priv->irq_enable &= ~BIT(d->hwirq); ++ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); ++} ++ ++static void ++mt7988_irq_unmask(struct irq_data *d) ++{ ++ struct mt7530_priv *priv = irq_data_get_irq_chip_data(d); ++ ++ priv->irq_enable |= BIT(d->hwirq); ++ mt7530_mii_write(priv, MT7530_SYS_INT_EN, priv->irq_enable); ++} ++ ++static struct irq_chip mt7988_irq_chip = { ++ .name = KBUILD_MODNAME, ++ .irq_mask = mt7988_irq_mask, ++ .irq_unmask = mt7988_irq_unmask, ++}; ++ ++static int ++mt7988_irq_map(struct irq_domain *domain, unsigned int irq, ++ irq_hw_number_t hwirq) ++{ ++ irq_set_chip_data(irq, domain->host_data); ++ irq_set_chip_and_handler(irq, &mt7988_irq_chip, handle_simple_irq); ++ irq_set_nested_thread(irq, true); ++ irq_set_noprobe(irq); ++ ++ return 0; ++} ++ ++static const struct irq_domain_ops mt7988_irq_domain_ops = { ++ .map = mt7988_irq_map, ++ .xlate = irq_domain_xlate_onecell, ++}; ++ ++static void + mt7530_setup_mdio_irq(struct mt7530_priv *priv) + { + struct dsa_switch *ds = priv->ds; +@@ -2017,8 +2058,15 @@ mt7530_setup_irq(struct mt7530_priv *pri + return priv->irq ? : -EINVAL; + } + +- priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, +- &mt7530_irq_domain_ops, priv); ++ if (priv->id == ID_MT7988) ++ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, ++ &mt7988_irq_domain_ops, ++ priv); ++ else ++ priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS, ++ &mt7530_irq_domain_ops, ++ priv); ++ + if (!priv->irq_domain) { + dev_err(dev, "failed to create IRQ domain\n"); + return -ENOMEM; +@@ -2507,6 +2555,25 @@ static void mt7531_mac_port_get_caps(str + } + } + ++static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port, ++ struct phylink_config *config) ++{ ++ phy_interface_zero(config->supported_interfaces); ++ ++ switch (port) { ++ case 0 ... 4: /* Internal phy */ ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ break; ++ ++ case 6: ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | ++ MAC_10000FD; ++ } ++} ++ + static int + mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state) + { +@@ -2583,6 +2650,17 @@ static bool mt753x_is_mac_port(u32 port) + } + + static int ++mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++ phy_interface_t interface) ++{ ++ if (dsa_is_cpu_port(ds, port) && ++ interface == PHY_INTERFACE_MODE_INTERNAL) ++ return 0; ++ ++ return -EINVAL; ++} ++ ++static int + mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) + { +@@ -2652,7 +2730,8 @@ mt753x_phylink_mac_config(struct dsa_swi + + switch (port) { + case 0 ... 4: /* Internal phy */ +- if (state->interface != PHY_INTERFACE_MODE_GMII) ++ if (state->interface != PHY_INTERFACE_MODE_GMII && ++ state->interface != PHY_INTERFACE_MODE_INTERNAL) + goto unsupported; + break; + case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */ +@@ -2730,7 +2809,8 @@ static void mt753x_phylink_mac_link_up(s + /* MT753x MAC works in 1G full duplex mode for all up-clocked + * variants. + */ +- if (interface == PHY_INTERFACE_MODE_TRGMII || ++ if (interface == PHY_INTERFACE_MODE_INTERNAL || ++ interface == PHY_INTERFACE_MODE_TRGMII || + (phy_interface_mode_is_8023z(interface))) { + speed = SPEED_1000; + duplex = DUPLEX_FULL; +@@ -2810,6 +2890,21 @@ mt7531_cpu_port_config(struct dsa_switch + return 0; + } + ++static int ++mt7988_cpu_port_config(struct dsa_switch *ds, int port) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ mt7530_write(priv, MT7530_PMCR_P(port), ++ PMCR_CPU_PORT_SETTING(priv->id)); ++ ++ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_INTERNAL, NULL, ++ SPEED_10000, DUPLEX_FULL, true, true); ++ ++ return 0; ++} ++ + static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) + { +@@ -2955,6 +3050,27 @@ static int mt753x_set_mac_eee(struct dsa + return 0; + } + ++static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface) ++{ ++ return 0; ++} ++ ++static int mt7988_setup(struct dsa_switch *ds) ++{ ++ struct mt7530_priv *priv = ds->priv; ++ ++ /* Reset the switch */ ++ reset_control_assert(priv->rstc); ++ usleep_range(20, 50); ++ reset_control_deassert(priv->rstc); ++ usleep_range(20, 50); ++ ++ /* Reset the switch PHYs */ ++ mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_PHY_RST); ++ ++ return mt7531_setup_common(ds); ++} ++ + const struct dsa_switch_ops mt7530_switch_ops = { + .get_tag_protocol = mtk_get_tag_protocol, + .setup = mt753x_setup, +@@ -3023,6 +3139,17 @@ const struct mt753x_info mt753x_table[] + .mac_port_get_caps = mt7531_mac_port_get_caps, + .mac_port_config = mt7531_mac_config, + }, ++ [ID_MT7988] = { ++ .id = ID_MT7988, ++ .pcs_ops = &mt7530_pcs_ops, ++ .sw_setup = mt7988_setup, ++ .phy_read = mt7531_ind_phy_read, ++ .phy_write = mt7531_ind_phy_write, ++ .pad_setup = mt7988_pad_setup, ++ .cpu_port_config = mt7988_cpu_port_config, ++ .mac_port_get_caps = mt7988_mac_port_get_caps, ++ .mac_port_config = mt7988_mac_config, ++ }, + }; + EXPORT_SYMBOL_GPL(mt753x_table); + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -18,6 +18,7 @@ enum mt753x_id { + ID_MT7530 = 0, + ID_MT7621 = 1, + ID_MT7531 = 2, ++ ID_MT7988 = 3, + }; + + #define NUM_TRGMII_CTRL 5 +@@ -54,11 +55,11 @@ enum mt753x_id { + #define MT7531_MIRROR_PORT_SET(x) (((x) & MIRROR_MASK) << 16) + #define MT7531_CPU_PMAP_MASK GENMASK(7, 0) + +-#define MT753X_MIRROR_REG(id) (((id) == ID_MT7531) ? \ ++#define MT753X_MIRROR_REG(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ + MT7531_CFC : MT7530_MFC) +-#define MT753X_MIRROR_EN(id) (((id) == ID_MT7531) ? \ ++#define MT753X_MIRROR_EN(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ + MT7531_MIRROR_EN : MIRROR_EN) +-#define MT753X_MIRROR_MASK(id) (((id) == ID_MT7531) ? \ ++#define MT753X_MIRROR_MASK(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ + MT7531_MIRROR_MASK : MIRROR_MASK) + + /* Registers for BPDU and PAE frame control*/ +@@ -295,9 +296,8 @@ enum mt7530_vlan_port_acc_frm { + MT7531_FORCE_DPX | \ + MT7531_FORCE_RX_FC | \ + MT7531_FORCE_TX_FC) +-#define PMCR_FORCE_MODE_ID(id) (((id) == ID_MT7531) ? \ +- MT7531_FORCE_MODE : \ +- PMCR_FORCE_MODE) ++#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \ ++ MT7531_FORCE_MODE : PMCR_FORCE_MODE) + #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \ + PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \ + PMCR_TX_FC_EN | PMCR_RX_FC_EN | \ diff --git a/target/linux/generic/backport-5.15/790-v6.4-0014-net-dsa-mt7530-fix-support-for-MT7531BE.patch b/target/linux/generic/backport-5.15/790-v6.4-0014-net-dsa-mt7530-fix-support-for-MT7531BE.patch new file mode 100644 index 00000000000..5259730996d --- /dev/null +++ b/target/linux/generic/backport-5.15/790-v6.4-0014-net-dsa-mt7530-fix-support-for-MT7531BE.patch @@ -0,0 +1,118 @@ +From 91daa4f62ce878b6e1ac5908aceb83550332447f Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sun, 16 Apr 2023 13:08:14 +0100 +Subject: [PATCH] net: dsa: mt7530: fix support for MT7531BE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are two variants of the MT7531 switch IC which got different +features (and pins) regarding port 5: + * MT7531AE: SGMII/1000Base-X/2500Base-X SerDes PCS + * MT7531BE: RGMII + +Moving the creation of the SerDes PCS from mt753x_setup to mt7530_probe +with commit 6de285229773 ("net: dsa: mt7530: move SGMII PCS creation +to mt7530_probe function") works fine for MT7531AE which got two +instances of mtk-pcs-lynxi, however, MT7531BE requires mt7531_pll_setup +to setup clocks before the single PCS on port 6 (usually used as CPU +port) starts to work and hence the PCS creation failed on MT7531BE. + +Fix this by introducing a pointer to mt7531_create_sgmii function in +struct mt7530_priv and call it again at the end of mt753x_setup like it +was before commit 6de285229773 ("net: dsa: mt7530: move SGMII PCS +creation to mt7530_probe function"). + +Fixes: 6de285229773 ("net: dsa: mt7530: move SGMII PCS creation to mt7530_probe function") +Signed-off-by: Daniel Golle +Acked-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/ZDvlLhhqheobUvOK@makrotopia.org +Signed-off-by: Jakub Kicinski +--- + drivers/net/dsa/mt7530-mdio.c | 16 ++++++++-------- + drivers/net/dsa/mt7530.c | 6 ++++++ + drivers/net/dsa/mt7530.h | 4 ++-- + 3 files changed, 16 insertions(+), 10 deletions(-) + +--- a/drivers/net/dsa/mt7530-mdio.c ++++ b/drivers/net/dsa/mt7530-mdio.c +@@ -81,14 +81,17 @@ static const struct regmap_bus mt7530_re + }; + + static int +-mt7531_create_sgmii(struct mt7530_priv *priv) ++mt7531_create_sgmii(struct mt7530_priv *priv, bool dual_sgmii) + { +- struct regmap_config *mt7531_pcs_config[2]; ++ struct regmap_config *mt7531_pcs_config[2] = {}; + struct phylink_pcs *pcs; + struct regmap *regmap; + int i, ret = 0; + +- for (i = 0; i < 2; i++) { ++ /* MT7531AE has two SGMII units for port 5 and port 6 ++ * MT7531BE has only one SGMII unit for port 6 ++ */ ++ for (i = dual_sgmii ? 0 : 1; i < 2; i++) { + mt7531_pcs_config[i] = devm_kzalloc(priv->dev, + sizeof(struct regmap_config), + GFP_KERNEL); +@@ -208,11 +211,8 @@ mt7530_probe(struct mdio_device *mdiodev + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + +- if (priv->id == ID_MT7531) { +- ret = mt7531_create_sgmii(priv); +- if (ret) +- return ret; +- } ++ if (priv->id == ID_MT7531) ++ priv->create_sgmii = mt7531_create_sgmii; + + return dsa_register_switch(priv->ds); + } +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -3017,6 +3017,12 @@ mt753x_setup(struct dsa_switch *ds) + if (ret && priv->irq) + mt7530_free_irq_common(priv); + ++ if (priv->create_sgmii) { ++ ret = priv->create_sgmii(priv, mt7531_dual_sgmii_supported(priv)); ++ if (ret && priv->irq) ++ mt7530_free_irq(priv); ++ } ++ + return ret; + } + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -741,10 +741,10 @@ struct mt753x_info { + * registers + * @p6_interface Holding the current port 6 interface + * @p5_intf_sel: Holding the current port 5 interface select +- * + * @irq: IRQ number of the switch + * @irq_domain: IRQ domain of the switch irq_chip + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN ++ * @create_sgmii: Pointer to function creating SGMII PCS instance(s) + */ + struct mt7530_priv { + struct device *dev; +@@ -763,7 +763,6 @@ struct mt7530_priv { + unsigned int p5_intf_sel; + u8 mirror_rx; + u8 mirror_tx; +- + struct mt7530_port ports[MT7530_NUM_PORTS]; + struct mt753x_pcs pcs[MT7530_NUM_PORTS]; + /* protect among processes for registers access*/ +@@ -771,6 +770,7 @@ struct mt7530_priv { + int irq; + struct irq_domain *irq_domain; + u32 irq_enable; ++ int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii); + }; + + struct mt7530_hw_vlan_entry { diff --git a/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch b/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch index 57137c34fc6..e2a0e25a794 100644 --- a/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch +++ b/target/linux/generic/backport-5.15/791-v6.2-01-net-phy-Add-driver-for-Motorcomm-yt8521-gigabit-ethernet.patch @@ -21,7 +21,7 @@ Signed-off-by: David S. Miller --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12697,6 +12697,7 @@ F: include/uapi/linux/meye.h +@@ -12700,6 +12700,7 @@ F: include/uapi/linux/meye.h MOTORCOMM PHY DRIVER M: Peter Geis diff --git a/target/linux/generic/backport-5.15/804-v5.18-0009-nvmem-Add-driver-for-OCOTP-in-Sunplus-SP7021.patch b/target/linux/generic/backport-5.15/804-v5.18-0009-nvmem-Add-driver-for-OCOTP-in-Sunplus-SP7021.patch index 2a9dc749478..ae177e0cb03 100644 --- a/target/linux/generic/backport-5.15/804-v5.18-0009-nvmem-Add-driver-for-OCOTP-in-Sunplus-SP7021.patch +++ b/target/linux/generic/backport-5.15/804-v5.18-0009-nvmem-Add-driver-for-OCOTP-in-Sunplus-SP7021.patch @@ -19,7 +19,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17962,6 +17962,11 @@ L: netdev@vger.kernel.org +@@ -17965,6 +17965,11 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/dlink/sundance.c diff --git a/target/linux/generic/backport-5.15/806-v6.0-0001-nvmem-microchip-otpc-add-support.patch b/target/linux/generic/backport-5.15/806-v6.0-0001-nvmem-microchip-otpc-add-support.patch index b1855d1f2f2..ad0460d4f36 100644 --- a/target/linux/generic/backport-5.15/806-v6.0-0001-nvmem-microchip-otpc-add-support.patch +++ b/target/linux/generic/backport-5.15/806-v6.0-0001-nvmem-microchip-otpc-add-support.patch @@ -57,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -12361,6 +12361,14 @@ S: Supported +@@ -12364,6 +12364,14 @@ S: Supported F: Documentation/devicetree/bindings/mtd/atmel-nand.txt F: drivers/mtd/nand/raw/atmel/* diff --git a/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch b/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch index d93ee0685b2..bd806a7a6df 100644 --- a/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch +++ b/target/linux/generic/pending-5.15/723-net-mt7531-ensure-all-MACs-are-powered-down-before-r.patch @@ -15,7 +15,7 @@ Signed-off-by: Alexander Couzens --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -2347,6 +2347,10 @@ mt7531_setup(struct dsa_switch *ds) +@@ -2440,6 +2440,10 @@ mt7531_setup(struct dsa_switch *ds) return -ENODEV; } diff --git a/target/linux/generic/pending-5.15/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch b/target/linux/generic/pending-5.15/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch index f9b88db9955..8a64a2a985e 100644 --- a/target/linux/generic/pending-5.15/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch +++ b/target/linux/generic/pending-5.15/795-mt7530-register-OF-node-for-internal-MDIO-bus.patch @@ -16,7 +16,7 @@ Signed-off-by: David Bauer --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c -@@ -2081,10 +2081,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr +@@ -2121,10 +2121,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr { struct dsa_switch *ds = priv->ds; struct device *dev = priv->dev; @@ -30,7 +30,7 @@ Signed-off-by: David Bauer bus = devm_mdiobus_alloc(dev); if (!bus) return -ENOMEM; -@@ -2101,7 +2104,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr +@@ -2141,7 +2144,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr if (priv->irq) mt7530_setup_mdio_irq(priv); diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 7268b693895..134afb63f9e 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -250,6 +250,8 @@ CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +CONFIG_NET_DSA_MT7530_MMIO=y CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 88ca94472cd..2de14752b46 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -272,6 +272,8 @@ CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +# CONFIG_NET_DSA_MT7530_MMIO is not set CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y diff --git a/target/linux/mediatek/mt7623/config-5.15 b/target/linux/mediatek/mt7623/config-5.15 index 77d20a3bdba..af0a5c1939f 100644 --- a/target/linux/mediatek/mt7623/config-5.15 +++ b/target/linux/mediatek/mt7623/config-5.15 @@ -372,6 +372,8 @@ CONFIG_NEON=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +# CONFIG_NET_DSA_MT7530_MMIO is not set CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y diff --git a/target/linux/mediatek/mt7629/config-5.15 b/target/linux/mediatek/mt7629/config-5.15 index 46b444108bc..08089dde2a3 100644 --- a/target/linux/mediatek/mt7629/config-5.15 +++ b/target/linux/mediatek/mt7629/config-5.15 @@ -197,6 +197,8 @@ CONFIG_NETFILTER=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +# CONFIG_NET_DSA_MT7530_MMIO is not set CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y diff --git a/target/linux/ramips/mt7621/config-5.15 b/target/linux/ramips/mt7621/config-5.15 index 1b8a48100df..1b4330c2d16 100644 --- a/target/linux/ramips/mt7621/config-5.15 +++ b/target/linux/ramips/mt7621/config-5.15 @@ -184,6 +184,8 @@ CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NET_DEVLINK=y CONFIG_NET_DSA=y CONFIG_NET_DSA_MT7530=y +CONFIG_NET_DSA_MT7530_MDIO=y +# CONFIG_NET_DSA_MT7530_MMIO is not set CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_MEDIATEK_SOC=y diff --git a/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch b/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch index e562dd8396c..17ff729f525 100644 --- a/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch +++ b/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch @@ -32,7 +32,7 @@ Signed-off-by: Guenter Roeck --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -15899,6 +15899,13 @@ S: Maintained +@@ -15902,6 +15902,13 @@ S: Maintained F: include/sound/rt*.h F: sound/soc/codecs/rt* diff --git a/target/linux/realtek/patches-5.15/700-net-dsa-add-support-for-rtl838x-switch.patch b/target/linux/realtek/patches-5.15/700-net-dsa-add-support-for-rtl838x-switch.patch index 8f400012635..8c6a4c36393 100644 --- a/target/linux/realtek/patches-5.15/700-net-dsa-add-support-for-rtl838x-switch.patch +++ b/target/linux/realtek/patches-5.15/700-net-dsa-add-support-for-rtl838x-switch.patch @@ -22,7 +22,7 @@ Submitted-by: John Crispin --- a/drivers/net/dsa/Kconfig +++ b/drivers/net/dsa/Kconfig -@@ -61,6 +61,8 @@ source "drivers/net/dsa/sja1105/Kconfig" +@@ -85,6 +85,8 @@ source "drivers/net/dsa/sja1105/Kconfig" source "drivers/net/dsa/xrs700x/Kconfig" @@ -33,7 +33,7 @@ Submitted-by: John Crispin select NET_DSA_TAG_RTL4_A --- a/drivers/net/dsa/Makefile +++ b/drivers/net/dsa/Makefile -@@ -22,5 +22,6 @@ obj-y += microchip/ +@@ -24,5 +24,6 @@ obj-y += microchip/ obj-y += mv88e6xxx/ obj-y += ocelot/ obj-y += qca/ From 987a0b2b3011a9e5ee3e4120b068fb2f113628a7 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 17:34:55 +0100 Subject: [PATCH 13/43] mediatek: update pending SoC Ethernet PHY driver Update driver for MediaTek's built-in Gigabit Ethernet PHYs which can be found in the MT7981 and MT7988 SoCs. Signed-off-by: Daniel Golle --- ...2c-Add-driver-for-Sony-IMX477-sensor.patch | 2 +- ...vicetree-Add-documentation-for-imx37.patch | 2 +- ...a-i2c-Add-IMX519-CMOS-sensor-binding.patch | 2 +- .../drivers/net/phy/mediatek-ge-soc.c | 1263 +++++++++++++++ target/linux/mediatek/filogic/config-5.15 | 2 +- target/linux/mediatek/mt7622/config-5.15 | 2 +- ...er-for-MediaTek-SoC-built-in-GE-PHYs.patch | 1427 +---------------- 7 files changed, 1301 insertions(+), 1399 deletions(-) create mode 100644 target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-ge-soc.c diff --git a/target/linux/bcm27xx/patches-5.15/950-0281-media-i2c-Add-driver-for-Sony-IMX477-sensor.patch b/target/linux/bcm27xx/patches-5.15/950-0281-media-i2c-Add-driver-for-Sony-IMX477-sensor.patch index e756fa2fff6..bb0afb1a2a3 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0281-media-i2c-Add-driver-for-Sony-IMX477-sensor.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0281-media-i2c-Add-driver-for-Sony-IMX477-sensor.patch @@ -25,7 +25,7 @@ Signed-off-by: Naushir Patuck --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17538,6 +17538,14 @@ T: git git://linuxtv.org/media_tree.git +@@ -17541,6 +17541,14 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml F: drivers/media/i2c/imx412.c diff --git a/target/linux/bcm27xx/patches-5.15/950-0413-Documentation-devicetree-Add-documentation-for-imx37.patch b/target/linux/bcm27xx/patches-5.15/950-0413-Documentation-devicetree-Add-documentation-for-imx37.patch index 27fd0e57938..f9021eea55f 100644 --- a/target/linux/bcm27xx/patches-5.15/950-0413-Documentation-devicetree-Add-documentation-for-imx37.patch +++ b/target/linux/bcm27xx/patches-5.15/950-0413-Documentation-devicetree-Add-documentation-for-imx37.patch @@ -132,7 +132,7 @@ Signed-off-by: David Plowman +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17552,6 +17552,7 @@ M: Raspberry Pi Kernel Maintenance +... --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -17556,6 +17556,14 @@ F: Documentation/devicetree/bindings/med +@@ -17559,6 +17559,14 @@ F: Documentation/devicetree/bindings/med F: Documentation/devicetree/bindings/media/i2c/imx477.yaml F: drivers/media/i2c/imx477.c diff --git a/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-ge-soc.c b/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-ge-soc.c new file mode 100644 index 00000000000..e48502ac3fd --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-ge-soc.c @@ -0,0 +1,1263 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include +#include +#include +#include +#include +#include +#include + +#define MTK_GPHY_ID_MT7981 0x03a29461 +#define MTK_GPHY_ID_MT7988 0x03a29481 + +#define MTK_EXT_PAGE_ACCESS 0x1f +#define MTK_PHY_PAGE_STANDARD 0x0000 +#define MTK_PHY_PAGE_EXTENDED_3 0x0003 + +#define MTK_PHY_LPI_REG_14 0x14 +#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0) + +#define MTK_PHY_LPI_REG_1c 0x1c +#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8) + +#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 +#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 + +#define ANALOG_INTERNAL_OPERATION_MAX_US 20 +#define TXRESERVE_MIN 0 +#define TXRESERVE_MAX 7 + +#define MTK_PHY_ANARG_RG 0x10 +#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8) + +/* Registers on MDIO_MMD_VEND1 */ +#define MTK_PHY_TXVLD_DA_RG 0x12 +#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10) +#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16 +#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10) +#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17 +#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18 +#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19 +#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20 +#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21 +#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22 +#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_RXADC_CTRL_RG7 0xc6 +#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) + +#define MTK_PHY_RXADC_CTRL_RG9 0xc8 +#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12) +#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8) +#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4) +#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0) + +#define MTK_PHY_LDO_OUTPUT_V 0xd7 + +#define MTK_PHY_RG_ANA_CAL_RG0 0xdb +#define MTK_PHY_RG_CAL_CKINV BIT(12) +#define MTK_PHY_RG_ANA_CALEN BIT(8) +#define MTK_PHY_RG_ZCALEN_A BIT(0) + +#define MTK_PHY_RG_ANA_CAL_RG1 0xdc +#define MTK_PHY_RG_ZCALEN_B BIT(12) +#define MTK_PHY_RG_ZCALEN_C BIT(8) +#define MTK_PHY_RG_ZCALEN_D BIT(4) +#define MTK_PHY_RG_TXVOS_CALEN BIT(0) + +#define MTK_PHY_RG_ANA_CAL_RG5 0xe0 +#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8) + +#define MTK_PHY_RG_TX_FILTER 0xfe + +#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120 +#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8) +#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0) + +#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122 +#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0) + +#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144 +#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5) + +#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172 +#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8) +#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0) + +#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173 +#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8) +#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) + +#define MTK_PHY_RG_AD_CAL_COMP 0x17a +#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8) + +#define MTK_PHY_RG_AD_CAL_CLK 0x17b +#define MTK_PHY_DA_CAL_CLK BIT(0) + +#define MTK_PHY_RG_AD_CALIN 0x17c +#define MTK_PHY_DA_CALIN_FLAG BIT(0) + +#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d +#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e +#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f +#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180 +#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181 +#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182 +#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183 +#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184 +#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DEV1E_REG19b 0x19b +#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8) + +#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a +#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b +#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c +#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d +#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e +#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f +#define MTK_PHY_RG_LP_IIR2_K4_L 0x230 +#define MTK_PHY_RG_LP_IIR2_K4_U 0x231 +#define MTK_PHY_RG_LP_IIR2_K5_L 0x232 +#define MTK_PHY_RG_LP_IIR2_K5_U 0x233 + +#define MTK_PHY_RG_DEV1E_REG234 0x234 +#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0) +#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4) +#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12) + +#define MTK_PHY_RG_LPF_CNT_VAL 0x235 + +#define MTK_PHY_RG_DEV1E_REG238 0x238 +#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0) +#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12) + +#define MTK_PHY_RG_DEV1E_REG239 0x239 +#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0) +#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12) + +#define MTK_PHY_RG_DEV1E_REG27C 0x27c +#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8) +#define MTK_PHY_RG_DEV1E_REG27D 0x27d +#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0) + +#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7 +#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0) +#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8) + +#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1 +#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0) +#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8) +#define MTK_PHY_LPI_TR_READY BIT(9) +#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10) + +#define MTK_PHY_RG_DEV1E_REG323 0x323 +#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0) +#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4) + +#define MTK_PHY_RG_DEV1E_REG324 0x324 +#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0) +#define MTK_PHY_SMI_DET_MAX_EN BIT(8) + +#define MTK_PHY_RG_DEV1E_REG326 0x326 +#define MTK_PHY_LPI_MODE_SD_ON BIT(0) +#define MTK_PHY_RESET_RANDUPD_CNT BIT(1) +#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2) +#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4) +#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5) + +#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502 +#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503 + +#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d +#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e +#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f +#define MTK_PHY_DA_TX_R50_PAIR_D 0x540 + +/* Registers on MDIO_MMD_VEND2 */ +#define MTK_PHY_LED0_ON_CTRL 0x24 +#define MTK_PHY_LED0_ON_MASK GENMASK(6, 0) +#define MTK_PHY_LED0_ON_LINK1000 BIT(0) +#define MTK_PHY_LED0_ON_LINK100 BIT(1) +#define MTK_PHY_LED0_ON_LINK10 BIT(2) +#define MTK_PHY_LED0_ON_LINKDOWN BIT(3) +#define MTK_PHY_LED0_ON_FDX BIT(4) /* Full duplex */ +#define MTK_PHY_LED0_ON_HDX BIT(5) /* Half duplex */ +#define MTK_PHY_LED0_FORCE_ON BIT(6) +#define MTK_PHY_LED0_POLARITY BIT(14) +#define MTK_PHY_LED0_ENABLE BIT(15) + +#define MTK_PHY_LED0_BLINK_CTRL 0x25 +#define MTK_PHY_LED0_1000TX BIT(0) +#define MTK_PHY_LED0_1000RX BIT(1) +#define MTK_PHY_LED0_100TX BIT(2) +#define MTK_PHY_LED0_100RX BIT(3) +#define MTK_PHY_LED0_10TX BIT(4) +#define MTK_PHY_LED0_10RX BIT(5) +#define MTK_PHY_LED0_COLLISION BIT(6) +#define MTK_PHY_LED0_RX_CRC_ERR BIT(7) +#define MTK_PHY_LED0_RX_IDLE_ERR BIT(8) +#define MTK_PHY_LED0_FORCE_BLINK BIT(9) + +#define MTK_PHY_LED1_ON_CTRL 0x26 +#define MTK_PHY_LED1_ON_MASK GENMASK(6, 0) +#define MTK_PHY_LED1_ON_LINK1000 BIT(0) +#define MTK_PHY_LED1_ON_LINK100 BIT(1) +#define MTK_PHY_LED1_ON_LINK10 BIT(2) +#define MTK_PHY_LED1_ON_LINKDOWN BIT(3) +#define MTK_PHY_LED1_ON_FDX BIT(4) /* Full duplex */ +#define MTK_PHY_LED1_ON_HDX BIT(5) /* Half duplex */ +#define MTK_PHY_LED1_FORCE_ON BIT(6) +#define MTK_PHY_LED1_POLARITY BIT(14) +#define MTK_PHY_LED1_ENABLE BIT(15) + +#define MTK_PHY_LED1_BLINK_CTRL 0x27 +#define MTK_PHY_LED1_1000TX BIT(0) +#define MTK_PHY_LED1_1000RX BIT(1) +#define MTK_PHY_LED1_100TX BIT(2) +#define MTK_PHY_LED1_100RX BIT(3) +#define MTK_PHY_LED1_10TX BIT(4) +#define MTK_PHY_LED1_10RX BIT(5) +#define MTK_PHY_LED1_COLLISION BIT(6) +#define MTK_PHY_LED1_RX_CRC_ERR BIT(7) +#define MTK_PHY_LED1_RX_IDLE_ERR BIT(8) +#define MTK_PHY_LED1_FORCE_BLINK BIT(9) + +#define MTK_PHY_RG_BG_RASEL 0x115 +#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) + +/* These macro privides efuse parsing for internal phy. */ +#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0)) + +#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0)) + +#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0)) + +#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0)) +#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0)) + +enum { + NO_PAIR, + PAIR_A, + PAIR_B, + PAIR_C, + PAIR_D, +}; + +enum { + GPHY_PORT0, + GPHY_PORT1, + GPHY_PORT2, + GPHY_PORT3, +}; + +enum calibration_mode { + EFUSE_K, + SW_K +}; + +enum CAL_ITEM { + REXT, + TX_OFFSET, + TX_AMP, + TX_R50, + TX_VCM +}; + +enum CAL_MODE { + EFUSE_M, + SW_M +}; + +struct mtk_socphy_shared_priv { + u32 boottrap; +}; + +static int mtk_socphy_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); +} + +static int mtk_socphy_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); +} + +/* One calibration cycle consists of: + * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high + * until AD_CAL_COMP is ready to output calibration result. + * 2.Wait until DA_CAL_CLK is available. + * 3.Fetch AD_CAL_COMP_OUT. + */ +static int cal_cycle(struct phy_device *phydev, int devad, + u32 regnum, u16 mask, u16 cal_val) +{ + int reg_val; + int ret; + + phy_modify_mmd(phydev, devad, regnum, + mask, cal_val); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, + MTK_PHY_DA_CALIN_FLAG); + + ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_AD_CAL_CLK, reg_val, + reg_val & MTK_PHY_DA_CAL_CLK, 500, + ANALOG_INTERNAL_OPERATION_MAX_US, false); + if (ret) { + phydev_err(phydev, "Calibration cycle timeout\n"); + return ret; + } + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, + MTK_PHY_DA_CALIN_FLAG); + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >> + MTK_PHY_AD_CAL_COMP_OUT_SHIFT; + phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); + + return ret; +} + +static int rext_fill_result(struct phy_device *phydev, u16 *buf) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, + MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL, + MTK_PHY_RG_BG_RASEL_MASK, buf[1]); + + return 0; +} + +static int rext_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 rext_cal_val[2]; + + rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]); + rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]); + rext_fill_result(phydev, rext_cal_val); + + return 0; +} + +static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, + MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, + MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, + MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, + MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]); + + return 0; +} + +static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 tx_offset_cal_val[4]; + + tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]); + tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]); + tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]); + tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]); + + tx_offset_fill_result(phydev, tx_offset_cal_val); + + return 0; +} + +static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) +{ + int i; + int bias[16] = {}; + const int vals_9461[16] = { 7, 1, 4, 7, + 7, 1, 4, 7, + 7, 1, 4, 7, + 7, 1, 4, 7 }; + const int vals_9481[16] = { 10, 6, 6, 10, + 10, 6, 6, 10, + 10, 6, 6, 10, + 10, 6, 6, 10 }; + switch (phydev->drv->phy_id) { + case MTK_GPHY_ID_MT7981: + /* We add some calibration to efuse values + * due to board level influence. + * GBE: +7, TBT: +1, HBT: +4, TST: +7 + */ + memcpy(bias, (const void *)vals_9461, sizeof(bias)); + break; + case MTK_GPHY_ID_MT7988: + memcpy(bias, (const void *)vals_9481, sizeof(bias)); + break; + } + + /* Prevent overflow */ + for (i = 0; i < 12; i++) { + if (buf[i >> 2] + bias[i] > 63) { + buf[i >> 2] = 63; + bias[i] = 0; + } + } + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, + MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, + MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, + MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, + MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, + MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, + MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, + MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, + MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, + MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, + MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, + MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, + MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, + MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, + MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, + MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, + MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]); + + return 0; +} + +static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 tx_amp_cal_val[4]; + + tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]); + tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]); + tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]); + tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]); + tx_amp_fill_result(phydev, tx_amp_cal_val); + + return 0; +} + +static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, + u8 txg_calen_x) +{ + int bias = 0; + u16 reg, val; + + if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) + bias = -2; + + val = clamp_val(bias + tx_r50_cal_val, 0, 63); + + switch (txg_calen_x) { + case PAIR_A: + reg = MTK_PHY_DA_TX_R50_PAIR_A; + break; + case PAIR_B: + reg = MTK_PHY_DA_TX_R50_PAIR_B; + break; + case PAIR_C: + reg = MTK_PHY_DA_TX_R50_PAIR_C; + break; + case PAIR_D: + reg = MTK_PHY_DA_TX_R50_PAIR_D; + break; + default: + return -EINVAL; + } + + phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8); + + return 0; +} + +static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf, + u8 txg_calen_x) +{ + u16 tx_r50_cal_val; + + switch (txg_calen_x) { + case PAIR_A: + tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]); + break; + case PAIR_B: + tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]); + break; + case PAIR_C: + tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]); + break; + case PAIR_D: + tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]); + break; + default: + return -EINVAL; + } + tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); + + return 0; +} + +static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x) +{ + u8 lower_idx, upper_idx, txreserve_val; + u8 lower_ret, upper_ret; + int ret; + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ANA_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_CAL_CKINV); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_TXVOS_CALEN); + + switch (rg_txreserve_x) { + case PAIR_A: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_A, + MTK_PHY_DASN_DAC_IN0_A_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_A, + MTK_PHY_DASN_DAC_IN1_A_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ZCALEN_A); + break; + case PAIR_B: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_B, + MTK_PHY_DASN_DAC_IN0_B_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_B, + MTK_PHY_DASN_DAC_IN1_B_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_B); + break; + case PAIR_C: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_C, + MTK_PHY_DASN_DAC_IN0_C_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_C, + MTK_PHY_DASN_DAC_IN1_C_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_C); + break; + case PAIR_D: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_D, + MTK_PHY_DASN_DAC_IN0_D_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_D, + MTK_PHY_DASN_DAC_IN1_D_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_D); + break; + default: + ret = -EINVAL; + goto restore; + } + + lower_idx = TXRESERVE_MIN; + upper_idx = TXRESERVE_MAX; + + phydev_dbg(phydev, "Start TX-VCM SW cal.\n"); + while ((upper_idx - lower_idx) > 1) { + txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2); + ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + txreserve_val << 12 | txreserve_val << 8 | + txreserve_val << 4 | txreserve_val); + if (ret == 1) { + upper_idx = txreserve_val; + upper_ret = ret; + } else if (ret == 0) { + lower_idx = txreserve_val; + lower_ret = ret; + } else { + goto restore; + } + } + + if (lower_idx == TXRESERVE_MIN) { + lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, + MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + lower_idx << 12 | lower_idx << 8 | + lower_idx << 4 | lower_idx); + ret = lower_ret; + } else if (upper_idx == TXRESERVE_MAX) { + upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, + MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + upper_idx << 12 | upper_idx << 8 | + upper_idx << 4 | upper_idx); + ret = upper_ret; + } + if (ret < 0) + goto restore; + + /* We calibrate TX-VCM in different logic. Check upper index and then + * lower index. If this calibration is valid, apply lower index's result. + */ + ret = upper_ret - lower_ret; + if (ret == 1) { + ret = 0; + /* Make sure we use upper_idx in our calibration system */ + cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + upper_idx << 12 | upper_idx << 8 | + upper_idx << 4 | upper_idx); + phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx); + } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 && + lower_ret == 1) { + ret = 0; + cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + lower_idx << 12 | lower_idx << 8 | + lower_idx << 4 | lower_idx); + phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n", + lower_idx); + } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && + lower_ret == 0) { + ret = 0; + phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n", + upper_idx); + } else { + ret = -EINVAL; + } + +restore: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ANA_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_TXVOS_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ZCALEN_A); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C | + MTK_PHY_RG_ZCALEN_D); + + return ret; +} + +static void mt798x_phy_common_finetune(struct phy_device *phydev) +{ + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* EnabRandUpdTrig = 1 */ + __phy_write(phydev, 0x11, 0x2f00); + __phy_write(phydev, 0x12, 0xe); + __phy_write(phydev, 0x10, 0x8fb0); + + /* NormMseLoThresh = 85 */ + __phy_write(phydev, 0x11, 0x55a0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x83aa); + + /* TrFreeze = 0 */ + __phy_write(phydev, 0x11, 0x0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9686); + + /* SSTrKp1000Slv = 5 */ + __phy_write(phydev, 0x11, 0xbaef); + __phy_write(phydev, 0x12, 0x2e); + __phy_write(phydev, 0x10, 0x968c); + + /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, + * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 + */ + __phy_write(phydev, 0x11, 0xd10a); + __phy_write(phydev, 0x12, 0x34); + __phy_write(phydev, 0x10, 0x8f82); + + /* VcoSlicerThreshBitsHigh */ + __phy_write(phydev, 0x11, 0x5555); + __phy_write(phydev, 0x12, 0x55); + __phy_write(phydev, 0x10, 0x8ec0); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, + MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, + BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); + + /* rg_tr_lpf_cnt_val = 512 */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); + + /* IIR2 related */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); + + /* FFE peaking */ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, + MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, + MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); + + /* Disable LDO pump */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0); + /* Adjust LDO output voltage */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); +} + +static void mt7981_phy_finetune(struct phy_device *phydev) +{ + u16 val[8] = { 0x01ce, 0x01c1, + 0x020f, 0x0202, + 0x03d0, 0x03c0, + 0x0013, 0x0005 }; + int i, k; + + /* 100M eye finetune: + * Keep middle level of TX MLT3 shapper as default. + * Only change TX MLT3 overshoot level here. + */ + for (k = 0, i = 1; i < 12; i++) { + if (i % 3 == 0) + continue; + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); + } + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ + __phy_write(phydev, 0x11, 0xc71); + __phy_write(phydev, 0x12, 0xc); + __phy_write(phydev, 0x10, 0x8fae); + + /* ResetSyncOffset = 6 */ + __phy_write(phydev, 0x11, 0x600); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8fc0); + + /* VgaDecRate = 1 */ + __phy_write(phydev, 0x11, 0x4c2a); + __phy_write(phydev, 0x12, 0x3e); + __phy_write(phydev, 0x10, 0x8fa4); + + /* FfeUpdGainForce = 4 */ + __phy_write(phydev, 0x11, 0x240); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9680); + + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); +} + +static void mt7988_phy_finetune(struct phy_device *phydev) +{ + u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, + 0x020d, 0x0206, 0x0384, 0x03d0, + 0x03c6, 0x030a, 0x0011, 0x0005 }; + int i; + + /* Set default MLT3 shaper first */ + for (i = 0; i < 12; i++) + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]); + + /* TCT finetune */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); + + /* Disable TX power saving */ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, + MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */ + __phy_write(phydev, 0x11, 0x671); + __phy_write(phydev, 0x12, 0xc); + __phy_write(phydev, 0x10, 0x8fae); + + /* ResetSyncOffset = 5 */ + __phy_write(phydev, 0x11, 0x500); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8fc0); + + /* VgaDecRate is 1 at default on mt7988 */ + + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); + /* TxClkOffset = 2 */ + __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, + FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); +} + +static void mt798x_phy_eee(struct phy_device *phydev) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120, + MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK | + MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) | + FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, + MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + 0xff)); + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_TESTMUX_ADC_CTRL, + MTK_PHY_RG_TXEN_DIG_MASK); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY); + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238, + MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK | + MTK_PHY_LPI_SLV_SEND_TX_EN, + FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, + MTK_PHY_LPI_SEND_LOC_TIMER_MASK | + MTK_PHY_LPI_TXPCS_LOC_RCV, + FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, + MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, + FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | + FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1, + MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, + FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, + 0x33) | + MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY | + MTK_PHY_LPI_VCO_EEE_STG0_EN); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323, + MTK_PHY_EEE_WAKE_MAS_INT_DC | + MTK_PHY_EEE_WAKE_SLV_INT_DC); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324, + MTK_PHY_SMI_DETCNT_MAX_MASK, + FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) | + MTK_PHY_SMI_DET_MAX_EN); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326, + MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT | + MTK_PHY_TREC_UPDATE_ENAB_CLR | + MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF | + MTK_PHY_TR_READY_SKIP_AFE_WAKEUP); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* Regsigdet_sel_1000 = 0 */ + __phy_write(phydev, 0x11, 0xb); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9690); + + /* REG_EEE_st2TrKf1000 = 3 */ + __phy_write(phydev, 0x11, 0x114f); + __phy_write(phydev, 0x12, 0x2); + __phy_write(phydev, 0x10, 0x969a); + + /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */ + __phy_write(phydev, 0x11, 0x3028); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x969e); + + /* RegEEE_slv_wake_int_timer_tar = 8 */ + __phy_write(phydev, 0x11, 0x5010); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96a0); + + /* RegEEE_trfreeze_timer2 = 586 */ + __phy_write(phydev, 0x11, 0x24a); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96a8); + + /* RegEEE100Stg1_tar = 16 */ + __phy_write(phydev, 0x11, 0x3210); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96b8); + + /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */ + __phy_write(phydev, 0x11, 0x1463); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96ca); + + /* DfeTailEnableVgaThresh1000 = 27 */ + __phy_write(phydev, 0x11, 0x36); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8f80); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); + __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK, + FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c)); + + __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK, + FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc)); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, + MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff)); +} + +static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, + u8 start_pair, u8 end_pair) +{ + u8 pair_n; + int ret; + + for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { + /* TX_OFFSET & TX_AMP have no SW calibration. */ + switch (cal_item) { + case TX_VCM: + ret = tx_vcm_cal_sw(phydev, pair_n); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + } + return 0; +} + +static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item, + u8 start_pair, u8 end_pair, u32 *buf) +{ + u8 pair_n; + int ret; + + for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { + /* TX_VCM has no efuse calibration. */ + switch (cal_item) { + case REXT: + ret = rext_cal_efuse(phydev, buf); + break; + case TX_OFFSET: + ret = tx_offset_cal_efuse(phydev, buf); + break; + case TX_AMP: + ret = tx_amp_cal_efuse(phydev, buf); + break; + case TX_R50: + ret = tx_r50_cal_efuse(phydev, buf, pair_n); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + } + + return 0; +} + +static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item, + enum CAL_MODE cal_mode, u8 start_pair, + u8 end_pair, u32 *buf) +{ + int ret; + + switch (cal_mode) { + case EFUSE_M: + ret = cal_efuse(phydev, cal_item, start_pair, + end_pair, buf); + break; + case SW_M: + ret = cal_sw(phydev, cal_item, start_pair, end_pair); + break; + default: + return -EINVAL; + } + + if (ret) { + phydev_err(phydev, "cal %d failed\n", cal_item); + return -EIO; + } + + return 0; +} + +static int mt798x_phy_calibration(struct phy_device *phydev) +{ + int ret = 0; + u32 *buf; + size_t len; + struct nvmem_cell *cell; + + cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); + if (IS_ERR(cell)) { + if (PTR_ERR(cell) == -EPROBE_DEFER) + return PTR_ERR(cell); + return 0; + } + + buf = (u32 *)nvmem_cell_read(cell, &len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + nvmem_cell_put(cell); + + if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { + phydev_err(phydev, "invalid efuse data\n"); + ret = -EINVAL; + goto out; + } + + ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf); + if (ret) + goto out; + +out: + kfree(buf); + return ret; +} + +static int mt798x_phy_config_init(struct phy_device *phydev) +{ + switch (phydev->drv->phy_id) { + case MTK_GPHY_ID_MT7981: + mt7981_phy_finetune(phydev); + break; + case MTK_GPHY_ID_MT7988: + mt7988_phy_finetune(phydev); + break; + } + + mt798x_phy_common_finetune(phydev); + mt798x_phy_eee(phydev); + + return mt798x_phy_calibration(phydev); +} + +static int mt7988_phy_setup_led(struct phy_device *phydev) +{ + struct mtk_socphy_shared_priv *priv = phydev->shared->priv; + int port = phydev->mdio.addr; + u32 reg = priv->boottrap; + struct pinctrl *pinctrl; + + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_POLARITY | + MTK_PHY_LED0_ON_LINK10 | + MTK_PHY_LED0_ON_LINK100 | + MTK_PHY_LED0_ON_LINK1000); + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL, + MTK_PHY_LED1_ENABLE | MTK_PHY_LED1_POLARITY | + MTK_PHY_LED1_ON_LINK10 | + MTK_PHY_LED1_ON_LINK100 | + MTK_PHY_LED1_ON_LINK1000); + + if ((port == GPHY_PORT0 && reg & BIT(8)) || + (port == GPHY_PORT1 && reg & BIT(9)) || + (port == GPHY_PORT2 && reg & BIT(10)) || + (port == GPHY_PORT3 && reg & BIT(11))) { + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED0_POLARITY); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL, + MTK_PHY_LED1_POLARITY); + } + + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL, + MTK_PHY_LED0_1000TX | MTK_PHY_LED0_1000RX | + MTK_PHY_LED0_100TX | MTK_PHY_LED0_100RX | + MTK_PHY_LED0_10TX | MTK_PHY_LED0_10RX); + phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_BLINK_CTRL, + MTK_PHY_LED1_1000TX | MTK_PHY_LED1_1000RX | + MTK_PHY_LED1_100TX | MTK_PHY_LED1_100RX | + MTK_PHY_LED1_10TX | MTK_PHY_LED1_10RX); + + pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led"); + if (IS_ERR(pinctrl)) { + dev_err(&phydev->mdio.bus->dev, "Failed to setup LED pins\n"); + return PTR_ERR(pinctrl); + } + + return 0; +} + +static int mt7988_phy_probe_shared(struct phy_device *phydev) +{ + struct mtk_socphy_shared_priv *priv = phydev->shared->priv; + void __iomem *boottrap; + struct device_node *np; + u32 reg; + + np = of_find_compatible_node(NULL, NULL, "mediatek,boottrap"); + if (!np) + return -ENOENT; + + boottrap = of_iomap(np, 0); + if (!boottrap) + return -ENOMEM; + + reg = readl(boottrap); + iounmap(boottrap); + + priv->boottrap = reg; + + return 0; +} + +static int mt7981_phy_probe(struct phy_device *phydev) +{ + return mt798x_phy_calibration(phydev); +} + +static int mt7988_phy_probe(struct phy_device *phydev) +{ + int err; + + err = devm_phy_package_join(&phydev->mdio.dev, phydev, 0, + sizeof(struct mtk_socphy_shared_priv)); + if (err) + return err; + + if (phy_package_probe_once(phydev)) { + err = mt7988_phy_probe_shared(phydev); + if (err) + return err; + } + + mt7988_phy_setup_led(phydev); + + return mt798x_phy_calibration(phydev); +} + +static struct phy_driver mtk_socphy_driver[] = { + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), + .name = "MediaTek MT7981 PHY", + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, + .probe = mt7981_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, + }, + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), + .name = "MediaTek MT7988 PHY", + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, + .probe = mt7988_phy_probe, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, + }, +}; + +module_phy_driver(mtk_socphy_driver); + +static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { + { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, + { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, + { } +}; + +MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver"); +MODULE_AUTHOR("Daniel Golle "); +MODULE_AUTHOR("SkyLake Huang "); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl); diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 134afb63f9e..e6ab85fb5d1 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -205,7 +205,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y CONFIG_MEDIATEK_GE_PHY=y -CONFIG_MEDIATEK_GE_PHY_SOC=y +CONFIG_MEDIATEK_GE_SOC_PHY=y CONFIG_MEDIATEK_WATCHDOG=y CONFIG_MEMFD_CREATE=y CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 2de14752b46..d584497ec19 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -226,7 +226,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y CONFIG_MEDIATEK_GE_PHY=y -# CONFIG_MEDIATEK_GE_PHY_SOC is not set +# CONFIG_MEDIATEK_GE_SOC_PHY is not set CONFIG_MEDIATEK_WATCHDOG=y CONFIG_MEMFD_CREATE=y CONFIG_MESSAGE_LOGLEVEL_DEFAULT=7 diff --git a/target/linux/mediatek/patches-5.15/730-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch b/target/linux/mediatek/patches-5.15/730-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch index 4e462881c2a..b8d1a606191 100644 --- a/target/linux/mediatek/patches-5.15/730-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch +++ b/target/linux/mediatek/patches-5.15/730-net-phy-add-driver-for-MediaTek-SoC-built-in-GE-PHYs.patch @@ -1,23 +1,27 @@ -From a6f143af419bfc3f52d82e88ac033d9833e720af Mon Sep 17 00:00:00 2001 +From 60ed9eb9605656c19ca402b7bd3f47552e901601 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 13 Feb 2023 02:33:14 +0000 Subject: [PATCH] net: phy: add driver for MediaTek SoC built-in GE PHYs Some of MediaTek's Filogic SoCs come with built-in gigabit Ethernet PHYs which require calibration data from the SoC's efuse. -Add support for these PHYs to the mediatek-ge driver if built for -MediaTek's ARM64 SoCs. +Despite the similar design the driver doesn't share any code with the +existing mediatek-ge.c, so add support for these PHYs by introducing a +new driver for only MediaTek's ARM64 SoCs. Signed-off-by: Daniel Golle --- - MAINTAINERS | 8 + - drivers/net/phy/Kconfig | 12 + - drivers/net/phy/mediatek-ge.c | 1351 +++++++++++++++++++++++++++++++++ - 3 files changed, 1371 insertions(+) + MAINTAINERS | 9 + + drivers/net/phy/Kconfig | 12 + + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mediatek-ge-soc.c | 1263 +++++++++++++++++++++++++++++ + drivers/net/phy/mediatek-ge.c | 3 +- + 5 files changed, 1287 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/phy/mediatek-ge-soc.c --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -11797,6 +11797,14 @@ S: Maintained +@@ -11797,6 +11797,15 @@ S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c F: include/linux/pcs/pcs-mtk-lynxi.h @@ -27,6 +31,7 @@ Signed-off-by: Daniel Golle +M: SkyLake Huang +L: netdev@vger.kernel.org +S: Maintained ++F: drivers/net/phy/mediatek-ge-soc.c +F: drivers/net/phy/mediatek-ge.c + MEDIATEK I2C CONTROLLER DRIVER @@ -38,9 +43,9 @@ Signed-off-by: Daniel Golle help Supports the MediaTek Gigabit Ethernet PHYs. -+config MEDIATEK_GE_PHY_SOC -+ bool "MediaTek SoC Ethernet PHYs" -+ depends on (ARM64 && ARCH_MEDIATEK && MEDIATEK_GE_PHY) || COMPILE_TEST ++config MEDIATEK_GE_SOC_PHY ++ tristate "MediaTek SoC Ethernet PHYs" ++ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST + select NVMEM_MTK_EFUSE + help + Supports MediaTek SoC built-in Gigabit Ethernet PHYs. @@ -53,1391 +58,25 @@ Signed-off-by: Daniel Golle config MICREL_PHY tristate "Micrel PHYs" help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -81,6 +81,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o + obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o + obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o + obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o ++obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o + obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o + obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o + obj-$(CONFIG_MICREL_PHY) += micrel.o --- a/drivers/net/phy/mediatek-ge.c +++ b/drivers/net/phy/mediatek-ge.c -@@ -2,6 +2,9 @@ - #include - #include - #include -+#include -+#include -+#include - #include - - #define MTK_EXT_PAGE_ACCESS 0x1f -@@ -12,6 +15,275 @@ - #define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 - #define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 - -+#define ANALOG_INTERNAL_OPERATION_MAX_US (20) -+#define ZCAL_CTRL_MIN (0) -+#define ZCAL_CTRL_MAX (63) -+#define TXRESERVE_MIN (0) -+#define TXRESERVE_MAX (7) -+ -+#define MTK_PHY_ANARG_RG (0x10) -+#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8) -+ -+/* Registers on MDIO_MMD_VEND1 */ -+enum { -+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_0TO1 = 0, -+ MTK_PHY_1st_OVERSHOOT_LEVEL_0TO1, -+ MTK_PHY_2nd_OVERSHOOT_LEVEL_0TO1, -+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_1TO0, -+ MTK_PHY_1st_OVERSHOOT_LEVEL_1TO0, -+ MTK_PHY_2nd_OVERSHOOT_LEVEL_1TO0, -+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_0TON1, /* N means negative */ -+ MTK_PHY_1st_OVERSHOOT_LEVEL_0TON1, -+ MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1, -+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_N1TO0, -+ MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0, -+ MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0, -+ MTK_PHY_TX_MLT3_END, -+}; -+ -+#define MTK_PHY_TXVLD_DA_RG (0x12) -+#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10) -+#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 (0x16) -+#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10) -+#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 (0x17) -+#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 (0x18) -+#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 (0x19) -+#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 (0x20) -+#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 (0x21) -+#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 (0x22) -+#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8) -+#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_TANA_CAL_MODE (0xc1) -+#define MTK_PHY_TANA_CAL_MODE_SHIFT (8) -+ -+#define MTK_PHY_RXADC_CTRL_RG7 (0xc6) -+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) -+ -+#define MTK_PHY_RXADC_CTRL_RG9 (0xc8) -+#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12) -+#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8) -+#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4) -+#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0) -+ -+#define MTK_PHY_LDO_OUTPUT_V (0xd7) -+ -+#define MTK_PHY_RG_ANA_CAL_RG0 (0xdb) -+#define MTK_PHY_RG_CAL_CKINV BIT(12) -+#define MTK_PHY_RG_ANA_CALEN BIT(8) -+#define MTK_PHY_RG_REXT_CALEN BIT(4) -+#define MTK_PHY_RG_ZCALEN_A BIT(0) -+ -+#define MTK_PHY_RG_ANA_CAL_RG1 (0xdc) -+#define MTK_PHY_RG_ZCALEN_B BIT(12) -+#define MTK_PHY_RG_ZCALEN_C BIT(8) -+#define MTK_PHY_RG_ZCALEN_D BIT(4) -+#define MTK_PHY_RG_TXVOS_CALEN BIT(0) -+ -+#define MTK_PHY_RG_ANA_CAL_RG2 (0xdd) -+#define MTK_PHY_RG_TXG_CALEN_A BIT(12) -+#define MTK_PHY_RG_TXG_CALEN_B BIT(8) -+#define MTK_PHY_RG_TXG_CALEN_C BIT(4) -+#define MTK_PHY_RG_TXG_CALEN_D BIT(0) -+ -+#define MTK_PHY_RG_ANA_CAL_RG5 (0xe0) -+#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8) -+#define MTK_PHY_RG_ZCAL_CTRL_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_RG_TX_FILTER (0xfe) -+ -+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B (0x172) -+#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8) -+#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0) -+ -+#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D (0x173) -+#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8) -+#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) -+ -+#define MTK_PHY_RG_AD_CAL_COMP (0x17a) -+#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8) -+ -+#define MTK_PHY_RG_AD_CAL_CLK (0x17b) -+#define MTK_PHY_DA_CAL_CLK BIT(0) -+ -+#define MTK_PHY_RG_AD_CALIN (0x17c) -+#define MTK_PHY_DA_CALIN_FLAG BIT(0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_A (0x17d) -+#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_B (0x17e) -+#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_C (0x17f) -+#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN0_D (0x180) -+#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_A (0x181) -+#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_B (0x182) -+#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_C (0x183) -+#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_DASN_DAC_IN1_D (0x180) -+#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0) -+ -+#define MTK_PHY_RG_LP_IIR2_K1_L (0x22a) -+#define MTK_PHY_RG_LP_IIR2_K1_U (0x22b) -+#define MTK_PHY_RG_LP_IIR2_K2_L (0x22c) -+#define MTK_PHY_RG_LP_IIR2_K2_U (0x22d) -+#define MTK_PHY_RG_LP_IIR2_K3_L (0x22e) -+#define MTK_PHY_RG_LP_IIR2_K3_U (0x22f) -+#define MTK_PHY_RG_LP_IIR2_K4_L (0x230) -+#define MTK_PHY_RG_LP_IIR2_K4_U (0x231) -+#define MTK_PHY_RG_LP_IIR2_K5_L (0x232) -+#define MTK_PHY_RG_LP_IIR2_K5_U (0x233) -+ -+#define MTK_PHY_RG_DEV1E_REG234 (0x234) -+#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0) -+#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4) -+ -+#define MTK_PHY_RG_LPF_CNT_VAL (0x235) -+ -+#define MTK_PHY_RG_DEV1E_REG27C (0x27c) -+#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8) -+#define MTK_PHY_RG_DEV1E_REG27D (0x27d) -+#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0) -+ -+#define MTK_PHY_LDO_PUMP_EN_PAIRAB (0x502) -+#define MTK_PHY_LDO_PUMP_EN_PAIRCD (0x503) -+ -+#define MTK_PHY_DA_TX_R50_PAIR_A (0x53d) -+#define MTK_PHY_DA_TX_R50_PAIR_B (0x53e) -+#define MTK_PHY_DA_TX_R50_PAIR_C (0x53f) -+#define MTK_PHY_DA_TX_R50_PAIR_D (0x540) -+ -+/* Registers on MDIO_MMD_VEND2 */ -+#define MTK_PHY_LED0_ON_CTRL (0x24) -+#define MTK_PHY_LED0_ON_MASK GENMASK(6, 0) -+#define MTK_PHY_LED0_ON_LINK1000 BIT(0) -+#define MTK_PHY_LED0_ON_LINK100 BIT(1) -+#define MTK_PHY_LED0_ON_LINK10 BIT(2) -+#define MTK_PHY_LED0_ON_LINKDOWN BIT(3) -+#define MTK_PHY_LED0_ON_FDX BIT(4) /* Full duplex */ -+#define MTK_PHY_LED0_ON_HDX BIT(5) /* Half duplex */ -+#define MTK_PHY_LED0_FORCE_ON BIT(6) -+#define MTK_PHY_LED0_POLARITY BIT(14) -+#define MTK_PHY_LED0_ENABLE BIT(15) -+ -+#define MTK_PHY_LED0_BLINK_CTRL (0x25) -+#define MTK_PHY_LED0_1000TX BIT(0) -+#define MTK_PHY_LED0_1000RX BIT(1) -+#define MTK_PHY_LED0_100TX BIT(2) -+#define MTK_PHY_LED0_100RX BIT(3) -+#define MTK_PHY_LED0_10TX BIT(4) -+#define MTK_PHY_LED0_10RX BIT(5) -+#define MTK_PHY_LED0_COLLISION BIT(6) -+#define MTK_PHY_LED0_RX_CRC_ERR BIT(7) -+#define MTK_PHY_LED0_RX_IDLE_ERR BIT(8) -+#define MTK_PHY_LED0_FORCE_BLINK BIT(9) -+ -+#define MTK_PHY_ANA_TEST_BUS_CTRL_RG (0x100) -+#define MTK_PHY_ANA_TEST_MODE_MASK GENMASK(15, 8) -+ -+#define MTK_PHY_RG_DASN_TXT_DMY2 (0x110) -+#define MTK_PHY_TST_DMY2_MASK GENMASK(5, 0) -+ -+#define MTK_PHY_RG_BG_RASEL (0x115) -+#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) -+ -+/* These macro privides efuse parsing for internal phy. */ -+#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) -+#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) -+#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0)) -+#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0)) -+#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0)) -+ -+#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0)) -+#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0)) -+#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0)) -+ -+#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_A_10M(x) (((x) >> 12) & GENMASK(5, 0)) -+#define EFS_DA_TX_R50_B_10M(x) (((x) >> 18) & GENMASK(5, 0)) -+ -+#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0)) -+#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0)) -+ -+enum { -+ NO_PAIR, -+ PAIR_A, -+ PAIR_B, -+ PAIR_C, -+ PAIR_D, -+}; -+ -+enum { -+ GPHY_PORT0, -+ GPHY_PORT1, -+ GPHY_PORT2, -+ GPHY_PORT3, -+}; -+ -+enum calibration_mode { -+ EFUSE_K, -+ SW_K -+}; -+ -+enum CAL_ITEM { -+ REXT, -+ TX_OFFSET, -+ TX_AMP, -+ TX_R50, -+ TX_VCM -+}; -+ -+enum CAL_MODE { -+ SW_EFUSE_M, -+ EFUSE_M, -+ SW_M -+}; -+ -+const u8 mt798x_zcal_to_r50[64] = { -+ 7, 8, 9, 9, 10, 10, 11, 11, -+ 12, 13, 13, 14, 14, 15, 16, 16, -+ 17, 18, 18, 19, 20, 21, 21, 22, -+ 23, 24, 24, 25, 26, 27, 28, 29, -+ 30, 31, 32, 33, 34, 35, 36, 37, -+ 38, 40, 41, 42, 43, 45, 46, 48, -+ 49, 51, 52, 54, 55, 57, 59, 61, -+ 62, 63, 63, 63, 63, 63, 63, 63 -+}; -+ -+const char pair[4] = {'A', 'B', 'C', 'D'}; -+ - static int mtk_gephy_read_page(struct phy_device *phydev) - { - return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); -@@ -102,6 +374,1059 @@ static int mt7531_phy_config_init(struct - return 0; - } - -+#ifdef CONFIG_MEDIATEK_GE_PHY_SOC -+/* One calibration cycle consists of: -+ * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high -+ * until AD_CAL_COMP is ready to output calibration result. -+ * 2.Wait until DA_CAL_CLK is available. -+ * 3.Fetch AD_CAL_COMP_OUT. -+ */ -+static int cal_cycle(struct phy_device *phydev, int devad, -+ u32 regnum, u16 mask, u16 cal_val) -+{ -+ unsigned long timeout; -+ int reg_val; -+ int ret; -+ -+ phy_modify_mmd(phydev, devad, regnum, -+ mask, cal_val); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, -+ MTK_PHY_DA_CALIN_FLAG); -+ -+ timeout = jiffies + usecs_to_jiffies(ANALOG_INTERNAL_OPERATION_MAX_US); -+ do { -+ reg_val = phy_read_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_AD_CAL_CLK); -+ } while (time_before(jiffies, timeout) && !(reg_val & BIT(0))); -+ -+ if (!(reg_val & BIT(0))) { -+ dev_err(&phydev->mdio.dev, "Calibration cycle timeout\n"); -+ return -ETIMEDOUT; -+ } -+ -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, -+ MTK_PHY_DA_CALIN_FLAG); -+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >> -+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT; -+ dev_dbg(&phydev->mdio.dev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); -+ -+ return ret; -+} -+ -+static int rext_fill_result(struct phy_device *phydev, u16 *buf) -+{ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL, -+ MTK_PHY_RG_BG_RASEL_MASK, buf[1]); -+ -+ return 0; -+} -+ -+static int rext_cal_efuse(struct phy_device *phydev, u32 *buf) -+{ -+ u16 rext_cal_val[2]; -+ -+ rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]); -+ rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]); -+ rext_fill_result(phydev, rext_cal_val); -+ -+ return 0; -+} -+ -+static int rext_cal_sw(struct phy_device *phydev) -+{ -+ u8 rg_zcal_ctrl_def; -+ u8 zcal_lower, zcal_upper, rg_zcal_ctrl; -+ u8 lower_ret, upper_ret; -+ u16 rext_cal_val[2]; -+ int ret; -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_ANA_TEST_BUS_CTRL_RG, -+ MTK_PHY_ANA_TEST_MODE_MASK, MTK_PHY_TANA_CAL_MODE << 8); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_TXVOS_CALEN); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN | -+ MTK_PHY_RG_REXT_CALEN); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_DASN_TXT_DMY2, -+ MTK_PHY_TST_DMY2_MASK, 0x1); -+ -+ rg_zcal_ctrl_def = phy_read_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG5) & -+ MTK_PHY_RG_ZCAL_CTRL_MASK; -+ zcal_lower = ZCAL_CTRL_MIN; -+ zcal_upper = ZCAL_CTRL_MAX; -+ -+ dev_dbg(&phydev->mdio.dev, "Start REXT SW cal.\n"); -+ while ((zcal_upper - zcal_lower) > 1) { -+ rg_zcal_ctrl = DIV_ROUND_CLOSEST(zcal_lower + zcal_upper, 2); -+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, rg_zcal_ctrl); -+ if (ret == 1) { -+ zcal_upper = rg_zcal_ctrl; -+ upper_ret = ret; -+ } else if (ret == 0) { -+ zcal_lower = rg_zcal_ctrl; -+ lower_ret = ret; -+ } else { -+ goto restore; -+ } -+ } -+ -+ if (zcal_lower == ZCAL_CTRL_MIN) { -+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, zcal_lower); -+ ret = lower_ret; -+ } else if (zcal_upper == ZCAL_CTRL_MAX) { -+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, zcal_upper); -+ ret = upper_ret; -+ } -+ if (ret < 0) -+ goto restore; -+ -+ ret = upper_ret - lower_ret; -+ if (ret == 1) { -+ rext_cal_val[0] = zcal_upper; -+ rext_cal_val[1] = zcal_upper >> 3; -+ rext_fill_result(phydev, rext_cal_val); -+ dev_info(&phydev->mdio.dev, "REXT SW cal result: 0x%x\n", -+ zcal_upper); -+ ret = 0; -+ } else { -+ ret = -EINVAL; -+ } -+ -+restore: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, -+ MTK_PHY_ANA_TEST_BUS_CTRL_RG, -+ MTK_PHY_ANA_TEST_MODE_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN | -+ MTK_PHY_RG_REXT_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_DASN_TXT_DMY2, -+ MTK_PHY_TST_DMY2_MASK); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, rg_zcal_ctrl_def); -+ -+ return ret; -+} -+ -+static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf) -+{ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, -+ MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, -+ MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, -+ MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, -+ MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]); -+ -+ return 0; -+} -+ -+static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf) -+{ -+ u16 tx_offset_cal_val[4]; -+ -+ tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]); -+ tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]); -+ tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]); -+ tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]); -+ -+ tx_offset_fill_result(phydev, tx_offset_cal_val); -+ -+ return 0; -+} -+ -+static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) -+{ -+ int i; -+ int bias[16] = {0}; -+ const int vals_9461[16] = { 7, 1, 4, 7, -+ 7, 1, 4, 7, -+ 7, 1, 4, 7, -+ 7, 1, 4, 7 }; -+ const int vals_9481[16] = { 10, 6, 6, 10, -+ 10, 6, 6, 10, -+ 10, 6, 6, 10, -+ 10, 6, 6, 10 }; -+ -+ switch (phydev->drv->phy_id) { -+ case 0x03a29461: -+ /* We add some calibration to efuse values -+ * due to board level influence. -+ * GBE: +7, TBT: +1, HBT: +4, TST: +7 -+ */ -+ memcpy(bias, (const void *)vals_9461, sizeof(bias)); -+ for (i = 0; i <= 12; i += 4) { -+ if (likely(buf[i >> 2] + bias[i] >= 32)) { -+ bias[i] -= 13; -+ } else { -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, -+ 0x5c, 0x7 << i, bias[i] << i); -+ bias[i + 1] += 13; -+ bias[i + 2] += 13; -+ bias[i + 3] += 13; -+ } -+ } -+ break; -+ case 0x03a29481: -+ memcpy(bias, (const void *)vals_9481, sizeof(bias)); -+ break; -+ default: -+ break; -+ } -+ -+ /* Prevent overflow */ -+ for (i = 0; i < 12; i++) { -+ if (buf[i >> 2] + bias[i] > 63) { -+ buf[i >> 2] = 63; -+ bias[i] = 0; -+ } else if (buf[i >> 2] + bias[i] < 0) { -+ /* Bias caused by board design may change in the future. -+ * So check negative cases, too. -+ */ -+ buf[i >> 2] = 0; -+ bias[i] = 0; -+ } -+ } -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, -+ MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -+ MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -+ MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -+ MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -+ MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -+ MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]); -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -+ MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -+ MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]); -+ -+ return 0; -+} -+ -+static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf) -+{ -+ u16 tx_amp_cal_val[4]; -+ -+ tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]); -+ tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]); -+ tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]); -+ tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]); -+ tx_amp_fill_result(phydev, tx_amp_cal_val); -+ -+ return 0; -+} -+ -+static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, -+ u8 txg_calen_x) -+{ -+ int bias = 0; -+ u16 reg, val; -+ -+ switch (phydev->drv->phy_id) { -+ case 0x03a29481: -+ { -+ bias = -2; -+ break; -+ } -+ /* 0x03a29461 enters default case */ -+ default: -+ break; -+ } -+ -+ val = clamp_val(bias + tx_r50_cal_val, 0, 63); -+ -+ switch (txg_calen_x) { -+ case PAIR_A: -+ reg = MTK_PHY_DA_TX_R50_PAIR_A; -+ break; -+ case PAIR_B: -+ reg = MTK_PHY_DA_TX_R50_PAIR_B; -+ break; -+ case PAIR_C: -+ reg = MTK_PHY_DA_TX_R50_PAIR_C; -+ break; -+ case PAIR_D: -+ reg = MTK_PHY_DA_TX_R50_PAIR_D; -+ break; -+ } -+ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8); -+ -+ return 0; -+} -+ -+static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf, -+ u8 txg_calen_x) -+{ -+ u16 tx_r50_cal_val; -+ -+ switch (txg_calen_x) { -+ case PAIR_A: -+ tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]); -+ break; -+ case PAIR_B: -+ tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]); -+ break; -+ case PAIR_C: -+ tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]); -+ break; -+ case PAIR_D: -+ tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]); -+ break; -+ } -+ tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); -+ -+ return 0; -+} -+ -+static int tx_r50_cal_sw(struct phy_device *phydev, u8 txg_calen_x) -+{ -+ u8 zcal_lower, zcal_upper, rg_zcal_ctrl; -+ u8 lower_ret, upper_ret; -+ u8 rg_zcal_ctrl_def; -+ u16 tx_r50_cal_val; -+ int ret; -+ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_ANA_TEST_BUS_CTRL_RG, -+ MTK_PHY_ANA_TEST_MODE_MASK, MTK_PHY_TANA_CAL_MODE << 8); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_TXVOS_CALEN); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG2, -+ BIT(txg_calen_x * 4)); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_DASN_TXT_DMY2, -+ MTK_PHY_TST_DMY2_MASK, 0x1); -+ -+ rg_zcal_ctrl_def = phy_read_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG5) & -+ MTK_PHY_RG_ZCAL_CTRL_MASK; -+ zcal_lower = ZCAL_CTRL_MIN; -+ zcal_upper = ZCAL_CTRL_MAX; -+ -+ dev_dbg(&phydev->mdio.dev, "Start TX-R50 Pair%c SW cal.\n", -+ pair[txg_calen_x]); -+ while ((zcal_upper - zcal_lower) > 1) { -+ rg_zcal_ctrl = DIV_ROUND_CLOSEST(zcal_lower + zcal_upper, 2); -+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, rg_zcal_ctrl); -+ if (ret == 1) { -+ zcal_upper = rg_zcal_ctrl; -+ upper_ret = ret; -+ } else if (ret == 0) { -+ zcal_lower = rg_zcal_ctrl; -+ lower_ret = ret; -+ } else { -+ goto restore; -+ } -+ } -+ -+ if (zcal_lower == ZCAL_CTRL_MIN) { -+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, zcal_lower); -+ ret = lower_ret; -+ } else if (zcal_upper == ZCAL_CTRL_MAX) { -+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, zcal_upper); -+ ret = upper_ret; -+ } -+ if (ret < 0) -+ goto restore; -+ -+ ret = upper_ret - lower_ret; -+ if (ret == 1) { -+ tx_r50_cal_val = mt798x_zcal_to_r50[zcal_upper]; -+ tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); -+ dev_info(&phydev->mdio.dev, -+ "TX-R50 Pair%c SW cal result: 0x%x\n", -+ pair[txg_calen_x], zcal_lower); -+ ret = 0; -+ } else { -+ ret = -EINVAL; -+ } -+ -+restore: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_ANA_TEST_BUS_CTRL_RG, -+ MTK_PHY_ANA_TEST_MODE_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_CAL_CKINV | MTK_PHY_RG_ANA_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG2, -+ BIT(txg_calen_x * 4)); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_DASN_TXT_DMY2, -+ MTK_PHY_TST_DMY2_MASK); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, -+ MTK_PHY_RG_ZCAL_CTRL_MASK, rg_zcal_ctrl_def); -+ -+ return ret; -+} -+ -+static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x) -+{ -+ u8 lower_idx, upper_idx, txreserve_val; -+ u8 lower_ret, upper_ret; -+ int ret; -+ -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ANA_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_CAL_CKINV); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_TXVOS_CALEN); -+ -+ switch (rg_txreserve_x) { -+ case PAIR_A: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_A, -+ MTK_PHY_DASN_DAC_IN0_A_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_A, -+ MTK_PHY_DASN_DAC_IN1_A_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ZCALEN_A); -+ break; -+ case PAIR_B: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_B, -+ MTK_PHY_DASN_DAC_IN0_B_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_B, -+ MTK_PHY_DASN_DAC_IN1_B_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_B); -+ break; -+ case PAIR_C: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_C, -+ MTK_PHY_DASN_DAC_IN0_C_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_C, -+ MTK_PHY_DASN_DAC_IN1_C_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_C); -+ break; -+ case PAIR_D: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN0_D, -+ MTK_PHY_DASN_DAC_IN0_D_MASK); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_DASN_DAC_IN1_D, -+ MTK_PHY_DASN_DAC_IN1_D_MASK); -+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_D); -+ break; -+ default: -+ ret = -EINVAL; -+ goto restore; -+ } -+ -+ lower_idx = TXRESERVE_MIN; -+ upper_idx = TXRESERVE_MAX; -+ -+ dev_dbg(&phydev->mdio.dev, "Start TX-VCM SW cal.\n"); -+ while ((upper_idx - lower_idx) > 1) { -+ txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2); -+ ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ txreserve_val << 12 | txreserve_val << 8 | -+ txreserve_val << 4 | txreserve_val); -+ if (ret == 1) { -+ upper_idx = txreserve_val; -+ upper_ret = ret; -+ } else if (ret == 0) { -+ lower_idx = txreserve_val; -+ lower_ret = ret; -+ } else { -+ goto restore; -+ } -+ } -+ -+ if (lower_idx == TXRESERVE_MIN) { -+ lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ lower_idx << 12 | lower_idx << 8 | -+ lower_idx << 4 | lower_idx); -+ ret = lower_ret; -+ } else if (upper_idx == TXRESERVE_MAX) { -+ upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, -+ MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ upper_idx << 12 | upper_idx << 8 | -+ upper_idx << 4 | upper_idx); -+ ret = upper_ret; -+ } -+ if (ret < 0) -+ goto restore; -+ -+ /* We calibrate TX-VCM in different logic. Check upper index and then -+ * lower index. If this calibration is valid, apply lower index's result. -+ */ -+ ret = upper_ret - lower_ret; -+ if (ret == 1) { -+ ret = 0; -+ /* Make sure we use upper_idx in our calibration system */ -+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ upper_idx << 12 | upper_idx << 8 | -+ upper_idx << 4 | upper_idx); -+ dev_info(&phydev->mdio.dev, "TX-VCM SW cal result: 0x%x\n", -+ upper_idx); -+ } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 && -+ lower_ret == 1) { -+ ret = 0; -+ cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, -+ MTK_PHY_DA_RX_PSBN_TBT_MASK | -+ MTK_PHY_DA_RX_PSBN_HBT_MASK | -+ MTK_PHY_DA_RX_PSBN_GBE_MASK | -+ MTK_PHY_DA_RX_PSBN_LP_MASK, -+ lower_idx << 12 | lower_idx << 8 | -+ lower_idx << 4 | lower_idx); -+ dev_warn(&phydev->mdio.dev, -+ "TX-VCM SW cal result at low margin 0x%x\n", -+ lower_idx); -+ } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && -+ lower_ret == 0) { -+ ret = 0; -+ dev_warn(&phydev->mdio.dev, -+ "TX-VCM SW cal result at high margin 0x%x\n", -+ upper_idx); -+ } else { -+ ret = -EINVAL; -+ } -+ -+restore: -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ANA_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_TXVOS_CALEN); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, -+ MTK_PHY_RG_ZCALEN_A); -+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, -+ MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C | -+ MTK_PHY_RG_ZCALEN_D); -+ -+ return ret; -+} -+ -+static inline void mt7981_phy_finetune(struct phy_device *phydev) -+{ -+ u32 i; -+ -+ /* 100M eye finetune: -+ * Keep middle level of TX MLT3 shapper as default. -+ * Only change TX MLT3 overshoot level here. -+ */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_0TO1, -+ 0x1ce); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_0TO1, -+ 0x1c1); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_1TO0, -+ 0x20f); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_1TO0, -+ 0x202); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_0TON1, -+ 0x3d0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1, -+ 0x3c0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0, -+ 0x13); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0, -+ 0x5); -+ -+ /* TX-AMP finetune: -+ * 100M +4, 1000M +6 to default value. -+ * If efuse values aren't valid, TX-AMP uses the below values. -+ */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, 0x9824); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, -+ 0x9026); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, -+ 0x2624); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, -+ 0x2426); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, -+ 0x2624); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, -+ 0x2426); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, -+ 0x2624); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, -+ 0x2426); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ /* EnabRandUpdTrig = 1 */ -+ __phy_write(phydev, 0x11, 0x2f00); -+ __phy_write(phydev, 0x12, 0xe); -+ __phy_write(phydev, 0x10, 0x8fb0); -+ -+ /* SlvDSPreadyTime = 0xc */ -+ __phy_write(phydev, 0x11, 0x671); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* NormMseLoThresh = 85 */ -+ __phy_write(phydev, 0x11, 0x55a0); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x83aa); -+ -+ /* InhibitDisableDfeTail1000 = 1 */ -+ __phy_write(phydev, 0x11, 0x2b); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8f80); -+ -+ /* SSTr related */ -+ __phy_write(phydev, 0x11, 0xbaef); -+ __phy_write(phydev, 0x12, 0x2e); -+ __phy_write(phydev, 0x10, 0x968c); -+ -+ /* VcoSlicerThreshBitsHigh */ -+ __phy_write(phydev, 0x11, 0x5555); -+ __phy_write(phydev, 0x12, 0x55); -+ __phy_write(phydev, 0x10, 0x8ec0); -+ -+ /* ResetSyncOffset = 6 */ -+ __phy_write(phydev, 0x11, 0x600); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8fc0); -+ -+ /* VgaDecRate = 1 */ -+ __phy_write(phydev, 0x11, 0x4c2a); -+ __phy_write(phydev, 0x12, 0x3e); -+ __phy_write(phydev, 0x10, 0x8fa4); -+ -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, -+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); -+ -+ /* rg_tr_lpf_cnt_val = 512 */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); -+ -+ /* IIR2 related */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); -+ -+ /* FFE peaking */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, -+ MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, -+ MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); -+ -+ /* TX shape */ -+ /* 10/100/1000 TX shaper is enabled by default */ -+ for (i = 0x202; i < 0x230; i += 2) { -+ if (i == 0x20c || i == 0x218 || i == 0x224) -+ continue; -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, i, 0x2219); -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, i + 1, 0x23); -+ } -+} -+ -+static inline void mt7988_phy_finetune(struct phy_device *phydev) -+{ -+ u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, -+ 0x020d, 0x0206, 0x0384, 0x03d0, -+ 0x03c6, 0x030a, 0x0011, 0x0005 }; -+ int i; -+ -+ for (i = 0; i < MTK_PHY_TX_MLT3_END; i++) -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]); -+ -+ /* TCT finetune */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); -+ -+ /* Disable TX power saving */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, -+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); -+ /* EnabRandUpdTrig = 1 */ -+ __phy_write(phydev, 0x11, 0x2f00); -+ __phy_write(phydev, 0x12, 0xe); -+ __phy_write(phydev, 0x10, 0x8fb0); -+ -+ /* SlvDSPreadyTime = 0xc */ -+ __phy_write(phydev, 0x11, 0x671); -+ __phy_write(phydev, 0x12, 0xc); -+ __phy_write(phydev, 0x10, 0x8fae); -+ -+ /* NormMseLoThresh = 85 */ -+ __phy_write(phydev, 0x11, 0x55a0); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x83aa); -+ -+ /* InhibitDisableDfeTail1000 = 1 */ -+ __phy_write(phydev, 0x11, 0x2b); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8f80); -+ -+ /* SSTr related */ -+ __phy_write(phydev, 0x11, 0xbaef); -+ __phy_write(phydev, 0x12, 0x2e); -+ __phy_write(phydev, 0x10, 0x968c); -+ -+ /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, -+ * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 -+ */ -+ __phy_write(phydev, 0x11, 0xd10a); -+ __phy_write(phydev, 0x12, 0x34); -+ __phy_write(phydev, 0x10, 0x8f82); -+ -+ /* VcoSlicerThreshBitsHigh */ -+ __phy_write(phydev, 0x11, 0x5555); -+ __phy_write(phydev, 0x12, 0x55); -+ __phy_write(phydev, 0x10, 0x8ec0); -+ -+ /* ResetSyncOffset = 5 */ -+ __phy_write(phydev, 0x11, 0x500); -+ __phy_write(phydev, 0x12, 0x0); -+ __phy_write(phydev, 0x10, 0x8fc0); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); -+ /* TxClkOffset = 2 */ -+ __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, -+ FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); -+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); -+ -+ /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, -+ MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, -+ BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); -+ -+ /* rg_tr_lpf_cnt_val = 512 */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); -+ -+ /* IIR2 related */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); -+ -+ /* FFE peaking */ -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, -+ MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); -+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, -+ MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); -+ -+ /* TX shape */ -+ /* 10/100/1000 TX shaper is enabled by default */ -+ for (i = 0x202; i < 0x230; i += 2) { -+ if (i == 0x20c || i == 0x218 || i == 0x224) -+ continue; -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, i, 0x2219); -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, i + 1, 0x23); -+ } -+ -+ /* Disable LDO pump */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0); -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0); -+ -+ /* Adjust LDO output voltage */ -+ phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); -+} -+ -+static inline int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, -+ u8 start_pair, u8 end_pair) -+{ -+ u8 pair_n; -+ int ret; -+ -+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { -+ /* TX_OFFSET & TX_AMP have no SW calibration. */ -+ switch (cal_item) { -+ case REXT: -+ ret = rext_cal_sw(phydev); -+ break; -+ case TX_R50: -+ ret = tx_r50_cal_sw(phydev, pair_n); -+ break; -+ case TX_VCM: -+ ret = tx_vcm_cal_sw(phydev, pair_n); -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (ret) -+ return ret; -+ } -+ return 0; -+} -+ -+static inline int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item, -+ u8 start_pair, u8 end_pair, u32 *buf) -+{ -+ u8 pair_n; -+ int ret; -+ -+ for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { -+ /* TX_VCM has no efuse calibration. */ -+ switch (cal_item) { -+ case REXT: -+ ret = rext_cal_efuse(phydev, buf); -+ break; -+ case TX_OFFSET: -+ ret = tx_offset_cal_efuse(phydev, buf); -+ break; -+ case TX_AMP: -+ ret = tx_amp_cal_efuse(phydev, buf); -+ break; -+ case TX_R50: -+ ret = tx_r50_cal_efuse(phydev, buf, pair_n); -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (ret) -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item, -+ bool efs_valid, enum CAL_MODE cal_mode, u8 start_pair, -+ u8 end_pair, u32 *buf) -+{ -+ char cal_prop[5][20] = { "mediatek,rext", "mediatek,tx_offset", -+ "mediatek,tx_amp", "mediatek,tx_r50", -+ "mediatek,tx_vcm" }; -+ const char *dts_cal_mode; -+ u8 final_cal_mode = 0; -+ bool is_cal = true; -+ int ret, cal_ret; -+ -+ ret = of_property_read_string(phydev->mdio.dev.of_node, -+ cal_prop[cal_item], &dts_cal_mode); -+ -+ switch (cal_mode) { -+ case SW_EFUSE_M: -+ if ((efs_valid && ret) || -+ (efs_valid && !ret && strcmp("efuse", dts_cal_mode) == 0)) { -+ cal_ret = cal_efuse(phydev, cal_item, start_pair, -+ end_pair, buf); -+ final_cal_mode = EFUSE_K; -+ } else if ((!efs_valid && ret) || -+ (!ret && strcmp("sw", dts_cal_mode) == 0)) { -+ cal_ret = cal_sw(phydev, cal_item, start_pair, end_pair); -+ final_cal_mode = SW_K; -+ } else { -+ is_cal = false; -+ } -+ break; -+ case EFUSE_M: -+ if ((efs_valid && ret) || -+ (efs_valid && !ret && strcmp("efuse", dts_cal_mode) == 0)) { -+ cal_ret = cal_efuse(phydev, cal_item, start_pair, -+ end_pair, buf); -+ final_cal_mode = EFUSE_K; -+ } else { -+ is_cal = false; -+ } -+ break; -+ case SW_M: -+ if (ret || (!ret && strcmp("sw", dts_cal_mode) == 0)) { -+ cal_ret = cal_sw(phydev, cal_item, start_pair, end_pair); -+ final_cal_mode = SW_K; -+ } else { -+ is_cal = false; -+ } -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ if (cal_ret) { -+ dev_err(&phydev->mdio.dev, "[%s]cal failed\n", cal_prop[cal_item]); -+ return -EIO; -+ } -+ -+ if (!is_cal) { -+ dev_dbg(&phydev->mdio.dev, "[%s]K mode: %s(not supported)\n", -+ cal_prop[cal_item], dts_cal_mode); -+ return -EIO; -+ } -+ -+ dev_dbg(&phydev->mdio.dev, "[%s]K mode: %s(dts: %s), efs-valid: %s\n", -+ cal_prop[cal_item], -+ final_cal_mode ? "SW" : "EFUSE", -+ ret ? "not set" : dts_cal_mode, -+ efs_valid ? "yes" : "no"); -+ return 0; -+} -+ -+static int mt798x_phy_calibration(struct phy_device *phydev) -+{ -+ int ret = 0; -+ u32 *buf; -+ bool efs_valid = true; -+ size_t len; -+ struct nvmem_cell *cell; -+ -+ if (phydev->interface != PHY_INTERFACE_MODE_GMII) -+ return -EINVAL; -+ -+ cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); -+ if (IS_ERR(cell)) { -+ if (PTR_ERR(cell) == -EPROBE_DEFER) -+ return PTR_ERR(cell); -+ return 0; -+ } -+ -+ buf = (u32 *)nvmem_cell_read(cell, &len); -+ if (IS_ERR(buf)) -+ return PTR_ERR(buf); -+ nvmem_cell_put(cell); -+ -+ if (!buf[0] || !buf[1] || !buf[2] || !buf[3]) -+ efs_valid = false; -+ -+ if (len < 4 * sizeof(u32)) { -+ dev_err(&phydev->mdio.dev, "invalid calibration data\n"); -+ ret = -EINVAL; -+ goto out; -+ } -+ -+ ret = start_cal(phydev, REXT, efs_valid, SW_EFUSE_M, -+ NO_PAIR, NO_PAIR, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_OFFSET, efs_valid, EFUSE_M, -+ NO_PAIR, NO_PAIR, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_AMP, efs_valid, EFUSE_M, -+ NO_PAIR, NO_PAIR, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_R50, efs_valid, EFUSE_M, -+ PAIR_A, PAIR_D, buf); -+ if (ret) -+ goto out; -+ ret = start_cal(phydev, TX_VCM, efs_valid, SW_M, -+ PAIR_A, PAIR_A, buf); -+ if (ret) -+ goto out; -+ -+out: -+ kfree(buf); -+ return ret; -+} -+ -+static int mt7981_phy_probe(struct phy_device *phydev) -+{ -+ mt7981_phy_finetune(phydev); -+ -+ return mt798x_phy_calibration(phydev); -+} -+ -+static int mt7988_phy_probe(struct phy_device *phydev) -+{ -+ struct device_node *np; -+ void __iomem *boottrap; -+ u32 reg; -+ int port; -+ -+ /* Setup LED polarity according to boottrap's polarity */ -+ np = of_find_compatible_node(NULL, NULL, "mediatek,boottrap"); -+ if (!np) -+ return -ENOENT; -+ boottrap = of_iomap(np, 0); -+ if (!boottrap) -+ return -ENOMEM; -+ reg = readl(boottrap); -+ port = phydev->mdio.addr; -+ if ((port == GPHY_PORT0 && reg & BIT(8)) || -+ (port == GPHY_PORT1 && reg & BIT(9)) || -+ (port == GPHY_PORT2 && reg & BIT(10)) || -+ (port == GPHY_PORT3 && reg & BIT(11))) { -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_ON_LINK10 | -+ MTK_PHY_LED0_ON_LINK100 | -+ MTK_PHY_LED0_ON_LINK1000); -+ } else { -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, -+ MTK_PHY_LED0_ENABLE | MTK_PHY_LED0_POLARITY | -+ MTK_PHY_LED0_ON_LINK10 | -+ MTK_PHY_LED0_ON_LINK100 | -+ MTK_PHY_LED0_ON_LINK1000); -+ } -+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_BLINK_CTRL, -+ MTK_PHY_LED0_1000TX | MTK_PHY_LED0_1000RX | -+ MTK_PHY_LED0_100TX | MTK_PHY_LED0_100RX | -+ MTK_PHY_LED0_10TX | MTK_PHY_LED0_10RX); -+ -+ mt7988_phy_finetune(phydev); -+ -+ return mt798x_phy_calibration(phydev); -+} -+#endif -+ - static struct phy_driver mtk_gephy_driver[] = { - { - PHY_ID_MATCH_EXACT(0x03a29412), -@@ -131,6 +1456,30 @@ static struct phy_driver mtk_gephy_drive - .read_page = mtk_gephy_read_page, - .write_page = mtk_gephy_write_page, - }, -+#ifdef CONFIG_MEDIATEK_GE_PHY_SOC -+ { -+ PHY_ID_MATCH_EXACT(0x03a29461), -+ .name = "MediaTek MT7981 PHY", -+ .probe = mt7981_phy_probe, -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_gephy_read_page, -+ .write_page = mtk_gephy_write_page, -+ }, -+ { -+ PHY_ID_MATCH_EXACT(0x03a29481), -+ .name = "MediaTek MT7988 PHY", -+ .probe = mt7988_phy_probe, -+ .config_intr = genphy_no_config_intr, -+ .handle_interrupt = genphy_handle_interrupt_no_ack, -+ .suspend = genphy_suspend, -+ .resume = genphy_resume, -+ .read_page = mtk_gephy_read_page, -+ .write_page = mtk_gephy_write_page, -+ }, -+#endif - }; - +@@ -136,7 +136,8 @@ static struct phy_driver mtk_gephy_drive module_phy_driver(mtk_gephy_driver); -@@ -141,6 +1490,8 @@ static struct mdio_device_id __maybe_unu + + static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { +- { PHY_ID_MATCH_VENDOR(0x03a29400) }, ++ { PHY_ID_MATCH_EXACT(0x03a29441) }, ++ { PHY_ID_MATCH_EXACT(0x03a29412) }, + { } }; - MODULE_DESCRIPTION("MediaTek Gigabit Ethernet PHY driver"); -+MODULE_AUTHOR("Daniel Golle "); -+MODULE_AUTHOR("SkyLake Huang "); - MODULE_AUTHOR("DENG, Qingfang "); - MODULE_LICENSE("GPL"); - From ef2a831dabacfda6c36c79b8f963b5fdd9b2d080 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 17:41:22 +0100 Subject: [PATCH 14/43] mediatek: add driver for built-in 2.5G Ethernet PHY Add driver for the built-in 2.5G Ethernet PHY found in the MT7988 SoC. To function the PHY also needs firmware files which have not yet been published via linux-firmware. Signed-off-by: Daniel Golle --- .../drivers/net/phy/mediatek-2p5ge.c | 262 ++++++++++++++++++ target/linux/mediatek/filogic/config-5.15 | 1 + target/linux/mediatek/mt7622/config-5.15 | 1 + ...phy-add-driver-for-MediaTek-2.5G-PHY.patch | 39 +++ 4 files changed, 303 insertions(+) create mode 100644 target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c create mode 100644 target/linux/mediatek/patches-5.15/732-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch diff --git a/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c b/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c new file mode 100644 index 00000000000..c12e6b8eb6f --- /dev/null +++ b/target/linux/mediatek/files-5.15/drivers/net/phy/mediatek-2p5ge.c @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek/mediatek-2p5ge-phy-dmb.bin" +#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek/mediatek-2p5ge-phy-pmb.bin" + +#define MD32_EN_CFG 0x18 +#define MD32_EN BIT(0) + +#define BASE100T_STATUS_EXTEND 0x10 +#define BASE1000T_STATUS_EXTEND 0x11 +#define EXTEND_CTRL_AND_STATUS 0x16 + +#define PHY_AUX_CTRL_STATUS 0x1d +#define PHY_AUX_DPX_MASK GENMASK(5, 5) +#define PHY_AUX_SPEED_MASK GENMASK(4, 2) + +/* Registers on MDIO_MMD_VEND1 */ +#define MTK_PHY_LINK_STATUS_MISC 0xa2 +#define MTK_PHY_FDX_ENABLE BIT(5) + +/* Registers on MDIO_MMD_VEND2 */ +#define MTK_PHY_LED0_ON_CTRL 0x24 +#define MTK_PHY_LED0_ON_LINK1000 BIT(0) +#define MTK_PHY_LED0_ON_LINK100 BIT(1) +#define MTK_PHY_LED0_ON_LINK10 BIT(2) +#define MTK_PHY_LED0_ON_LINK2500 BIT(7) +#define MTK_PHY_LED0_POLARITY BIT(14) + +#define MTK_PHY_LED1_ON_CTRL 0x26 +#define MTK_PHY_LED1_ON_FDX BIT(4) +#define MTK_PHY_LED1_ON_HDX BIT(5) +#define MTK_PHY_LED1_POLARITY BIT(14) + +enum { + PHY_AUX_SPD_10 = 0, + PHY_AUX_SPD_100, + PHY_AUX_SPD_1000, + PHY_AUX_SPD_2500, +}; + +static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev) +{ + int ret; + int i; + const struct firmware *fw; + struct device *dev = &phydev->mdio.dev; + struct device_node *np; + void __iomem *dmb_addr; + void __iomem *pmb_addr; + void __iomem *mcucsr_base; + u16 reg; + struct pinctrl *pinctrl; + + np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw"); + if (!np) + return -ENOENT; + + dmb_addr = of_iomap(np, 0); + if (!dmb_addr) + return -ENOMEM; + pmb_addr = of_iomap(np, 1); + if (!pmb_addr) + return -ENOMEM; + mcucsr_base = of_iomap(np, 2); + if (!mcucsr_base) + return -ENOMEM; + + ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev); + if (ret) { + dev_err(dev, "failed to load firmware: %s, ret: %d\n", + MEDAITEK_2P5GE_PHY_DMB_FW, ret); + return ret; + } + for (i = 0; i < fw->size - 1; i += 4) + writel(*((uint32_t *)(fw->data + i)), dmb_addr + i); + release_firmware(fw); + + ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev); + if (ret) { + dev_err(dev, "failed to load firmware: %s, ret: %d\n", + MEDIATEK_2P5GE_PHY_PMB_FW, ret); + return ret; + } + for (i = 0; i < fw->size - 1; i += 4) + writel(*((uint32_t *)(fw->data + i)), pmb_addr + i); + release_firmware(fw); + + reg = readw(mcucsr_base + MD32_EN_CFG); + writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG); + dev_dbg(dev, "Firmware loading/trigger ok.\n"); + + /* Setup LED */ + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED0_POLARITY); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL, + MTK_PHY_LED0_ON_LINK10 | + MTK_PHY_LED0_ON_LINK100 | + MTK_PHY_LED0_ON_LINK1000 | + MTK_PHY_LED0_ON_LINK2500); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL, + MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX); + + pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led"); + if (IS_ERR(pinctrl)) { + dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n"); + return PTR_ERR(pinctrl); + } + + return 0; +} + +static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev) +{ + bool changed = false; + u32 adv; + int ret; + + if (phydev->autoneg == AUTONEG_DISABLE) { + /* Configure half duplex with genphy_setup_forced, + * because genphy_c45_pma_setup_forced does not support. + */ + return phydev->duplex != DUPLEX_FULL + ? genphy_setup_forced(phydev) + : genphy_c45_pma_setup_forced(phydev); + } + + ret = genphy_c45_an_config_aneg(phydev); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); + ret = phy_modify_changed(phydev, MII_CTRL1000, + ADVERTISE_1000FULL | ADVERTISE_1000HALF, + adv); + if (ret < 0) + return ret; + if (ret > 0) + changed = true; + + return genphy_c45_check_and_restart_aneg(phydev, changed); +} + +static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev) +{ + int ret; + + ret = genphy_read_abilities(phydev); + if (ret) + return ret; + + /* We don't support HDX at MAC layer on mt798x. + * So mask phy's HDX capabilities, too. + */ + linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, + phydev->supported); + linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported); + + return 0; +} + +static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev) +{ + int ret; + + ret = genphy_update_link(phydev); + if (ret) + return ret; + + phydev->speed = SPEED_UNKNOWN; + phydev->duplex = DUPLEX_UNKNOWN; + phydev->pause = 0; + phydev->asym_pause = 0; + + if (!phydev->link) + return 0; + + if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { + ret = genphy_c45_read_lpa(phydev); + if (ret < 0) + return ret; + + /* Read the link partner's 1G advertisement */ + ret = phy_read(phydev, MII_STAT1000); + if (ret < 0) + return ret; + mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret); + } else if (phydev->autoneg == AUTONEG_DISABLE) { + linkmode_zero(phydev->lp_advertising); + } + + ret = phy_read(phydev, PHY_AUX_CTRL_STATUS); + if (ret < 0) + return ret; + + switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) { + case PHY_AUX_SPD_10: + phydev->speed = SPEED_10; + break; + case PHY_AUX_SPD_100: + phydev->speed = SPEED_100; + break; + case PHY_AUX_SPD_1000: + phydev->speed = SPEED_1000; + break; + case PHY_AUX_SPD_2500: + phydev->speed = SPEED_2500; + phydev->duplex = DUPLEX_FULL; /* 2.5G must be FDX */ + break; + } + + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC); + if (ret < 0) + return ret; + + phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF; + + return 0; +} + +static struct phy_driver mtk_gephy_driver[] = { + { + PHY_ID_MATCH_EXACT(0x00339c11), + .name = "MediaTek MT798x 2.5GbE PHY", + .config_init = mt798x_2p5ge_phy_config_init, + .config_aneg = mt798x_2p5ge_phy_config_aneg, + .get_features = mt798x_2p5ge_phy_get_features, + .read_status = mt798x_2p5ge_phy_read_status, + }, +}; + +module_phy_driver(mtk_gephy_driver); + +static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = { + { PHY_ID_MATCH_VENDOR(0x00339c00) }, + { } +}; + +MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver"); +MODULE_AUTHOR("SkyLake Huang "); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl); +MODULE_FIRMWARE(MEDAITEK_2P5GE_PHY_DMB_FW); +MODULE_FIRMWARE(MEDIATEK_2P5GE_PHY_PMB_FW); diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index e6ab85fb5d1..224d10d0e17 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -204,6 +204,7 @@ CONFIG_MAXLINEAR_GPHY=y CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y +CONFIG_MEDIATEK_2P5G_PHY=y CONFIG_MEDIATEK_GE_PHY=y CONFIG_MEDIATEK_GE_SOC_PHY=y CONFIG_MEDIATEK_WATCHDOG=y diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index d584497ec19..79df71c9907 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -225,6 +225,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y +# CONFIG_MEDIATEK_2P5G_PHY is not set CONFIG_MEDIATEK_GE_PHY=y # CONFIG_MEDIATEK_GE_SOC_PHY is not set CONFIG_MEDIATEK_WATCHDOG=y diff --git a/target/linux/mediatek/patches-5.15/732-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch b/target/linux/mediatek/patches-5.15/732-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch new file mode 100644 index 00000000000..a2a3bab6322 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/732-net-phy-add-driver-for-MediaTek-2.5G-PHY.patch @@ -0,0 +1,39 @@ +From 128dc09b0af36772062142ce9e85b19c84ac789a Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 28 Feb 2023 17:53:37 +0000 +Subject: [PATCH] net: phy: add driver for MediaTek 2.5G PHY + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/Kconfig | 7 ++ + drivers/net/phy/Makefile | 1 + + drivers/net/phy/mediatek-2p5ge.c | 220 +++++++++++++++++++++++++++++++ + 3 files changed, 226 insertions(+) + create mode 100644 drivers/net/phy/mediatek-2p5ge.c + +--- a/drivers/net/phy/Kconfig ++++ b/drivers/net/phy/Kconfig +@@ -304,6 +304,13 @@ config MEDIATEK_GE_SOC_PHY + present in the SoCs efuse and will dynamically calibrate VCM + (common-mode voltage) during startup. + ++config MEDIATEK_2P5G_PHY ++ tristate "MediaTek 2.5G Ethernet PHY" ++ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST ++ default NET_MEDIATEK_SOC ++ help ++ Supports the MediaTek 2.5G Ethernet PHY. ++ + config MICREL_PHY + tristate "Micrel PHYs" + help +--- a/drivers/net/phy/Makefile ++++ b/drivers/net/phy/Makefile +@@ -80,6 +80,7 @@ obj-$(CONFIG_MARVELL_10G_PHY) += marvell + obj-$(CONFIG_MARVELL_PHY) += marvell.o + obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o + obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o ++obj-$(CONFIG_MEDIATEK_2P5G_PHY) += mediatek-2p5ge.o + obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o + obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o + obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o From a3cf3e2c489d5b6f534d1b4d6f7b462f81c9c141 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 17:13:33 +0100 Subject: [PATCH 15/43] mediatek: filogic: add driver for Richtek RT5190A regulator The Richtek RT5190A is used on the MT7988 reference board. Backport and enable the driver on the filogic subtarget, so we can support cpufreq on the MT7988 reference board. Signed-off-by: Daniel Golle --- target/linux/mediatek/filogic/config-5.15 | 3 +- target/linux/mediatek/mt7622/config-5.15 | 1 + target/linux/mediatek/mt7623/config-5.15 | 1 + ...dd-bindings-for-Richtek-RT5190A-PMIC.patch | 180 ++++++ ...a-Add-support-for-Richtek-RT5190A-PM.patch | 562 ++++++++++++++++++ 5 files changed, 746 insertions(+), 1 deletion(-) create mode 100644 target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch create mode 100644 target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 224d10d0e17..3e6a1654f20 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -16,7 +16,6 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ARCH_WANTS_NO_INSTR=y CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y -# CONFIG_ARM64_CNP is not set CONFIG_ARM64_CRYPTO=y CONFIG_ARM64_ERRATUM_843419=y CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y @@ -354,10 +353,12 @@ CONFIG_REED_SOLOMON=y CONFIG_REED_SOLOMON_DEC8=y CONFIG_REED_SOLOMON_ENC8=y CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y CONFIG_REGMAP_MMIO=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MT6380=y +CONFIG_REGULATOR_RT5190A=y CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y diff --git a/target/linux/mediatek/mt7622/config-5.15 b/target/linux/mediatek/mt7622/config-5.15 index 79df71c9907..30a5ff948fa 100644 --- a/target/linux/mediatek/mt7622/config-5.15 +++ b/target/linux/mediatek/mt7622/config-5.15 @@ -377,6 +377,7 @@ CONFIG_REGMAP_MMIO=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MT6380=y +# CONFIG_REGULATOR_RT5190A is not set CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y diff --git a/target/linux/mediatek/mt7623/config-5.15 b/target/linux/mediatek/mt7623/config-5.15 index af0a5c1939f..039a904f197 100644 --- a/target/linux/mediatek/mt7623/config-5.15 +++ b/target/linux/mediatek/mt7623/config-5.15 @@ -472,6 +472,7 @@ CONFIG_REGULATOR_MT6323=y # CONFIG_REGULATOR_MT6358 is not set # CONFIG_REGULATOR_MT6380 is not set # CONFIG_REGULATOR_MT6397 is not set +# CONFIG_REGULATOR_RT5190A is not set # CONFIG_REGULATOR_QCOM_LABIBB is not set # CONFIG_REGULATOR_QCOM_SPMI is not set # CONFIG_REGULATOR_QCOM_USB_VBUS is not set diff --git a/target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch b/target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch new file mode 100644 index 00000000000..30891d34872 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/830-v5.18-regulator-Add-bindings-for-Richtek-RT5190A-PMIC.patch @@ -0,0 +1,180 @@ +From b77e70f6b8f2cc62fba847f3008a430a09ef275d Mon Sep 17 00:00:00 2001 +From: ChiYuan Huang +Date: Wed, 9 Mar 2022 16:01:42 +0800 +Subject: [PATCH 1/2] regulator: Add bindings for Richtek RT5190A PMIC + +Add bindings for Richtek RT5190A PMIC. + +Signed-off-by: ChiYuan Huang +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/1646812903-32496-2-git-send-email-u0084500@gmail.com +Signed-off-by: Mark Brown +--- + .../regulator/richtek,rt5190a-regulator.yaml | 141 ++++++++++++++++++ + .../regulator/richtek,rt5190a-regulator.h | 15 ++ + 2 files changed, 156 insertions(+) + create mode 100644 Documentation/devicetree/bindings/regulator/richtek,rt5190a-regulator.yaml + create mode 100644 include/dt-bindings/regulator/richtek,rt5190a-regulator.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/regulator/richtek,rt5190a-regulator.yaml +@@ -0,0 +1,141 @@ ++# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause ++%YAML 1.2 ++--- ++$id: http://devicetree.org/schemas/regulator/richtek,rt5190a-regulator.yaml# ++$schema: http://devicetree.org/meta-schemas/core.yaml# ++ ++title: Richtek RT5190A PMIC Regulator ++ ++maintainers: ++ - ChiYuan Huang ++ ++description: | ++ The RT5190A integrates 1 channel buck controller, 3 channels high efficiency ++ synchronous buck converters, 1 LDO, I2C control interface and peripherial ++ logical control. ++ ++ It also supports mute AC OFF depop sound and quick setting storage while ++ input power is removed. ++ ++properties: ++ compatible: ++ enum: ++ - richtek,rt5190a ++ ++ reg: ++ maxItems: 1 ++ ++ interrupts: ++ maxItems: 1 ++ ++ vin2-supply: ++ description: phandle to buck2 input voltage. ++ ++ vin3-supply: ++ description: phandle to buck3 input voltage. ++ ++ vin4-supply: ++ description: phandle to buck4 input voltage. ++ ++ vinldo-supply: ++ description: phandle to ldo input voltage ++ ++ richtek,mute-enable: ++ description: | ++ The mute function uses 'mutein', 'muteout', and 'vdet' pins as the control ++ signal. When enabled, The normal behavior is to bypass the 'mutein' signal ++ 'muteout'. But if the power source removal is detected from 'vdet', ++ whatever the 'mutein' signal is, it will pull down the 'muteout' to force ++ speakers mute. this function is commonly used to prevent the speaker pop ++ noise during AC power turned off in the modern TV system design. ++ type: boolean ++ ++ regulators: ++ type: object ++ ++ patternProperties: ++ "^buck[1-4]$|^ldo$": ++ type: object ++ $ref: regulator.yaml# ++ description: | ++ regulator description for buck1 and buck4. ++ ++ properties: ++ regulator-allowed-modes: ++ description: | ++ buck operating mode, only buck1/4 support mode operating. ++ 0: auto mode ++ 1: force pwm mode ++ items: ++ enum: [0, 1] ++ ++ richtek,latchup-enable: ++ type: boolean ++ description: | ++ If specified, undervolt protection mode changes from the default ++ hiccup to latchup. ++ ++ unevaluatedProperties: false ++ ++ additionalProperties: false ++ ++required: ++ - compatible ++ - reg ++ - regulators ++ ++additionalProperties: false ++ ++examples: ++ - | ++ #include ++ #include ++ ++ i2c { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pmic@64 { ++ compatible = "richtek,rt5190a"; ++ reg = <0x64>; ++ interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>; ++ vin2-supply = <&rt5190_buck1>; ++ vin3-supply = <&rt5190_buck1>; ++ vin4-supply = <&rt5190_buck1>; ++ ++ regulators { ++ rt5190_buck1: buck1 { ++ regulator-name = "rt5190a-buck1"; ++ regulator-min-microvolt = <5090000>; ++ regulator-max-microvolt = <5090000>; ++ regulator-allowed-modes = ; ++ regulator-boot-on; ++ }; ++ buck2 { ++ regulator-name = "rt5190a-buck2"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-boot-on; ++ }; ++ buck3 { ++ regulator-name = "rt5190a-buck3"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <1400000>; ++ regulator-boot-on; ++ }; ++ buck4 { ++ regulator-name = "rt5190a-buck4"; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-allowed-modes = ; ++ regulator-boot-on; ++ }; ++ ldo { ++ regulator-name = "rt5190a-ldo"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-boot-on; ++ }; ++ }; ++ }; ++ }; +--- /dev/null ++++ b/include/dt-bindings/regulator/richtek,rt5190a-regulator.h +@@ -0,0 +1,15 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++ ++#ifndef __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__ ++#define __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__ ++ ++/* ++ * BUCK/LDO mode constants which may be used in devicetree properties ++ * (eg. regulator-allowed-modes). ++ * See the manufacturer's datasheet for more information on these modes. ++ */ ++ ++#define RT5190A_OPMODE_AUTO 0 ++#define RT5190A_OPMODE_FPWM 1 ++ ++#endif diff --git a/target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch b/target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch new file mode 100644 index 00000000000..0e0f099e505 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/831-v5.18-regulator-rt5190a-Add-support-for-Richtek-RT5190A-PM.patch @@ -0,0 +1,562 @@ +From 760423dfad53877b468490758fe7ea968ded9402 Mon Sep 17 00:00:00 2001 +From: ChiYuan Huang +Date: Wed, 9 Mar 2022 16:01:43 +0800 +Subject: [PATCH 2/2] regulator: rt5190a: Add support for Richtek RT5190A PMIC + +Add support for Richtek RT5190A PMIC. + +Signed-off-by: ChiYuan Huang +Link: https://lore.kernel.org/r/1646812903-32496-3-git-send-email-u0084500@gmail.com +Signed-off-by: Mark Brown +--- + drivers/regulator/Kconfig | 10 + + drivers/regulator/Makefile | 1 + + drivers/regulator/rt5190a-regulator.c | 513 ++++++++++++++++++++++++++ + 3 files changed, 524 insertions(+) + create mode 100644 drivers/regulator/rt5190a-regulator.c + +--- a/drivers/regulator/Kconfig ++++ b/drivers/regulator/Kconfig +@@ -1037,6 +1037,16 @@ config REGULATOR_RT5033 + RT5033 PMIC. The device supports multiple regulators like + current source, LDO and Buck. + ++config REGULATOR_RT5190A ++ tristate "Richtek RT5190A PMIC" ++ depends on I2C ++ select REGMAP_I2C ++ help ++ This adds support for voltage regulator in Richtek RT5190A PMIC. ++ It integratas 1 channel buck controller, 3 channels high efficiency ++ buck converters, 1 LDO, mute AC OFF depop function, with the general ++ I2C control interface. ++ + config REGULATOR_RT6160 + tristate "Richtek RT6160 BuckBoost voltage regulator" + depends on I2C +--- a/drivers/regulator/Makefile ++++ b/drivers/regulator/Makefile +@@ -125,6 +125,7 @@ obj-$(CONFIG_REGULATOR_ROHM) += rohm-reg + obj-$(CONFIG_REGULATOR_RT4801) += rt4801-regulator.o + obj-$(CONFIG_REGULATOR_RT4831) += rt4831-regulator.o + obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o ++obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o + obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o + obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o + obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o +--- /dev/null ++++ b/drivers/regulator/rt5190a-regulator.c +@@ -0,0 +1,513 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RT5190A_REG_MANUFACTURE 0x00 ++#define RT5190A_REG_BUCK2VSEL 0x04 ++#define RT5190A_REG_BUCK3VSEL 0x05 ++#define RT5190A_REG_DCDCCNTL 0x06 ++#define RT5190A_REG_ENABLE 0x07 ++#define RT5190A_REG_DISCHARGE 0x09 ++#define RT5190A_REG_PROTMODE 0x0A ++#define RT5190A_REG_MUTECNTL 0x0B ++#define RT5190A_REG_PGSTAT 0x0F ++#define RT5190A_REG_OVINT 0x10 ++#define RT5190A_REG_HOTDIEMASK 0x17 ++ ++#define RT5190A_VSEL_MASK GENMASK(6, 0) ++#define RT5190A_RID_BITMASK(rid) BIT(rid + 1) ++#define RT5190A_BUCK1_DISCHG_MASK GENMASK(1, 0) ++#define RT5190A_BUCK1_DISCHG_ONVAL 0x01 ++#define RT5190A_OVERVOLT_MASK GENMASK(7, 0) ++#define RT5190A_UNDERVOLT_MASK GENMASK(15, 8) ++#define RT5190A_CH234OT_MASK BIT(29) ++#define RT5190A_CHIPOT_MASK BIT(28) ++ ++#define RT5190A_BUCK23_MINUV 600000 ++#define RT5190A_BUCK23_MAXUV 1400000 ++#define RT5190A_BUCK23_STEPUV 10000 ++#define RT5190A_BUCK23_STEPNUM ((1400000 - 600000) / 10000 + 1) ++ ++enum { ++ RT5190A_IDX_BUCK1 = 0, ++ RT5190A_IDX_BUCK2, ++ RT5190A_IDX_BUCK3, ++ RT5190A_IDX_BUCK4, ++ RT5190A_IDX_LDO, ++ RT5190A_MAX_IDX ++}; ++ ++struct rt5190a_priv { ++ struct device *dev; ++ struct regmap *regmap; ++ struct regulator_desc rdesc[RT5190A_MAX_IDX]; ++ struct regulator_dev *rdev[RT5190A_MAX_IDX]; ++}; ++ ++static int rt5190a_get_error_flags(struct regulator_dev *rdev, ++ unsigned int *flags) ++{ ++ struct regmap *regmap = rdev_get_regmap(rdev); ++ int rid = rdev_get_id(rdev); ++ unsigned int pgood_stat; ++ int ret; ++ ++ ret = regmap_read(regmap, RT5190A_REG_PGSTAT, &pgood_stat); ++ if (ret) ++ return ret; ++ ++ if (!(pgood_stat & RT5190A_RID_BITMASK(rid))) ++ *flags = REGULATOR_ERROR_FAIL; ++ else ++ *flags = 0; ++ ++ return 0; ++} ++ ++static int rt5190a_fixed_buck_set_mode(struct regulator_dev *rdev, ++ unsigned int mode) ++{ ++ struct regmap *regmap = rdev_get_regmap(rdev); ++ int rid = rdev_get_id(rdev); ++ unsigned int mask = RT5190A_RID_BITMASK(rid), val; ++ ++ switch (mode) { ++ case REGULATOR_MODE_FAST: ++ val = mask; ++ break; ++ case REGULATOR_MODE_NORMAL: ++ val = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return regmap_update_bits(regmap, RT5190A_REG_DCDCCNTL, mask, val); ++} ++ ++static unsigned int rt5190a_fixed_buck_get_mode(struct regulator_dev *rdev) ++{ ++ struct regmap *regmap = rdev_get_regmap(rdev); ++ int rid = rdev_get_id(rdev); ++ unsigned int val; ++ int ret; ++ ++ ret = regmap_read(regmap, RT5190A_REG_DCDCCNTL, &val); ++ if (ret) { ++ dev_err(&rdev->dev, "Failed to get mode [%d]\n", ret); ++ return ret; ++ } ++ ++ if (val & RT5190A_RID_BITMASK(rid)) ++ return REGULATOR_MODE_FAST; ++ ++ return REGULATOR_MODE_NORMAL; ++} ++ ++static const struct regulator_ops rt5190a_ranged_buck_ops = { ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++ .set_voltage_sel = regulator_set_voltage_sel_regmap, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, ++ .list_voltage = regulator_list_voltage_linear, ++ .set_active_discharge = regulator_set_active_discharge_regmap, ++ .get_error_flags = rt5190a_get_error_flags, ++}; ++ ++static const struct regulator_ops rt5190a_fixed_buck_ops = { ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++ .set_active_discharge = regulator_set_active_discharge_regmap, ++ .set_mode = rt5190a_fixed_buck_set_mode, ++ .get_mode = rt5190a_fixed_buck_get_mode, ++ .get_error_flags = rt5190a_get_error_flags, ++}; ++ ++static const struct regulator_ops rt5190a_fixed_ldo_ops = { ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++ .set_active_discharge = regulator_set_active_discharge_regmap, ++ .get_error_flags = rt5190a_get_error_flags, ++}; ++ ++static irqreturn_t rt5190a_irq_handler(int irq, void *data) ++{ ++ struct rt5190a_priv *priv = data; ++ __le32 raws; ++ unsigned int events, fields; ++ static const struct { ++ unsigned int bitmask; ++ unsigned int report; ++ } event_tbl[] = { ++ { RT5190A_OVERVOLT_MASK, REGULATOR_ERROR_REGULATION_OUT }, ++ { RT5190A_UNDERVOLT_MASK, REGULATOR_ERROR_UNDER_VOLTAGE } ++ }; ++ int i, j, ret; ++ ++ ret = regmap_raw_read(priv->regmap, RT5190A_REG_OVINT, &raws, ++ sizeof(raws)); ++ if (ret) { ++ dev_err(priv->dev, "Failed to read events\n"); ++ return IRQ_NONE; ++ } ++ ++ events = le32_to_cpu(raws); ++ ++ ret = regmap_raw_write(priv->regmap, RT5190A_REG_OVINT, &raws, ++ sizeof(raws)); ++ if (ret) ++ dev_err(priv->dev, "Failed to write-clear events\n"); ++ ++ /* Handle OV,UV events */ ++ for (i = 0; i < ARRAY_SIZE(event_tbl); i++) { ++ fields = events & event_tbl[i].bitmask; ++ fields >>= ffs(event_tbl[i].bitmask) - 1; ++ ++ for (j = 0; j < RT5190A_MAX_IDX; j++) { ++ if (!(fields & RT5190A_RID_BITMASK(j))) ++ continue; ++ ++ regulator_notifier_call_chain(priv->rdev[j], ++ event_tbl[i].report, ++ NULL); ++ } ++ } ++ ++ /* Handle CH234 OT event */ ++ if (events & RT5190A_CH234OT_MASK) { ++ for (j = RT5190A_IDX_BUCK2; j < RT5190A_IDX_LDO; j++) { ++ regulator_notifier_call_chain(priv->rdev[j], ++ REGULATOR_ERROR_OVER_TEMP, ++ NULL); ++ } ++ } ++ ++ /* Warning if CHIP OT occur */ ++ if (events & RT5190A_CHIPOT_MASK) ++ dev_warn(priv->dev, "CHIP overheat\n"); ++ ++ return IRQ_HANDLED; ++} ++ ++static unsigned int rt5190a_of_map_mode(unsigned int mode) ++{ ++ switch (mode) { ++ case RT5190A_OPMODE_AUTO: ++ return REGULATOR_MODE_NORMAL; ++ case RT5190A_OPMODE_FPWM: ++ return REGULATOR_MODE_FAST; ++ default: ++ return REGULATOR_MODE_INVALID; ++ } ++} ++ ++static int rt5190a_of_parse_cb(struct rt5190a_priv *priv, int rid, ++ struct of_regulator_match *match) ++{ ++ struct regulator_desc *desc = priv->rdesc + rid; ++ struct regulator_init_data *init_data = match->init_data; ++ struct device_node *np = match->of_node; ++ bool latchup_enable; ++ unsigned int mask = RT5190A_RID_BITMASK(rid), val; ++ ++ switch (rid) { ++ case RT5190A_IDX_BUCK1: ++ case RT5190A_IDX_BUCK4: ++ case RT5190A_IDX_LDO: ++ init_data->constraints.apply_uV = 0; ++ ++ if (init_data->constraints.min_uV == ++ init_data->constraints.max_uV) ++ desc->fixed_uV = init_data->constraints.min_uV; ++ else { ++ dev_err(priv->dev, ++ "Variable voltage for fixed regulator\n"); ++ return -EINVAL; ++ } ++ break; ++ default: ++ break; ++ } ++ ++ latchup_enable = of_property_read_bool(np, "richtek,latchup-enable"); ++ ++ /* latchup: 0, default hiccup: 1 */ ++ val = !latchup_enable ? mask : 0; ++ ++ return regmap_update_bits(priv->regmap, RT5190A_REG_PROTMODE, mask, val); ++} ++ ++static void rt5190a_fillin_regulator_desc(struct regulator_desc *desc, int rid) ++{ ++ static const char * const regu_name[] = { "buck1", "buck2", ++ "buck3", "buck4", ++ "ldo" }; ++ static const char * const supply[] = { NULL, "vin2", "vin3", "vin4", ++ "vinldo" }; ++ ++ desc->name = regu_name[rid]; ++ desc->supply_name = supply[rid]; ++ desc->owner = THIS_MODULE; ++ desc->type = REGULATOR_VOLTAGE; ++ desc->id = rid; ++ desc->enable_reg = RT5190A_REG_ENABLE; ++ desc->enable_mask = RT5190A_RID_BITMASK(rid); ++ desc->active_discharge_reg = RT5190A_REG_DISCHARGE; ++ desc->active_discharge_mask = RT5190A_RID_BITMASK(rid); ++ desc->active_discharge_on = RT5190A_RID_BITMASK(rid); ++ ++ switch (rid) { ++ case RT5190A_IDX_BUCK1: ++ desc->active_discharge_mask = RT5190A_BUCK1_DISCHG_MASK; ++ desc->active_discharge_on = RT5190A_BUCK1_DISCHG_ONVAL; ++ desc->n_voltages = 1; ++ desc->ops = &rt5190a_fixed_buck_ops; ++ desc->of_map_mode = rt5190a_of_map_mode; ++ break; ++ case RT5190A_IDX_BUCK2: ++ desc->vsel_reg = RT5190A_REG_BUCK2VSEL; ++ desc->vsel_mask = RT5190A_VSEL_MASK; ++ desc->min_uV = RT5190A_BUCK23_MINUV; ++ desc->uV_step = RT5190A_BUCK23_STEPUV; ++ desc->n_voltages = RT5190A_BUCK23_STEPNUM; ++ desc->ops = &rt5190a_ranged_buck_ops; ++ break; ++ case RT5190A_IDX_BUCK3: ++ desc->vsel_reg = RT5190A_REG_BUCK3VSEL; ++ desc->vsel_mask = RT5190A_VSEL_MASK; ++ desc->min_uV = RT5190A_BUCK23_MINUV; ++ desc->uV_step = RT5190A_BUCK23_STEPUV; ++ desc->n_voltages = RT5190A_BUCK23_STEPNUM; ++ desc->ops = &rt5190a_ranged_buck_ops; ++ break; ++ case RT5190A_IDX_BUCK4: ++ desc->n_voltages = 1; ++ desc->ops = &rt5190a_fixed_buck_ops; ++ desc->of_map_mode = rt5190a_of_map_mode; ++ break; ++ case RT5190A_IDX_LDO: ++ desc->n_voltages = 1; ++ desc->ops = &rt5190a_fixed_ldo_ops; ++ break; ++ } ++} ++ ++static struct of_regulator_match rt5190a_regulator_match[] = { ++ { .name = "buck1", }, ++ { .name = "buck2", }, ++ { .name = "buck3", }, ++ { .name = "buck4", }, ++ { .name = "ldo", } ++}; ++ ++static int rt5190a_parse_regulator_dt_data(struct rt5190a_priv *priv) ++{ ++ struct device_node *regulator_np; ++ struct regulator_desc *reg_desc; ++ struct of_regulator_match *match; ++ int i, ret; ++ ++ for (i = 0; i < RT5190A_MAX_IDX; i++) { ++ reg_desc = priv->rdesc + i; ++ match = rt5190a_regulator_match + i; ++ ++ rt5190a_fillin_regulator_desc(reg_desc, i); ++ ++ match->desc = reg_desc; ++ } ++ ++ regulator_np = of_get_child_by_name(priv->dev->of_node, "regulators"); ++ if (!regulator_np) { ++ dev_err(priv->dev, "Could not find 'regulators' node\n"); ++ return -ENODEV; ++ } ++ ++ ret = of_regulator_match(priv->dev, regulator_np, ++ rt5190a_regulator_match, ++ ARRAY_SIZE(rt5190a_regulator_match)); ++ ++ of_node_put(regulator_np); ++ ++ if (ret < 0) { ++ dev_err(priv->dev, ++ "Error parsing regulator init data: %d\n", ret); ++ return ret; ++ } ++ ++ for (i = 0; i < RT5190A_MAX_IDX; i++) { ++ match = rt5190a_regulator_match + i; ++ ++ ret = rt5190a_of_parse_cb(priv, i, match); ++ if (ret) { ++ dev_err(priv->dev, "Failed in [%d] of_parse_cb\n", i); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct reg_sequence rt5190a_init_patch[] = { ++ { 0x09, 0x3d, }, ++ { 0x0a, 0x3e, }, ++ { 0x0b, 0x01, }, ++ { 0x10, 0xff, }, ++ { 0x11, 0xff, }, ++ { 0x12, 0xff, }, ++ { 0x13, 0xff, }, ++ { 0x14, 0, }, ++ { 0x15, 0, }, ++ { 0x16, 0x3e, }, ++ { 0x17, 0, } ++}; ++ ++static int rt5190a_device_initialize(struct rt5190a_priv *priv) ++{ ++ bool mute_enable; ++ int ret; ++ ++ ret = regmap_register_patch(priv->regmap, rt5190a_init_patch, ++ ARRAY_SIZE(rt5190a_init_patch)); ++ if (ret) { ++ dev_err(priv->dev, "Failed to do register patch\n"); ++ return ret; ++ } ++ ++ mute_enable = device_property_read_bool(priv->dev, ++ "richtek,mute-enable"); ++ ++ if (mute_enable) { ++ ret = regmap_write(priv->regmap, RT5190A_REG_MUTECNTL, 0x00); ++ if (ret) { ++ dev_err(priv->dev, "Failed to enable mute function\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rt5190a_device_check(struct rt5190a_priv *priv) ++{ ++ u16 devid; ++ int ret; ++ ++ ret = regmap_raw_read(priv->regmap, RT5190A_REG_MANUFACTURE, &devid, ++ sizeof(devid)); ++ if (ret) ++ return ret; ++ ++ if (devid) { ++ dev_err(priv->dev, "Incorrect device id 0x%04x\n", devid); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static const struct regmap_config rt5190a_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = RT5190A_REG_HOTDIEMASK, ++}; ++ ++static int rt5190a_probe(struct i2c_client *i2c) ++{ ++ struct rt5190a_priv *priv; ++ struct regulator_config cfg = {}; ++ int i, ret; ++ ++ priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); ++ if (!priv) ++ return -ENOMEM; ++ ++ priv->dev = &i2c->dev; ++ ++ priv->regmap = devm_regmap_init_i2c(i2c, &rt5190a_regmap_config); ++ if (IS_ERR(priv->regmap)) { ++ dev_err(&i2c->dev, "Failed to allocate regmap\n"); ++ return PTR_ERR(priv->regmap); ++ } ++ ++ ret = rt5190a_device_check(priv); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to check device %d\n", ret); ++ return ret; ++ } ++ ++ ret = rt5190a_device_initialize(priv); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to initialize the device\n"); ++ return ret; ++ } ++ ++ ret = rt5190a_parse_regulator_dt_data(priv); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to parse regulator dt\n"); ++ return ret; ++ } ++ ++ cfg.dev = &i2c->dev; ++ cfg.regmap = priv->regmap; ++ ++ for (i = 0; i < RT5190A_MAX_IDX; i++) { ++ struct regulator_desc *desc = priv->rdesc + i; ++ struct of_regulator_match *match = rt5190a_regulator_match + i; ++ ++ cfg.init_data = match->init_data; ++ cfg.of_node = match->of_node; ++ ++ priv->rdev[i] = devm_regulator_register(&i2c->dev, desc, &cfg); ++ if (IS_ERR(priv->rdev[i])) { ++ dev_err(&i2c->dev, "Failed to register regulator %s\n", ++ desc->name); ++ return PTR_ERR(priv->rdev[i]); ++ } ++ } ++ ++ if (i2c->irq) { ++ ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, ++ rt5190a_irq_handler, ++ IRQF_ONESHOT, ++ dev_name(&i2c->dev), priv); ++ if (ret) { ++ dev_err(&i2c->dev, "Failed to register interrupt\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct of_device_id __maybe_unused rt5190a_device_table[] = { ++ { .compatible = "richtek,rt5190a", }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, rt5190a_device_table); ++ ++static struct i2c_driver rt5190a_driver = { ++ .driver = { ++ .name = "rt5190a", ++ .of_match_table = rt5190a_device_table, ++ }, ++ .probe_new = rt5190a_probe, ++}; ++module_i2c_driver(rt5190a_driver); ++ ++MODULE_AUTHOR("ChiYuan Huang "); ++MODULE_DESCRIPTION("Richtek RT5190A Regulator Driver"); ++MODULE_LICENSE("GPL v2"); From e4555d69a1c7c811188d8e257e77ac917d15f492 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 30 Apr 2023 18:03:00 +0100 Subject: [PATCH 16/43] mediatek: backport cpufreq changes to support MT7988 Backport cpufreq changes from upstream so that the MediaTek MT7988 SoC can be supported. Signed-off-by: Daniel Golle --- ...-Cleanup-variables-and-error-handlin.patch | 166 ++++++++++++ ...ufreq-mediatek-Remove-unused-headers.patch | 25 ++ ...ediatek-Enable-clocks-and-regulators.patch | 117 ++++++++ ...diatek-Use-device-print-to-show-logs.patch | 161 +++++++++++ ...freq-mediatek-Replace-old_-with-pre_.patch | 201 ++++++++++++++ ...k-Record-previous-target-vproc-value.patch | 64 +++++ ...ediatek-Make-sram-regulator-optional.patch | 30 +++ ...-Fix-NULL-pointer-dereference-in-med.patch | 32 +++ ...-Move-voltage-limits-to-platform-dat.patch | 227 ++++++++++++++++ ...-Refine-mtk_cpufreq_voltage_tracking.patch | 255 ++++++++++++++++++ ...ediatek-Add-opp-notification-support.patch | 184 +++++++++++++ ...-Fix-potential-deadlock-problem-in-m.patch | 43 +++ ...freq-mediatek-Link-CCI-device-to-CPU.patch | 188 +++++++++++++ ...freq-mediatek-Add-support-for-MT8186.patch | 42 +++ ...-Handle-sram-regulator-probe-deferra.patch | 35 +++ ...-fix-error-return-code-in-mtk_cpu_dv.patch | 29 ++ ...mediatek-fix-passing-zero-to-PTR_ERR.patch | 47 ++++ ...-fix-KP-caused-by-handler-usage-afte.patch | 149 ++++++++++ ...-raise-proc-sram-max-voltage-for-MT8.patch | 55 ++++ ...-Raise-proc-and-sram-max-voltage-for.patch | 58 ++++ ...freq-mediatek-Add-support-for-MT7988.patch | 41 +++ ...ek-don-t-request-unsupported-voltage.patch | 29 ++ 22 files changed, 2178 insertions(+) create mode 100644 target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch create mode 100644 target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch create mode 100644 target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch create mode 100644 target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch create mode 100644 target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch create mode 100644 target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch create mode 100644 target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch create mode 100644 target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch create mode 100644 target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch create mode 100644 target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch create mode 100644 target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch create mode 100644 target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch create mode 100644 target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch create mode 100644 target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch create mode 100644 target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch create mode 100644 target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch create mode 100644 target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch create mode 100644 target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch create mode 100644 target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch create mode 100644 target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch create mode 100644 target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch create mode 100644 target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch diff --git a/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch b/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch new file mode 100644 index 00000000000..8fad64a5702 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-01-cpufreq-mediatek-Cleanup-variables-and-error-handlin.patch @@ -0,0 +1,166 @@ +From 7a768326fdba542144833b9198a6d0edab52fad2 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 8 Apr 2022 12:58:56 +0800 +Subject: [PATCH 01/21] cpufreq: mediatek: Cleanup variables and error handling + in mtk_cpu_dvfs_info_init() + +- Remove several unnecessary varaibles in mtk_cpu_dvfs_info_init(). +- Unify error message format and use dev_err_probe() if possible. + +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 89 ++++++++++++------------------ + 1 file changed, 34 insertions(+), 55 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -302,96 +302,75 @@ static int mtk_cpufreq_set_target(struct + static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) + { + struct device *cpu_dev; +- struct regulator *proc_reg = ERR_PTR(-ENODEV); +- struct regulator *sram_reg = ERR_PTR(-ENODEV); +- struct clk *cpu_clk = ERR_PTR(-ENODEV); +- struct clk *inter_clk = ERR_PTR(-ENODEV); + struct dev_pm_opp *opp; + unsigned long rate; + int ret; + + cpu_dev = get_cpu_device(cpu); + if (!cpu_dev) { +- pr_err("failed to get cpu%d device\n", cpu); ++ dev_err(cpu_dev, "failed to get cpu%d device\n", cpu); + return -ENODEV; + } ++ info->cpu_dev = cpu_dev; + +- cpu_clk = clk_get(cpu_dev, "cpu"); +- if (IS_ERR(cpu_clk)) { +- if (PTR_ERR(cpu_clk) == -EPROBE_DEFER) +- pr_warn("cpu clk for cpu%d not ready, retry.\n", cpu); +- else +- pr_err("failed to get cpu clk for cpu%d\n", cpu); +- +- ret = PTR_ERR(cpu_clk); +- return ret; +- } +- +- inter_clk = clk_get(cpu_dev, "intermediate"); +- if (IS_ERR(inter_clk)) { +- if (PTR_ERR(inter_clk) == -EPROBE_DEFER) +- pr_warn("intermediate clk for cpu%d not ready, retry.\n", +- cpu); +- else +- pr_err("failed to get intermediate clk for cpu%d\n", +- cpu); ++ info->cpu_clk = clk_get(cpu_dev, "cpu"); ++ if (IS_ERR(info->cpu_clk)) { ++ ret = PTR_ERR(info->cpu_clk); ++ return dev_err_probe(cpu_dev, ret, ++ "cpu%d: failed to get cpu clk\n", cpu); ++ } + +- ret = PTR_ERR(inter_clk); ++ info->inter_clk = clk_get(cpu_dev, "intermediate"); ++ if (IS_ERR(info->inter_clk)) { ++ ret = PTR_ERR(info->inter_clk); ++ dev_err_probe(cpu_dev, ret, ++ "cpu%d: failed to get intermediate clk\n", cpu); + goto out_free_resources; + } + +- proc_reg = regulator_get_optional(cpu_dev, "proc"); +- if (IS_ERR(proc_reg)) { +- if (PTR_ERR(proc_reg) == -EPROBE_DEFER) +- pr_warn("proc regulator for cpu%d not ready, retry.\n", +- cpu); +- else +- pr_err("failed to get proc regulator for cpu%d\n", +- cpu); +- +- ret = PTR_ERR(proc_reg); ++ info->proc_reg = regulator_get_optional(cpu_dev, "proc"); ++ if (IS_ERR(info->proc_reg)) { ++ ret = PTR_ERR(info->proc_reg); ++ dev_err_probe(cpu_dev, ret, ++ "cpu%d: failed to get proc regulator\n", cpu); + goto out_free_resources; + } + + /* Both presence and absence of sram regulator are valid cases. */ +- sram_reg = regulator_get_exclusive(cpu_dev, "sram"); ++ info->sram_reg = regulator_get_exclusive(cpu_dev, "sram"); ++ if (IS_ERR(info->sram_reg)) ++ info->sram_reg = NULL; + + /* Get OPP-sharing information from "operating-points-v2" bindings */ + ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); + if (ret) { +- pr_err("failed to get OPP-sharing information for cpu%d\n", +- cpu); ++ dev_err(cpu_dev, ++ "cpu%d: failed to get OPP-sharing information\n", cpu); + goto out_free_resources; + } + + ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); + if (ret) { +- pr_warn("no OPP table for cpu%d\n", cpu); ++ dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu); + goto out_free_resources; + } + + /* Search a safe voltage for intermediate frequency. */ +- rate = clk_get_rate(inter_clk); ++ rate = clk_get_rate(info->inter_clk); + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); + if (IS_ERR(opp)) { +- pr_err("failed to get intermediate opp for cpu%d\n", cpu); ++ dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu); + ret = PTR_ERR(opp); + goto out_free_opp_table; + } + info->intermediate_voltage = dev_pm_opp_get_voltage(opp); + dev_pm_opp_put(opp); + +- info->cpu_dev = cpu_dev; +- info->proc_reg = proc_reg; +- info->sram_reg = IS_ERR(sram_reg) ? NULL : sram_reg; +- info->cpu_clk = cpu_clk; +- info->inter_clk = inter_clk; +- + /* + * If SRAM regulator is present, software "voltage tracking" is needed + * for this CPU power domain. + */ +- info->need_voltage_tracking = !IS_ERR(sram_reg); ++ info->need_voltage_tracking = (info->sram_reg != NULL); + + return 0; + +@@ -399,14 +378,14 @@ out_free_opp_table: + dev_pm_opp_of_cpumask_remove_table(&info->cpus); + + out_free_resources: +- if (!IS_ERR(proc_reg)) +- regulator_put(proc_reg); +- if (!IS_ERR(sram_reg)) +- regulator_put(sram_reg); +- if (!IS_ERR(cpu_clk)) +- clk_put(cpu_clk); +- if (!IS_ERR(inter_clk)) +- clk_put(inter_clk); ++ if (!IS_ERR(info->proc_reg)) ++ regulator_put(info->proc_reg); ++ if (!IS_ERR(info->sram_reg)) ++ regulator_put(info->sram_reg); ++ if (!IS_ERR(info->cpu_clk)) ++ clk_put(info->cpu_clk); ++ if (!IS_ERR(info->inter_clk)) ++ clk_put(info->inter_clk); + + return ret; + } diff --git a/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch b/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch new file mode 100644 index 00000000000..eebeeb09028 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-02-cpufreq-mediatek-Remove-unused-headers.patch @@ -0,0 +1,25 @@ +From 756104b856d4bc3121420af3ced342f5fc2b2123 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 8 Apr 2022 12:58:57 +0800 +Subject: [PATCH 02/21] cpufreq: mediatek: Remove unused headers + +Remove unused headers. + +Signed-off-by: Jia-Wei Chang +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -13,8 +13,6 @@ + #include + #include + #include +-#include +-#include + + #define MIN_VOLT_SHIFT (100000) + #define MAX_VOLT_SHIFT (200000) diff --git a/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch b/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch new file mode 100644 index 00000000000..c97d5fc3d91 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-03-cpufreq-mediatek-Enable-clocks-and-regulators.patch @@ -0,0 +1,117 @@ +From 342d5545e9f40496db9ae0d31c2427dd5f369a43 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 8 Apr 2022 12:58:58 +0800 +Subject: [PATCH 03/21] cpufreq: mediatek: Enable clocks and regulators + +We need to enable regulators so that the max and min requested values will +be recorded. +The intermediate clock is not always enabled by CCF in different projects, +so we should enable it in the cpufreq driver. + +Signed-off-by: Andrew-sh.Cheng +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 50 +++++++++++++++++++++++++++--- + 1 file changed, 45 insertions(+), 5 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -334,10 +334,23 @@ static int mtk_cpu_dvfs_info_init(struct + goto out_free_resources; + } + ++ ret = regulator_enable(info->proc_reg); ++ if (ret) { ++ dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu); ++ goto out_free_resources; ++ } ++ + /* Both presence and absence of sram regulator are valid cases. */ + info->sram_reg = regulator_get_exclusive(cpu_dev, "sram"); + if (IS_ERR(info->sram_reg)) + info->sram_reg = NULL; ++ else { ++ ret = regulator_enable(info->sram_reg); ++ if (ret) { ++ dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); ++ goto out_free_resources; ++ } ++ } + + /* Get OPP-sharing information from "operating-points-v2" bindings */ + ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus); +@@ -353,13 +366,21 @@ static int mtk_cpu_dvfs_info_init(struct + goto out_free_resources; + } + ++ ret = clk_prepare_enable(info->cpu_clk); ++ if (ret) ++ goto out_free_opp_table; ++ ++ ret = clk_prepare_enable(info->inter_clk); ++ if (ret) ++ goto out_disable_mux_clock; ++ + /* Search a safe voltage for intermediate frequency. */ + rate = clk_get_rate(info->inter_clk); + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); + if (IS_ERR(opp)) { + dev_err(cpu_dev, "cpu%d: failed to get intermediate opp\n", cpu); + ret = PTR_ERR(opp); +- goto out_free_opp_table; ++ goto out_disable_inter_clock; + } + info->intermediate_voltage = dev_pm_opp_get_voltage(opp); + dev_pm_opp_put(opp); +@@ -372,10 +393,21 @@ static int mtk_cpu_dvfs_info_init(struct + + return 0; + ++out_disable_inter_clock: ++ clk_disable_unprepare(info->inter_clk); ++ ++out_disable_mux_clock: ++ clk_disable_unprepare(info->cpu_clk); ++ + out_free_opp_table: + dev_pm_opp_of_cpumask_remove_table(&info->cpus); + + out_free_resources: ++ if (regulator_is_enabled(info->proc_reg)) ++ regulator_disable(info->proc_reg); ++ if (info->sram_reg && regulator_is_enabled(info->sram_reg)) ++ regulator_disable(info->sram_reg); ++ + if (!IS_ERR(info->proc_reg)) + regulator_put(info->proc_reg); + if (!IS_ERR(info->sram_reg)) +@@ -390,14 +422,22 @@ out_free_resources: + + static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) + { +- if (!IS_ERR(info->proc_reg)) ++ if (!IS_ERR(info->proc_reg)) { ++ regulator_disable(info->proc_reg); + regulator_put(info->proc_reg); +- if (!IS_ERR(info->sram_reg)) ++ } ++ if (!IS_ERR(info->sram_reg)) { ++ regulator_disable(info->sram_reg); + regulator_put(info->sram_reg); +- if (!IS_ERR(info->cpu_clk)) ++ } ++ if (!IS_ERR(info->cpu_clk)) { ++ clk_disable_unprepare(info->cpu_clk); + clk_put(info->cpu_clk); +- if (!IS_ERR(info->inter_clk)) ++ } ++ if (!IS_ERR(info->inter_clk)) { ++ clk_disable_unprepare(info->inter_clk); + clk_put(info->inter_clk); ++ } + + dev_pm_opp_of_cpumask_remove_table(&info->cpus); + } diff --git a/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch b/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch new file mode 100644 index 00000000000..18e1da728a8 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-04-cpufreq-mediatek-Use-device-print-to-show-logs.patch @@ -0,0 +1,161 @@ +From a02e2b359141035d2d6999940bc1b9f83ec88587 Mon Sep 17 00:00:00 2001 +From: Rex-BC Chen +Date: Fri, 22 Apr 2022 15:52:27 +0800 +Subject: [PATCH 04/21] cpufreq: mediatek: Use device print to show logs + +- Replace pr_* with dev_* to show logs. +- Remove usage of __func__. + +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 54 ++++++++++++++++-------------- + 1 file changed, 28 insertions(+), 26 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -67,7 +67,8 @@ static int mtk_cpufreq_voltage_tracking( + + old_vproc = regulator_get_voltage(proc_reg); + if (old_vproc < 0) { +- pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); ++ dev_err(info->cpu_dev, ++ "invalid Vproc value: %d\n", old_vproc); + return old_vproc; + } + /* Vsram should not exceed the maximum allowed voltage of SoC. */ +@@ -83,14 +84,14 @@ static int mtk_cpufreq_voltage_tracking( + do { + old_vsram = regulator_get_voltage(sram_reg); + if (old_vsram < 0) { +- pr_err("%s: invalid Vsram value: %d\n", +- __func__, old_vsram); ++ dev_err(info->cpu_dev, ++ "invalid Vsram value: %d\n", old_vsram); + return old_vsram; + } + old_vproc = regulator_get_voltage(proc_reg); + if (old_vproc < 0) { +- pr_err("%s: invalid Vproc value: %d\n", +- __func__, old_vproc); ++ dev_err(info->cpu_dev, ++ "invalid Vproc value: %d\n", old_vproc); + return old_vproc; + } + +@@ -138,14 +139,14 @@ static int mtk_cpufreq_voltage_tracking( + do { + old_vproc = regulator_get_voltage(proc_reg); + if (old_vproc < 0) { +- pr_err("%s: invalid Vproc value: %d\n", +- __func__, old_vproc); ++ dev_err(info->cpu_dev, ++ "invalid Vproc value: %d\n", old_vproc); + return old_vproc; + } + old_vsram = regulator_get_voltage(sram_reg); + if (old_vsram < 0) { +- pr_err("%s: invalid Vsram value: %d\n", +- __func__, old_vsram); ++ dev_err(info->cpu_dev, ++ "invalid Vsram value: %d\n", old_vsram); + return old_vsram; + } + +@@ -216,7 +217,7 @@ static int mtk_cpufreq_set_target(struct + old_freq_hz = clk_get_rate(cpu_clk); + old_vproc = regulator_get_voltage(info->proc_reg); + if (old_vproc < 0) { +- pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc); ++ dev_err(cpu_dev, "invalid Vproc value: %d\n", old_vproc); + return old_vproc; + } + +@@ -224,8 +225,8 @@ static int mtk_cpufreq_set_target(struct + + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz); + if (IS_ERR(opp)) { +- pr_err("cpu%d: failed to find OPP for %ld\n", +- policy->cpu, freq_hz); ++ dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n", ++ policy->cpu, freq_hz); + return PTR_ERR(opp); + } + vproc = dev_pm_opp_get_voltage(opp); +@@ -239,8 +240,8 @@ static int mtk_cpufreq_set_target(struct + if (old_vproc < target_vproc) { + ret = mtk_cpufreq_set_voltage(info, target_vproc); + if (ret) { +- pr_err("cpu%d: failed to scale up voltage!\n", +- policy->cpu); ++ dev_err(cpu_dev, ++ "cpu%d: failed to scale up voltage!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, old_vproc); + return ret; + } +@@ -249,8 +250,8 @@ static int mtk_cpufreq_set_target(struct + /* Reparent the CPU clock to intermediate clock. */ + ret = clk_set_parent(cpu_clk, info->inter_clk); + if (ret) { +- pr_err("cpu%d: failed to re-parent cpu clock!\n", +- policy->cpu); ++ dev_err(cpu_dev, ++ "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, old_vproc); + WARN_ON(1); + return ret; +@@ -259,8 +260,8 @@ static int mtk_cpufreq_set_target(struct + /* Set the original PLL to target rate. */ + ret = clk_set_rate(armpll, freq_hz); + if (ret) { +- pr_err("cpu%d: failed to scale cpu clock rate!\n", +- policy->cpu); ++ dev_err(cpu_dev, ++ "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); + clk_set_parent(cpu_clk, armpll); + mtk_cpufreq_set_voltage(info, old_vproc); + return ret; +@@ -269,8 +270,8 @@ static int mtk_cpufreq_set_target(struct + /* Set parent of CPU clock back to the original PLL. */ + ret = clk_set_parent(cpu_clk, armpll); + if (ret) { +- pr_err("cpu%d: failed to re-parent cpu clock!\n", +- policy->cpu); ++ dev_err(cpu_dev, ++ "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, inter_vproc); + WARN_ON(1); + return ret; +@@ -283,8 +284,8 @@ static int mtk_cpufreq_set_target(struct + if (vproc < inter_vproc || vproc < old_vproc) { + ret = mtk_cpufreq_set_voltage(info, vproc); + if (ret) { +- pr_err("cpu%d: failed to scale down voltage!\n", +- policy->cpu); ++ dev_err(cpu_dev, ++ "cpu%d: failed to scale down voltage!\n", policy->cpu); + clk_set_parent(cpu_clk, info->inter_clk); + clk_set_rate(armpll, old_freq_hz); + clk_set_parent(cpu_clk, armpll); +@@ -450,15 +451,16 @@ static int mtk_cpufreq_init(struct cpufr + + info = mtk_cpu_dvfs_info_lookup(policy->cpu); + if (!info) { +- pr_err("dvfs info for cpu%d is not initialized.\n", +- policy->cpu); ++ dev_err(info->cpu_dev, ++ "dvfs info for cpu%d is not initialized.\n", policy->cpu); + return -EINVAL; + } + + ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table); + if (ret) { +- pr_err("failed to init cpufreq table for cpu%d: %d\n", +- policy->cpu, ret); ++ dev_err(info->cpu_dev, ++ "failed to init cpufreq table for cpu%d: %d\n", ++ policy->cpu, ret); + return ret; + } + diff --git a/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch b/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch new file mode 100644 index 00000000000..8506f4e4776 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-05-cpufreq-mediatek-Replace-old_-with-pre_.patch @@ -0,0 +1,201 @@ +From 35832d9f9c5c1da01420d962dc56e7e61d104829 Mon Sep 17 00:00:00 2001 +From: Rex-BC Chen +Date: Fri, 22 Apr 2022 15:52:28 +0800 +Subject: [PATCH 05/21] cpufreq: mediatek: Replace old_* with pre_* + +To make driver more readable, replace old_* with pre_*. + +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 84 +++++++++++++++--------------- + 1 file changed, 42 insertions(+), 42 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -63,18 +63,18 @@ static int mtk_cpufreq_voltage_tracking( + { + struct regulator *proc_reg = info->proc_reg; + struct regulator *sram_reg = info->sram_reg; +- int old_vproc, old_vsram, new_vsram, vsram, vproc, ret; ++ int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; + +- old_vproc = regulator_get_voltage(proc_reg); +- if (old_vproc < 0) { ++ pre_vproc = regulator_get_voltage(proc_reg); ++ if (pre_vproc < 0) { + dev_err(info->cpu_dev, +- "invalid Vproc value: %d\n", old_vproc); +- return old_vproc; ++ "invalid Vproc value: %d\n", pre_vproc); ++ return pre_vproc; + } + /* Vsram should not exceed the maximum allowed voltage of SoC. */ + new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); + +- if (old_vproc < new_vproc) { ++ if (pre_vproc < new_vproc) { + /* + * When scaling up voltages, Vsram and Vproc scale up step + * by step. At each step, set Vsram to (Vproc + 200mV) first, +@@ -82,20 +82,20 @@ static int mtk_cpufreq_voltage_tracking( + * Keep doing it until Vsram and Vproc hit target voltages. + */ + do { +- old_vsram = regulator_get_voltage(sram_reg); +- if (old_vsram < 0) { ++ pre_vsram = regulator_get_voltage(sram_reg); ++ if (pre_vsram < 0) { + dev_err(info->cpu_dev, +- "invalid Vsram value: %d\n", old_vsram); +- return old_vsram; ++ "invalid Vsram value: %d\n", pre_vsram); ++ return pre_vsram; + } +- old_vproc = regulator_get_voltage(proc_reg); +- if (old_vproc < 0) { ++ pre_vproc = regulator_get_voltage(proc_reg); ++ if (pre_vproc < 0) { + dev_err(info->cpu_dev, +- "invalid Vproc value: %d\n", old_vproc); +- return old_vproc; ++ "invalid Vproc value: %d\n", pre_vproc); ++ return pre_vproc; + } + +- vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT); ++ vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT); + + if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { + vsram = MAX_VOLT_LIMIT; +@@ -124,12 +124,12 @@ static int mtk_cpufreq_voltage_tracking( + ret = regulator_set_voltage(proc_reg, vproc, + vproc + VOLT_TOL); + if (ret) { +- regulator_set_voltage(sram_reg, old_vsram, +- old_vsram); ++ regulator_set_voltage(sram_reg, pre_vsram, ++ pre_vsram); + return ret; + } + } while (vproc < new_vproc || vsram < new_vsram); +- } else if (old_vproc > new_vproc) { ++ } else if (pre_vproc > new_vproc) { + /* + * When scaling down voltages, Vsram and Vproc scale down step + * by step. At each step, set Vproc to (Vsram - 200mV) first, +@@ -137,20 +137,20 @@ static int mtk_cpufreq_voltage_tracking( + * Keep doing it until Vsram and Vproc hit target voltages. + */ + do { +- old_vproc = regulator_get_voltage(proc_reg); +- if (old_vproc < 0) { ++ pre_vproc = regulator_get_voltage(proc_reg); ++ if (pre_vproc < 0) { + dev_err(info->cpu_dev, +- "invalid Vproc value: %d\n", old_vproc); +- return old_vproc; ++ "invalid Vproc value: %d\n", pre_vproc); ++ return pre_vproc; + } +- old_vsram = regulator_get_voltage(sram_reg); +- if (old_vsram < 0) { ++ pre_vsram = regulator_get_voltage(sram_reg); ++ if (pre_vsram < 0) { + dev_err(info->cpu_dev, +- "invalid Vsram value: %d\n", old_vsram); +- return old_vsram; ++ "invalid Vsram value: %d\n", pre_vsram); ++ return pre_vsram; + } + +- vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT); ++ vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT); + ret = regulator_set_voltage(proc_reg, vproc, + vproc + VOLT_TOL); + if (ret) +@@ -180,8 +180,8 @@ static int mtk_cpufreq_voltage_tracking( + } + + if (ret) { +- regulator_set_voltage(proc_reg, old_vproc, +- old_vproc); ++ regulator_set_voltage(proc_reg, pre_vproc, ++ pre_vproc); + return ret; + } + } while (vproc > new_vproc + VOLT_TOL || +@@ -209,16 +209,16 @@ static int mtk_cpufreq_set_target(struct + struct mtk_cpu_dvfs_info *info = policy->driver_data; + struct device *cpu_dev = info->cpu_dev; + struct dev_pm_opp *opp; +- long freq_hz, old_freq_hz; +- int vproc, old_vproc, inter_vproc, target_vproc, ret; ++ long freq_hz, pre_freq_hz; ++ int vproc, pre_vproc, inter_vproc, target_vproc, ret; + + inter_vproc = info->intermediate_voltage; + +- old_freq_hz = clk_get_rate(cpu_clk); +- old_vproc = regulator_get_voltage(info->proc_reg); +- if (old_vproc < 0) { +- dev_err(cpu_dev, "invalid Vproc value: %d\n", old_vproc); +- return old_vproc; ++ pre_freq_hz = clk_get_rate(cpu_clk); ++ pre_vproc = regulator_get_voltage(info->proc_reg); ++ if (pre_vproc < 0) { ++ dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); ++ return pre_vproc; + } + + freq_hz = freq_table[index].frequency * 1000; +@@ -237,12 +237,12 @@ static int mtk_cpufreq_set_target(struct + * current voltage, scale up voltage first. + */ + target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; +- if (old_vproc < target_vproc) { ++ if (pre_vproc < target_vproc) { + ret = mtk_cpufreq_set_voltage(info, target_vproc); + if (ret) { + dev_err(cpu_dev, + "cpu%d: failed to scale up voltage!\n", policy->cpu); +- mtk_cpufreq_set_voltage(info, old_vproc); ++ mtk_cpufreq_set_voltage(info, pre_vproc); + return ret; + } + } +@@ -252,7 +252,7 @@ static int mtk_cpufreq_set_target(struct + if (ret) { + dev_err(cpu_dev, + "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); +- mtk_cpufreq_set_voltage(info, old_vproc); ++ mtk_cpufreq_set_voltage(info, pre_vproc); + WARN_ON(1); + return ret; + } +@@ -263,7 +263,7 @@ static int mtk_cpufreq_set_target(struct + dev_err(cpu_dev, + "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); + clk_set_parent(cpu_clk, armpll); +- mtk_cpufreq_set_voltage(info, old_vproc); ++ mtk_cpufreq_set_voltage(info, pre_vproc); + return ret; + } + +@@ -281,13 +281,13 @@ static int mtk_cpufreq_set_target(struct + * If the new voltage is lower than the intermediate voltage or the + * original voltage, scale down to the new voltage. + */ +- if (vproc < inter_vproc || vproc < old_vproc) { ++ if (vproc < inter_vproc || vproc < pre_vproc) { + ret = mtk_cpufreq_set_voltage(info, vproc); + if (ret) { + dev_err(cpu_dev, + "cpu%d: failed to scale down voltage!\n", policy->cpu); + clk_set_parent(cpu_clk, info->inter_clk); +- clk_set_rate(armpll, old_freq_hz); ++ clk_set_rate(armpll, pre_freq_hz); + clk_set_parent(cpu_clk, armpll); + return ret; + } diff --git a/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch b/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch new file mode 100644 index 00000000000..94e6617d267 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-06-cpufreq-mediatek-Record-previous-target-vproc-value.patch @@ -0,0 +1,64 @@ +From 34737eb8d0daa0d4183f10286a2f55d8788066bc Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 22 Apr 2022 15:52:29 +0800 +Subject: [PATCH 06/21] cpufreq: mediatek: Record previous target vproc value + +We found the buck voltage may not be exactly the same with what we set +because CPU may share the same buck with other module. +Therefore, we need to record the previous desired value instead of reading +it from regulators. + +Signed-off-by: Andrew-sh.Cheng +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -40,6 +40,7 @@ struct mtk_cpu_dvfs_info { + struct list_head list_head; + int intermediate_voltage; + bool need_voltage_tracking; ++ int pre_vproc; + }; + + static struct platform_device *cpufreq_pdev; +@@ -193,11 +194,17 @@ static int mtk_cpufreq_voltage_tracking( + + static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) + { ++ int ret; ++ + if (info->need_voltage_tracking) +- return mtk_cpufreq_voltage_tracking(info, vproc); ++ ret = mtk_cpufreq_voltage_tracking(info, vproc); + else +- return regulator_set_voltage(info->proc_reg, vproc, +- vproc + VOLT_TOL); ++ ret = regulator_set_voltage(info->proc_reg, vproc, ++ MAX_VOLT_LIMIT); ++ if (!ret) ++ info->pre_vproc = vproc; ++ ++ return ret; + } + + static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, +@@ -215,7 +222,12 @@ static int mtk_cpufreq_set_target(struct + inter_vproc = info->intermediate_voltage; + + pre_freq_hz = clk_get_rate(cpu_clk); +- pre_vproc = regulator_get_voltage(info->proc_reg); ++ ++ if (unlikely(info->pre_vproc <= 0)) ++ pre_vproc = regulator_get_voltage(info->proc_reg); ++ else ++ pre_vproc = info->pre_vproc; ++ + if (pre_vproc < 0) { + dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); + return pre_vproc; diff --git a/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch b/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch new file mode 100644 index 00000000000..4b74873b158 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-07-cpufreq-mediatek-Make-sram-regulator-optional.patch @@ -0,0 +1,30 @@ +From f6114c2bc563a8050e9dc874ad87e1448865f031 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 22 Apr 2022 15:52:33 +0800 +Subject: [PATCH 07/21] cpufreq: mediatek: Make sram regulator optional + +For some MediaTek SoCs, like MT8186, it's possible that the sram regulator +is shared between CPU and CCI. +We hope regulator framework can return error for error handling rather +than a dummy handler from regulator_get api. +Therefore, we choose to use regulator_get_optional. + +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -354,7 +354,7 @@ static int mtk_cpu_dvfs_info_init(struct + } + + /* Both presence and absence of sram regulator are valid cases. */ +- info->sram_reg = regulator_get_exclusive(cpu_dev, "sram"); ++ info->sram_reg = regulator_get_optional(cpu_dev, "sram"); + if (IS_ERR(info->sram_reg)) + info->sram_reg = NULL; + else { diff --git a/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch b/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch new file mode 100644 index 00000000000..f2f572a753f --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-08-cpufreq-mediatek-Fix-NULL-pointer-dereference-in-med.patch @@ -0,0 +1,32 @@ +From fa7030d8ad4638acfd9e0fac84a20716d031dc95 Mon Sep 17 00:00:00 2001 +From: Wan Jiabing +Date: Tue, 26 Apr 2022 19:17:14 +0800 +Subject: [PATCH 08/21] cpufreq: mediatek: Fix NULL pointer dereference in + mediatek-cpufreq + +Fix following coccicheck error: +drivers/cpufreq/mediatek-cpufreq.c:464:16-23: ERROR: info is NULL but dereferenced. + +Use pr_err instead of dev_err to avoid dereferring a NULL pointer. + +Fixes: f52b16ba9fe4 ("cpufreq: mediatek: Use device print to show logs") +Signed-off-by: Wan Jiabing +Reviewed-by: Matthias Brugger +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -463,8 +463,8 @@ static int mtk_cpufreq_init(struct cpufr + + info = mtk_cpu_dvfs_info_lookup(policy->cpu); + if (!info) { +- dev_err(info->cpu_dev, +- "dvfs info for cpu%d is not initialized.\n", policy->cpu); ++ pr_err("dvfs info for cpu%d is not initialized.\n", ++ policy->cpu); + return -EINVAL; + } + diff --git a/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch b/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch new file mode 100644 index 00000000000..23b319648dc --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-09-cpufreq-mediatek-Move-voltage-limits-to-platform-dat.patch @@ -0,0 +1,227 @@ +From be2354b064e6bafbbad599ae2e10569ba4f7d5a6 Mon Sep 17 00:00:00 2001 +From: Rex-BC Chen +Date: Thu, 5 May 2022 19:52:19 +0800 +Subject: [PATCH 09/21] cpufreq: mediatek: Move voltage limits to platform data + +Voltages and shifts are defined as macros originally. +There are different requirements of these values for each MediaTek SoCs. +Therefore, we add the platform data and move these values into it. + +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 84 +++++++++++++++++++++--------- + 1 file changed, 58 insertions(+), 26 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -10,15 +10,21 @@ + #include + #include + #include ++#include + #include + #include + #include + +-#define MIN_VOLT_SHIFT (100000) +-#define MAX_VOLT_SHIFT (200000) +-#define MAX_VOLT_LIMIT (1150000) + #define VOLT_TOL (10000) + ++struct mtk_cpufreq_platform_data { ++ int min_volt_shift; ++ int max_volt_shift; ++ int proc_max_volt; ++ int sram_min_volt; ++ int sram_max_volt; ++}; ++ + /* + * The struct mtk_cpu_dvfs_info holds necessary information for doing CPU DVFS + * on each CPU power/clock domain of Mediatek SoCs. Each CPU cluster in +@@ -41,6 +47,7 @@ struct mtk_cpu_dvfs_info { + int intermediate_voltage; + bool need_voltage_tracking; + int pre_vproc; ++ const struct mtk_cpufreq_platform_data *soc_data; + }; + + static struct platform_device *cpufreq_pdev; +@@ -62,6 +69,7 @@ static struct mtk_cpu_dvfs_info *mtk_cpu + static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, + int new_vproc) + { ++ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data; + struct regulator *proc_reg = info->proc_reg; + struct regulator *sram_reg = info->sram_reg; + int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; +@@ -73,7 +81,8 @@ static int mtk_cpufreq_voltage_tracking( + return pre_vproc; + } + /* Vsram should not exceed the maximum allowed voltage of SoC. */ +- new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT); ++ new_vsram = min(new_vproc + soc_data->min_volt_shift, ++ soc_data->sram_max_volt); + + if (pre_vproc < new_vproc) { + /* +@@ -96,10 +105,11 @@ static int mtk_cpufreq_voltage_tracking( + return pre_vproc; + } + +- vsram = min(new_vsram, pre_vproc + MAX_VOLT_SHIFT); ++ vsram = min(new_vsram, ++ pre_vproc + soc_data->min_volt_shift); + +- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { +- vsram = MAX_VOLT_LIMIT; ++ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { ++ vsram = soc_data->sram_max_volt; + + /* + * If the target Vsram hits the maximum voltage, +@@ -117,7 +127,7 @@ static int mtk_cpufreq_voltage_tracking( + ret = regulator_set_voltage(sram_reg, vsram, + vsram + VOLT_TOL); + +- vproc = vsram - MIN_VOLT_SHIFT; ++ vproc = vsram - soc_data->min_volt_shift; + } + if (ret) + return ret; +@@ -151,7 +161,8 @@ static int mtk_cpufreq_voltage_tracking( + return pre_vsram; + } + +- vproc = max(new_vproc, pre_vsram - MAX_VOLT_SHIFT); ++ vproc = max(new_vproc, ++ pre_vsram - soc_data->max_volt_shift); + ret = regulator_set_voltage(proc_reg, vproc, + vproc + VOLT_TOL); + if (ret) +@@ -160,10 +171,11 @@ static int mtk_cpufreq_voltage_tracking( + if (vproc == new_vproc) + vsram = new_vsram; + else +- vsram = max(new_vsram, vproc + MIN_VOLT_SHIFT); ++ vsram = max(new_vsram, ++ vproc + soc_data->min_volt_shift); + +- if (vsram + VOLT_TOL >= MAX_VOLT_LIMIT) { +- vsram = MAX_VOLT_LIMIT; ++ if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { ++ vsram = soc_data->sram_max_volt; + + /* + * If the target Vsram hits the maximum voltage, +@@ -194,13 +206,14 @@ static int mtk_cpufreq_voltage_tracking( + + static int mtk_cpufreq_set_voltage(struct mtk_cpu_dvfs_info *info, int vproc) + { ++ const struct mtk_cpufreq_platform_data *soc_data = info->soc_data; + int ret; + + if (info->need_voltage_tracking) + ret = mtk_cpufreq_voltage_tracking(info, vproc); + else + ret = regulator_set_voltage(info->proc_reg, vproc, +- MAX_VOLT_LIMIT); ++ soc_data->proc_max_volt); + if (!ret) + info->pre_vproc = vproc; + +@@ -509,9 +522,17 @@ static struct cpufreq_driver mtk_cpufreq + + static int mtk_cpufreq_probe(struct platform_device *pdev) + { ++ const struct mtk_cpufreq_platform_data *data; + struct mtk_cpu_dvfs_info *info, *tmp; + int cpu, ret; + ++ data = dev_get_platdata(&pdev->dev); ++ if (!data) { ++ dev_err(&pdev->dev, ++ "failed to get mtk cpufreq platform data\n"); ++ return -ENODEV; ++ } ++ + for_each_possible_cpu(cpu) { + info = mtk_cpu_dvfs_info_lookup(cpu); + if (info) +@@ -523,6 +544,7 @@ static int mtk_cpufreq_probe(struct plat + goto release_dvfs_info_list; + } + ++ info->soc_data = data; + ret = mtk_cpu_dvfs_info_init(info, cpu); + if (ret) { + dev_err(&pdev->dev, +@@ -558,20 +580,27 @@ static struct platform_driver mtk_cpufre + .probe = mtk_cpufreq_probe, + }; + ++static const struct mtk_cpufreq_platform_data mt2701_platform_data = { ++ .min_volt_shift = 100000, ++ .max_volt_shift = 200000, ++ .proc_max_volt = 1150000, ++ .sram_min_volt = 0, ++ .sram_max_volt = 1150000, ++}; ++ + /* List of machines supported by this driver */ + static const struct of_device_id mtk_cpufreq_machines[] __initconst = { +- { .compatible = "mediatek,mt2701", }, +- { .compatible = "mediatek,mt2712", }, +- { .compatible = "mediatek,mt7622", }, +- { .compatible = "mediatek,mt7623", }, +- { .compatible = "mediatek,mt8167", }, +- { .compatible = "mediatek,mt817x", }, +- { .compatible = "mediatek,mt8173", }, +- { .compatible = "mediatek,mt8176", }, +- { .compatible = "mediatek,mt8183", }, +- { .compatible = "mediatek,mt8365", }, +- { .compatible = "mediatek,mt8516", }, +- ++ { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, + { } + }; + MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); +@@ -580,6 +609,7 @@ static int __init mtk_cpufreq_driver_ini + { + struct device_node *np; + const struct of_device_id *match; ++ const struct mtk_cpufreq_platform_data *data; + int err; + + np = of_find_node_by_path("/"); +@@ -592,6 +622,7 @@ static int __init mtk_cpufreq_driver_ini + pr_debug("Machine is not compatible with mtk-cpufreq\n"); + return -ENODEV; + } ++ data = match->data; + + err = platform_driver_register(&mtk_cpufreq_platdrv); + if (err) +@@ -603,7 +634,8 @@ static int __init mtk_cpufreq_driver_ini + * and the device registration codes are put here to handle defer + * probing. + */ +- cpufreq_pdev = platform_device_register_simple("mtk-cpufreq", -1, NULL, 0); ++ cpufreq_pdev = platform_device_register_data(NULL, "mtk-cpufreq", -1, ++ data, sizeof(*data)); + if (IS_ERR(cpufreq_pdev)) { + pr_err("failed to register mtk-cpufreq platform device\n"); + platform_driver_unregister(&mtk_cpufreq_platdrv); diff --git a/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch b/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch new file mode 100644 index 00000000000..0ba9471ffa7 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-10-cpufreq-mediatek-Refine-mtk_cpufreq_voltage_tracking.patch @@ -0,0 +1,255 @@ +From 944b041c91f1e1cd762c39c1222f078550149486 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Thu, 5 May 2022 19:52:20 +0800 +Subject: [PATCH 10/21] cpufreq: mediatek: Refine + mtk_cpufreq_voltage_tracking() + +Because the difference of sram and proc should in a range of min_volt_shift +and max_volt_shift. We need to adjust the sram and proc step by step. + +We replace VOLT_TOL (voltage tolerance) with the platform data and update the +logic to determine the voltage boundary and invoking regulator_set_voltage. + +- Use 'sram_min_volt' and 'sram_max_volt' to determine the voltage boundary + of sram regulator. +- Use (sram_min_volt - min_volt_shift) and 'proc_max_volt' to determine the + voltage boundary of vproc regulator. + +Moreover, to prevent infinite loop when tracking voltage, we calculate the +maximum value for each platform data. +We assume min voltage is 0 and tracking target voltage using +min_volt_shift for each iteration. +The retry_max is 3 times of expeted iteration count. + +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 147 ++++++++++------------------- + 1 file changed, 51 insertions(+), 96 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -15,8 +16,6 @@ + #include + #include + +-#define VOLT_TOL (10000) +- + struct mtk_cpufreq_platform_data { + int min_volt_shift; + int max_volt_shift; +@@ -48,6 +47,7 @@ struct mtk_cpu_dvfs_info { + bool need_voltage_tracking; + int pre_vproc; + const struct mtk_cpufreq_platform_data *soc_data; ++ int vtrack_max; + }; + + static struct platform_device *cpufreq_pdev; +@@ -73,6 +73,7 @@ static int mtk_cpufreq_voltage_tracking( + struct regulator *proc_reg = info->proc_reg; + struct regulator *sram_reg = info->sram_reg; + int pre_vproc, pre_vsram, new_vsram, vsram, vproc, ret; ++ int retry = info->vtrack_max; + + pre_vproc = regulator_get_voltage(proc_reg); + if (pre_vproc < 0) { +@@ -80,91 +81,44 @@ static int mtk_cpufreq_voltage_tracking( + "invalid Vproc value: %d\n", pre_vproc); + return pre_vproc; + } +- /* Vsram should not exceed the maximum allowed voltage of SoC. */ +- new_vsram = min(new_vproc + soc_data->min_volt_shift, +- soc_data->sram_max_volt); +- +- if (pre_vproc < new_vproc) { +- /* +- * When scaling up voltages, Vsram and Vproc scale up step +- * by step. At each step, set Vsram to (Vproc + 200mV) first, +- * then set Vproc to (Vsram - 100mV). +- * Keep doing it until Vsram and Vproc hit target voltages. +- */ +- do { +- pre_vsram = regulator_get_voltage(sram_reg); +- if (pre_vsram < 0) { +- dev_err(info->cpu_dev, +- "invalid Vsram value: %d\n", pre_vsram); +- return pre_vsram; +- } +- pre_vproc = regulator_get_voltage(proc_reg); +- if (pre_vproc < 0) { +- dev_err(info->cpu_dev, +- "invalid Vproc value: %d\n", pre_vproc); +- return pre_vproc; +- } + +- vsram = min(new_vsram, +- pre_vproc + soc_data->min_volt_shift); ++ pre_vsram = regulator_get_voltage(sram_reg); ++ if (pre_vsram < 0) { ++ dev_err(info->cpu_dev, "invalid Vsram value: %d\n", pre_vsram); ++ return pre_vsram; ++ } + +- if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { +- vsram = soc_data->sram_max_volt; ++ new_vsram = clamp(new_vproc + soc_data->min_volt_shift, ++ soc_data->sram_min_volt, soc_data->sram_max_volt); ++ ++ do { ++ if (pre_vproc <= new_vproc) { ++ vsram = clamp(pre_vproc + soc_data->max_volt_shift, ++ soc_data->sram_min_volt, new_vsram); ++ ret = regulator_set_voltage(sram_reg, vsram, ++ soc_data->sram_max_volt); + +- /* +- * If the target Vsram hits the maximum voltage, +- * try to set the exact voltage value first. +- */ +- ret = regulator_set_voltage(sram_reg, vsram, +- vsram); +- if (ret) +- ret = regulator_set_voltage(sram_reg, +- vsram - VOLT_TOL, +- vsram); ++ if (ret) ++ return ret; + ++ if (vsram == soc_data->sram_max_volt || ++ new_vsram == soc_data->sram_min_volt) + vproc = new_vproc; +- } else { +- ret = regulator_set_voltage(sram_reg, vsram, +- vsram + VOLT_TOL); +- ++ else + vproc = vsram - soc_data->min_volt_shift; +- } +- if (ret) +- return ret; + + ret = regulator_set_voltage(proc_reg, vproc, +- vproc + VOLT_TOL); ++ soc_data->proc_max_volt); + if (ret) { + regulator_set_voltage(sram_reg, pre_vsram, +- pre_vsram); ++ soc_data->sram_max_volt); + return ret; + } +- } while (vproc < new_vproc || vsram < new_vsram); +- } else if (pre_vproc > new_vproc) { +- /* +- * When scaling down voltages, Vsram and Vproc scale down step +- * by step. At each step, set Vproc to (Vsram - 200mV) first, +- * then set Vproc to (Vproc + 100mV). +- * Keep doing it until Vsram and Vproc hit target voltages. +- */ +- do { +- pre_vproc = regulator_get_voltage(proc_reg); +- if (pre_vproc < 0) { +- dev_err(info->cpu_dev, +- "invalid Vproc value: %d\n", pre_vproc); +- return pre_vproc; +- } +- pre_vsram = regulator_get_voltage(sram_reg); +- if (pre_vsram < 0) { +- dev_err(info->cpu_dev, +- "invalid Vsram value: %d\n", pre_vsram); +- return pre_vsram; +- } +- ++ } else if (pre_vproc > new_vproc) { + vproc = max(new_vproc, + pre_vsram - soc_data->max_volt_shift); + ret = regulator_set_voltage(proc_reg, vproc, +- vproc + VOLT_TOL); ++ soc_data->proc_max_volt); + if (ret) + return ret; + +@@ -174,32 +128,24 @@ static int mtk_cpufreq_voltage_tracking( + vsram = max(new_vsram, + vproc + soc_data->min_volt_shift); + +- if (vsram + VOLT_TOL >= soc_data->sram_max_volt) { +- vsram = soc_data->sram_max_volt; +- +- /* +- * If the target Vsram hits the maximum voltage, +- * try to set the exact voltage value first. +- */ +- ret = regulator_set_voltage(sram_reg, vsram, +- vsram); +- if (ret) +- ret = regulator_set_voltage(sram_reg, +- vsram - VOLT_TOL, +- vsram); +- } else { +- ret = regulator_set_voltage(sram_reg, vsram, +- vsram + VOLT_TOL); +- } +- ++ ret = regulator_set_voltage(sram_reg, vsram, ++ soc_data->sram_max_volt); + if (ret) { + regulator_set_voltage(proc_reg, pre_vproc, +- pre_vproc); ++ soc_data->proc_max_volt); + return ret; + } +- } while (vproc > new_vproc + VOLT_TOL || +- vsram > new_vsram + VOLT_TOL); +- } ++ } ++ ++ pre_vproc = vproc; ++ pre_vsram = vsram; ++ ++ if (--retry < 0) { ++ dev_err(info->cpu_dev, ++ "over loop count, failed to set voltage\n"); ++ return -EINVAL; ++ } ++ } while (vproc != new_vproc || vsram != new_vsram); + + return 0; + } +@@ -261,8 +207,8 @@ static int mtk_cpufreq_set_target(struct + * If the new voltage or the intermediate voltage is higher than the + * current voltage, scale up voltage first. + */ +- target_vproc = (inter_vproc > vproc) ? inter_vproc : vproc; +- if (pre_vproc < target_vproc) { ++ target_vproc = max(inter_vproc, vproc); ++ if (pre_vproc <= target_vproc) { + ret = mtk_cpufreq_set_voltage(info, target_vproc); + if (ret) { + dev_err(cpu_dev, +@@ -417,6 +363,15 @@ static int mtk_cpu_dvfs_info_init(struct + */ + info->need_voltage_tracking = (info->sram_reg != NULL); + ++ /* ++ * We assume min voltage is 0 and tracking target voltage using ++ * min_volt_shift for each iteration. ++ * The vtrack_max is 3 times of expeted iteration count. ++ */ ++ info->vtrack_max = 3 * DIV_ROUND_UP(max(info->soc_data->sram_max_volt, ++ info->soc_data->proc_max_volt), ++ info->soc_data->min_volt_shift); ++ + return 0; + + out_disable_inter_clock: diff --git a/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch b/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch new file mode 100644 index 00000000000..2cb99b907a6 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-11-cpufreq-mediatek-Add-opp-notification-support.patch @@ -0,0 +1,184 @@ +From 01be227eff7e5fc01f7c8de8f6daddd5fb17ddd1 Mon Sep 17 00:00:00 2001 +From: Rex-BC Chen +Date: Thu, 5 May 2022 19:52:21 +0800 +Subject: [PATCH 11/21] cpufreq: mediatek: Add opp notification support + +From this opp notifier, cpufreq should listen to opp notification and do +proper actions when receiving events of disable and voltage adjustment. + +One of the user for this opp notifier is MediaTek SVS. +The MediaTek Smart Voltage Scaling (SVS) is a hardware which calculates +suitable SVS bank voltages to OPP voltage table. + +Signed-off-by: Andrew-sh.Cheng +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +[ Viresh: Renamed opp_freq as current_freq and moved its initialization ] +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 90 +++++++++++++++++++++++++++--- + 1 file changed, 82 insertions(+), 8 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -46,6 +46,11 @@ struct mtk_cpu_dvfs_info { + int intermediate_voltage; + bool need_voltage_tracking; + int pre_vproc; ++ /* Avoid race condition for regulators between notify and policy */ ++ struct mutex reg_lock; ++ struct notifier_block opp_nb; ++ unsigned int opp_cpu; ++ unsigned long current_freq; + const struct mtk_cpufreq_platform_data *soc_data; + int vtrack_max; + }; +@@ -182,6 +187,8 @@ static int mtk_cpufreq_set_target(struct + + pre_freq_hz = clk_get_rate(cpu_clk); + ++ mutex_lock(&info->reg_lock); ++ + if (unlikely(info->pre_vproc <= 0)) + pre_vproc = regulator_get_voltage(info->proc_reg); + else +@@ -214,7 +221,7 @@ static int mtk_cpufreq_set_target(struct + dev_err(cpu_dev, + "cpu%d: failed to scale up voltage!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, pre_vproc); +- return ret; ++ goto out; + } + } + +@@ -224,8 +231,7 @@ static int mtk_cpufreq_set_target(struct + dev_err(cpu_dev, + "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, pre_vproc); +- WARN_ON(1); +- return ret; ++ goto out; + } + + /* Set the original PLL to target rate. */ +@@ -235,7 +241,7 @@ static int mtk_cpufreq_set_target(struct + "cpu%d: failed to scale cpu clock rate!\n", policy->cpu); + clk_set_parent(cpu_clk, armpll); + mtk_cpufreq_set_voltage(info, pre_vproc); +- return ret; ++ goto out; + } + + /* Set parent of CPU clock back to the original PLL. */ +@@ -244,8 +250,7 @@ static int mtk_cpufreq_set_target(struct + dev_err(cpu_dev, + "cpu%d: failed to re-parent cpu clock!\n", policy->cpu); + mtk_cpufreq_set_voltage(info, inter_vproc); +- WARN_ON(1); +- return ret; ++ goto out; + } + + /* +@@ -260,15 +265,72 @@ static int mtk_cpufreq_set_target(struct + clk_set_parent(cpu_clk, info->inter_clk); + clk_set_rate(armpll, pre_freq_hz); + clk_set_parent(cpu_clk, armpll); +- return ret; ++ goto out; + } + } + +- return 0; ++ info->current_freq = freq_hz; ++ ++out: ++ mutex_unlock(&info->reg_lock); ++ ++ return ret; + } + + #define DYNAMIC_POWER "dynamic-power-coefficient" + ++static int mtk_cpufreq_opp_notifier(struct notifier_block *nb, ++ unsigned long event, void *data) ++{ ++ struct dev_pm_opp *opp = data; ++ struct dev_pm_opp *new_opp; ++ struct mtk_cpu_dvfs_info *info; ++ unsigned long freq, volt; ++ struct cpufreq_policy *policy; ++ int ret = 0; ++ ++ info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb); ++ ++ if (event == OPP_EVENT_ADJUST_VOLTAGE) { ++ freq = dev_pm_opp_get_freq(opp); ++ ++ mutex_lock(&info->reg_lock); ++ if (info->current_freq == freq) { ++ volt = dev_pm_opp_get_voltage(opp); ++ ret = mtk_cpufreq_set_voltage(info, volt); ++ if (ret) ++ dev_err(info->cpu_dev, ++ "failed to scale voltage: %d\n", ret); ++ } ++ mutex_unlock(&info->reg_lock); ++ } else if (event == OPP_EVENT_DISABLE) { ++ freq = dev_pm_opp_get_freq(opp); ++ ++ /* case of current opp item is disabled */ ++ if (info->current_freq == freq) { ++ freq = 1; ++ new_opp = dev_pm_opp_find_freq_ceil(info->cpu_dev, ++ &freq); ++ if (IS_ERR(new_opp)) { ++ dev_err(info->cpu_dev, ++ "all opp items are disabled\n"); ++ ret = PTR_ERR(new_opp); ++ return notifier_from_errno(ret); ++ } ++ ++ dev_pm_opp_put(new_opp); ++ policy = cpufreq_cpu_get(info->opp_cpu); ++ if (policy) { ++ cpufreq_driver_target(policy, freq / 1000, ++ CPUFREQ_RELATION_L); ++ cpufreq_cpu_put(policy); ++ } ++ } ++ } ++ ++ return notifier_from_errno(ret); ++} ++ + static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) + { + struct device *cpu_dev; +@@ -357,6 +419,17 @@ static int mtk_cpu_dvfs_info_init(struct + info->intermediate_voltage = dev_pm_opp_get_voltage(opp); + dev_pm_opp_put(opp); + ++ mutex_init(&info->reg_lock); ++ info->current_freq = clk_get_rate(info->cpu_clk); ++ ++ info->opp_cpu = cpu; ++ info->opp_nb.notifier_call = mtk_cpufreq_opp_notifier; ++ ret = dev_pm_opp_register_notifier(cpu_dev, &info->opp_nb); ++ if (ret) { ++ dev_err(cpu_dev, "cpu%d: failed to register opp notifier\n", cpu); ++ goto out_disable_inter_clock; ++ } ++ + /* + * If SRAM regulator is present, software "voltage tracking" is needed + * for this CPU power domain. +@@ -421,6 +494,7 @@ static void mtk_cpu_dvfs_info_release(st + } + + dev_pm_opp_of_cpumask_remove_table(&info->cpus); ++ dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb); + } + + static int mtk_cpufreq_init(struct cpufreq_policy *policy) diff --git a/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch b/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch new file mode 100644 index 00000000000..76bd795c004 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-12-cpufreq-mediatek-Fix-potential-deadlock-problem-in-m.patch @@ -0,0 +1,43 @@ +From 6a1bd7cf4ed7a1948f564aaf16d34b7352c0029b Mon Sep 17 00:00:00 2001 +From: Wan Jiabing +Date: Tue, 10 May 2022 17:05:31 +0800 +Subject: [PATCH 12/21] cpufreq: mediatek: Fix potential deadlock problem in + mtk_cpufreq_set_target + +Fix following coccichek error: +./drivers/cpufreq/mediatek-cpufreq.c:199:2-8: preceding lock on line +./drivers/cpufreq/mediatek-cpufreq.c:208:2-8: preceding lock on line + +mutex_lock is acquired but not released before return. +Use 'goto out' to help releasing the mutex_lock. + +Fixes: c210063b40ac ("cpufreq: mediatek: Add opp notification support") +Signed-off-by: Wan Jiabing +Reviewed-by: Rex-BC Chen +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -196,7 +196,8 @@ static int mtk_cpufreq_set_target(struct + + if (pre_vproc < 0) { + dev_err(cpu_dev, "invalid Vproc value: %d\n", pre_vproc); +- return pre_vproc; ++ ret = pre_vproc; ++ goto out; + } + + freq_hz = freq_table[index].frequency * 1000; +@@ -205,7 +206,8 @@ static int mtk_cpufreq_set_target(struct + if (IS_ERR(opp)) { + dev_err(cpu_dev, "cpu%d: failed to find OPP for %ld\n", + policy->cpu, freq_hz); +- return PTR_ERR(opp); ++ ret = PTR_ERR(opp); ++ goto out; + } + vproc = dev_pm_opp_get_voltage(opp); + dev_pm_opp_put(opp); diff --git a/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch b/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch new file mode 100644 index 00000000000..eeaa466c326 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-13-cpufreq-mediatek-Link-CCI-device-to-CPU.patch @@ -0,0 +1,188 @@ +From 15aaf74fb734a3e69b10d00b97b322711b81e222 Mon Sep 17 00:00:00 2001 +From: Rex-BC Chen +Date: Thu, 5 May 2022 19:52:22 +0800 +Subject: [PATCH 13/21] cpufreq: mediatek: Link CCI device to CPU + +In some MediaTek SoCs, like MT8183, CPU and CCI share the same power +supplies. Cpufreq needs to check if CCI devfreq exists and wait until +CCI devfreq ready before scaling frequency. + +Before CCI devfreq is ready, we record the voltage when booting to +kernel and use the max(cpu target voltage, booting voltage) to +prevent cpufreq adjust to the lower voltage which will cause the CCI +crash because of high frequency and low voltage. + +- Add is_ccifreq_ready() to link CCI device to CPI, and CPU will start + DVFS when CCI is ready. +- Add platform data for MT8183. + +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Kevin Hilman +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 82 +++++++++++++++++++++++++++++- + 1 file changed, 81 insertions(+), 1 deletion(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -22,6 +22,7 @@ struct mtk_cpufreq_platform_data { + int proc_max_volt; + int sram_min_volt; + int sram_max_volt; ++ bool ccifreq_supported; + }; + + /* +@@ -38,6 +39,7 @@ struct mtk_cpufreq_platform_data { + struct mtk_cpu_dvfs_info { + struct cpumask cpus; + struct device *cpu_dev; ++ struct device *cci_dev; + struct regulator *proc_reg; + struct regulator *sram_reg; + struct clk *cpu_clk; +@@ -45,6 +47,7 @@ struct mtk_cpu_dvfs_info { + struct list_head list_head; + int intermediate_voltage; + bool need_voltage_tracking; ++ int vproc_on_boot; + int pre_vproc; + /* Avoid race condition for regulators between notify and policy */ + struct mutex reg_lock; +@@ -53,6 +56,7 @@ struct mtk_cpu_dvfs_info { + unsigned long current_freq; + const struct mtk_cpufreq_platform_data *soc_data; + int vtrack_max; ++ bool ccifreq_bound; + }; + + static struct platform_device *cpufreq_pdev; +@@ -171,6 +175,28 @@ static int mtk_cpufreq_set_voltage(struc + return ret; + } + ++static bool is_ccifreq_ready(struct mtk_cpu_dvfs_info *info) ++{ ++ struct device_link *sup_link; ++ ++ if (info->ccifreq_bound) ++ return true; ++ ++ sup_link = device_link_add(info->cpu_dev, info->cci_dev, ++ DL_FLAG_AUTOREMOVE_CONSUMER); ++ if (!sup_link) { ++ dev_err(info->cpu_dev, "cpu%d: sup_link is NULL\n", info->opp_cpu); ++ return false; ++ } ++ ++ if (sup_link->supplier->links.status != DL_DEV_DRIVER_BOUND) ++ return false; ++ ++ info->ccifreq_bound = true; ++ ++ return true; ++} ++ + static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, + unsigned int index) + { +@@ -213,6 +239,14 @@ static int mtk_cpufreq_set_target(struct + dev_pm_opp_put(opp); + + /* ++ * If MediaTek cci is supported but is not ready, we will use the value ++ * of max(target cpu voltage, booting voltage) to prevent high freqeuncy ++ * low voltage crash. ++ */ ++ if (info->soc_data->ccifreq_supported && !is_ccifreq_ready(info)) ++ vproc = max(vproc, info->vproc_on_boot); ++ ++ /* + * If the new voltage or the intermediate voltage is higher than the + * current voltage, scale up voltage first. + */ +@@ -333,6 +367,23 @@ static int mtk_cpufreq_opp_notifier(stru + return notifier_from_errno(ret); + } + ++static struct device *of_get_cci(struct device *cpu_dev) ++{ ++ struct device_node *np; ++ struct platform_device *pdev; ++ ++ np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0); ++ if (IS_ERR_OR_NULL(np)) ++ return NULL; ++ ++ pdev = of_find_device_by_node(np); ++ of_node_put(np); ++ if (IS_ERR_OR_NULL(pdev)) ++ return NULL; ++ ++ return &pdev->dev; ++} ++ + static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) + { + struct device *cpu_dev; +@@ -347,6 +398,16 @@ static int mtk_cpu_dvfs_info_init(struct + } + info->cpu_dev = cpu_dev; + ++ info->ccifreq_bound = false; ++ if (info->soc_data->ccifreq_supported) { ++ info->cci_dev = of_get_cci(info->cpu_dev); ++ if (IS_ERR_OR_NULL(info->cci_dev)) { ++ ret = PTR_ERR(info->cci_dev); ++ dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu); ++ return -ENODEV; ++ } ++ } ++ + info->cpu_clk = clk_get(cpu_dev, "cpu"); + if (IS_ERR(info->cpu_clk)) { + ret = PTR_ERR(info->cpu_clk); +@@ -410,6 +471,15 @@ static int mtk_cpu_dvfs_info_init(struct + if (ret) + goto out_disable_mux_clock; + ++ if (info->soc_data->ccifreq_supported) { ++ info->vproc_on_boot = regulator_get_voltage(info->proc_reg); ++ if (info->vproc_on_boot < 0) { ++ dev_err(info->cpu_dev, ++ "invalid Vproc value: %d\n", info->vproc_on_boot); ++ goto out_disable_inter_clock; ++ } ++ } ++ + /* Search a safe voltage for intermediate frequency. */ + rate = clk_get_rate(info->inter_clk); + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); +@@ -617,6 +687,16 @@ static const struct mtk_cpufreq_platform + .proc_max_volt = 1150000, + .sram_min_volt = 0, + .sram_max_volt = 1150000, ++ .ccifreq_supported = false, ++}; ++ ++static const struct mtk_cpufreq_platform_data mt8183_platform_data = { ++ .min_volt_shift = 100000, ++ .max_volt_shift = 200000, ++ .proc_max_volt = 1150000, ++ .sram_min_volt = 0, ++ .sram_max_volt = 1150000, ++ .ccifreq_supported = true, + }; + + /* List of machines supported by this driver */ +@@ -629,7 +709,7 @@ static const struct of_device_id mtk_cpu + { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, +- { .compatible = "mediatek,mt8183", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, + { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, + { } diff --git a/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch b/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch new file mode 100644 index 00000000000..31000cfbe05 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-14-cpufreq-mediatek-Add-support-for-MT8186.patch @@ -0,0 +1,42 @@ +From b6be0baa6615afc65c3963adab674e36af1d4d5f Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Thu, 5 May 2022 19:52:23 +0800 +Subject: [PATCH 14/21] cpufreq: mediatek: Add support for MT8186 + +The platform data of MT8186 is different from previous MediaTek SoCs, +so we add a new compatible and platform data for it. + +Signed-off-by: Jia-Wei Chang +Signed-off-by: Rex-BC Chen +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -699,6 +699,15 @@ static const struct mtk_cpufreq_platform + .ccifreq_supported = true, + }; + ++static const struct mtk_cpufreq_platform_data mt8186_platform_data = { ++ .min_volt_shift = 100000, ++ .max_volt_shift = 250000, ++ .proc_max_volt = 1118750, ++ .sram_min_volt = 850000, ++ .sram_max_volt = 1118750, ++ .ccifreq_supported = true, ++}; ++ + /* List of machines supported by this driver */ + static const struct of_device_id mtk_cpufreq_machines[] __initconst = { + { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, +@@ -710,6 +719,7 @@ static const struct of_device_id mtk_cpu + { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, ++ { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data }, + { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, + { } diff --git a/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch b/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch new file mode 100644 index 00000000000..c0137894c93 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-15-cpufreq-mediatek-Handle-sram-regulator-probe-deferra.patch @@ -0,0 +1,35 @@ +From 75d19b24aa3203d6c78e4c431c2cc07157ce12fe Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Wed, 13 Jul 2022 13:15:36 +0200 +Subject: [PATCH 15/21] cpufreq: mediatek: Handle sram regulator probe deferral + +If the regulator_get_optional() call for the SRAM regulator returns +a probe deferral, we must bail out and retry probing later: failing +to do this will produce unstabilities on platforms requiring the +handling for this regulator. + +Fixes: ffa7bdf7f344 ("cpufreq: mediatek: Make sram regulator optional") +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -439,9 +439,13 @@ static int mtk_cpu_dvfs_info_init(struct + + /* Both presence and absence of sram regulator are valid cases. */ + info->sram_reg = regulator_get_optional(cpu_dev, "sram"); +- if (IS_ERR(info->sram_reg)) ++ if (IS_ERR(info->sram_reg)) { ++ ret = PTR_ERR(info->sram_reg); ++ if (ret == -EPROBE_DEFER) ++ goto out_free_resources; ++ + info->sram_reg = NULL; +- else { ++ } else { + ret = regulator_enable(info->sram_reg); + if (ret) { + dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); diff --git a/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch b/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch new file mode 100644 index 00000000000..45c4477ff1a --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-16-cpufreq-mediatek-fix-error-return-code-in-mtk_cpu_dv.patch @@ -0,0 +1,29 @@ +From dd1174c21dacacd6c0129c1dabc5decad35c02c2 Mon Sep 17 00:00:00 2001 +From: Yang Yingliang +Date: Tue, 17 May 2022 21:34:50 +0800 +Subject: [PATCH 16/21] cpufreq: mediatek: fix error return code in + mtk_cpu_dvfs_info_init() + +If regulator_get_voltage() fails, it should return the error code in +mtk_cpu_dvfs_info_init(). + +Fixes: 0daa47325bae ("cpufreq: mediatek: Link CCI device to CPU") +Reported-by: Hulk Robot +Signed-off-by: Yang Yingliang +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Rex-BC Chen +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -478,6 +478,7 @@ static int mtk_cpu_dvfs_info_init(struct + if (info->soc_data->ccifreq_supported) { + info->vproc_on_boot = regulator_get_voltage(info->proc_reg); + if (info->vproc_on_boot < 0) { ++ ret = info->vproc_on_boot; + dev_err(info->cpu_dev, + "invalid Vproc value: %d\n", info->vproc_on_boot); + goto out_disable_inter_clock; diff --git a/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch b/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch new file mode 100644 index 00000000000..557d02b822b --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-17-cpufreq-mediatek-fix-passing-zero-to-PTR_ERR.patch @@ -0,0 +1,47 @@ +From 230a74d459244411db91bfd678f17fcf7aedfcd0 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 24 Mar 2023 18:11:27 +0800 +Subject: [PATCH 17/21] cpufreq: mediatek: fix passing zero to 'PTR_ERR' + +In order to prevent passing zero to 'PTR_ERR' in +mtk_cpu_dvfs_info_init(), we fix the return value of of_get_cci() using +error pointer by explicitly casting error number. + +Signed-off-by: Jia-Wei Chang +Fixes: 0daa47325bae ("cpufreq: mediatek: Link CCI device to CPU") +Reported-by: Dan Carpenter +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -373,13 +373,13 @@ static struct device *of_get_cci(struct + struct platform_device *pdev; + + np = of_parse_phandle(cpu_dev->of_node, "mediatek,cci", 0); +- if (IS_ERR_OR_NULL(np)) +- return NULL; ++ if (!np) ++ return ERR_PTR(-ENODEV); + + pdev = of_find_device_by_node(np); + of_node_put(np); +- if (IS_ERR_OR_NULL(pdev)) +- return NULL; ++ if (!pdev) ++ return ERR_PTR(-ENODEV); + + return &pdev->dev; + } +@@ -401,7 +401,7 @@ static int mtk_cpu_dvfs_info_init(struct + info->ccifreq_bound = false; + if (info->soc_data->ccifreq_supported) { + info->cci_dev = of_get_cci(info->cpu_dev); +- if (IS_ERR_OR_NULL(info->cci_dev)) { ++ if (IS_ERR(info->cci_dev)) { + ret = PTR_ERR(info->cci_dev); + dev_err(cpu_dev, "cpu%d: failed to get cci device\n", cpu); + return -ENODEV; diff --git a/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch b/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch new file mode 100644 index 00000000000..61531d38ad2 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-18-cpufreq-mediatek-fix-KP-caused-by-handler-usage-afte.patch @@ -0,0 +1,149 @@ +From fced531b7c7e18192e7982637c8e8f20c29aad64 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 24 Mar 2023 18:11:28 +0800 +Subject: [PATCH 18/21] cpufreq: mediatek: fix KP caused by handler usage after + regulator_put/clk_put + +Any kind of failure in mtk_cpu_dvfs_info_init() will lead to calling +regulator_put() or clk_put() and the KP will occur since the regulator/clk +handlers are used after released in mtk_cpu_dvfs_info_release(). + +To prevent the usage after regulator_put()/clk_put(), the regulator/clk +handlers are addressed in a way of "Free the Last Thing Style". + +Signed-off-by: Jia-Wei Chang +Fixes: 4b9ceb757bbb ("cpufreq: mediatek: Enable clocks and regulators") +Suggested-by: AngeloGioacchino Del Regno +Suggested-by: Dan Carpenter +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 62 +++++++++++++++--------------- + 1 file changed, 30 insertions(+), 32 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -420,7 +420,7 @@ static int mtk_cpu_dvfs_info_init(struct + ret = PTR_ERR(info->inter_clk); + dev_err_probe(cpu_dev, ret, + "cpu%d: failed to get intermediate clk\n", cpu); +- goto out_free_resources; ++ goto out_free_mux_clock; + } + + info->proc_reg = regulator_get_optional(cpu_dev, "proc"); +@@ -428,13 +428,13 @@ static int mtk_cpu_dvfs_info_init(struct + ret = PTR_ERR(info->proc_reg); + dev_err_probe(cpu_dev, ret, + "cpu%d: failed to get proc regulator\n", cpu); +- goto out_free_resources; ++ goto out_free_inter_clock; + } + + ret = regulator_enable(info->proc_reg); + if (ret) { + dev_warn(cpu_dev, "cpu%d: failed to enable vproc\n", cpu); +- goto out_free_resources; ++ goto out_free_proc_reg; + } + + /* Both presence and absence of sram regulator are valid cases. */ +@@ -442,14 +442,14 @@ static int mtk_cpu_dvfs_info_init(struct + if (IS_ERR(info->sram_reg)) { + ret = PTR_ERR(info->sram_reg); + if (ret == -EPROBE_DEFER) +- goto out_free_resources; ++ goto out_disable_proc_reg; + + info->sram_reg = NULL; + } else { + ret = regulator_enable(info->sram_reg); + if (ret) { + dev_warn(cpu_dev, "cpu%d: failed to enable vsram\n", cpu); +- goto out_free_resources; ++ goto out_free_sram_reg; + } + } + +@@ -458,13 +458,13 @@ static int mtk_cpu_dvfs_info_init(struct + if (ret) { + dev_err(cpu_dev, + "cpu%d: failed to get OPP-sharing information\n", cpu); +- goto out_free_resources; ++ goto out_disable_sram_reg; + } + + ret = dev_pm_opp_of_cpumask_add_table(&info->cpus); + if (ret) { + dev_warn(cpu_dev, "cpu%d: no OPP table\n", cpu); +- goto out_free_resources; ++ goto out_disable_sram_reg; + } + + ret = clk_prepare_enable(info->cpu_clk); +@@ -533,43 +533,41 @@ out_disable_mux_clock: + out_free_opp_table: + dev_pm_opp_of_cpumask_remove_table(&info->cpus); + +-out_free_resources: +- if (regulator_is_enabled(info->proc_reg)) +- regulator_disable(info->proc_reg); +- if (info->sram_reg && regulator_is_enabled(info->sram_reg)) ++out_disable_sram_reg: ++ if (info->sram_reg) + regulator_disable(info->sram_reg); + +- if (!IS_ERR(info->proc_reg)) +- regulator_put(info->proc_reg); +- if (!IS_ERR(info->sram_reg)) ++out_free_sram_reg: ++ if (info->sram_reg) + regulator_put(info->sram_reg); +- if (!IS_ERR(info->cpu_clk)) +- clk_put(info->cpu_clk); +- if (!IS_ERR(info->inter_clk)) +- clk_put(info->inter_clk); ++ ++out_disable_proc_reg: ++ regulator_disable(info->proc_reg); ++ ++out_free_proc_reg: ++ regulator_put(info->proc_reg); ++ ++out_free_inter_clock: ++ clk_put(info->inter_clk); ++ ++out_free_mux_clock: ++ clk_put(info->cpu_clk); + + return ret; + } + + static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) + { +- if (!IS_ERR(info->proc_reg)) { +- regulator_disable(info->proc_reg); +- regulator_put(info->proc_reg); +- } +- if (!IS_ERR(info->sram_reg)) { ++ regulator_disable(info->proc_reg); ++ regulator_put(info->proc_reg); ++ if (info->sram_reg) { + regulator_disable(info->sram_reg); + regulator_put(info->sram_reg); + } +- if (!IS_ERR(info->cpu_clk)) { +- clk_disable_unprepare(info->cpu_clk); +- clk_put(info->cpu_clk); +- } +- if (!IS_ERR(info->inter_clk)) { +- clk_disable_unprepare(info->inter_clk); +- clk_put(info->inter_clk); +- } +- ++ clk_disable_unprepare(info->cpu_clk); ++ clk_put(info->cpu_clk); ++ clk_disable_unprepare(info->inter_clk); ++ clk_put(info->inter_clk); + dev_pm_opp_of_cpumask_remove_table(&info->cpus); + dev_pm_opp_unregister_notifier(info->cpu_dev, &info->opp_nb); + } diff --git a/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch b/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch new file mode 100644 index 00000000000..2b7d229f1c5 --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-19-cpufreq-mediatek-raise-proc-sram-max-voltage-for-MT8.patch @@ -0,0 +1,55 @@ +From 24bc42a2d44cb821818717a5c607270921ec5d20 Mon Sep 17 00:00:00 2001 +From: Jia-Wei Chang +Date: Fri, 24 Mar 2023 18:11:29 +0800 +Subject: [PATCH 19/21] cpufreq: mediatek: raise proc/sram max voltage for + MT8516 + +Since the upper boundary of proc/sram voltage of MT8516 is 1300 mV, +which is greater than the value of MT2701 1150 mV, we fix it by adding +the corresponding platform data and specify proc/sram_max_volt to +support MT8516. + +Signed-off-by: Jia-Wei Chang +Fixes: ead858bd128d ("cpufreq: mediatek: Move voltage limits to platform data") +Fixes: 6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()") +Reported-by: Nick Hainke +Reviewed-by: AngeloGioacchino Del Regno +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -711,20 +711,29 @@ static const struct mtk_cpufreq_platform + .ccifreq_supported = true, + }; + ++static const struct mtk_cpufreq_platform_data mt8516_platform_data = { ++ .min_volt_shift = 100000, ++ .max_volt_shift = 200000, ++ .proc_max_volt = 1310000, ++ .sram_min_volt = 0, ++ .sram_max_volt = 1310000, ++ .ccifreq_supported = false, ++}; ++ + /* List of machines supported by this driver */ + static const struct of_device_id mtk_cpufreq_machines[] __initconst = { + { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, +- { .compatible = "mediatek,mt8167", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, + { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8176", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8183", .data = &mt8183_platform_data }, + { .compatible = "mediatek,mt8186", .data = &mt8186_platform_data }, + { .compatible = "mediatek,mt8365", .data = &mt2701_platform_data }, +- { .compatible = "mediatek,mt8516", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt8516", .data = &mt8516_platform_data }, + { } + }; + MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); diff --git a/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch b/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch new file mode 100644 index 00000000000..2de8eb6394c --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-20-cpufreq-mediatek-Raise-proc-and-sram-max-voltage-for.patch @@ -0,0 +1,58 @@ +From fe6ef09358dc0cfead9d383a8676fbe7a40fcef7 Mon Sep 17 00:00:00 2001 +From: AngeloGioacchino Del Regno +Date: Fri, 24 Mar 2023 18:11:30 +0800 +Subject: [PATCH 20/21] cpufreq: mediatek: Raise proc and sram max voltage for + MT7622/7623 + +During the addition of SRAM voltage tracking for CCI scaling, this +driver got some voltage limits set for the vtrack algorithm: these +were moved to platform data first, then enforced in a later commit +6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()") +using these as max values for the regulator_set_voltage() calls. + +In this case, the vsram/vproc constraints for MT7622 and MT7623 +were supposed to be the same as MT2701 (and a number of other SoCs), +but that turned out to be a mistake because the aforementioned two +SoCs' maximum voltage for both VPROC and VPROC_SRAM is 1.36V. + +Fix that by adding new platform data for MT7622/7623 declaring the +right {proc,sram}_max_volt parameter. + +Fixes: ead858bd128d ("cpufreq: mediatek: Move voltage limits to platform data") +Fixes: 6a17b3876bc8 ("cpufreq: mediatek: Refine mtk_cpufreq_voltage_tracking()") +Signed-off-by: AngeloGioacchino Del Regno +Signed-off-by: Jia-Wei Chang +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/mediatek-cpufreq.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -693,6 +693,15 @@ static const struct mtk_cpufreq_platform + .ccifreq_supported = false, + }; + ++static const struct mtk_cpufreq_platform_data mt7622_platform_data = { ++ .min_volt_shift = 100000, ++ .max_volt_shift = 200000, ++ .proc_max_volt = 1360000, ++ .sram_min_volt = 0, ++ .sram_max_volt = 1360000, ++ .ccifreq_supported = false, ++}; ++ + static const struct mtk_cpufreq_platform_data mt8183_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, +@@ -724,8 +733,8 @@ static const struct mtk_cpufreq_platform + static const struct of_device_id mtk_cpufreq_machines[] __initconst = { + { .compatible = "mediatek,mt2701", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, +- { .compatible = "mediatek,mt7622", .data = &mt2701_platform_data }, +- { .compatible = "mediatek,mt7623", .data = &mt2701_platform_data }, ++ { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, ++ { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, + { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, + { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, diff --git a/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch b/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch new file mode 100644 index 00000000000..6acd3d607fb --- /dev/null +++ b/target/linux/mediatek/patches-5.15/350-21-cpufreq-mediatek-Add-support-for-MT7988.patch @@ -0,0 +1,41 @@ +From 4983a1517e7ddbc6f53fc07607e4ebeb51412843 Mon Sep 17 00:00:00 2001 +From: Sam Shih +Date: Tue, 28 Feb 2023 19:59:22 +0800 +Subject: [PATCH 21/21] cpufreq: mediatek: Add support for MT7988 + +This add cpufreq support for mediatek MT7988 SoC. + +The platform data of MT7988 is different from previous MediaTek SoCs, +so we add a new compatible and platform data for it. + +Signed-off-by: Sam Shih +--- + drivers/cpufreq/mediatek-cpufreq.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -702,6 +702,15 @@ static const struct mtk_cpufreq_platform + .ccifreq_supported = false, + }; + ++static const struct mtk_cpufreq_platform_data mt7988_platform_data = { ++ .min_volt_shift = 100000, ++ .max_volt_shift = 200000, ++ .proc_max_volt = 900000, ++ .sram_min_volt = 0, ++ .sram_max_volt = 1150000, ++ .ccifreq_supported = true, ++}; ++ + static const struct mtk_cpufreq_platform_data mt8183_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, +@@ -735,6 +744,7 @@ static const struct of_device_id mtk_cpu + { .compatible = "mediatek,mt2712", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt7622", .data = &mt7622_platform_data }, + { .compatible = "mediatek,mt7623", .data = &mt7622_platform_data }, ++ { .compatible = "mediatek,mt7988", .data = &mt7988_platform_data }, + { .compatible = "mediatek,mt8167", .data = &mt8516_platform_data }, + { .compatible = "mediatek,mt817x", .data = &mt2701_platform_data }, + { .compatible = "mediatek,mt8173", .data = &mt2701_platform_data }, diff --git a/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch b/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch new file mode 100644 index 00000000000..a7a4bd8ea2b --- /dev/null +++ b/target/linux/mediatek/patches-5.15/351-cpufreq-mediatek-don-t-request-unsupported-voltage.patch @@ -0,0 +1,29 @@ +From 20aad28ba5d62f1618408c264384d0b2ad7417db Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Mon, 22 May 2023 23:25:48 +0100 +Subject: [PATCH] cpufreq: mediatek: don't request unsupported voltage + +PMICs on MT7622 and MT7623 boards only support up to 1350000uV despite +the SoC's processor and SRAM voltage can be up to 1360000uV. As a +work-around specify max. processor and SRAM voltage as 1350000uV to +avoid requesting an unsupported voltage from the regulator. + +Signed-off-by: Daniel Golle +--- + drivers/cpufreq/mediatek-cpufreq.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/cpufreq/mediatek-cpufreq.c ++++ b/drivers/cpufreq/mediatek-cpufreq.c +@@ -696,9 +696,9 @@ static const struct mtk_cpufreq_platform + static const struct mtk_cpufreq_platform_data mt7622_platform_data = { + .min_volt_shift = 100000, + .max_volt_shift = 200000, +- .proc_max_volt = 1360000, ++ .proc_max_volt = 1350000, + .sram_min_volt = 0, +- .sram_max_volt = 1360000, ++ .sram_max_volt = 1350000, + .ccifreq_supported = false, + }; + From e3a681bab4b2c193704e76b8a6091e57f0fab14e Mon Sep 17 00:00:00 2001 From: Sam Shih Date: Sun, 19 Feb 2023 10:18:36 +0800 Subject: [PATCH 17/43] mediatek: add basic mt7988 device tree support This add basic device tree support for mediatek MT7988 SoC Signed-off-by: Sam Shih Signed-off-by: Daniel Golle --- .../mediatek/mt7988a-dsa-10g-spim-nand.dts | 200 ++++ .../dts/mediatek/mt7988a-rfb-spim-nand.dtsi | 70 ++ .../arm64/boot/dts/mediatek/mt7988a-rfb.dtsi | 175 ++++ .../arch/arm64/boot/dts/mediatek/mt7988a.dtsi | 853 ++++++++++++++++++ .../filogic/base-files/etc/board.d/02_network | 3 + target/linux/mediatek/filogic/config-5.15 | 1 + target/linux/mediatek/image/filogic.mk | 18 + 7 files changed, 1320 insertions(+) create mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts create mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtsi create mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dtsi create mode 100644 target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts new file mode 100644 index 00000000000..98dbf8d6913 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-dsa-10g-spim-nand.dts @@ -0,0 +1,200 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7988a-rfb-spim-nand.dtsi" +#include + +/ { + model = "MediaTek MT7988A DSA 10G SPIM-NAND RFB"; + compatible = "mediatek,mt7988a-dsa-10g-spim-snand", + "mediatek,mt7988a-rfb-snand", + "mediatek,mt7988"; + + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11000000 \ + pci=pcie_bus_perf"; + }; + + memory { + reg = <0 0x40000000 0 0x40000000>; + }; +}; + +ð { + pinctrl-0 = <&mdio0_pins>; + pinctrl-names = "default"; + status = "okay"; + + gmac0: mac@0 { + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "internal"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "internal"; + phy-connection-type = "internal"; + phy = <&phy15>; + }; + + gmac2: mac@2 { + compatible = "mediatek,eth-mac"; + reg = <2>; + phy-mode = "10gbase-kr"; + phy-connection-type = "10gbase-kr"; + phy = <&phy8>; + }; + + mdio0: mdio-bus { + #address-cells = <1>; + #size-cells = <0>; + + /* external Aquantia AQR113C */ + phy0: ethernet-phy@0 { + reg = <0>; + compatible = "ethernet-phy-ieee802.3-c45"; + reset-gpios = <&pio 72 1>; + reset-assert-us = <100000>; + reset-deassert-us = <221000>; + }; + + /* external Aquantia AQR113C */ + phy8: ethernet-phy@8 { + reg = <8>; + compatible = "ethernet-phy-ieee802.3-c45"; + reset-gpios = <&pio 71 1>; + reset-assert-us = <100000>; + reset-deassert-us = <221000>; + }; + + /* external Maxlinear GPY211C */ + phy5: ethernet-phy@5 { + reg = <5>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + }; + + /* external Maxlinear GPY211C */ + phy13: ethernet-phy@13 { + reg = <13>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "2500base-x"; + }; + + /* internal 2.5G PHY */ + phy15: ethernet-phy@15 { + reg = <15>; + pinctrl-names = "i2p5gbe-led"; + pinctrl-0 = <&i2p5gbe_led0_pins>; + compatible = "ethernet-phy-ieee802.3-c45"; + phy-mode = "internal"; + }; + }; +}; + +&switch { + status = "okay"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan0"; + phy-mode = "internal"; + phy-handle = <&gsw_phy0>; + }; + + port@1 { + reg = <1>; + label = "lan1"; + phy-mode = "internal"; + phy-handle = <&gsw_phy1>; + }; + + port@2 { + reg = <2>; + label = "lan2"; + phy-mode = "internal"; + phy-handle = <&gsw_phy2>; + }; + + port@3 { + reg = <3>; + label = "lan3"; + phy-mode = "internal"; + phy-handle = <&gsw_phy3>; + }; + + port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "internal"; + + fixed-link { + speed = <10000>; + full-duplex; + pause; + }; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy0: ethernet-phy@0 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <0>; + phy-mode = "internal"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe0_led0_pins>; + nvmem-cells = <&phy_calibration_p0>; + nvmem-cell-names = "phy-cal-data"; + }; + + gsw_phy1: ethernet-phy@1 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <1>; + phy-mode = "internal"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe1_led0_pins>; + nvmem-cells = <&phy_calibration_p1>; + nvmem-cell-names = "phy-cal-data"; + }; + + gsw_phy2: ethernet-phy@2 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <2>; + phy-mode = "internal"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe2_led0_pins>; + nvmem-cells = <&phy_calibration_p2>; + nvmem-cell-names = "phy-cal-data"; + }; + + gsw_phy3: ethernet-phy@3 { + compatible = "ethernet-phy-id03a2.9481"; + reg = <3>; + phy-mode = "internal"; + pinctrl-names = "gbe-led"; + pinctrl-0 = <&gbe3_led0_pins>; + nvmem-cells = <&phy_calibration_p3>; + nvmem-cell-names = "phy-cal-data"; + }; + }; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtsi new file mode 100644 index 00000000000..e4c05712509 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb-spim-nand.dtsi @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7988a-rfb.dtsi" + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + }; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + + spi_nand: spi_nand@0 { + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + }; + +}; + +&spi_nand { + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "BL2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "Factory"; + reg = <0x180000 0x0400000>; + }; + + partition@580000 { + label = "FIP"; + reg = <0x580000 0x0200000>; + }; + + partition@780000 { + label = "ubi"; + reg = <0x780000 0x7080000>; + }; + }; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dtsi new file mode 100644 index 00000000000..423b3860c6c --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a-rfb.dtsi @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2022 MediaTek Inc. + * Author: Sam.Shih + */ + +/dts-v1/; +#include "mt7988a.dtsi" +#include + +&cpu0 { + proc-supply = <&rt5190_buck3>; +}; + +&cpu1 { + proc-supply = <&rt5190_buck3>; +}; + +&cpu2 { + proc-supply = <&rt5190_buck3>; +}; + +&cpu3 { + proc-supply = <&rt5190_buck3>; +}; + +&cci { + proc-supply = <&rt5190_buck3>; +}; + +ð { + status = "okay"; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + status = "okay"; + + rt5190a_64: rt5190a@64 { + compatible = "richtek,rt5190a"; + reg = <0x64>; + /*interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;*/ + vin2-supply = <&rt5190_buck1>; + vin3-supply = <&rt5190_buck1>; + vin4-supply = <&rt5190_buck1>; + + regulators { + rt5190_buck1: buck1 { + regulator-name = "rt5190a-buck1"; + regulator-min-microvolt = <5090000>; + regulator-max-microvolt = <5090000>; + regulator-allowed-modes = + ; + regulator-boot-on; + regulator-always-on; + }; + buck2 { + regulator-name = "vcore"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + regulator-always-on; + }; + rt5190_buck3: buck3 { + regulator-name = "vproc"; + regulator-min-microvolt = <600000>; + regulator-max-microvolt = <1400000>; + regulator-boot-on; + }; + buck4 { + regulator-name = "rt5190a-buck4"; + regulator-min-microvolt = <850000>; + regulator-max-microvolt = <850000>; + regulator-allowed-modes = + ; + regulator-boot-on; + regulator-always-on; + }; + ldo { + regulator-name = "rt5190a-ldo"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + regulator-always-on; + }; + }; + }; +}; + +&pcie0 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie0_pins>; + status = "okay"; +}; + +&pcie1 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie1_pins>; + status = "okay"; +}; + +&pcie2 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie2_pins>; + status = "disabled"; +}; + +&pcie3 { + pinctrl-names = "default"; + pinctrl-0 = <&pcie3_pins>; + status = "okay"; +}; + +&ssusb0 { + status = "okay"; +}; + +&ssusb1 { + status = "okay"; +}; + +&tphy { + status = "okay"; +}; + +&pio { + pcie0_pins: pcie0-pins { + mux { + function = "pcie"; + groups = "pcie_2l_0_pereset", "pcie_clk_req_n0_0", + "pcie_wake_n0_0"; + }; + }; + + pcie1_pins: pcie1-pins { + mux { + function = "pcie"; + groups = "pcie_2l_1_pereset", "pcie_clk_req_n1", + "pcie_wake_n1_0"; + }; + }; + + pcie2_pins: pcie2-pins { + mux { + function = "pcie"; + groups = "pcie_1l_0_pereset", "pcie_clk_req_n2_0", + "pcie_wake_n2_0"; + }; + }; + + pcie3_pins: pcie3-pins { + mux { + function = "pcie"; + groups = "pcie_1l_1_pereset", "pcie_clk_req_n3", + "pcie_wake_n3_0"; + }; + }; +}; + +&spi0 { + status = "disabled"; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +&xphy { + status = "okay"; +}; diff --git a/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi new file mode 100644 index 00000000000..13ad39500d1 --- /dev/null +++ b/target/linux/mediatek/files-5.15/arch/arm64/boot/dts/mediatek/mt7988a.dtsi @@ -0,0 +1,853 @@ +// SPDX-License-Identifier: (GPL-2.0 OR MIT) +/* + * Copyright (C) 2023 MediaTek Inc. + * Author: Sam.Shih + */ + +#include +#include +#include +#include +#include +#include +#include + +/ { + compatible = "mediatek,mt7988"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + clk40m: oscillator@0 { + compatible = "fixed-clock"; + clock-frequency = <40000000>; + #clock-cells = <0>; + clock-output-names = "clkxtal"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a73"; + enable-method = "psci"; + reg = <0x0>; + clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + mediatek,cci = <&cci>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a73"; + enable-method = "psci"; + reg = <0x1>; + clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + mediatek,cci = <&cci>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a73"; + enable-method = "psci"; + reg = <0x2>; + clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + mediatek,cci = <&cci>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a73"; + enable-method = "psci"; + reg = <0x3>; + clocks = <&mcusys CLK_MCU_ARM_DIV_SEL>, + <&topckgen CLK_TOP_XTAL>; + clock-names = "cpu", "intermediate"; + operating-points-v2 = <&cluster0_opp>; + mediatek,cci = <&cci>; + }; + + cluster0_opp: opp_table0 { + compatible = "operating-points-v2"; + opp-shared; + opp00 { + opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <850000>; + }; + opp01 { + opp-hz = /bits/ 64 <1100000000>; + opp-microvolt = <850000>; + }; + opp02 { + opp-hz = /bits/ 64 <1500000000>; + opp-microvolt = <850000>; + }; + opp03 { + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <900000>; + }; + }; + }; + + cci: cci { + compatible = "mediatek,mt7988-cci", + "mediatek,mt8183-cci"; + clocks = <&mcusys CLK_MCU_BUS_DIV_SEL>, + <&topckgen CLK_TOP_XTAL>; + clock-names = "cci", "intermediate"; + operating-points-v2 = <&cci_opp>; + }; + + cci_opp: opp_table_cci { + compatible = "operating-points-v2"; + opp-shared; + opp00 { + opp-hz = /bits/ 64 <480000000>; + opp-microvolt = <850000>; + }; + opp01 { + opp-hz = /bits/ 64 <660000000>; + opp-microvolt = <850000>; + }; + opp02 { + opp-hz = /bits/ 64 <900000000>; + opp-microvolt = <850000>; + }; + opp03 { + opp-hz = /bits/ 64 <1080000000>; + opp-microvolt = <900000>; + }; + }; + + pmu { + compatible = "arm,cortex-a73-pmu"; + interrupt-parent = <&gic>; + interrupt = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + /* 192 KiB reserved for ARM Trusted Firmware (BL31) */ + secmon_reserved: secmon@43000000 { + reg = <0 0x43000000 0 0x30000>; + no-map; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + ranges; + + gic: interrupt-controller@c000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-parent = <&gic>; + interrupt-controller; + reg = <0 0x0c000000 0 0x40000>, /* GICD */ + <0 0x0c080000 0 0x200000>, /* GICR */ + <0 0x0c400000 0 0x2000>, /* GICC */ + <0 0x0c410000 0 0x1000>, /* GICH */ + <0 0x0c420000 0 0x2000>; /* GICV */ + + interrupts = ; + }; + + phyfw: phy-firmware@f000000 { + compatible = "mediatek,2p5gphy-fw"; + reg = <0 0x0f000000 0 0x8000>, + <0 0x0f100000 0 0x20000>, + <0 0x0f0f0000 0 0x200>; + }; + + infracfg: infracfg@10001000 { + compatible = "mediatek,mt7988-infracfg", "syscon"; + reg = <0 0x10001000 0 0x1000>; + #clock-cells = <1>; + }; + + topckgen: topckgen@1001b000 { + compatible = "mediatek,mt7988-topckgen", "syscon"; + reg = <0 0x1001b000 0 0x1000>; + #clock-cells = <1>; + }; + + watchdog: watchdog@1001c000 { + compatible = "mediatek,mt7988-wdt", + "mediatek,mt6589-wdt", + "syscon"; + reg = <0 0x1001c000 0 0x1000>; + interrupts = ; + #reset-cells = <1>; + }; + + apmixedsys: apmixedsys@1001e000 { + compatible = "mediatek,mt7988-apmixedsys"; + reg = <0 0x1001e000 0 0x1000>; + #clock-cells = <1>; + }; + + pio: pinctrl@1001f000 { + compatible = "mediatek,mt7988-pinctrl"; + reg = <0 0x1001f000 0 0x1000>, + <0 0x11c10000 0 0x1000>, + <0 0x11d00000 0 0x1000>, + <0 0x11d20000 0 0x1000>, + <0 0x11e00000 0 0x1000>, + <0 0x11f00000 0 0x1000>, + <0 0x1000b000 0 0x1000>; + reg-names = "gpio_base", "iocfg_tr_base", + "iocfg_br_base", "iocfg_rb_base", + "iocfg_lb_base", "iocfg_tl_base", "eint"; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pio 0 0 83>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; + #interrupt-cells = <2>; + + mdio0_pins: mdio0-pins { + mux { + function = "eth"; + groups = "mdc_mdio0"; + }; + + conf { + groups = "mdc_mdio0"; + drive-strength = ; + }; + }; + + i2c0_pins: i2c0-pins-g0 { + mux { + function = "i2c"; + groups = "i2c0_1"; + }; + }; + + i2c1_pins: i2c1-pins-g0 { + mux { + function = "i2c"; + groups = "i2c1_0"; + }; + }; + + i2c2_pins: i2c2-pins-g0 { + mux { + function = "i2c"; + groups = "i2c2_1"; + }; + }; + + gbe0_led0_pins: gbe0-pins { + mux { + function = "led"; + groups = "gbe0_led0"; + }; + }; + + gbe1_led0_pins: gbe1-pins { + mux { + function = "led"; + groups = "gbe1_led0"; + }; + }; + + gbe2_led0_pins: gbe2-pins { + mux { + function = "led"; + groups = "gbe2_led0"; + }; + }; + + gbe3_led0_pins: gbe3-pins { + mux { + function = "led"; + groups = "gbe3_led0"; + }; + }; + + i2p5gbe_led0_pins: 2p5gbe-pins { + mux { + function = "led"; + groups = "2p5gbe_led0"; + }; + }; + }; + + boottrap: boottrap@1001f6f0 { + compatible = "mediatek,boottrap"; + reg = <0 0x1001f6f0 0 0x4>; + }; + + sgmiisys0: syscon@10060000 { + compatible = "mediatek,mt7988-sgmiisys", + "mediatek,mt7988-sgmiisys_0", + "syscon"; + reg = <0 0x10060000 0 0x1000>; + #clock-cells = <1>; + }; + + sgmiisys1: syscon@10070000 { + compatible = "mediatek,mt7988-sgmiisys", + "mediatek,mt7988-sgmiisys_1", + "syscon"; + reg = <0 0x10070000 0 0x1000>; + #clock-cells = <1>; + }; + + usxgmiisys0: usxgmiisys@10080000 { + compatible = "mediatek,mt7988-usxgmiisys", + "mediatek,mt7988-usxgmiisys_0", + "syscon"; + reg = <0 0x10080000 0 0x1000>; + #clock-cells = <1>; + }; + + usxgmiisys1: usxgmiisys@10081000 { + compatible = "mediatek,mt7988-usxgmiisys", + "mediatek,mt7988-usxgmiisys_1", + "syscon"; + reg = <0 0x10081000 0 0x1000>; + #clock-cells = <1>; + }; + + xfi_pextp0: xfi_pextp@11f20000 { + compatible = "mediatek,mt7988-xfi_pextp", + "mediatek,mt7988-xfi_pextp_0", + "syscon"; + reg = <0 0x11f20000 0 0x10000>; + #clock-cells = <1>; + }; + + xfi_pextp1: xfi_pextp@11f30000 { + compatible = "mediatek,mt7988-xfi_pextp", + "mediatek,mt7988-xfi_pextp_1", + "syscon"; + reg = <0 0x11f30000 0 0x10000>; + #clock-cells = <1>; + }; + + xfi_pll: xfi_pll@11f40000 { + compatible = "mediatek,mt7988-xfi_pll", "syscon"; + reg = <0 0x11f40000 0 0x1000>; + #clock-cells = <1>; + }; + + mcusys: mcusys@100e0000 { + compatible = "mediatek,mt7988-mcusys", "syscon"; + reg = <0 0x100e0000 0 0x1000>; + #clock-cells = <1>; + }; + + uart0: serial@11000000 { + compatible = "mediatek,mt7986-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11000000 0 0x100>; + interrupts = ; + /* + * 8250-mtk driver don't control "baud" clock since commit + * e32a83c70cf9 (kernel v5.7), but both "baud" and "bus" clocks + * still need to be passed to the driver to prevent probe fail + */ + clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_52M_UART0_CK>; + clock-names = "baud", "bus"; + assigned-clocks = <&topckgen CLK_TOP_UART_SEL>, + <&infracfg CLK_INFRA_MUX_UART0_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_XTAL>, + <&topckgen CLK_TOP_UART_SEL>; + status = "disabled"; + }; + + i2c0: i2c@11003000 { + compatible = "mediatek,mt7988-i2c", + "mediatek,mt7981-i2c"; + reg = <0 0x11003000 0 0x1000>, + <0 0x10217080 0 0x80>; + interrupts = ; + clock-div = <1>; + clocks = <&infracfg CLK_INFRA_I2C_BCK>, + <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@11004000 { + compatible = "mediatek,mt7988-i2c", + "mediatek,mt7981-i2c"; + reg = <0 0x11004000 0 0x1000>, + <0 0x10217100 0 0x80>; + interrupts = ; + clock-div = <1>; + clocks = <&infracfg CLK_INFRA_I2C_BCK>, + <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c2: i2c@11005000 { + compatible = "mediatek,mt7988-i2c", + "mediatek,mt7981-i2c"; + reg = <0 0x11005000 0 0x1000>, + <0 0x10217180 0 0x80>; + interrupts = ; + clock-div = <1>; + clocks = <&infracfg CLK_INFRA_I2C_BCK>, + <&infracfg CLK_INFRA_66M_AP_DMA_BCK>; + clock-names = "main", "dma"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi0: spi@11007000 { + compatible = "mediatek,ipm-spi-quad", "mediatek,spi-ipm"; + reg = <0 0x11007000 0 0x100>; + interrupts = ; + clocks = <&topckgen CLK_TOP_MPLL_D2>, + <&topckgen CLK_TOP_SPI_SEL>, + <&infracfg CLK_INFRA_104M_SPI0>, + <&infracfg CLK_INFRA_66M_SPI0_HCK>; + clock-names = "parent-clk", "sel-clk", "spi-clk", + "spi-hclk"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + }; + + pcie2: pcie@11280000 { + compatible = "mediatek,mt7988-pcie", + "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + reg = <0 0x11280000 0 0x2000>; + reg-names = "pcie-mac"; + linux,pci-domain = <3>; + interrupts = ; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x20000000 0x00 + 0x20000000 0x00 0x00200000>, + <0x82000000 0x00 0x20200000 0x00 + 0x20200000 0x00 0x07e00000>; + clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P2>, + <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P2>, + <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P2>, + <&infracfg CLK_INFRA_133M_PCIE_CK_P2>; + clock-names = "pl_250m", "tl_26m", "peri_26m", + "top_133m"; + status = "disabled"; + + phys = <&xphyu3port0 PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &pcie_intc2 0>, + <0 0 0 2 &pcie_intc2 1>, + <0 0 0 3 &pcie_intc2 2>, + <0 0 0 4 &pcie_intc2 3>; + pcie_intc2: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + pcie3: pcie@11290000 { + compatible = "mediatek,mt7988-pcie", + "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + reg = <0 0x11290000 0 0x2000>; + reg-names = "pcie-mac"; + linux,pci-domain = <2>; + interrupts = ; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x28000000 0x00 + 0x28000000 0x00 0x00200000>, + <0x82000000 0x00 0x28200000 0x00 + 0x28200000 0x00 0x07e00000>; + clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P3>, + <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P3>, + <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P3>, + <&infracfg CLK_INFRA_133M_PCIE_CK_P3>; + clock-names = "pl_250m", "tl_26m", "peri_26m", + "top_133m"; + status = "disabled"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &pcie_intc3 0>, + <0 0 0 2 &pcie_intc3 1>, + <0 0 0 3 &pcie_intc3 2>, + <0 0 0 4 &pcie_intc3 3>; + pcie_intc3: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + pcie0: pcie@11300000 { + compatible = "mediatek,mt7988-pcie", + "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + reg = <0 0x11300000 0 0x2000>; + reg-names = "pcie-mac"; + linux,pci-domain = <0>; + interrupts = ; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x30000000 0x00 + 0x30000000 0x00 0x00200000>, + <0x82000000 0x00 0x30200000 0x00 + 0x30200000 0x00 0x07e00000>; + clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P0>, + <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P0>, + <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P0>, + <&infracfg CLK_INFRA_133M_PCIE_CK_P0>; + clock-names = "pl_250m", "tl_26m", "peri_26m", + "top_133m"; + status = "disabled"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &pcie_intc0 0>, + <0 0 0 2 &pcie_intc0 1>, + <0 0 0 3 &pcie_intc0 2>, + <0 0 0 4 &pcie_intc0 3>; + pcie_intc0: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + pcie1: pcie@11310000 { + compatible = "mediatek,mt7988-pcie", + "mediatek,mt7986-pcie", + "mediatek,mt8192-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + reg = <0 0x11310000 0 0x2000>; + reg-names = "pcie-mac"; + linux,pci-domain = <1>; + interrupts = ; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x38000000 0x00 + 0x38000000 0x00 0x00200000>, + <0x82000000 0x00 0x38200000 0x00 + 0x38200000 0x00 0x07e00000>; + clocks = <&infracfg CLK_INFRA_PCIE_PIPE_P1>, + <&infracfg CLK_INFRA_PCIE_GFMUX_TL_P1>, + <&infracfg CLK_INFRA_PCIE_PERI_26M_CK_P1>, + <&infracfg CLK_INFRA_133M_PCIE_CK_P1>; + clock-names = "pl_250m", "tl_26m", "peri_26m", + "top_133m"; + status = "disabled"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0x7>; + interrupt-map = <0 0 0 1 &pcie_intc1 0>, + <0 0 0 2 &pcie_intc1 1>, + <0 0 0 3 &pcie_intc1 2>, + <0 0 0 4 &pcie_intc1 3>; + pcie_intc1: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + ssusb0: usb@11190000 { + compatible = "mediatek,mt7988-xhci", + "mediatek,mtk-xhci"; + reg = <0 0x11190000 0 0x2e00>, + <0 0x11193e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts = ; + phys = <&xphyu2port0 PHY_TYPE_USB2>, + <&xphyu3port0 PHY_TYPE_USB3>; + clocks = <&infracfg CLK_INFRA_USB_SYS>, + <&infracfg CLK_INFRA_USB_XHCI>, + <&infracfg CLK_INFRA_USB_REF>, + <&infracfg CLK_INFRA_66M_USB_HCK>, + <&infracfg CLK_INFRA_133M_USB_HCK>; + clock-names = "sys_ck", + "xhci_ck", + "ref_ck", + "mcu_ck", + "dma_ck"; + #address-cells = <2>; + #size-cells = <2>; + mediatek,p0_speed_fixup; + status = "disabled"; + }; + + ssusb1: usb@11200000 { + compatible = "mediatek,mt7988-xhci", + "mediatek,mtk-xhci"; + reg = <0 0x11200000 0 0x2e00>, + <0 0x11203e00 0 0x0100>; + reg-names = "mac", "ippc"; + interrupts = ; + phys = <&tphyu2port0 PHY_TYPE_USB2>, + <&tphyu3port0 PHY_TYPE_USB3>; + clocks = <&infracfg CLK_INFRA_USB_SYS_CK_P1>, + <&infracfg CLK_INFRA_USB_XHCI_CK_P1>, + <&infracfg CLK_INFRA_USB_CK_P1>, + <&infracfg CLK_INFRA_66M_USB_HCK_CK_P1>, + <&infracfg CLK_INFRA_133M_USB_HCK_CK_P1>; + clock-names = "sys_ck", + "xhci_ck", + "ref_ck", + "mcu_ck", + "dma_ck"; + #address-cells = <2>; + #size-cells = <2>; + status = "disabled"; + }; + + tphy: tphy@11c50000 { + compatible = "mediatek,mt7988", + "mediatek,generic-tphy-v2"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + tphyu2port0: usb-phy@11c50000 { + reg = <0 0x11c50000 0 0x700>; + clocks = <&infracfg CLK_INFRA_USB_UTMI_CK_P1>; + clock-names = "ref"; + #phy-cells = <1>; + }; + tphyu3port0: usb-phy@11c50700 { + reg = <0 0x11c50700 0 0x900>; + clocks = <&infracfg CLK_INFRA_USB_PIPE_CK_P1>; + clock-names = "ref"; + #phy-cells = <1>; + mediatek,usb3-pll-ssc-delta; + mediatek,usb3-pll-ssc-delta1; + }; + }; + + topmisc: topmisc@11d10000 { + compatible = "mediatek,mt7988-topmisc", "syscon", + "mediatek,mt7988-power-controller"; + reg = <0 0x11d10000 0 0x10000>; + #clock-cells = <1>; + #power-domain-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + }; + + xphy: xphy@11e10000 { + compatible = "mediatek,mt7988", + "mediatek,xsphy"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + xphyu2port0: usb-phy@11e10000 { + reg = <0 0x11e10000 0 0x400>; + clocks = <&infracfg CLK_INFRA_USB_UTMI>; + clock-names = "ref"; + #phy-cells = <1>; + }; + + xphyu3port0: usb-phy@11e13000 { + reg = <0 0x11e13400 0 0x500>; + clocks = <&infracfg CLK_INFRA_USB_PIPE>; + clock-names = "ref"; + #phy-cells = <1>; + mediatek,syscon-type = <&topmisc 0x218 0>; + }; + }; + + efuse: efuse@11f50000 { + compatible = "mediatek,efuse"; + reg = <0 0x11f50000 0 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + lvts_calibration: calib@918 { + reg = <0x918 0x28>; + }; + phy_calibration_p0: calib@940 { + reg = <0x940 0x10>; + }; + phy_calibration_p1: calib@954 { + reg = <0x954 0x10>; + }; + phy_calibration_p2: calib@968 { + reg = <0x968 0x10>; + }; + phy_calibration_p3: calib@97c { + reg = <0x97c 0x10>; + }; + cpufreq_calibration: calib@278 { + reg = <0x278 0x1>; + }; + }; + + ethsys: syscon@15000000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mediatek,mt7988-ethsys", "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + switch: switch@15020000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "mediatek,mt7988-switch"; + reg = <0 0x15020000 0 0x8000>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&gic>; + interrupts = ; + resets = <ðrst 0>; + }; + + ethwarp: syscon@15031000 { + compatible = "mediatek,mt7988-ethwarp", "syscon", "simple-mfd"; + reg = <0 0x15031000 0 0x1000>; + #clock-cells = <1>; + + ethrst: reset-controller { + compatible = "ti,syscon-reset"; + #reset-cells = <1>; + ti,reset-bits = < + 0x8 9 0x8 9 0 0 (ASSERT_SET | DEASSERT_CLEAR | STATUS_NONE) + >; + }; + }; + + eth: ethernet@15100000 { + compatible = "mediatek,mt7988-eth"; + reg = <0 0x15100000 0 0x80000>, + <0 0x15400000 0 0x380000>; + interrupts = , + , + , + ; + clocks = <ðsys CLK_ETHDMA_XGP1_EN>, + <ðsys CLK_ETHDMA_XGP2_EN>, + <ðsys CLK_ETHDMA_XGP3_EN>, + <ðsys CLK_ETHDMA_FE_EN>, + <ðsys CLK_ETHDMA_GP2_EN>, + <ðsys CLK_ETHDMA_GP1_EN>, + <ðsys CLK_ETHDMA_GP3_EN>, + <ðsys CLK_ETHDMA_ESW_EN>, + <ðsys CLK_ETHDMA_CRYPT0_EN>, + <&sgmiisys0 CLK_SGM0_TX_EN>, + <&sgmiisys0 CLK_SGM0_RX_EN>, + <&sgmiisys1 CLK_SGM1_TX_EN>, + <&sgmiisys1 CLK_SGM1_RX_EN>, + <ðwarp CLK_ETHWARP_WOCPU2_EN>, + <ðwarp CLK_ETHWARP_WOCPU1_EN>, + <ðwarp CLK_ETHWARP_WOCPU0_EN>, + <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, + <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, + <&topckgen CLK_TOP_SGM_0_SEL>, + <&topckgen CLK_TOP_SGM_1_SEL>, + <&topckgen CLK_TOP_XFI_PHY_0_XTAL_SEL>, + <&topckgen CLK_TOP_XFI_PHY_1_XTAL_SEL>, + <&topckgen CLK_TOP_ETH_GMII_SEL>, + <&topckgen CLK_TOP_ETH_REFCK_50M_SEL>, + <&topckgen CLK_TOP_ETH_SYS_200M_SEL>, + <&topckgen CLK_TOP_ETH_SYS_SEL>, + <&topckgen CLK_TOP_ETH_XGMII_SEL>, + <&topckgen CLK_TOP_ETH_MII_SEL>, + <&topckgen CLK_TOP_NETSYS_SEL>, + <&topckgen CLK_TOP_NETSYS_500M_SEL>, + <&topckgen CLK_TOP_NETSYS_PAO_2X_SEL>, + <&topckgen CLK_TOP_NETSYS_SYNC_250M_SEL>, + <&topckgen CLK_TOP_NETSYS_PPEFB_250M_SEL>, + <&topckgen CLK_TOP_NETSYS_WARP_SEL>; + clock-names = "xgp1", "xgp2", "xgp3", "fe", "gp2", "gp1", + "gp3", "esw", "crypto", "sgmii_tx250m", + "sgmii_rx250m", "sgmii2_tx250m", "sgmii2_rx250m", + "ethwarp_wocpu2", "ethwarp_wocpu1", + "ethwarp_wocpu0", "top_usxgmii0_sel", + "top_usxgmii1_sel", "top_sgm0_sel", + "top_sgm1_sel", "top_xfi_phy0_xtal_sel", + "top_xfi_phy1_xtal_sel", "top_eth_gmii_sel", + "top_eth_refck_50m_sel", "top_eth_sys_200m_sel", + "top_eth_sys_sel", "top_eth_xgmii_sel", + "top_eth_mii_sel", "top_netsys_sel", + "top_netsys_500m_sel", "top_netsys_pao_2x_sel", + "top_netsys_sync_250m_sel", + "top_netsys_ppefb_250m_sel", + "top_netsys_warp_sel"; + assigned-clocks = <&topckgen CLK_TOP_NETSYS_2X_SEL>, + <&topckgen CLK_TOP_NETSYS_GSW_SEL>, + <&topckgen CLK_TOP_USXGMII_SBUS_0_SEL>, + <&topckgen CLK_TOP_USXGMII_SBUS_1_SEL>, + <&topckgen CLK_TOP_SGM_0_SEL>, + <&topckgen CLK_TOP_SGM_1_SEL>; + assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>, + <&topckgen CLK_TOP_NET1PLL_D4>, + <&topckgen CLK_TOP_NET1PLL_D8_D4>, + <&topckgen CLK_TOP_NET1PLL_D8_D4>, + <&apmixedsys CLK_APMIXED_SGMPLL>, + <&apmixedsys CLK_APMIXED_SGMPLL>; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>; + mediatek,usxgmiisys = <&usxgmiisys0>, <&usxgmiisys1>; + mediatek,xfi_pextp = <&xfi_pextp0>, <&xfi_pextp1>; + mediatek,xfi_pll = <&xfi_pll>; + mediatek,infracfg = <&topmisc>; + mediatek,toprgu = <&watchdog>; + #reset-cells = <1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; +}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index 63f898a9cd2..2fca00921b8 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -26,6 +26,9 @@ mediatek_setup_interfaces() mediatek,mt7986b-rfb) ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" eth1 ;; + mediatek,mt7988a-dsa-10g-spim-snand) + ucidef_set_interfaces_lan_wan "lan0 lan1 lan2 lan3" "eth1 eth2" + ;; tplink,tl-xdr4288|\ tplink,tl-xdr6088) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4 lan5" eth1 diff --git a/target/linux/mediatek/filogic/config-5.15 b/target/linux/mediatek/filogic/config-5.15 index 3e6a1654f20..4cae8c50ac7 100644 --- a/target/linux/mediatek/filogic/config-5.15 +++ b/target/linux/mediatek/filogic/config-5.15 @@ -360,6 +360,7 @@ CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MT6380=y CONFIG_REGULATOR_RT5190A=y CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_TI_SYSCON=y CONFIG_RFS_ACCEL=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y CONFIG_RPS=y diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 92d1dcfad24..72adb490666 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -206,6 +206,24 @@ define Device/mediatek_mt7986b-rfb endef TARGET_DEVICES += mediatek_mt7986b-rfb +define Device/mediatek_mt7988a-rfb-nand + DEVICE_VENDOR := MediaTek + DEVICE_MODEL := MT7988a nand rfb + DEVICE_DTS := mt7988a-dsa-10g-spim-nand + DEVICE_DTS_DIR := $(DTS_DIR)/ + KERNEL_LOADADDR := 0x48000000 + SUPPORTED_DEVICES := mediatek,mt7988a-rfb + UBINIZE_OPTS := -E 5 + BLOCKSIZE := 128k + PAGESIZE := 2048 + IMAGE_SIZE := 65536k + KERNEL_IN_UBI := 1 + IMAGES += factory.bin + IMAGE/factory.bin := append-ubi | check-size $$$$(IMAGE_SIZE) + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef +TARGET_DEVICES += mediatek_mt7988a-rfb-nand + define Device/tplink_tl-xdr-common DEVICE_VENDOR := TP-Link DEVICE_DTS_DIR := ../dts From 7855378fcd7ed7cb0a223238a99bac0b8e46c380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Tue, 23 May 2023 14:17:47 +0200 Subject: [PATCH 18/43] prereq: SetupHostCommand: fix wrong check result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tony has reported, that CI tools job is failing for him in macOS container due to prereq check failure for GNU `install` utility. Michael diagnosed it and from his traces it was clear, that the issue is caused by a wrong return value in the success check case, so lets fix it accordingly. Fixes: f75204036ccc ("prereq-build: allow host command symlinks to update") Reported-by: Tony Ambardar Diagnosed-by: Michael Pratt Signed-off-by: Petr Štetiar --- include/prereq.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/prereq.mk b/include/prereq.mk index 5646b24efaa..74c3914d060 100644 --- a/include/prereq.mk +++ b/include/prereq.mk @@ -113,7 +113,7 @@ define SetupHostCommand ;; \ esac; \ ln -sf "$$$$$$$$bin" "$(STAGING_DIR_HOST)/bin/$(strip $(1))"; \ - exit 1; \ + exit 0; \ fi; \ fi; \ done; \ From 71ca2a31546d5f14faac03838bf700cf22f85215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Tue, 23 May 2023 14:27:05 +0200 Subject: [PATCH 19/43] ci: tools: run the job on changes in include directory as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to prevent regressions like with #12617. Signed-off-by: Petr Štetiar --- .github/workflows/tools.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index b9d712c2a69..76ebdc664b8 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -3,11 +3,13 @@ name: Build host tools on: pull_request: paths: + - 'include/**' - 'tools/**' - '.github/workflows/build-tools.yml' - '.github/workflows/tools.yml' push: paths: + - 'include/**' - 'tools/**' - '.github/workflows/build-tools.yml' - '.github/workflows/tools.yml' From 8fc2a0f00f7f62ded3c849e78742c3d87d52ec91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20=C5=A0tetiar?= Date: Tue, 23 May 2023 16:56:09 +0200 Subject: [PATCH 20/43] ci: push-containers: trigger job on release branching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently all 23.05 related CI jobs are failing as the containers are not available, so lets fix it by pushing those containers when the version.mk changes. Signed-off-by: Petr Štetiar --- .github/workflows/push-containers.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/push-containers.yml b/.github/workflows/push-containers.yml index bad39c2fc2c..28b07244ef6 100644 --- a/.github/workflows/push-containers.yml +++ b/.github/workflows/push-containers.yml @@ -3,6 +3,7 @@ name: Build and Push prebuilt tools container on: push: paths: + - 'include/version.mk' - 'tools/**' - '.github/workflows/build-tools.yml' - '.github/workflows/push-containers.yml' From ce2e7c52f8ebc7ea92a1436ee2dbeecf149132dc Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 20 Dec 2022 20:02:35 +0100 Subject: [PATCH 21/43] CI: build: package external toolchain after build Package external toolchain after correct build. Signed-off-by: Christian Marangi --- .github/workflows/build.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 52fba8e1063..0e5f36c1120 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,6 +47,10 @@ on: mbedtls wolfssl openssl + build_external_toolchain: + type: boolean + upload_external_toolchain: + type: boolean permissions: contents: read @@ -376,6 +380,12 @@ jobs: working-directory: openwrt run: make -j$(nproc) BUILD_LOG=1 || ret=$? .github/workflows/scripts/show_build_failures.sh + - name: Build external toolchain + if: inputs.build_external_toolchain == true + shell: su buildbot -c "sh -e {0}" + working-directory: openwrt + run: make target/toolchain/compile -j$(nproc) BUILD_LOG=1 || ret=$? .github/workflows/scripts/show_build_failures.sh + - name: Coverity prepare toolchain if: inputs.coverity_check_packages != '' shell: su buildbot -c "sh -e {0}" @@ -433,3 +443,19 @@ jobs: with: name: ${{ inputs.target }}-${{ inputs.subtarget }}-logs path: "openwrt/logs" + + - name: Find external toolchain name + id: get-toolchain-name + if: inputs.upload_external_toolchain == true + working-directory: openwrt + run: | + TOOLCHAIN_NAME=$(ls bin/targets/${{inputs.target }}/${{ inputs.subtarget }} | grep toolchain) + echo "toolchain-name=$TOOLCHAIN_NAME" >> $GITHUB_OUTPUT + + - name: Upload prebuilt toolchain + if: inputs.upload_external_toolchain == true + uses: actions/upload-artifact@v3 + with: + name: ${{ inputs.target }}-${{ inputs.subtarget }}-external-toolchain + path: openwrt/bin/targets/${{ inputs.target }}/${{ inputs.subtarget }}/${{ steps.get-toolchain-name.outputs.toolchain-name }} + retention-days: 1 From 803b0110485a12c1119a51044d17979795ede966 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 17 Dec 2022 02:02:26 +0100 Subject: [PATCH 22/43] CI: build: add option to configure container to use Add option to configure container to use for build test. By default the tools container is used if no option is provided. Signed-off-by: Christian Marangi --- .github/workflows/build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0e5f36c1120..ef7fc51d9ad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,6 +5,9 @@ on: secrets: coverity_api_token: inputs: + container_name: + type: string + default: tools target: required: true type: string @@ -120,7 +123,7 @@ jobs: needs: setup_build runs-on: ubuntu-latest - container: ghcr.io/${{ needs.setup_build.outputs.owner_lc }}/tools:${{ needs.setup_build.outputs.container_tag }} + container: ghcr.io/${{ needs.setup_build.outputs.owner_lc }}/${{ inputs.container_name }}:${{ needs.setup_build.outputs.container_tag }} permissions: contents: read From 23a5c715a9296e828be5c32eadf68eacdb326a0a Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Tue, 23 May 2023 15:25:56 +0200 Subject: [PATCH 23/43] CI: build: add checks to test if toolchain container can be used Add checks to test if toolchain container can be used. This is to handle case of new target or migration of any sort. If the toolchain container can't be found, the tools container is used instead. Signed-off-by: Christian Marangi --- .github/workflows/build.yml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ef7fc51d9ad..f60e4748a09 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,6 +66,7 @@ jobs: owner_lc: ${{ steps.lower_owner.outputs.owner_lc }} ccache_hash: ${{ steps.ccache_hash.outputs.ccache_hash }} container_tag: ${{ steps.determine_tools_container.outputs.container_tag }} + container_name: ${{ steps.determine_tools_container.outputs.container_name }} steps: - name: Checkout @@ -99,6 +100,7 @@ jobs: - name: Determine tools container tag id: determine_tools_container run: | + CONTAINER_NAME=${{ inputs.container_name }} CONTAINER_TAG=latest if [ -n "${{ github.base_ref }}" ]; then if echo "${{ github.base_ref }}" | grep -q -E '^openwrt-[0-9][0-9]\.[0-9][0-9]$'; then @@ -115,15 +117,29 @@ jobs: CONTAINER_TAG=openwrt-"$(echo ${{ github.ref_name }} | sed 's/^v\([0-9][0-9]\.[0-9][0-9]\)\..\+/\1/')" fi fi - echo "Tools container to use tools:$CONTAINER_TAG" + + if [ "$CONTAINER_NAME" = "toolchain" ]; then + GHCR_TOKEN=$(echo ${{ secrets.GITHUB_TOKEN }} | base64) + GHCR_HEADER="Authorization: Bearer ${GHCR_TOKEN}" + GHCR_MANIFEST_LINK=https://ghcr.io/v2/${{ steps.lower_owner.outputs.owner_lc }}/${{ inputs.container_name }}/manifests/${{ inputs.target }}-${{ inputs.subtarget }}-"$CONTAINER_TAG" + # Check if container exist + if [ $(curl -s -o /dev/null -w "%{http_code}" -H "$GHCR_HEADER" -I "$GHCR_MANIFEST_LINK") = 200 ]; then + CONTAINER_TAG=${{ inputs.target }}-${{ inputs.subtarget }}-"$CONTAINER_TAG" + else + CONTAINER_NAME=tools + fi + fi + + echo "Tools container to use $CONTAINER_NAME:$CONTAINER_TAG" echo "container_tag=$CONTAINER_TAG" >> $GITHUB_OUTPUT + echo "container_name=$CONTAINER_NAME" >> $GITHUB_OUTPUT build: name: Build ${{ inputs.target }}/${{ inputs.subtarget }} needs: setup_build runs-on: ubuntu-latest - container: ghcr.io/${{ needs.setup_build.outputs.owner_lc }}/${{ inputs.container_name }}:${{ needs.setup_build.outputs.container_tag }} + container: ghcr.io/${{ needs.setup_build.outputs.owner_lc }}/${{ needs.setup_build.outputs.container_name }}:${{ needs.setup_build.outputs.container_tag }} permissions: contents: read From e1370cdd497a07612413106d707973155ad3004b Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 17 Dec 2022 00:21:31 +0100 Subject: [PATCH 24/43] CI: push-containers: build and push container with external toolchain Build and push container with external toolchain embedded in the container image. Signed-off-by: Christian Marangi --- .github/workflows/Dockerfile.toolchain | 8 ++ .github/workflows/push-containers.yml | 156 ++++++++++++++++++++++--- 2 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/Dockerfile.toolchain diff --git a/.github/workflows/Dockerfile.toolchain b/.github/workflows/Dockerfile.toolchain new file mode 100644 index 00000000000..949bc2bb5c2 --- /dev/null +++ b/.github/workflows/Dockerfile.toolchain @@ -0,0 +1,8 @@ +ARG OWNER_LC +ARG CONTAINER_TAG + +FROM ghcr.io/$OWNER_LC/tools:$CONTAINER_TAG + +ARG TOOLCHAIN_NAME + +ADD $TOOLCHAIN_NAME /external-toolchain/ diff --git a/.github/workflows/push-containers.yml b/.github/workflows/push-containers.yml index 28b07244ef6..fcbaf96788d 100644 --- a/.github/workflows/push-containers.yml +++ b/.github/workflows/push-containers.yml @@ -8,6 +8,10 @@ on: - '.github/workflows/build-tools.yml' - '.github/workflows/push-containers.yml' - '.github/workflows/Dockerfile.tools' + - 'toolchain/**' + - '.github/workflows/build.yml' + - '.github/workflows/toolchain.yml' + - '.github/workflows/Dockerfile.toolchain' permissions: contents: read @@ -17,29 +21,21 @@ concurrency: cancel-in-progress: true jobs: - build-linux-buildbot: - name: Build tools with buildbot container - if: ${{ github.repository_owner == 'openwrt' }} - uses: ./.github/workflows/build-tools.yml - with: - generate_prebuilt_artifacts: true - - push-tools-container: - needs: build-linux-buildbot - name: Push prebuilt tools container + determine-container-info: + name: Determine needed info to push containers if: ${{ github.repository_owner == 'openwrt' }} runs-on: ubuntu-latest - - permissions: - contents: read - packages: write + outputs: + owner-lc: ${{ steps.generate-owner-lc.outputs.owner-lc }} + container-tag: ${{ steps.determine-container-tag.outputs.container-tag }} steps: - name: Set lower case owner name + id: generate-owner-lc env: OWNER: ${{ github.repository_owner }} run: | - echo "OWNER_LC=${OWNER,,}" >> "$GITHUB_ENV" + echo "owner-lc=${OWNER,,}" >> "$GITHUB_OUTPUT" # Per branch tools container tag # By default stick to latest @@ -50,6 +46,7 @@ jobs: # (example branch openwrt-22.03 -> tools:openwrt-22.03) # (example branch openwrt-22.03-test -> tools:openwrt-22.03) - name: Determine tools container tag + id: determine-container-tag run: | CONTAINER_TAG=latest @@ -63,9 +60,27 @@ jobs: fi fi - echo "Tools container to push tools:$CONTAINER_TAG" - echo "CONTAINER_TAG=$CONTAINER_TAG" >> "$GITHUB_ENV" + echo "Container tag to push for tools and toolchain is $CONTAINER_TAG" + echo "container-tag=$CONTAINER_TAG" >> "$GITHUB_OUTPUT" + build-linux-buildbot: + name: Build tools with buildbot container + if: ${{ github.repository_owner == 'openwrt' }} + uses: ./.github/workflows/build-tools.yml + with: + generate_prebuilt_artifacts: true + + push-tools-container: + needs: [ determine-container-info, build-linux-buildbot ] + if: ${{ github.repository_owner == 'openwrt' }} + name: Push prebuilt tools container + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: - name: Checkout uses: actions/checkout@v3 with: @@ -93,5 +108,110 @@ jobs: with: context: openwrt push: true - tags: ghcr.io/${{ env.OWNER_LC }}/tools:${{ env.CONTAINER_TAG }} + tags: ghcr.io/${{ needs.determine-container-info.outputs.owner-lc }}/tools:${{ needs.determine-container-info.outputs.container-tag }} file: openwrt/.github/workflows/Dockerfile.tools + + determine-targets: + name: Set targets + if: ${{ github.repository_owner == 'openwrt' }} + runs-on: ubuntu-latest + outputs: + target: ${{ steps.find_targets.outputs.target }} + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set targets + id: find_targets + run: | + export TARGETS="$(perl ./scripts/dump-target-info.pl targets 2>/dev/null \ + | awk '{ print $1 }')" + + JSON='[' + FIRST=1 + for TARGET in $TARGETS; do + TUPLE='{"target":"'"$(echo $TARGET | cut -d "/" -f 1)"'","subtarget":"'"$(echo $TARGET | cut -d "/" -f 2)"'"}' + [[ $FIRST -ne 1 ]] && JSON="$JSON"',' + JSON="$JSON""$TUPLE" + FIRST=0 + done + JSON="$JSON"']' + + echo -e "\n---- targets ----\n" + echo "$JSON" + echo -e "\n---- targets ----\n" + + echo "target=$JSON" >> $GITHUB_OUTPUT + + build: + name: Build Target Toolchain + if: ${{ github.repository_owner == 'openwrt' }} + needs: [ determine-targets, push-tools-container ] + permissions: + contents: read + packages: read + strategy: + fail-fast: False + matrix: + include: ${{fromJson(needs.determine-targets.outputs.target)}} + uses: ./.github/workflows/build.yml + with: + target: ${{ matrix.target }} + subtarget: ${{ matrix.subtarget }} + build_toolchain: true + build_external_toolchain: true + upload_external_toolchain: true + + push-toolchain-container: + name: Push Target Toolchain container + if: ${{ github.repository_owner == 'openwrt' }} + needs: [ determine-container-info, determine-targets, build ] + runs-on: ubuntu-latest + + strategy: + fail-fast: False + matrix: + include: ${{fromJson(needs.determine-targets.outputs.target)}} + + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + path: 'openwrt' + + - name: Download external toolchain from build job + uses: actions/download-artifact@v3 + with: + name: ${{ matrix.target }}-${{ matrix.subtarget }}-external-toolchain + path: openwrt + + - name: Find external toolchain name + id: get-toolchain-name + working-directory: openwrt + run: | + TOOLCHAIN_NAME=$(ls | grep toolchain-${{ matrix.target }}-${{ matrix.subtarget }}) + echo "toolchain-name=$TOOLCHAIN_NAME" >> $GITHUB_OUTPUT + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: openwrt + push: true + tags: ghcr.io/${{ needs.determine-container-info.outputs.owner-lc }}/toolchain:${{ matrix.target }}-${{ matrix.subtarget }}-${{ needs.determine-container-info.outputs.container-tag }} + file: openwrt/.github/workflows/Dockerfile.toolchain + build-args: | + OWNER_LC=${{ needs.determine-container-info.outputs.owner-lc }} + CONTAINER_TAG=${{ needs.determine-container-info.outputs.container-tag }} + TOOLCHAIN_NAME=${{ steps.get-toolchain-name.outputs.toolchain-name }} From 0fe5776f4a79a2b095912e258738e3203207e9dd Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sat, 17 Dec 2022 15:07:28 +0100 Subject: [PATCH 25/43] CI: build: Add support to use container included external toolchain Add support to use container included external toolchain and skip redownloading external sdk for each test. Signed-off-by: Christian Marangi --- .github/workflows/build.yml | 21 ++++++++++++++++++++- .github/workflows/coverity.yml | 1 + .github/workflows/kernel.yml | 1 + .github/workflows/packages.yml | 1 + 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f60e4748a09..fd93d5f8022 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -206,6 +206,11 @@ jobs: id: parse-toolchain working-directory: openwrt run: | + if [ -d /external-toolchain/ ]; then + echo "toolchain-type=external_container" >> $GITHUB_OUTPUT + exit 0 + fi + TOOLCHAIN_PATH=snapshots if [ -n "${{ github.base_ref }}" ]; then @@ -259,7 +264,7 @@ jobs: ccache-kernel-${{ inputs.target }}/${{ inputs.subtarget }}- - name: Download external toolchain/sdk - if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type != 'internal' + if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type != 'internal' && steps.parse-toolchain.outputs.toolchain-type != 'external_container' shell: su buildbot -c "sh -e {0}" working-directory: openwrt run: | @@ -296,6 +301,20 @@ jobs: echo CONFIG_TARGET_PER_DEVICE_ROOTFS=y >> .config echo CONFIG_TARGET_ALL_PROFILES=y >> .config + - name: Configure external toolchain in container + if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type == 'external_container' + shell: su buildbot -c "sh -e {0}" + working-directory: openwrt + run: | + echo CONFIG_DEVEL=y >> .config + echo CONFIG_AUTOREMOVE=y >> .config + echo CONFIG_CCACHE=y >> .config + + ./scripts/ext-toolchain.sh \ + --toolchain /external-toolchain/$(ls /external-toolchain/ | grep openwrt-toolchain)/toolchain-* \ + --overwrite-config \ + --config ${{ inputs.target }}/${{ inputs.subtarget }} + - name: Configure external toolchain if: inputs.build_toolchain == false && steps.parse-toolchain.outputs.toolchain-type == 'external_toolchain' shell: su buildbot -c "sh -e {0}" diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml index db59ef8ca68..10355456321 100644 --- a/.github/workflows/coverity.yml +++ b/.github/workflows/coverity.yml @@ -17,6 +17,7 @@ jobs: packages: read uses: ./.github/workflows/build.yml with: + container_name: toolchain target: x86 subtarget: 64 build_full: true diff --git a/.github/workflows/kernel.yml b/.github/workflows/kernel.yml index 02aee8b27cc..b918b2d88e4 100644 --- a/.github/workflows/kernel.yml +++ b/.github/workflows/kernel.yml @@ -109,6 +109,7 @@ jobs: include: ${{fromJson(needs.determine_targets.outputs.targets_subtargets)}} uses: ./.github/workflows/build.yml with: + container_name: toolchain target: ${{ matrix.target }} subtarget: ${{ matrix.subtarget }} build_kernel: true diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index e2f932b1ba3..d8270cbb820 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -43,6 +43,7 @@ jobs: subtarget: 64 uses: ./.github/workflows/build.yml with: + container_name: toolchain target: ${{ matrix.target }} subtarget: ${{ matrix.subtarget }} build_kernel: true From 957f1ee85eb243c5c7397b1e3842a3c61a6b852f Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 23 May 2023 14:55:48 +0200 Subject: [PATCH 26/43] kernel: qca-ssdk: backport support for building as kernel module Currently, SSDK is rather special in the sense that its not being built as a proper out of tree module at all but rather like a userspace application and that involves a lot of make magic which unfortunately broke with make version 4.4 and newer. Luckily QCA finally added a way to build SSDK as an out of tree module and it uses the kernel buildsystem which makes it compile with make 4.4 as well. So lets backport the support for it and switch to using it. Signed-off-by: Robert Marko --- package/kernel/qca-ssdk/Makefile | 6 +- ...upport-Linux-Style-Makefile-for-SSDK.patch | 286 ++++++++++++++++++ ...pilation-issue-in-Linux-Style-Makefi.patch | 27 ++ ...fix-compilation-issue-in-Miami-yocto.patch | 23 ++ 4 files changed, 340 insertions(+), 2 deletions(-) create mode 100644 package/kernel/qca-ssdk/patches/0012-qca-ssdk-Support-Linux-Style-Makefile-for-SSDK.patch create mode 100644 package/kernel/qca-ssdk/patches/0013-qca-ssdk-fix-compilation-issue-in-Linux-Style-Makefi.patch create mode 100644 package/kernel/qca-ssdk/patches/0014-qca-ssdk-fix-compilation-issue-in-Miami-yocto.patch diff --git a/package/kernel/qca-ssdk/Makefile b/package/kernel/qca-ssdk/Makefile index 62c60fc1bec..92f7b66490b 100644 --- a/package/kernel/qca-ssdk/Makefile +++ b/package/kernel/qca-ssdk/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=qca-ssdk -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/qca-ssdk.git PKG_SOURCE_PROTO:=git @@ -37,6 +37,8 @@ else TOOLCHAIN_BIN_PATH=$(TOOLCHAIN_DIR)/bin endif +LNX_CONFIG_OPTS = LNX_MAKEOPTS='$(KERNEL_MAKEOPTS)' MODULE_TYPE=KSLIB modules + MAKE_FLAGS+= \ TARGET_NAME=$(CONFIG_TARGET_NAME) \ TOOL_PATH=$(TOOLCHAIN_BIN_PATH) \ @@ -47,7 +49,7 @@ MAKE_FLAGS+= \ TARGET_SUFFIX=$(CONFIG_TARGET_SUFFIX) \ GCC_VERSION=$(GCC_VERSION) \ EXTRA_CFLAGS=-fno-stack-protector -I$(STAGING_DIR)/usr/include \ - $(KERNEL_MAKE_FLAGS) + $(LNX_CONFIG_OPTS) ifeq ($(CONFIG_TARGET_BOARD), "ipq807x") MAKE_FLAGS+= CHIP_TYPE=HPPE PTP_FEATURE=disable SWCONFIG_FEATURE=disable diff --git a/package/kernel/qca-ssdk/patches/0012-qca-ssdk-Support-Linux-Style-Makefile-for-SSDK.patch b/package/kernel/qca-ssdk/patches/0012-qca-ssdk-Support-Linux-Style-Makefile-for-SSDK.patch new file mode 100644 index 00000000000..91b7d570d8a --- /dev/null +++ b/package/kernel/qca-ssdk/patches/0012-qca-ssdk-Support-Linux-Style-Makefile-for-SSDK.patch @@ -0,0 +1,286 @@ +From edd3d4347cc73a99c7cf59aceeb1e8ad4d4dd303 Mon Sep 17 00:00:00 2001 +From: crao +Date: Tue, 15 Nov 2022 18:50:01 +0800 +Subject: [PATCH] [qca-ssdk]: Support Linux-Style Makefile for SSDK + +Change-Id: I8c4399433b6422ef6192f70bf08b0d3023cc94b6 +Signed-off-by: crao +--- + Makefile | 15 +++++++++++++ + Makefile.modules | 16 ++++++++++++++ + make/defs.mk | 1 + + make/linux_opt.mk | 54 ++++++++++++++++++++++++++++------------------- + make/target.mk | 12 +++++++++++ + src/api/Makefile | 2 +- + 6 files changed, 77 insertions(+), 23 deletions(-) + mode change 100755 => 100644 Makefile + create mode 100644 Makefile.modules + mode change 100755 => 100644 make/defs.mk + mode change 100755 => 100644 make/linux_opt.mk + mode change 100755 => 100644 make/target.mk + mode change 100755 => 100644 src/api/Makefile + +--- a/Makefile ++++ b/Makefile +@@ -12,6 +12,9 @@ include ./make/$(OS)_opt.mk + SUB_DIR=$(patsubst %/, %, $(dir $(wildcard src/*/Makefile))) + SUB_LIB=$(subst src/, , $(SUB_DIR)) + ++#################################################################### ++# SSDK-Style Makefile ++#################################################################### + all: $(BIN_DIR) kslib + mkdir -p ./temp/;cd ./temp;cp ../build/bin/ssdk_ks_km.a ./;ar -x ssdk_ks_km.a; cp ../ko_Makefile ./Makefile; + make -C $(SYS_PATH) M=$(PRJ_PATH)/temp/ CROSS_COMPILE=$(TOOLPREFIX) modules +@@ -20,6 +23,18 @@ all: $(BIN_DIR) kslib + rm -Rf ./temp/*.o ./temp/*.ko ./temp/*.a + @echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished." + ++#################################################################### ++# LNX Modules-Style Makefile ++#################################################################### ++modules: $(BIN_DIR) kslib_c ++ cp Makefile.modules ./Makefile; ++ make -C $(SYS_PATH) M=$(PRJ_PATH)/ $(LNX_MAKEOPTS) modules ++ cp *.ko build/bin; ++ @echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished." ++ ++kslib_c: ++ $(foreach i, $(SUB_LIB), $(MAKE) MODULE_TYPE=KSLIB -C src/$i src_list_loop || exit 1;) ++ + kslib:kslib_o + $(AR) -r $(BIN_DIR)/$(KS_MOD)_$(RUNMODE).a $(wildcard $(BLD_DIR)/KSLIB/*.o) + +--- /dev/null ++++ b/Makefile.modules +@@ -0,0 +1,16 @@ ++#################################################################### ++# Add All Local Flags ++#################################################################### ++ccflags-y += $(LNX_LOCAL_CFLAGS) -Wno-error ++ ++#################################################################### ++# Build Object List ++#################################################################### ++SRC_LIST := $(shell cat $(PRJ_PATH)/src_list.dep) ++OBJ_LIST := $(patsubst %.c,%.o,$(SRC_LIST)) ++ ++#################################################################### ++# Linux Kernel Module ++#################################################################### ++obj-m := qca-ssdk.o ++qca-ssdk-objs := $(OBJ_LIST) +--- a/make/defs.mk ++++ b/make/defs.mk +@@ -7,6 +7,7 @@ ifeq (,$(findstring $(LIB), $(COMPONENTS + endif + + SRC_FILE=$(addprefix $(PRJ_PATH)/$(LOC_DIR)/, $(SRC_LIST)) ++LOC_SRC_FILE=$(addprefix $(LOC_DIR)/, $(SRC_LIST)) + + OBJ_LIST=$(SRC_LIST:.c=.o) + OBJ_FILE=$(addprefix $(DST_DIR)/, $(OBJ_LIST)) +--- a/make/linux_opt.mk ++++ b/make/linux_opt.mk +@@ -295,7 +295,7 @@ ifeq (TRUE, $(DEBUG_ON)) + MODULE_CFLAG += -g + endif + +-MODULE_CFLAG += $(OPT_FLAG) -Wall -DVERSION=\"$(VERSION)\" -DBUILD_DATE=\"$(BUILD_DATE)\" -DOS=\"$(OS)\" -D"KBUILD_STR(s)=\#s" -D"KBUILD_MODNAME=KBUILD_STR(qca-ssdk)" ++MODULE_CFLAG += $(OPT_FLAG) -Wall -DVERSION=\"$(VERSION)\" -DBUILD_DATE=\"$(BUILD_DATE)\" -DOS=\"$(OS)\" -D"KBUILD_STR(s)=\#s" + + MODULE_INC += -I$(PRJ_PATH)/include \ + -I$(PRJ_PATH)/include/common \ +@@ -450,7 +450,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DKVER34 + MODULE_CFLAG += -DKVER32 + MODULE_CFLAG += -DLNX26_22 +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/source/include \ +@@ -473,7 +473,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DKVER32 + MODULE_CFLAG += -DLNX26_22 + ifeq ($(ARCH), arm64) +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/source \ +@@ -492,13 +492,13 @@ ifeq (KSLIB, $(MODULE_TYPE)) + -I$(SYS_PATH)/source/include/uapi + + ifneq ($(wildcard $(SYS_PATH)/include/linux/kconfig.h),) +- MODULE_INC += -include $(SYS_PATH)/include/linux/kconfig.h ++ SYS_INC += -include $(SYS_PATH)/include/linux/kconfig.h + else +- MODULE_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h ++ SYS_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h + endif + + else ifeq ($(ARCH), arm) +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/7.5.0/include/ \ + -I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \ +@@ -522,13 +522,13 @@ ifeq (KSLIB, $(MODULE_TYPE)) + -I$(TOOL_PATH)/../../lib/arm-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/9.3.0/include/ + + ifneq ($(wildcard $(SYS_PATH)/include/linux/kconfig.h),) +- MODULE_INC += -include $(SYS_PATH)/include/linux/kconfig.h ++ SYS_INC += -include $(SYS_PATH)/include/linux/kconfig.h + else +- MODULE_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h ++ SYS_INC += -include $(KERNEL_SRC)/include/linux/kconfig.h + endif + + else +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/source \ +@@ -564,7 +564,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DLNX26_22 + ifeq ($(ARCH), arm64) + KCONF_FILE = $(SYS_PATH)/source/include/linux/kconfig.h +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/source/include \ +@@ -581,7 +581,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + -I$(SYS_PATH)/source/arch/arm64/include/asm/mach \ + -include $(KCONF_FILE) + else ifeq ($(ARCH), arm) +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \ + -I$(SYS_PATH)/include \ +@@ -604,7 +604,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DKVER34 + MODULE_CFLAG += -DKVER32 + MODULE_CFLAG += -DLNX26_22 +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(TOOL_PATH)/../lib/gcc/$(TARGET_NAME)/$(GCC_VERSION)/include/ \ + -I$(TOOL_PATH)/../../lib/arm-poky-linux-gnueabi/gcc/arm-poky-linux-gnueabi/5.3.0/include/ \ + -I$(TOOL_PATH)/../../lib/armv7a-vfp-neon-rdk-linux-gnueabi/gcc/arm-rdk-linux-gnueabi/4.8.4/include/ \ +@@ -627,10 +627,10 @@ ifeq (KSLIB, $(MODULE_TYPE)) + -I$(EXT_PATH) \ + -I$(SYS_PATH)/source/arch/arm/include/asm/mach + ifneq ($(wildcard $(SYS_PATH)/include/linux/kconfig.h),) +- MODULE_INC += \ ++ SYS_INC += \ + -include $(SYS_PATH)/include/linux/kconfig.h + else +- MODULE_INC += \ ++ SYS_INC += \ + -include $(SYS_PATH)/source/include/linux/kconfig.h + endif + +@@ -641,7 +641,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DKVER32 + MODULE_CFLAG += -DLNX26_22 + MODULE_CFLAG += -Werror +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/source/include \ + -I$(SYS_PATH)/source/arch/arm/mach-msm/include \ +@@ -657,7 +657,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DKVER32 + MODULE_CFLAG += -DLNX26_22 + ifeq (mips, $(CPU)) +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/arch/mips/include \ + -I$(SYS_PATH)/arch/mips/include/asm/mach-ar7240 \ +@@ -678,7 +678,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + -O2 -fno-pic -pipe -mabi=32 -march=mips32r2 -DMODULE -mlong-calls -DEXPORT_SYMTAB + endif + else +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/arch/arm/include \ + -I$(SYS_PATH)/arch/arm/include/asm \ +@@ -695,7 +695,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + MODULE_CFLAG += -DKVER26 + MODULE_CFLAG += -DLNX26_22 + ifeq (mips, $(CPU)) +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/arch/mips/include \ + -I$(SYS_PATH)/arch/mips/include/asm/mach-ar7240 \ +@@ -708,7 +708,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + -O2 -fno-pic -pipe -mabi=32 -march=mips32r2 -DMODULE -mlong-calls -DEXPORT_SYMTAB + endif + else +- MODULE_INC += -I$(SYS_PATH) \ ++ SYS_INC += -I$(SYS_PATH) \ + -I$(SYS_PATH)/include \ + -I$(SYS_PATH)/arch/arm/include \ + -I$(SYS_PATH)/arch/arm/include/asm \ +@@ -721,8 +721,7 @@ ifeq (KSLIB, $(MODULE_TYPE)) + + endif + +- MODULE_CFLAG += -D__KERNEL__ -DKERNEL_MODULE $(CPU_CFLAG) +- ++ MODULE_CFLAG += -D__KERNEL__ -DKERNEL_MODULE + + endif + +@@ -748,4 +747,15 @@ ifneq (TRUE, $(KERNEL_MODE)) + endif + endif + +-LOCAL_CFLAGS += $(MODULE_INC) $(MODULE_CFLAG) $(EXTRA_CFLAGS) ++LOCAL_CFLAGS += $(MODULE_INC) $(SYS_INC) $(MODULE_CFLAG) $(EXTRA_CFLAGS) ++ ++#################################################################### ++# cflags for SSDK-Style Makefile ++#################################################################### ++LOCAL_CFLAGS += $(CPU_CFLAG) -D"KBUILD_MODNAME=KBUILD_STR(qca-ssdk)" ++ ++#################################################################### ++# cflags for LNX Modules-Style Makefile ++#################################################################### ++LNX_LOCAL_CFLAGS += $(MODULE_INC) $(MODULE_CFLAG) ${EXTRA_INC} ++export LNX_LOCAL_CFLAGS +--- a/make/target.mk ++++ b/make/target.mk +@@ -3,6 +3,18 @@ include $(PRJ_PATH)/make/$(OS)_opt.mk + + include $(PRJ_PATH)/make/tools.mk + ++#################################################################### ++# LNX Modules-Style Makefile ++#################################################################### ++src_list_loop: src_list ++ $(foreach i, $(SUB_DIR), $(MAKE) -C $(i) src_list_loop || exit 1;) ++ ++src_list: ++ echo -n "$(LOC_SRC_FILE) " >> $(PRJ_PATH)/src_list.dep ++ ++#################################################################### ++# SSDK-Style Makefile ++#################################################################### + obj: $(OBJ_LIST) + $(OBJ_LOOP) + +--- a/src/api/Makefile ++++ b/src/api/Makefile +@@ -1,4 +1,4 @@ +-LOC_DIR=src/sal ++LOC_DIR=src/api + LIB=API + + include $(PRJ_PATH)/make/config.mk diff --git a/package/kernel/qca-ssdk/patches/0013-qca-ssdk-fix-compilation-issue-in-Linux-Style-Makefi.patch b/package/kernel/qca-ssdk/patches/0013-qca-ssdk-fix-compilation-issue-in-Linux-Style-Makefi.patch new file mode 100644 index 00000000000..792cd9e31b5 --- /dev/null +++ b/package/kernel/qca-ssdk/patches/0013-qca-ssdk-fix-compilation-issue-in-Linux-Style-Makefi.patch @@ -0,0 +1,27 @@ +From 3026f89b06049df01d5fe19c5fccc972637aa344 Mon Sep 17 00:00:00 2001 +From: crao +Date: Tue, 7 Mar 2023 17:15:07 +0800 +Subject: [PATCH] [qca-ssdk]: fix compilation issue in Linux-Style Makefile + +Change-Id: If38251fc0a2bf4abc666d30f4812c0d9507310dc +Signed-off-by: crao +--- + Makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + mode change 100644 => 100755 Makefile + +--- a/Makefile ++++ b/Makefile +@@ -27,9 +27,9 @@ all: $(BIN_DIR) kslib + # LNX Modules-Style Makefile + #################################################################### + modules: $(BIN_DIR) kslib_c +- cp Makefile.modules ./Makefile; +- make -C $(SYS_PATH) M=$(PRJ_PATH)/ $(LNX_MAKEOPTS) modules +- cp *.ko build/bin; ++ mkdir -p ./temp/;cp * ./temp -a;cd ./temp;cp ../Makefile.modules ./Makefile; ++ make -C $(SYS_PATH) M=$(PRJ_PATH)/temp $(LNX_MAKEOPTS) modules ++ cp temp/*.ko build/bin; + @echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished." + + kslib_c: diff --git a/package/kernel/qca-ssdk/patches/0014-qca-ssdk-fix-compilation-issue-in-Miami-yocto.patch b/package/kernel/qca-ssdk/patches/0014-qca-ssdk-fix-compilation-issue-in-Miami-yocto.patch new file mode 100644 index 00000000000..53c0c341316 --- /dev/null +++ b/package/kernel/qca-ssdk/patches/0014-qca-ssdk-fix-compilation-issue-in-Miami-yocto.patch @@ -0,0 +1,23 @@ +From 6e4efd68e6e560a1994bc273fe6f7a72139f3957 Mon Sep 17 00:00:00 2001 +From: crao +Date: Wed, 15 Mar 2023 11:19:39 +0800 +Subject: [PATCH] [qca-ssdk]: fix compilation issue in Miami yocto + +Change-Id: I8526b9e43667d72ae9afa4ef8a13167088d194ba +Signed-off-by: crao +--- + Makefile | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/Makefile ++++ b/Makefile +@@ -29,7 +29,9 @@ all: $(BIN_DIR) kslib + modules: $(BIN_DIR) kslib_c + mkdir -p ./temp/;cp * ./temp -a;cd ./temp;cp ../Makefile.modules ./Makefile; + make -C $(SYS_PATH) M=$(PRJ_PATH)/temp $(LNX_MAKEOPTS) modules ++ cp $(PRJ_PATH)/temp/Module.symvers $(PRJ_PATH)/Module.symvers; + cp temp/*.ko build/bin; ++ rm -Rf ./temp/*.o ./temp/*.ko ./temp/*.a + @echo "---Build [SSDK-$(VERSION)] at $(BUILD_DATE) finished." + + kslib_c: From 3d63bf4da7254de27191674ee79d884ac4a5b611 Mon Sep 17 00:00:00 2001 From: Tomasz Maciej Nowak Date: Thu, 27 Apr 2023 16:34:48 +0200 Subject: [PATCH 27/43] ubnt-ledbar: add kernel 6.1 compat As of ed5c2f5fd10d ("i2c: Make remove callback return void") return value of remove function is ignored. Signed-off-by: Tomasz Maciej Nowak --- package/kernel/ubnt-ledbar/src/leds-ubnt-ledbar.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/package/kernel/ubnt-ledbar/src/leds-ubnt-ledbar.c b/package/kernel/ubnt-ledbar/src/leds-ubnt-ledbar.c index 555340c5e87..ee9d34601c6 100644 --- a/package/kernel/ubnt-ledbar/src/leds-ubnt-ledbar.c +++ b/package/kernel/ubnt-ledbar/src/leds-ubnt-ledbar.c @@ -9,6 +9,7 @@ #include #include #include +#include /** * Driver for the Ubiquiti RGB LED controller (LEDBAR). @@ -218,13 +219,19 @@ static int ubnt_ledbar_probe(struct i2c_client *client, return ubnt_ledbar_apply_state(ledbar); } +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0) static int ubnt_ledbar_remove(struct i2c_client *client) +#else +static void ubnt_ledbar_remove(struct i2c_client *client) +#endif { struct ubnt_ledbar *ledbar = i2c_get_clientdata(client); mutex_destroy(&ledbar->lock); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0) return 0; +#endif } static const struct i2c_device_id ubnt_ledbar_id[] = { From e81298463ed45cd03d45837c12f4c0a4b85f6cd4 Mon Sep 17 00:00:00 2001 From: Tomasz Maciej Nowak Date: Thu, 27 Apr 2023 16:34:49 +0200 Subject: [PATCH 28/43] ubnt-ledbar: depend on mediatek and ramips subtargets It's only used on devices in mt7621 and mt7622 subtargets, so no reason to compile it for others. Signed-off-by: Tomasz Maciej Nowak --- package/kernel/ubnt-ledbar/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package/kernel/ubnt-ledbar/Makefile b/package/kernel/ubnt-ledbar/Makefile index 90eccf1c21b..69236ffbb33 100644 --- a/package/kernel/ubnt-ledbar/Makefile +++ b/package/kernel/ubnt-ledbar/Makefile @@ -20,7 +20,7 @@ define KernelPackage/leds-ubnt-ledbar FILES:= \ $(PKG_BUILD_DIR)/leds-ubnt-ledbar.ko AUTOLOAD:=$(call AutoProbe,leds-ubnt-ledbar,1) - DEPENDS:=+kmod-i2c-core + DEPENDS:=@TARGET_mediatek_mt7622||TARGET_ramips_mt7621 +kmod-i2c-core endef define KernelPackage/leds-ubnt-ledbar/description From 5636ffc22d784a2a4acc5e406e54f8a5858f1435 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Mon, 29 Aug 2022 08:03:08 +0200 Subject: [PATCH 29/43] tools/meson: update to 1.1.0 Remove upstreamed: - 010-wsl2.patch Release Notes: - 0.62.0 https://mesonbuild.com/Release-notes-for-0-62-0.html - 0.63.0 https://mesonbuild.com/Release-notes-for-0-63-0.html - 0.64.0 https://mesonbuild.com/Release-notes-for-0-64-0.html - 1.0.0 https://mesonbuild.com/Release-notes-for-1-0-0.html - 1.1.0 https://mesonbuild.com/Release-notes-for-1-1-0.html Signed-off-by: Nick Hainke --- tools/meson/Makefile | 4 ++-- tools/meson/patches/010-wsl2.patch | 21 --------------------- 2 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 tools/meson/patches/010-wsl2.patch diff --git a/tools/meson/Makefile b/tools/meson/Makefile index d53ed897a35..f0810ced96c 100644 --- a/tools/meson/Makefile +++ b/tools/meson/Makefile @@ -1,11 +1,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=meson -PKG_VERSION:=0.61.5 +PKG_VERSION:=1.1.0 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/mesonbuild/meson/releases/download/$(PKG_VERSION) -PKG_HASH:=5e9a0d65c1a51936362b9686d1c5e9e184a6fd245d57e7269750ce50c20f5d9a +PKG_HASH:=d9616c44cd6c53689ff8f05fc6958a693f2e17c3472a8daf83cee55dabff829f PKG_MAINTAINER:=Andre Heider PKG_LICENSE:=Apache-2.0 diff --git a/tools/meson/patches/010-wsl2.patch b/tools/meson/patches/010-wsl2.patch deleted file mode 100644 index 4ab799d6992..00000000000 --- a/tools/meson/patches/010-wsl2.patch +++ /dev/null @@ -1,21 +0,0 @@ -From 7d1ef4343ed5b2b7ab51469177a42c32c47f0528 Mon Sep 17 00:00:00 2001 -From: Rosen Penev -Date: Tue, 6 Sep 2022 01:36:17 -0700 -Subject: [PATCH] minstall: handle extra error for selinuxenabled - -Microsoft's WSL2 uses a Plan 9 filesystem, which returns IOError when file is missing. ---- - mesonbuild/minstall.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/mesonbuild/minstall.py -+++ b/mesonbuild/minstall.py -@@ -229,7 +229,7 @@ def restore_selinux_contexts() -> None: - ''' - try: - subprocess.check_call(['selinuxenabled']) -- except (FileNotFoundError, NotADirectoryError, PermissionError, subprocess.CalledProcessError): -+ except (FileNotFoundError, NotADirectoryError, OSError, PermissionError, subprocess.CalledProcessError): - # If we don't have selinux or selinuxenabled returned 1, failure - # is ignored quietly. - return From afe1bf11f2539f75e30ab3206891dbe6f8c43bd5 Mon Sep 17 00:00:00 2001 From: Tony Ambardar Date: Sun, 21 May 2023 02:14:37 -0700 Subject: [PATCH 30/43] bpftools: update, split off bpftool and libbpf packages My original bpftools package made "variant" builds of bpftool and libbpf as a convenience, since both used the same local kernel sources with the same versioning. This is no longer the case, since the commit below switched to using an out-of-tree build mirror hosting repos for each. Replace bpftools with separate bpftool and libbpf packages, each simplified and correctly versioned. Also fix the broken libbpf ABI introduced in the same commit. Existing build .config files are not impacted. Fixes: 00cbf6f6ab1d ("bpftools: update to standalone bpftools + libbpf, use the latest version") Signed-off-by: Tony Ambardar --- package/libs/libbpf/Makefile | 75 +++++++++++++++++++ package/libs/libbpf/patches/001-cflags.patch | 10 +++ .../utils/{bpftools => bpftool}/Makefile | 64 ++-------------- .../patches/001-cflags.patch | 0 .../patches/002-includes.patch | 0 5 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 package/libs/libbpf/Makefile create mode 100644 package/libs/libbpf/patches/001-cflags.patch rename package/network/utils/{bpftools => bpftool}/Makefile (55%) rename package/network/utils/{bpftools => bpftool}/patches/001-cflags.patch (100%) rename package/network/utils/{bpftools => bpftool}/patches/002-includes.patch (100%) diff --git a/package/libs/libbpf/Makefile b/package/libs/libbpf/Makefile new file mode 100644 index 00000000000..ee7666f734d --- /dev/null +++ b/package/libs/libbpf/Makefile @@ -0,0 +1,75 @@ +# +# Copyright (C) 2020-2023 Tony Ambardar +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libbpf +PKG_VERSION:=1.2.0 +PKG_RELEASE:=1 + +PKG_SOURCE_URL:=https://github.com/libbpf/libbpf +PKG_SOURCE_PROTO:=git +PKG_SOURCE_VERSION:=fbd60dbff51c870f5e80a17c4f2fd639eb80af90 +PKG_MIRROR_HASH:=80a80dfba71576e017b596fb28068e2a92de629e426f063e4b37314c8d576336 +PKG_ABI_VERSION:=$(firstword $(subst .,$(space),$(PKG_VERSION))) + +PKG_MAINTAINER:=Tony Ambardar + +PKG_BUILD_FLAGS:=no-mips16 +PKG_BUILD_PARALLEL:=1 +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/nls.mk + +define Package/libbpf + SECTION:=libs + CATEGORY:=Libraries + TITLE:=libbpf - eBPF helper library + LICENSE:=LGPL-2.1 OR BSD-2-Clause + ABI_VERSION:=$(PKG_ABI_VERSION) + URL:=http://www.kernel.org + DEPENDS:=+libelf +endef + +define Package/libbpf/description + libbpf is a library for loading eBPF programs and reading and manipulating eBPF objects from user-space. +endef + +MAKE_VARS = \ + EXTRA_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \ + LDFLAGS="$(TARGET_LDFLAGS)" + +MAKE_FLAGS += \ + $(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \ + LIBSUBDIR=lib + +MAKE_PATH = src + +define Build/InstallDev/libbpf + $(INSTALL_DIR) $(1)/usr/include/bpf + $(CP) $(PKG_INSTALL_DIR)/usr/include/bpf/*.h $(1)/usr/include/bpf/ + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.{a,so*} \ + $(1)/usr/lib/ + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig + $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libbpf.pc \ + $(1)/usr/lib/pkgconfig/ + $(SED) 's,/usr/include,$$$${prefix}/include,g' \ + $(1)/usr/lib/pkgconfig/libbpf.pc + $(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' \ + $(1)/usr/lib/pkgconfig/libbpf.pc +endef + +Build/InstallDev=$(Build/InstallDev/libbpf) + +define Package/libbpf/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.so.* $(1)/usr/lib/ +endef + +$(eval $(call BuildPackage,libbpf)) diff --git a/package/libs/libbpf/patches/001-cflags.patch b/package/libs/libbpf/patches/001-cflags.patch new file mode 100644 index 00000000000..d6ffc3f907f --- /dev/null +++ b/package/libs/libbpf/patches/001-cflags.patch @@ -0,0 +1,10 @@ +--- a/src/Makefile ++++ b/src/Makefile +@@ -34,6 +34,7 @@ ALL_CFLAGS := $(INCLUDES) + + SHARED_CFLAGS += -fPIC -fvisibility=hidden -DSHARED + ++CFLAGS = $(EXTRA_CFLAGS) + CFLAGS ?= -g -O2 -Werror -Wall -std=gnu89 + ALL_CFLAGS += $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 $(EXTRA_CFLAGS) + ALL_LDFLAGS += $(LDFLAGS) $(EXTRA_LDFLAGS) diff --git a/package/network/utils/bpftools/Makefile b/package/network/utils/bpftool/Makefile similarity index 55% rename from package/network/utils/bpftools/Makefile rename to package/network/utils/bpftool/Makefile index 047d2a0967e..cbbba2dba59 100644 --- a/package/network/utils/bpftools/Makefile +++ b/package/network/utils/bpftool/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2020 Tony Ambardar +# Copyright (C) 2020-2023 Tony Ambardar # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -8,14 +8,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=bpftools +PKG_VERSION:=7.2.0 PKG_RELEASE:=1 PKG_SOURCE_URL:=https://github.com/libbpf/bpftool PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=7.1.0 -PKG_SOURCE_VERSION:=b01941c8f7890489f09713348a7d89567538504b -PKG_MIRROR_HASH:=641fb337342e25ae784a3efe72c71d8c88600a326300d8d5834e26be21547015 -PKG_ABI_VERSION:=$(call abi_version_str,$(PKG_SOURCE_DATE)) +PKG_SOURCE_VERSION:=19ff0564980a7429e730f6987a0b0bf418b3c676 +PKG_MIRROR_HASH:=f9b9871f64986dd2e5dab7060bb919398256ba93964da49c62efaf0e6bc9bbc4 PKG_MAINTAINER:=Tony Ambardar @@ -63,27 +62,8 @@ define Package/bpftool-full/description eBPF programs and jited code. endef -define Package/libbpf - SECTION:=libs - CATEGORY:=Libraries - TITLE:=libbpf - eBPF helper library - VARIANT:=lib - LICENSE:=LGPL-2.1 OR BSD-2-Clause - ABI_VERSION:=$(PKG_ABI_VERSION) - URL:=http://www.kernel.org - DEPENDS:=+libelf -endef - -define Package/libbpf/description - libbpf is a library for loading eBPF programs and reading and manipulating eBPF objects from user-space. -endef - - -# LTO not compatible with DSO using PIC -ifneq ($(BUILD_VARIANT),lib) - TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto - TARGET_LDFLAGS += -Wl,--gc-sections -flto -endif +TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto +TARGET_LDFLAGS += -Wl,--gc-sections -flto ifeq ($(BUILD_VARIANT),full) full:=1 @@ -99,7 +79,6 @@ MAKE_FLAGS += \ OUTPUT="$(PKG_BUILD_DIR)/" \ prefix="/usr" \ $(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='') \ - LIBSUBDIR=lib \ check_feat=0 \ feature-clang-bpf-co-re=0 \ feature-libbfd=$(full) \ @@ -108,30 +87,7 @@ MAKE_FLAGS += \ feature-disassembler-four-args=1 \ feature-disassembler-init-styled=1 -ifeq ($(BUILD_VARIANT),lib) - MAKE_PATH = libbpf/src -else - MAKE_PATH = src -endif - -define Build/InstallDev/libbpf - $(INSTALL_DIR) $(1)/usr/include/bpf - $(CP) $(PKG_INSTALL_DIR)/usr/include/bpf/*.h $(1)/usr/include/bpf/ - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.{a,so*} \ - $(1)/usr/lib/ - $(INSTALL_DIR) $(1)/usr/lib/pkgconfig - $(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libbpf.pc \ - $(1)/usr/lib/pkgconfig/ - $(SED) 's,/usr/include,$$$${prefix}/include,g' \ - $(1)/usr/lib/pkgconfig/libbpf.pc - $(SED) 's,/usr/lib,$$$${exec_prefix}/lib,g' \ - $(1)/usr/lib/pkgconfig/libbpf.pc -endef - -ifeq ($(BUILD_VARIANT),lib) - Build/InstallDev=$(Build/InstallDev/libbpf) -endif +MAKE_PATH = src define Package/bpftool-$(BUILD_VARIANT)/install $(INSTALL_DIR) $(1)/usr/libexec @@ -139,11 +95,5 @@ define Package/bpftool-$(BUILD_VARIANT)/install $(1)/usr/libexec/bpftool-$(BUILD_VARIANT) endef -define Package/libbpf/install - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbpf.so.* $(1)/usr/lib/ -endef - -$(eval $(call BuildPackage,libbpf)) $(eval $(call BuildPackage,bpftool-full)) $(eval $(call BuildPackage,bpftool-minimal)) diff --git a/package/network/utils/bpftools/patches/001-cflags.patch b/package/network/utils/bpftool/patches/001-cflags.patch similarity index 100% rename from package/network/utils/bpftools/patches/001-cflags.patch rename to package/network/utils/bpftool/patches/001-cflags.patch diff --git a/package/network/utils/bpftools/patches/002-includes.patch b/package/network/utils/bpftool/patches/002-includes.patch similarity index 100% rename from package/network/utils/bpftools/patches/002-includes.patch rename to package/network/utils/bpftool/patches/002-includes.patch From bcb094f549c6d012938a65201ef742b0235e6840 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 22 May 2023 23:28:05 +0200 Subject: [PATCH 31/43] generic: 6.1: disable CONFIG_SURFACE_PLATFORMS by default There is no need for Surface platform drivers to be enabled by default, especially on OpenWrt so disable CONFIG_SURFACE_PLATFORMS in the generic config. Signed-off-by: Robert Marko --- target/linux/generic/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index b6ece6c6e1a..4429f1e67b0 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -6536,6 +6536,7 @@ CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES=y # CONFIG_SUNXI_SRAM is not set # CONFIG_SUN_PARTITION is not set # CONFIG_SURFACE_3_BUTTON is not set +# CONFIG_SURFACE_PLATFORMS is not set # CONFIG_SUSPEND is not set # CONFIG_SUSPEND_SKIP_SYNC is not set CONFIG_SWAP=y From bccc6a58ce65e5b9d957614782f469aaf3347131 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 22 May 2023 23:31:05 +0200 Subject: [PATCH 32/43] generic: 6.1: disable CONFIG_ARCH_NXP by default There is no reason for CONFIG_ARCH_NXP to have to be disabled in individual targets, so just disable CONFIG_ARCH_NXP in generic config. Signed-off-by: Robert Marko --- target/linux/generic/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 4429f1e67b0..e0884c3b368 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -277,6 +277,7 @@ CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 # CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_NPCM is not set # CONFIG_ARCH_NSPIRE is not set +# CONFIG_ARCH_NXP is not set # CONFIG_ARCH_OMAP is not set # CONFIG_ARCH_OMAP1 is not set # CONFIG_ARCH_OMAP2 is not set From 62e88d22b968737e63947655e033660b467e6313 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 22 May 2023 23:34:01 +0200 Subject: [PATCH 33/43] generic: 6.1: disable CONFIG_HP_WATCHDOG by default There is no reason for HP ProLiant HW watchdog to be disabled in individual targets, so disable it in generic config. Signed-off-by: Robert Marko --- target/linux/generic/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index e0884c3b368..65c000bb204 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -2481,6 +2481,7 @@ CONFIG_HIGH_RES_TIMERS=y CONFIG_HPET_MMAP_DEFAULT=y # CONFIG_HPFS_FS is not set # CONFIG_HP_ILO is not set +# CONFIG_HP_WATCHDOG is not set # CONFIG_HP_WIRELESS is not set # CONFIG_HSA_AMD is not set # CONFIG_HSI is not set From 16799045bf955d7058d93b8a4efd47bf60c7d3ab Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 22 May 2023 23:36:44 +0200 Subject: [PATCH 34/43] generic: 6.1: disable CONFIG_OCTEON_EP by default There is no reason for Octeon PCI endpoint driver to be disabled in targets so disable it in generic config. Signed-off-by: Robert Marko --- target/linux/generic/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 65c000bb204..8b2e8e4d984 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -4563,6 +4563,7 @@ CONFIG_NMI_LOG_BUF_SHIFT=13 # CONFIG_OCFS2_FS is not set # CONFIG_OCTEONTX2_AF is not set # CONFIG_OCTEONTX2_PF is not set +# CONFIG_OCTEON_EP is not set # CONFIG_OF_OVERLAY is not set CONFIG_OF_RESERVED_MEM=y # CONFIG_OF_UNITTEST is not set From 344540d727385ae95796ac8abbb0d687f5a3fdd5 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 22 May 2023 23:38:44 +0200 Subject: [PATCH 35/43] generic: 6.1: disable CONFIG_VMWARE_VMCI by default There is no reason for VMware VMCI to be disabled in targets, so disable it in the generic config. Signed-off-by: Robert Marko --- target/linux/generic/config-6.1 | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-6.1 b/target/linux/generic/config-6.1 index 8b2e8e4d984..6a4913535d7 100644 --- a/target/linux/generic/config-6.1 +++ b/target/linux/generic/config-6.1 @@ -7610,6 +7610,7 @@ CONFIG_VLAN_8021Q=y CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_3G_OPT is not set # CONFIG_VMWARE_PVSCSI is not set +# CONFIG_VMWARE_VMCI is not set # CONFIG_VMXNET3 is not set # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_VOP_BUS is not set From 3591353f5143fc46e31f921484177a9d6f1089a2 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Mon, 22 May 2023 23:42:13 +0200 Subject: [PATCH 36/43] generic: filter out CONFIG_PAHOLE_HAS_SPLIT_BTF CONFIG_PAHOLE_HAS_SPLIT_BTF should be runtime detected as it depends on pahole being available on the host, so filter it out of configs. Signed-off-by: Robert Marko --- target/linux/generic/config-filter | 1 + 1 file changed, 1 insertion(+) diff --git a/target/linux/generic/config-filter b/target/linux/generic/config-filter index 201b68dddf2..e7aa90f8b54 100644 --- a/target/linux/generic/config-filter +++ b/target/linux/generic/config-filter @@ -10,6 +10,7 @@ CONFIG_CLANG_VERSION=.* # CONFIG_LD_.* is not set CONFIG_LLD_VERSION=.* CONFIG_PAHOLE_VERSION=.* +CONFIG_PAHOLE_HAS_SPLIT_BTF=.* CONFIG_PLUGIN_HOSTCC=".*" # CONFIG_SET_FS is not set # CONFIG_TASKS_.* is not set From f5a5ce8822e9add9627ecb6ea289c8de2b8a76a9 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 25 May 2023 13:52:03 +0200 Subject: [PATCH 37/43] CI: ignore master branch for push events Due to problem with migrating from master to main as the default branch and downstream project still requiring the master branch to be present, we currently have for push events double CI runs, one for main and one for master. To solve this ignore any push event to the master branch for every workflow that react on push events. Signed-off-by: Christian Marangi --- .github/workflows/kernel.yml | 2 ++ .github/workflows/packages.yml | 2 ++ .github/workflows/push-containers.yml | 2 ++ .github/workflows/toolchain.yml | 2 ++ .github/workflows/tools.yml | 2 ++ 5 files changed, 10 insertions(+) diff --git a/.github/workflows/kernel.yml b/.github/workflows/kernel.yml index b918b2d88e4..6be7ef28c2f 100644 --- a/.github/workflows/kernel.yml +++ b/.github/workflows/kernel.yml @@ -17,6 +17,8 @@ on: - 'include/kernel*' - 'package/kernel/**' - 'target/linux/**' + branches-ignore: + - master permissions: contents: read diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index d8270cbb820..d4d3565cd70 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -19,6 +19,8 @@ on: - 'package/**' - 'target/linux/generic/**' - 'toolchain/**' + branches-ignore: + - master permissions: contents: read diff --git a/.github/workflows/push-containers.yml b/.github/workflows/push-containers.yml index fcbaf96788d..eb6ffd30c1e 100644 --- a/.github/workflows/push-containers.yml +++ b/.github/workflows/push-containers.yml @@ -12,6 +12,8 @@ on: - '.github/workflows/build.yml' - '.github/workflows/toolchain.yml' - '.github/workflows/Dockerfile.toolchain' + branches-ignore: + - master permissions: contents: read diff --git a/.github/workflows/toolchain.yml b/.github/workflows/toolchain.yml index 5755ca25b9d..54e31069e6f 100644 --- a/.github/workflows/toolchain.yml +++ b/.github/workflows/toolchain.yml @@ -11,6 +11,8 @@ on: - '.github/workflows/build.yml' - '.github/workflows/toolchain.yml' - 'toolchain/**' + branches-ignore: + - master permissions: contents: read diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 76ebdc664b8..83bf5e98f5a 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -13,6 +13,8 @@ on: - 'tools/**' - '.github/workflows/build-tools.yml' - '.github/workflows/tools.yml' + branches-ignore: + - master permissions: contents: read From bf8187d5dc4d4bbb23770955744bca1787f32ac0 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 25 May 2023 18:24:00 +0200 Subject: [PATCH 38/43] CI: use split target and subtarget in label workflow With eecc6e48117b ("CI: rework build workflow to have split target and subtarget directly") target and subtarget are split in 2 different variables. Label workflow were not aligned to this change and are currently broken. Fix them and correctly pass split target and subtarget. Fixes: eecc6e48117b ("CI: rework build workflow to have split target and subtarget directly") Signed-off-by: Christian Marangi --- .github/workflows/label-kernel.yml | 5 ++++- .github/workflows/label-target.yml | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/label-kernel.yml b/.github/workflows/label-kernel.yml index 1156e0ad985..6c79014edb6 100644 --- a/.github/workflows/label-kernel.yml +++ b/.github/workflows/label-kernel.yml @@ -20,7 +20,8 @@ jobs: env: CI_EVENT_LABEL_NAME: ${{ github.event.label.name }} run: | - echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1\/\2"/p' | tee --append $GITHUB_OUTPUT + echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1"/p' | tee --append $GITHUB_OUTPUT + echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/subtarget="\2"/p' | tee --append $GITHUB_OUTPUT build_kernel: name: Build Kernel with external toolchain @@ -31,6 +32,7 @@ jobs: uses: ./.github/workflows/build.yml with: target: ${{ needs.set_target.outputs.target }} + subtarget: ${{ needs.set_target.outputs.subtarget }} build_kernel: true build_all_kmods: true @@ -43,3 +45,4 @@ jobs: uses: ./.github/workflows/check-kernel-patches.yml with: target: ${{ needs.set_target.outputs.target }} + subtarget: ${{ needs.set_target.outputs.subtarget }} diff --git a/.github/workflows/label-target.yml b/.github/workflows/label-target.yml index e1890240764..4c3df28f51b 100644 --- a/.github/workflows/label-target.yml +++ b/.github/workflows/label-target.yml @@ -20,7 +20,8 @@ jobs: env: CI_EVENT_LABEL_NAME: ${{ github.event.label.name }} run: | - echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1\/\2"/p' | tee --append $GITHUB_OUTPUT + echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/target="\1"/p' | tee --append $GITHUB_OUTPUT + echo "$CI_EVENT_LABEL_NAME" | sed -n 's/.*:\(.*\):\(.*\)$/subtarget="\2"/p' | tee --append $GITHUB_OUTPUT build_target: name: Build target @@ -31,6 +32,7 @@ jobs: uses: ./.github/workflows/build.yml with: target: ${{ needs.set_target.outputs.target }} + subtarget: ${{ needs.set_target.outputs.subtarget }} build_full: true build_all_kmods: true build_all_boards: true From 8aa5a860101cc3f8d35ca968746320495c4b469e Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 25 May 2023 23:09:59 +0200 Subject: [PATCH 39/43] CI: correctly output subtarget in label workflow Commit bf8187d5dc4d ("CI: use split target and subtarget in label workflow") didn't correctly output subtarget resulting in calling with an empty subtarget. Fix this and correctly output generated subtarget. Fixes: bf8187d5dc4d ("CI: use split target and subtarget in label workflow") Signed-off-by: Christian Marangi --- .github/workflows/label-kernel.yml | 1 + .github/workflows/label-target.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/label-kernel.yml b/.github/workflows/label-kernel.yml index 6c79014edb6..243d285e289 100644 --- a/.github/workflows/label-kernel.yml +++ b/.github/workflows/label-kernel.yml @@ -13,6 +13,7 @@ jobs: runs-on: ubuntu-latest outputs: target: ${{ steps.set_target.outputs.target }} + subtarget: ${{ steps.set_target.outputs.subtarget }} steps: - name: Set target diff --git a/.github/workflows/label-target.yml b/.github/workflows/label-target.yml index 4c3df28f51b..3a624598b1e 100644 --- a/.github/workflows/label-target.yml +++ b/.github/workflows/label-target.yml @@ -13,6 +13,7 @@ jobs: runs-on: ubuntu-latest outputs: target: ${{ steps.set_target.outputs.target }} + subtarget: ${{ steps.set_target.outputs.subtarget }} steps: - name: Set target From 0063e71d66766818fba286efe2a0ed8746c265e5 Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Thu, 25 May 2023 02:44:21 +0200 Subject: [PATCH 40/43] CI: build: fix parse toolchain step failing for git strict rules Commit 1cb8cdb ("ci: use new buildbot worker images with Debian 11") introduced new Git version with strict rules for owner of the git directory. To handle this and not cause major change, just move the parsing before the change of ownership of the openwrt directory permitting the correct run of git fetch command with the same user that did the repository checkout. Fixes: 1cb8cdb ("ci: use new buildbot worker images with Debian 11") Signed-off-by: Christian Marangi --- .github/workflows/build.yml | 44 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd93d5f8022..78f856962e6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -179,28 +179,6 @@ jobs: repository: openwrt/telephony path: openwrt/feeds/telephony - - name: Fix permission - run: | - chown -R buildbot:buildbot openwrt - - - name: Prepare prebuilt tools - shell: su buildbot -c "sh -e {0}" - working-directory: openwrt - run: | - mkdir -p staging_dir build_dir - ln -s /prebuilt_tools/staging_dir/host staging_dir/host - ln -s /prebuilt_tools/build_dir/host build_dir/host - - ./scripts/ext-tools.sh --refresh - - - name: Update & Install feeds - if: inputs.include_feeds == true - shell: su buildbot -c "sh -e {0}" - working-directory: openwrt - run: | - ./scripts/feeds update -a - ./scripts/feeds install -a - - name: Parse toolchain file if: inputs.build_toolchain == false id: parse-toolchain @@ -255,6 +233,28 @@ jobs: echo "TOOLCHAIN_FILE=$TOOLCHAIN_FILE" >> "$GITHUB_ENV" echo "TOOLCHAIN_PATH=$TOOLCHAIN_PATH" >> "$GITHUB_ENV" + - name: Fix permission + run: | + chown -R buildbot:buildbot openwrt + + - name: Prepare prebuilt tools + shell: su buildbot -c "sh -e {0}" + working-directory: openwrt + run: | + mkdir -p staging_dir build_dir + ln -s /prebuilt_tools/staging_dir/host staging_dir/host + ln -s /prebuilt_tools/build_dir/host build_dir/host + + ./scripts/ext-tools.sh --refresh + + - name: Update & Install feeds + if: inputs.include_feeds == true + shell: su buildbot -c "sh -e {0}" + working-directory: openwrt + run: | + ./scripts/feeds update -a + ./scripts/feeds install -a + - name: Cache ccache uses: actions/cache@v3 with: From b28b8ed1f45de1ecff0a893345a0fcbf3fff3bbe Mon Sep 17 00:00:00 2001 From: Kazuki Hashimoto Date: Wed, 24 May 2023 23:56:36 +0900 Subject: [PATCH 41/43] kernel: 6.1: Synchronize MGLRU patches with upstream Replace the refreshed 5.15 backports with backports for 6.1. This fixes FMODE_CAN_ODIRECT having the same value as FMODE_NOREUSE. Signed-off-by: Kazuki Hashimoto --- ...-gen-LRU-rename-lru_gen_struct-to-l.patch} | 59 ++- ...-gen-LRU-rename-lrugen-lists-to-lru.patch} | 80 +++- ...-gen-LRU-remove-eviction-fairness-s.patch} | 34 +- ...-gen-LRU-remove-aging-fairness-safe.patch} | 34 +- ...ti-gen-LRU-shuffle-should_run_aging.patch} | 20 +- ...-gen-LRU-per-node-lru_gen_folio-lis.patch} | 118 +++-- ...-gen-LRU-clarify-scan_control-flags.patch} | 47 +- ...-gen-LRU-simplify-arch_has_hw_pte_y.patch} | 17 +- ...-multi-gen-LRU-avoid-futile-retries.patch} | 21 +- ...-10-UPSTREAM-mm-add-vma_has_recency.patch} | 45 +- ...TREAM-mm-support-POSIX_FADV_NOREUSE.patch} | 29 +- ...i-gen-LRU-section-for-working-set-pr.patch | 74 +++ ...i-gen-LRU-section-for-rmap-PT-walk-f.patch | 64 +++ ...ti-gen-LRU-section-for-Bloom-filters.patch | 250 ++++++++++ ...-multi-gen-LRU-section-for-memcg-LRU.patch | 440 ++++++++++++++++++ ...i-gen-LRU-improve-lru_gen_exit_memcg.patch | 45 ++ ...multi-gen-LRU-improve-walk_pmd_range.patch | 140 ++++++ ...i-gen-LRU-simplify-lru_gen_look_arou.patch | 153 ++++++ 18 files changed, 1505 insertions(+), 165 deletions(-) rename target/linux/generic/backport-6.1/{020-v6.3-21-mm-multi-gen-LRU-rename-lru_gen_struct-to-lru_gen_pa.patch => 020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch} (81%) rename target/linux/generic/backport-6.1/{020-v6.3-22-mm-multi-gen-LRU-rename-lrugen-lists-to-lrugen-pages.patch => 020-v6.3-02-UPSTREAM-mm-multi-gen-LRU-rename-lrugen-lists-to-lru.patch} (60%) rename target/linux/generic/backport-6.1/{020-v6.3-23-mm-multi-gen-LRU-remove-eviction-fairness-safeguard.patch => 020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch} (79%) rename target/linux/generic/backport-6.1/{020-v6.3-24-mm-multi-gen-LRU-remove-aging-fairness-safeguard.patch => 020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch} (85%) rename target/linux/generic/backport-6.1/{020-v6.3-25-mm-multi-gen-LRU-shuffle-should_run_aging.patch => 020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch} (87%) rename target/linux/generic/backport-6.1/{020-v6.3-26-mm-multi-gen-LRU-per-node-lru_gen_page-lists.patch => 020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch} (85%) rename target/linux/generic/backport-6.1/{020-v6.3-27-mm-multi-gen-LRU-clarify-scan_control-flags.patch => 020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch} (71%) rename target/linux/generic/backport-6.1/{020-v6.3-28-mm-multi-gen-LRU-simplify-arch_has_hw_pte_young-chec.patch => 020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch} (67%) rename target/linux/generic/backport-6.1/{020-v6.3-29-mm-multi-gen-LRU-avoid-futile-retries.patch => 020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch} (74%) rename target/linux/generic/backport-6.1/{020-v6.3-19-mm-add-vma_has_recency.patch => 020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch} (75%) rename target/linux/generic/backport-6.1/{020-v6.3-20-mm-support-POSIX_FADV_NOREUSE.patch => 020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch} (78%) create mode 100644 target/linux/generic/backport-6.1/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch diff --git a/target/linux/generic/backport-6.1/020-v6.3-21-mm-multi-gen-LRU-rename-lru_gen_struct-to-lru_gen_pa.patch b/target/linux/generic/backport-6.1/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch similarity index 81% rename from target/linux/generic/backport-6.1/020-v6.3-21-mm-multi-gen-LRU-rename-lru_gen_struct-to-lru_gen_pa.patch rename to target/linux/generic/backport-6.1/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch index 881ef4e528f..d63b03e6e87 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-21-mm-multi-gen-LRU-rename-lru_gen_struct-to-lru_gen_pa.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-01-UPSTREAM-mm-multi-gen-LRU-rename-lru_gen_struct-to-l.patch @@ -1,7 +1,7 @@ -From 348fdbada9fb3f0bf1a53651be46319105af187f Mon Sep 17 00:00:00 2001 +From 8c20e2eb5f2a0175b774134685e4d7bd93e85ff8 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:18:59 -0700 -Subject: [PATCH 21/29] mm: multi-gen LRU: rename lru_gen_struct to +Subject: [PATCH 01/19] UPSTREAM: mm: multi-gen LRU: rename lru_gen_struct to lru_gen_folio Patch series "mm: multi-gen LRU: memcg LRU", v3. @@ -115,6 +115,10 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit 391655fe08d1f942359a11148aa9aaf3f99d6d6f) +Change-Id: I7df67e0e2435ba28f10eaa57d28d98b61a9210a6 +Signed-off-by: T.J. Mercier --- include/linux/mm_inline.h | 4 ++-- include/linux/mmzone.h | 6 +++--- @@ -122,9 +126,11 @@ Signed-off-by: Andrew Morton mm/workingset.c | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) +diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h +index e8ed225d8f7ca..f63968bd7de59 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h -@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(s +@@ -178,7 +178,7 @@ static inline void lru_gen_update_size(struct lruvec *lruvec, struct folio *foli int zone = folio_zonenum(folio); int delta = folio_nr_pages(folio); enum lru_list lru = type * LRU_INACTIVE_FILE; @@ -133,7 +139,7 @@ Signed-off-by: Andrew Morton VM_WARN_ON_ONCE(old_gen != -1 && old_gen >= MAX_NR_GENS); VM_WARN_ON_ONCE(new_gen != -1 && new_gen >= MAX_NR_GENS); -@@ -224,7 +224,7 @@ static inline bool lru_gen_add_folio(str +@@ -224,7 +224,7 @@ static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, int gen = folio_lru_gen(folio); int type = folio_is_file_lru(folio); int zone = folio_zonenum(folio); @@ -142,6 +148,8 @@ Signed-off-by: Andrew Morton VM_WARN_ON_ONCE_FOLIO(gen != -1, folio); +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index 5f74891556f33..bd3e4689f72dc 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -404,7 +404,7 @@ enum { @@ -171,9 +179,11 @@ Signed-off-by: Andrew Morton /* to concurrently iterate lru_gen_mm_list */ struct lru_gen_mm_state mm_state; #endif +diff --git a/mm/vmscan.c b/mm/vmscan.c +index d18296109aa7e..27142caf284c1 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lr +@@ -3190,7 +3190,7 @@ static int get_nr_gens(struct lruvec *lruvec, int type) static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) { @@ -191,7 +201,7 @@ Signed-off-by: Andrew Morton int hist = lru_hist_from_seq(lrugen->min_seq[type]); pos->refaulted = lrugen->avg_refaulted[type][tier] + -@@ -3611,7 +3611,7 @@ static void read_ctrl_pos(struct lruvec +@@ -3611,7 +3611,7 @@ static void read_ctrl_pos(struct lruvec *lruvec, int type, int tier, int gain, static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover) { int hist, tier; @@ -200,7 +210,7 @@ Signed-off-by: Andrew Morton bool clear = carryover ? NR_HIST_GENS == 1 : NR_HIST_GENS > 1; unsigned long seq = carryover ? lrugen->min_seq[type] : lrugen->max_seq + 1; -@@ -3688,7 +3688,7 @@ static int folio_update_gen(struct folio +@@ -3688,7 +3688,7 @@ static int folio_update_gen(struct folio *folio, int gen) static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclaiming) { int type = folio_is_file_lru(folio); @@ -209,7 +219,7 @@ Signed-off-by: Andrew Morton int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); unsigned long new_flags, old_flags = READ_ONCE(folio->flags); -@@ -3733,7 +3733,7 @@ static void update_batch_size(struct lru +@@ -3733,7 +3733,7 @@ static void update_batch_size(struct lru_gen_mm_walk *walk, struct folio *folio, static void reset_batch_size(struct lruvec *lruvec, struct lru_gen_mm_walk *walk) { int gen, type, zone; @@ -218,7 +228,7 @@ Signed-off-by: Andrew Morton walk->batched = 0; -@@ -4253,7 +4253,7 @@ static bool inc_min_seq(struct lruvec *l +@@ -4250,7 +4250,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap) { int zone; int remaining = MAX_LRU_BATCH; @@ -227,7 +237,7 @@ Signed-off-by: Andrew Morton int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); if (type == LRU_GEN_ANON && !can_swap) -@@ -4289,7 +4289,7 @@ static bool try_to_inc_min_seq(struct lr +@@ -4286,7 +4286,7 @@ static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) { int gen, type, zone; bool success = false; @@ -236,7 +246,7 @@ Signed-off-by: Andrew Morton DEFINE_MIN_SEQ(lruvec); VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); -@@ -4310,7 +4310,7 @@ next: +@@ -4307,7 +4307,7 @@ static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) ; } @@ -245,7 +255,7 @@ Signed-off-by: Andrew Morton if (can_swap) { min_seq[LRU_GEN_ANON] = min(min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FILE]); min_seq[LRU_GEN_FILE] = max(min_seq[LRU_GEN_ANON], lrugen->min_seq[LRU_GEN_FILE]); -@@ -4332,7 +4332,7 @@ static void inc_max_seq(struct lruvec *l +@@ -4329,7 +4329,7 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan) { int prev, next; int type, zone; @@ -254,7 +264,7 @@ Signed-off-by: Andrew Morton spin_lock_irq(&lruvec->lru_lock); -@@ -4390,7 +4390,7 @@ static bool try_to_inc_max_seq(struct lr +@@ -4387,7 +4387,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, bool success; struct lru_gen_mm_walk *walk; struct mm_struct *mm = NULL; @@ -263,7 +273,7 @@ Signed-off-by: Andrew Morton VM_WARN_ON_ONCE(max_seq > READ_ONCE(lrugen->max_seq)); -@@ -4455,7 +4455,7 @@ static bool should_run_aging(struct lruv +@@ -4452,7 +4452,7 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig unsigned long old = 0; unsigned long young = 0; unsigned long total = 0; @@ -272,7 +282,7 @@ Signed-off-by: Andrew Morton struct mem_cgroup *memcg = lruvec_memcg(lruvec); for (type = !can_swap; type < ANON_AND_FILE; type++) { -@@ -4740,7 +4740,7 @@ static bool sort_folio(struct lruvec *lr +@@ -4737,7 +4737,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx) int delta = folio_nr_pages(folio); int refs = folio_lru_refs(folio); int tier = lru_tier_from_refs(refs); @@ -281,7 +291,7 @@ Signed-off-by: Andrew Morton VM_WARN_ON_ONCE_FOLIO(gen >= MAX_NR_GENS, folio); -@@ -4840,7 +4840,7 @@ static int scan_folios(struct lruvec *lr +@@ -4837,7 +4837,7 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc, int scanned = 0; int isolated = 0; int remaining = MAX_LRU_BATCH; @@ -290,7 +300,7 @@ Signed-off-by: Andrew Morton struct mem_cgroup *memcg = lruvec_memcg(lruvec); VM_WARN_ON_ONCE(!list_empty(list)); -@@ -5240,7 +5240,7 @@ done: +@@ -5237,7 +5237,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc static bool __maybe_unused state_is_valid(struct lruvec *lruvec) { @@ -299,7 +309,7 @@ Signed-off-by: Andrew Morton if (lrugen->enabled) { enum lru_list lru; -@@ -5522,7 +5522,7 @@ static void lru_gen_seq_show_full(struct +@@ -5519,7 +5519,7 @@ static void lru_gen_seq_show_full(struct seq_file *m, struct lruvec *lruvec, int i; int type, tier; int hist = lru_hist_from_seq(seq); @@ -308,7 +318,7 @@ Signed-off-by: Andrew Morton for (tier = 0; tier < MAX_NR_TIERS; tier++) { seq_printf(m, " %10d", tier); -@@ -5572,7 +5572,7 @@ static int lru_gen_seq_show(struct seq_f +@@ -5569,7 +5569,7 @@ static int lru_gen_seq_show(struct seq_file *m, void *v) unsigned long seq; bool full = !debugfs_real_fops(m->file)->write; struct lruvec *lruvec = v; @@ -317,7 +327,7 @@ Signed-off-by: Andrew Morton int nid = lruvec_pgdat(lruvec)->node_id; struct mem_cgroup *memcg = lruvec_memcg(lruvec); DEFINE_MAX_SEQ(lruvec); -@@ -5826,7 +5826,7 @@ void lru_gen_init_lruvec(struct lruvec * +@@ -5823,7 +5823,7 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) { int i; int gen, type, zone; @@ -326,9 +336,11 @@ Signed-off-by: Andrew Morton lrugen->max_seq = MIN_NR_GENS + 1; lrugen->enabled = lru_gen_enabled(); +diff --git a/mm/workingset.c b/mm/workingset.c +index ae7e984b23c6b..688aaa73f64e8 100644 --- a/mm/workingset.c +++ b/mm/workingset.c -@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct fol +@@ -223,7 +223,7 @@ static void *lru_gen_eviction(struct folio *folio) unsigned long token; unsigned long min_seq; struct lruvec *lruvec; @@ -337,7 +349,7 @@ Signed-off-by: Andrew Morton int type = folio_is_file_lru(folio); int delta = folio_nr_pages(folio); int refs = folio_lru_refs(folio); -@@ -252,7 +252,7 @@ static void lru_gen_refault(struct folio +@@ -252,7 +252,7 @@ static void lru_gen_refault(struct folio *folio, void *shadow) unsigned long token; unsigned long min_seq; struct lruvec *lruvec; @@ -346,3 +358,6 @@ Signed-off-by: Andrew Morton struct mem_cgroup *memcg; struct pglist_data *pgdat; int type = folio_is_file_lru(folio); +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-22-mm-multi-gen-LRU-rename-lrugen-lists-to-lrugen-pages.patch b/target/linux/generic/backport-6.1/020-v6.3-02-UPSTREAM-mm-multi-gen-LRU-rename-lrugen-lists-to-lru.patch similarity index 60% rename from target/linux/generic/backport-6.1/020-v6.3-22-mm-multi-gen-LRU-rename-lrugen-lists-to-lrugen-pages.patch rename to target/linux/generic/backport-6.1/020-v6.3-02-UPSTREAM-mm-multi-gen-LRU-rename-lrugen-lists-to-lru.patch index 7940380c5ce..65fb0144b1e 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-22-mm-multi-gen-LRU-rename-lrugen-lists-to-lrugen-pages.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-02-UPSTREAM-mm-multi-gen-LRU-rename-lrugen-lists-to-lru.patch @@ -1,7 +1,7 @@ -From afd37e73db04c7e6b47411120ac5f6a7eca51fec Mon Sep 17 00:00:00 2001 +From 656287d55d9cfc72a4bcd4d9bd098570f12ce409 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:00 -0700 -Subject: [PATCH 22/29] mm: multi-gen LRU: rename lrugen->lists[] to +Subject: [PATCH 02/19] UPSTREAM: mm: multi-gen LRU: rename lrugen->lists[] to lrugen->folios[] lru_gen_folio will be chained into per-node lists by the coming @@ -17,15 +17,54 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit 6df1b2212950aae2b2188c6645ea18e2a9e3fdd5) +Change-Id: I09f53e0fb2cd6b8b3adbb8a80b15dc5efbeae857 +Signed-off-by: T.J. Mercier --- - include/linux/mm_inline.h | 4 ++-- - include/linux/mmzone.h | 8 ++++---- - mm/vmscan.c | 20 ++++++++++---------- - 3 files changed, 16 insertions(+), 16 deletions(-) + Documentation/mm/multigen_lru.rst | 8 ++++---- + include/linux/mm_inline.h | 4 ++-- + include/linux/mmzone.h | 8 ++++---- + mm/vmscan.c | 20 ++++++++++---------- + 4 files changed, 20 insertions(+), 20 deletions(-) +diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst +index d7062c6a89464..d8f721f98868a 100644 +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -89,15 +89,15 @@ variables are monotonically increasing. + + Generation numbers are truncated into ``order_base_2(MAX_NR_GENS+1)`` + bits in order to fit into the gen counter in ``folio->flags``. Each +-truncated generation number is an index to ``lrugen->lists[]``. The ++truncated generation number is an index to ``lrugen->folios[]``. The + sliding window technique is used to track at least ``MIN_NR_GENS`` and + at most ``MAX_NR_GENS`` generations. The gen counter stores a value + within ``[1, MAX_NR_GENS]`` while a page is on one of +-``lrugen->lists[]``; otherwise it stores zero. ++``lrugen->folios[]``; otherwise it stores zero. + + Each generation is divided into multiple tiers. A page accessed ``N`` + times through file descriptors is in tier ``order_base_2(N)``. Unlike +-generations, tiers do not have dedicated ``lrugen->lists[]``. In ++generations, tiers do not have dedicated ``lrugen->folios[]``. In + contrast to moving across generations, which requires the LRU lock, + moving across tiers only involves atomic operations on + ``folio->flags`` and therefore has a negligible cost. A feedback loop +@@ -127,7 +127,7 @@ page mapped by this PTE to ``(max_seq%MAX_NR_GENS)+1``. + Eviction + -------- + The eviction consumes old generations. Given an ``lruvec``, it +-increments ``min_seq`` when ``lrugen->lists[]`` indexed by ++increments ``min_seq`` when ``lrugen->folios[]`` indexed by + ``min_seq%MAX_NR_GENS`` becomes empty. To select a type and a tier to + evict from, it first compares ``min_seq[]`` to select the older type. + If both types are equally old, it selects the one whose first tier has +diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h +index f63968bd7de59..da38e3d962e2f 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h -@@ -256,9 +256,9 @@ static inline bool lru_gen_add_folio(str +@@ -256,9 +256,9 @@ static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, lru_gen_update_size(lruvec, folio, -1, gen); /* for folio_rotate_reclaimable() */ if (reclaiming) @@ -37,6 +76,8 @@ Signed-off-by: Andrew Morton return true; } +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index bd3e4689f72dc..02e4323744715 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -312,7 +312,7 @@ enum lruvec_flags { @@ -68,9 +109,11 @@ Signed-off-by: Andrew Morton /* the multi-gen LRU sizes, eventually consistent */ long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; /* the exponential moving average of refaulted */ +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 27142caf284c1..b02fed912f742 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -4261,7 +4261,7 @@ static bool inc_min_seq(struct lruvec *l +@@ -4258,7 +4258,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap) /* prevent cold/hot inversion if force_scan is true */ for (zone = 0; zone < MAX_NR_ZONES; zone++) { @@ -79,7 +122,7 @@ Signed-off-by: Andrew Morton while (!list_empty(head)) { struct folio *folio = lru_to_folio(head); -@@ -4272,7 +4272,7 @@ static bool inc_min_seq(struct lruvec *l +@@ -4269,7 +4269,7 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, bool can_swap) VM_WARN_ON_ONCE_FOLIO(folio_zonenum(folio) != zone, folio); new_gen = folio_inc_gen(lruvec, folio, false); @@ -88,7 +131,7 @@ Signed-off-by: Andrew Morton if (!--remaining) return false; -@@ -4300,7 +4300,7 @@ static bool try_to_inc_min_seq(struct lr +@@ -4297,7 +4297,7 @@ static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) gen = lru_gen_from_seq(min_seq[type]); for (zone = 0; zone < MAX_NR_ZONES; zone++) { @@ -97,7 +140,7 @@ Signed-off-by: Andrew Morton goto next; } -@@ -4765,7 +4765,7 @@ static bool sort_folio(struct lruvec *lr +@@ -4762,7 +4762,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx) /* promoted */ if (gen != lru_gen_from_seq(lrugen->min_seq[type])) { @@ -106,7 +149,7 @@ Signed-off-by: Andrew Morton return true; } -@@ -4774,7 +4774,7 @@ static bool sort_folio(struct lruvec *lr +@@ -4771,7 +4771,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx) int hist = lru_hist_from_seq(lrugen->min_seq[type]); gen = folio_inc_gen(lruvec, folio, false); @@ -115,7 +158,7 @@ Signed-off-by: Andrew Morton WRITE_ONCE(lrugen->protected[hist][type][tier - 1], lrugen->protected[hist][type][tier - 1] + delta); -@@ -4786,7 +4786,7 @@ static bool sort_folio(struct lruvec *lr +@@ -4783,7 +4783,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx) if (folio_test_locked(folio) || folio_test_writeback(folio) || (type == LRU_GEN_FILE && folio_test_dirty(folio))) { gen = folio_inc_gen(lruvec, folio, true); @@ -124,7 +167,7 @@ Signed-off-by: Andrew Morton return true; } -@@ -4853,7 +4853,7 @@ static int scan_folios(struct lruvec *lr +@@ -4850,7 +4850,7 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc, for (zone = sc->reclaim_idx; zone >= 0; zone--) { LIST_HEAD(moved); int skipped = 0; @@ -133,7 +176,7 @@ Signed-off-by: Andrew Morton while (!list_empty(head)) { struct folio *folio = lru_to_folio(head); -@@ -5253,7 +5253,7 @@ static bool __maybe_unused state_is_vali +@@ -5250,7 +5250,7 @@ static bool __maybe_unused state_is_valid(struct lruvec *lruvec) int gen, type, zone; for_each_gen_type_zone(gen, type, zone) { @@ -142,7 +185,7 @@ Signed-off-by: Andrew Morton return false; } } -@@ -5298,7 +5298,7 @@ static bool drain_evictable(struct lruve +@@ -5295,7 +5295,7 @@ static bool drain_evictable(struct lruvec *lruvec) int remaining = MAX_LRU_BATCH; for_each_gen_type_zone(gen, type, zone) { @@ -151,7 +194,7 @@ Signed-off-by: Andrew Morton while (!list_empty(head)) { bool success; -@@ -5835,7 +5835,7 @@ void lru_gen_init_lruvec(struct lruvec * +@@ -5832,7 +5832,7 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) lrugen->timestamps[i] = jiffies; for_each_gen_type_zone(gen, type, zone) @@ -160,3 +203,6 @@ Signed-off-by: Andrew Morton lruvec->mm_state.seq = MIN_NR_GENS; init_waitqueue_head(&lruvec->mm_state.wait); +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-23-mm-multi-gen-LRU-remove-eviction-fairness-safeguard.patch b/target/linux/generic/backport-6.1/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch similarity index 79% rename from target/linux/generic/backport-6.1/020-v6.3-23-mm-multi-gen-LRU-remove-eviction-fairness-safeguard.patch rename to target/linux/generic/backport-6.1/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch index d214898a6d0..6d764bb2b44 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-23-mm-multi-gen-LRU-remove-eviction-fairness-safeguard.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-03-UPSTREAM-mm-multi-gen-LRU-remove-eviction-fairness-s.patch @@ -1,7 +1,8 @@ -From ce45f1c4b32cf69b166f56ef5bc6c761e06ed4e5 Mon Sep 17 00:00:00 2001 +From 14f9a7a15f3d1af351f30e0438fd747b7ac253b0 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:01 -0700 -Subject: [PATCH 23/29] mm: multi-gen LRU: remove eviction fairness safeguard +Subject: [PATCH 03/19] UPSTREAM: mm: multi-gen LRU: remove eviction fairness + safeguard Recall that the eviction consumes the oldest generation: first it bucket-sorts folios whose gen counters were updated by the aging and @@ -31,13 +32,19 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit a579086c99ed70cc4bfc104348dbe3dd8f2787e6) +Change-Id: I08ac1b3c90e29cafd0566785aaa4bcdb5db7d22c +Signed-off-by: T.J. Mercier --- - mm/vmscan.c | 82 +++++++++++++++-------------------------------------- - 1 file changed, 23 insertions(+), 59 deletions(-) + mm/vmscan.c | 81 +++++++++++++++-------------------------------------- + 1 file changed, 23 insertions(+), 58 deletions(-) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index b02fed912f742..991961180b320 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_c +@@ -448,6 +448,11 @@ static bool cgroup_reclaim(struct scan_control *sc) return sc->target_mem_cgroup; } @@ -49,7 +56,7 @@ Signed-off-by: Andrew Morton /** * writeback_throttling_sane - is the usual dirty throttling mechanism available? * @sc: scan_control in question -@@ -498,6 +503,11 @@ static bool cgroup_reclaim(struct scan_c +@@ -498,6 +503,11 @@ static bool cgroup_reclaim(struct scan_control *sc) return false; } @@ -61,7 +68,7 @@ Signed-off-by: Andrew Morton static bool writeback_throttling_sane(struct scan_control *sc) { return true; -@@ -4996,8 +5006,7 @@ static int isolate_folios(struct lruvec +@@ -4993,8 +5003,7 @@ static int isolate_folios(struct lruvec *lruvec, struct scan_control *sc, int sw return scanned; } @@ -71,7 +78,7 @@ Signed-off-by: Andrew Morton { int type; int scanned; -@@ -5086,9 +5095,6 @@ retry: +@@ -5083,9 +5092,6 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap goto retry; } @@ -81,7 +88,7 @@ Signed-off-by: Andrew Morton return scanned; } -@@ -5127,67 +5133,26 @@ done: +@@ -5124,67 +5130,26 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control * return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0; } @@ -158,7 +165,7 @@ Signed-off-by: Andrew Morton lru_add_drain(); -@@ -5211,7 +5176,7 @@ static void lru_gen_shrink_lruvec(struct +@@ -5208,7 +5173,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc if (!nr_to_scan) goto done; @@ -167,7 +174,7 @@ Signed-off-by: Andrew Morton if (!delta) goto done; -@@ -5219,7 +5184,7 @@ static void lru_gen_shrink_lruvec(struct +@@ -5216,7 +5181,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc if (scanned >= nr_to_scan) break; @@ -176,7 +183,7 @@ Signed-off-by: Andrew Morton break; cond_resched(); -@@ -5669,7 +5634,7 @@ static int run_eviction(struct lruvec *l +@@ -5666,7 +5631,7 @@ static int run_eviction(struct lruvec *lruvec, unsigned long seq, struct scan_co if (sc->nr_reclaimed >= nr_to_reclaim) return 0; @@ -185,3 +192,6 @@ Signed-off-by: Andrew Morton return 0; cond_resched(); +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-24-mm-multi-gen-LRU-remove-aging-fairness-safeguard.patch b/target/linux/generic/backport-6.1/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch similarity index 85% rename from target/linux/generic/backport-6.1/020-v6.3-24-mm-multi-gen-LRU-remove-aging-fairness-safeguard.patch rename to target/linux/generic/backport-6.1/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch index 7cbabd34e4f..c3f534a9e0c 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-24-mm-multi-gen-LRU-remove-aging-fairness-safeguard.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-04-BACKPORT-mm-multi-gen-LRU-remove-aging-fairness-safe.patch @@ -1,7 +1,8 @@ -From e20b7386fccc18c791796eb1dc1a91eee3ccf801 Mon Sep 17 00:00:00 2001 +From f3c93d2e37a3c56593d7ccf4f4bcf1b58426fdd8 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:02 -0700 -Subject: [PATCH 24/29] mm: multi-gen LRU: remove aging fairness safeguard +Subject: [PATCH 04/19] BACKPORT: mm: multi-gen LRU: remove aging fairness + safeguard Recall that the aging produces the youngest generation: first it scans for accessed folios and updates their gen counters; then it increments @@ -31,10 +32,18 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit 7348cc91821b0cb24dfb00e578047f68299a50ab) +[TJ: Resolved conflicts with older function signatures for +min_cgroup_below_min / min_cgroup_below_low] +Change-Id: I6e36ecfbaaefbc0a56d9a9d5d7cbe404ed7f57a5 +Signed-off-by: T.J. Mercier --- mm/vmscan.c | 126 ++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 67 deletions(-) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 991961180b320..5a2e83e673232 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -136,7 +136,6 @@ struct scan_control { @@ -45,7 +54,7 @@ Signed-off-by: Andrew Morton unsigned long last_reclaimed; #endif -@@ -4458,7 +4457,7 @@ done: +@@ -4455,7 +4454,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, return true; } @@ -54,7 +63,7 @@ Signed-off-by: Andrew Morton struct scan_control *sc, bool can_swap, unsigned long *nr_to_scan) { int gen, type, zone; -@@ -4467,6 +4466,13 @@ static bool should_run_aging(struct lruv +@@ -4464,6 +4463,13 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig unsigned long total = 0; struct lru_gen_folio *lrugen = &lruvec->lrugen; struct mem_cgroup *memcg = lruvec_memcg(lruvec); @@ -68,7 +77,7 @@ Signed-off-by: Andrew Morton for (type = !can_swap; type < ANON_AND_FILE; type++) { unsigned long seq; -@@ -4495,8 +4501,6 @@ static bool should_run_aging(struct lruv +@@ -4492,8 +4498,6 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig * stalls when the number of generations reaches MIN_NR_GENS. Hence, the * ideal number of generations is MIN_NR_GENS+1. */ @@ -77,7 +86,7 @@ Signed-off-by: Andrew Morton if (min_seq[!can_swap] + MIN_NR_GENS < max_seq) return false; -@@ -4515,40 +4519,54 @@ static bool should_run_aging(struct lruv +@@ -4512,40 +4516,54 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig return false; } @@ -153,7 +162,7 @@ Signed-off-by: Andrew Morton } /* to protect the working set of the last N jiffies */ -@@ -4557,46 +4575,32 @@ static unsigned long lru_gen_min_ttl __r +@@ -4554,46 +4572,32 @@ static unsigned long lru_gen_min_ttl __read_mostly; static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) { struct mem_cgroup *memcg; @@ -207,7 +216,7 @@ Signed-off-by: Andrew Morton */ if (mutex_trylock(&oom_lock)) { struct oom_control oc = { -@@ -5104,33 +5108,27 @@ retry: +@@ -5101,33 +5105,27 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap * reclaim. */ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, @@ -247,7 +256,7 @@ Signed-off-by: Andrew Morton } static unsigned long get_nr_to_reclaim(struct scan_control *sc) -@@ -5149,9 +5147,7 @@ static unsigned long get_nr_to_reclaim(s +@@ -5146,9 +5144,7 @@ static unsigned long get_nr_to_reclaim(struct scan_control *sc) static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) { struct blk_plug plug; @@ -257,7 +266,7 @@ Signed-off-by: Andrew Morton unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); lru_add_drain(); -@@ -5172,13 +5168,13 @@ static void lru_gen_shrink_lruvec(struct +@@ -5169,13 +5165,13 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc else swappiness = 0; @@ -274,7 +283,7 @@ Signed-off-by: Andrew Morton scanned += delta; if (scanned >= nr_to_scan) -@@ -5190,10 +5186,6 @@ static void lru_gen_shrink_lruvec(struct +@@ -5187,10 +5183,6 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc cond_resched(); } @@ -285,3 +294,6 @@ Signed-off-by: Andrew Morton clear_mm_walk(); blk_finish_plug(&plug); +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-25-mm-multi-gen-LRU-shuffle-should_run_aging.patch b/target/linux/generic/backport-6.1/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch similarity index 87% rename from target/linux/generic/backport-6.1/020-v6.3-25-mm-multi-gen-LRU-shuffle-should_run_aging.patch rename to target/linux/generic/backport-6.1/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch index bedbbd3e1b6..d6bfe2a91c2 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-25-mm-multi-gen-LRU-shuffle-should_run_aging.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-05-UPSTREAM-mm-multi-gen-LRU-shuffle-should_run_aging.patch @@ -1,12 +1,11 @@ -From 107d54931df3c28d81648122e219bf0034ef4e99 Mon Sep 17 00:00:00 2001 +From eca3858631e0cbad2ca6e40f788892749428e4cb Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:03 -0700 -Subject: [PATCH 25/29] mm: multi-gen LRU: shuffle should_run_aging() +Subject: [PATCH 05/19] UPSTREAM: mm: multi-gen LRU: shuffle should_run_aging() Move should_run_aging() next to its only caller left. Link: https://lkml.kernel.org/r/20221222041905.2431096-6-yuzhao@google.com -Signed-off-by: Yu Zhao Cc: Johannes Weiner Cc: Jonathan Corbet Cc: Michael Larabel @@ -15,13 +14,21 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit 77d4459a4a1a472b7309e475f962dda87d950abd) +Signed-off-by: T.J. Mercier +Change-Id: I3b0383fe16b93a783b4d8c0b3a0b325160392576 +Signed-off-by: Yu Zhao +Signed-off-by: T.J. Mercier --- mm/vmscan.c | 124 ++++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 62 deletions(-) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 5a2e83e673232..0c47952714b26 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -4457,68 +4457,6 @@ done: +@@ -4454,68 +4454,6 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, return true; } @@ -90,7 +97,7 @@ Signed-off-by: Andrew Morton static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) { int gen, type, zone; -@@ -5102,6 +5040,68 @@ retry: +@@ -5099,6 +5037,68 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap return scanned; } @@ -159,3 +166,6 @@ Signed-off-by: Andrew Morton /* * For future optimizations: * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-26-mm-multi-gen-LRU-per-node-lru_gen_page-lists.patch b/target/linux/generic/backport-6.1/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch similarity index 85% rename from target/linux/generic/backport-6.1/020-v6.3-26-mm-multi-gen-LRU-per-node-lru_gen_page-lists.patch rename to target/linux/generic/backport-6.1/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch index 45789ff2094..14f28820ec0 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-26-mm-multi-gen-LRU-per-node-lru_gen_page-lists.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-06-BACKPORT-mm-multi-gen-LRU-per-node-lru_gen_folio-lis.patch @@ -1,7 +1,8 @@ -From fa6363828d314e837c5f79e97ea5e8c0d2f7f062 Mon Sep 17 00:00:00 2001 +From 8ee8571e47aa75221e5fbd4c9c7802fc4244c346 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:04 -0700 -Subject: [PATCH 26/29] mm: multi-gen LRU: per-node lru_gen_folio lists +Subject: [PATCH 06/19] BACKPORT: mm: multi-gen LRU: per-node lru_gen_folio + lists For each node, memcgs are divided into two generations: the old and the young. For each generation, memcgs are randomly sharded into @@ -58,18 +59,26 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit e4dde56cd208674ce899b47589f263499e5b8cdc) +[TJ: Resolved conflicts with older function signatures for +min_cgroup_below_min / min_cgroup_below_low and includes] +Change-Id: Idc8a0f635e035d72dd911f807d1224cb47cbd655 +Signed-off-by: T.J. Mercier --- include/linux/memcontrol.h | 10 + include/linux/mm_inline.h | 17 ++ include/linux/mmzone.h | 117 +++++++++++- mm/memcontrol.c | 16 ++ - mm/folio_alloc.c | 1 + - mm/vmscan.c | 373 +++++++++++++++++++++++++++++++++---- - 6 files changed, 499 insertions(+), 35 deletions(-) + mm/page_alloc.c | 1 + + mm/vmscan.c | 374 +++++++++++++++++++++++++++++++++---- + 6 files changed, 500 insertions(+), 35 deletions(-) +diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h +index e039763029563..82d28b052a9e5 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h -@@ -790,6 +790,11 @@ static inline void obj_cgroup_put(struct +@@ -790,6 +790,11 @@ static inline void obj_cgroup_put(struct obj_cgroup *objcg) percpu_ref_put(&objcg->refcnt); } @@ -81,7 +90,7 @@ Signed-off-by: Andrew Morton static inline void mem_cgroup_put(struct mem_cgroup *memcg) { if (memcg) -@@ -1290,6 +1295,11 @@ static inline void obj_cgroup_put(struct +@@ -1290,6 +1295,11 @@ static inline void obj_cgroup_put(struct obj_cgroup *objcg) { } @@ -93,9 +102,11 @@ Signed-off-by: Andrew Morton static inline void mem_cgroup_put(struct mem_cgroup *memcg) { } +diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h +index da38e3d962e2f..c1fd3922dc5dd 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h -@@ -122,6 +122,18 @@ static inline bool lru_gen_in_fault(void +@@ -122,6 +122,18 @@ static inline bool lru_gen_in_fault(void) return current->in_lru_fault; } @@ -114,7 +125,7 @@ Signed-off-by: Andrew Morton static inline int lru_gen_from_seq(unsigned long seq) { return seq % MAX_NR_GENS; -@@ -297,6 +309,11 @@ static inline bool lru_gen_in_fault(void +@@ -297,6 +309,11 @@ static inline bool lru_gen_in_fault(void) return false; } @@ -126,6 +137,8 @@ Signed-off-by: Andrew Morton static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, bool reclaiming) { return false; +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index 02e4323744715..66e067a635682 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -7,6 +7,7 @@ @@ -167,7 +180,7 @@ Signed-off-by: Andrew Morton }; enum { -@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec * +@@ -479,12 +497,87 @@ void lru_gen_init_lruvec(struct lruvec *lruvec); void lru_gen_look_around(struct page_vma_mapped_walk *pvmw); #ifdef CONFIG_MEMCG @@ -256,7 +269,7 @@ Signed-off-by: Andrew Morton static inline void lru_gen_init_lruvec(struct lruvec *lruvec) { } -@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(s +@@ -494,6 +587,7 @@ static inline void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) } #ifdef CONFIG_MEMCG @@ -264,7 +277,7 @@ Signed-off-by: Andrew Morton static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) { } -@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(st +@@ -501,7 +595,24 @@ static inline void lru_gen_init_memcg(struct mem_cgroup *memcg) static inline void lru_gen_exit_memcg(struct mem_cgroup *memcg) { } @@ -299,9 +312,11 @@ Signed-off-by: Andrew Morton #endif CACHELINE_PADDING(_pad2_); +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 3e8f1ad0fe9db..7815d556e38cc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c -@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struc +@@ -477,6 +477,16 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, int nid) struct mem_cgroup_per_node *mz; struct mem_cgroup_tree_per_node *mctz; @@ -318,7 +333,7 @@ Signed-off-by: Andrew Morton mctz = soft_limit_tree.rb_tree_per_node[nid]; if (!mctz) return; -@@ -3522,6 +3532,9 @@ unsigned long mem_cgroup_soft_limit_recl +@@ -3522,6 +3532,9 @@ unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order, struct mem_cgroup_tree_per_node *mctz; unsigned long excess; @@ -328,7 +343,7 @@ Signed-off-by: Andrew Morton if (order > 0) return 0; -@@ -5382,6 +5395,7 @@ static int mem_cgroup_css_online(struct +@@ -5382,6 +5395,7 @@ static int mem_cgroup_css_online(struct cgroup_subsys_state *css) if (unlikely(mem_cgroup_is_root(memcg))) queue_delayed_work(system_unbound_wq, &stats_flush_dwork, 2UL*HZ); @@ -336,7 +351,7 @@ Signed-off-by: Andrew Morton return 0; offline_kmem: memcg_offline_kmem(memcg); -@@ -5413,6 +5427,7 @@ static void mem_cgroup_css_offline(struc +@@ -5413,6 +5427,7 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css) memcg_offline_kmem(memcg); reparent_shrinker_deferred(memcg); wb_memcg_offline(memcg); @@ -344,7 +359,7 @@ Signed-off-by: Andrew Morton drain_all_stock(memcg); -@@ -5424,6 +5439,7 @@ static void mem_cgroup_css_released(stru +@@ -5424,6 +5439,7 @@ static void mem_cgroup_css_released(struct cgroup_subsys_state *css) struct mem_cgroup *memcg = mem_cgroup_from_css(css); invalidate_reclaim_iterators(memcg); @@ -352,9 +367,11 @@ Signed-off-by: Andrew Morton } static void mem_cgroup_css_free(struct cgroup_subsys_state *css) +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 69668817fed37..473057b81a9df 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c -@@ -7957,6 +7957,7 @@ static void __init free_area_init_node(i +@@ -7957,6 +7957,7 @@ static void __init free_area_init_node(int nid) pgdat_set_deferred_range(pgdat); free_area_init_core(pgdat); @@ -362,6 +379,8 @@ Signed-off-by: Andrew Morton } static void __init free_area_init_memoryless_node(int nid) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 0c47952714b26..65eb28448f216 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -54,6 +54,8 @@ @@ -385,7 +404,7 @@ Signed-off-by: Andrew Morton /* Allocation order */ s8 order; -@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_ca +@@ -3160,6 +3157,9 @@ DEFINE_STATIC_KEY_ARRAY_FALSE(lru_gen_caps, NR_LRU_GEN_CAPS); for ((type) = 0; (type) < ANON_AND_FILE; (type)++) \ for ((zone) = 0; (zone) < MAX_NR_ZONES; (zone)++) @@ -395,7 +414,7 @@ Signed-off-by: Andrew Morton static struct lruvec *get_lruvec(struct mem_cgroup *memcg, int nid) { struct pglist_data *pgdat = NODE_DATA(nid); -@@ -4443,8 +4443,7 @@ done: +@@ -4440,8 +4440,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, if (sc->priority <= DEF_PRIORITY - 2) wait_event_killable(lruvec->mm_state.wait, max_seq < READ_ONCE(lrugen->max_seq)); @@ -405,7 +424,7 @@ Signed-off-by: Andrew Morton } VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); -@@ -4517,8 +4516,6 @@ static void lru_gen_age_node(struct pgli +@@ -4514,8 +4513,6 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) VM_WARN_ON_ONCE(!current_is_kswapd()); @@ -414,7 +433,7 @@ Signed-off-by: Andrew Morton /* check the order to exclude compaction-induced reclaim */ if (!min_ttl || sc->order || sc->priority == DEF_PRIORITY) return; -@@ -5107,8 +5104,7 @@ static bool should_run_aging(struct lruv +@@ -5104,8 +5101,7 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, * 1. Defer try_to_inc_max_seq() to workqueues to reduce latency for memcg * reclaim. */ @@ -424,7 +443,7 @@ Signed-off-by: Andrew Morton { unsigned long nr_to_scan; struct mem_cgroup *memcg = lruvec_memcg(lruvec); -@@ -5125,10 +5121,8 @@ static unsigned long get_nr_to_scan(stru +@@ -5122,10 +5118,8 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control * if (sc->priority == DEF_PRIORITY) return nr_to_scan; @@ -436,7 +455,7 @@ Signed-off-by: Andrew Morton } static unsigned long get_nr_to_reclaim(struct scan_control *sc) -@@ -5137,29 +5131,18 @@ static unsigned long get_nr_to_reclaim(s +@@ -5134,29 +5128,18 @@ static unsigned long get_nr_to_reclaim(struct scan_control *sc) if (!global_reclaim(sc)) return -1; @@ -468,7 +487,7 @@ Signed-off-by: Andrew Morton if (sc->may_swap) swappiness = get_swappiness(lruvec, sc); -@@ -5169,7 +5152,7 @@ static void lru_gen_shrink_lruvec(struct +@@ -5166,7 +5149,7 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc swappiness = 0; nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); @@ -477,7 +496,7 @@ Signed-off-by: Andrew Morton break; delta = evict_folios(lruvec, sc, swappiness); -@@ -5186,10 +5169,250 @@ static void lru_gen_shrink_lruvec(struct +@@ -5183,11 +5166,252 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc cond_resched(); } @@ -515,8 +534,9 @@ Signed-off-by: Andrew Morton + + shrink_slab(sc->gfp_mask, pgdat->node_id, memcg, sc->priority); + -+ vmpressure(sc->gfp_mask, memcg, false, sc->nr_scanned - scanned, -+ sc->nr_reclaimed - reclaimed); ++ if (!sc->proactive) ++ vmpressure(sc->gfp_mask, memcg, false, sc->nr_scanned - scanned, ++ sc->nr_reclaimed - reclaimed); + + sc->nr_reclaimed += current->reclaim_state->reclaimed_slab; + current->reclaim_state->reclaimed_slab = 0; @@ -538,7 +558,7 @@ Signed-off-by: Andrew Morton + struct mem_cgroup *memcg = NULL; + unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); + -+ bin = first_bin = prandom_u32_max(MEMCG_NR_BINS); ++ bin = first_bin = get_random_u32_below(MEMCG_NR_BINS); +restart: + gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq)); + @@ -601,11 +621,11 @@ Signed-off-by: Andrew Morton + if (try_to_shrink_lruvec(lruvec, sc)) + lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); + -+ clear_mm_walk(); -+ -+ blk_finish_plug(&plug); -+} -+ + clear_mm_walk(); + + blk_finish_plug(&plug); + } + +#else /* !CONFIG_MEMCG */ + +static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) @@ -671,9 +691,9 @@ Signed-off-by: Andrew Morton + if (current_is_kswapd()) + sc->nr_reclaimed += reclaimed; + - clear_mm_walk(); - - blk_finish_plug(&plug); ++ clear_mm_walk(); ++ ++ blk_finish_plug(&plug); + + /* kswapd should never fail */ + pgdat->kswapd_failures = 0; @@ -684,7 +704,7 @@ Signed-off-by: Andrew Morton +{ + int seg; + int old, new; -+ int bin = prandom_u32_max(MEMCG_NR_BINS); ++ int bin = get_random_u32_below(MEMCG_NR_BINS); + struct pglist_data *pgdat = lruvec_pgdat(lruvec); + + spin_lock(&pgdat->memcg_lru.lock); @@ -723,12 +743,13 @@ Signed-off-by: Andrew Morton + WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); + + spin_unlock(&pgdat->memcg_lru.lock); - } ++} +#endif - ++ /****************************************************************************** * state change -@@ -5647,11 +5870,11 @@ static int run_cmd(char cmd, int memcg_i + ******************************************************************************/ +@@ -5644,11 +5868,11 @@ static int run_cmd(char cmd, int memcg_id, int nid, unsigned long seq, if (!mem_cgroup_disabled()) { rcu_read_lock(); @@ -743,7 +764,7 @@ Signed-off-by: Andrew Morton rcu_read_unlock(); if (!memcg) -@@ -5799,6 +6022,19 @@ void lru_gen_init_lruvec(struct lruvec * +@@ -5796,6 +6020,19 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) } #ifdef CONFIG_MEMCG @@ -763,7 +784,7 @@ Signed-off-by: Andrew Morton void lru_gen_init_memcg(struct mem_cgroup *memcg) { INIT_LIST_HEAD(&memcg->mm_list.fifo); -@@ -5822,7 +6058,69 @@ void lru_gen_exit_memcg(struct mem_cgrou +@@ -5819,7 +6056,69 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg) } } } @@ -773,7 +794,7 @@ Signed-off-by: Andrew Morton +{ + int gen; + int nid; -+ int bin = prandom_u32_max(MEMCG_NR_BINS); ++ int bin = get_random_u32_below(MEMCG_NR_BINS); + + for_each_node(nid) { + struct pglist_data *pgdat = NODE_DATA(nid); @@ -834,7 +855,7 @@ Signed-off-by: Andrew Morton static int __init init_lru_gen(void) { -@@ -5849,6 +6147,10 @@ static void lru_gen_shrink_lruvec(struct +@@ -5846,6 +6145,10 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc { } @@ -845,7 +866,7 @@ Signed-off-by: Andrew Morton #endif /* CONFIG_LRU_GEN */ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) -@@ -5862,7 +6164,7 @@ static void shrink_lruvec(struct lruvec +@@ -5859,7 +6162,7 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) bool proportional_reclaim; struct blk_plug plug; @@ -854,7 +875,7 @@ Signed-off-by: Andrew Morton lru_gen_shrink_lruvec(lruvec, sc); return; } -@@ -6105,6 +6407,11 @@ static void shrink_node(pg_data_t *pgdat +@@ -6102,6 +6405,11 @@ static void shrink_node(pg_data_t *pgdat, struct scan_control *sc) struct lruvec *target_lruvec; bool reclaimable = false; @@ -866,3 +887,6 @@ Signed-off-by: Andrew Morton target_lruvec = mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat); again: +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-27-mm-multi-gen-LRU-clarify-scan_control-flags.patch b/target/linux/generic/backport-6.1/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch similarity index 71% rename from target/linux/generic/backport-6.1/020-v6.3-27-mm-multi-gen-LRU-clarify-scan_control-flags.patch rename to target/linux/generic/backport-6.1/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch index 89f7ed30afa..9aaf247a098 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-27-mm-multi-gen-LRU-clarify-scan_control-flags.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-07-BACKPORT-mm-multi-gen-LRU-clarify-scan_control-flags.patch @@ -1,7 +1,7 @@ -From 93147736b5b3a21bea24313bfc7a696829932009 Mon Sep 17 00:00:00 2001 +From 11b14ee8cbbbebd8204609076a9327a1171cd253 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:05 -0700 -Subject: [PATCH 27/29] mm: multi-gen LRU: clarify scan_control flags +Subject: [PATCH 07/19] BACKPORT: mm: multi-gen LRU: clarify scan_control flags Among the flags in scan_control: 1. sc->may_swap, which indicates swap constraint due to memsw.max, is @@ -12,7 +12,7 @@ Among the flags in scan_control: 3. !(sc->gfp_mask & __GFP_IO), which indicates IO constraint, lowers swappiness to prioritize file LRU, since clean file folios are more likely to exist. -4. sc->may_writefolio and sc->may_unmap, which indicates opportunistic +4. sc->may_writepage and sc->may_unmap, which indicates opportunistic reclaim, are rejected, since unmapped clean folios are already prioritized. Scanning for more of them is likely futile and can cause high reclaim latency when there is a large number of memcgs. @@ -29,13 +29,21 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit e9d4e1ee788097484606c32122f146d802a9c5fb) +[TJ: Resolved conflict with older function signature for min_cgroup_below_min, and over +cdded861182142ac4488a4d64c571107aeb77f53 ("ANDROID: MGLRU: Don't skip anon reclaim if swap low")] +Change-Id: Ic2e779eaf4e91a3921831b4e2fa10c740dc59d50 +Signed-off-by: T.J. Mercier --- mm/vmscan.c | 55 +++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 65eb28448f216..0a0e1250ffc87 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec +@@ -3185,6 +3185,9 @@ static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc) struct mem_cgroup *memcg = lruvec_memcg(lruvec); struct pglist_data *pgdat = lruvec_pgdat(lruvec); @@ -45,7 +53,7 @@ Signed-off-by: Andrew Morton if (!can_demote(pgdat->node_id, sc) && mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) return 0; -@@ -4226,7 +4229,7 @@ static void walk_mm(struct lruvec *lruve +@@ -4223,7 +4226,7 @@ static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_ } while (err == -EAGAIN); } @@ -54,7 +62,7 @@ Signed-off-by: Andrew Morton { struct lru_gen_mm_walk *walk = current->reclaim_state->mm_walk; -@@ -4234,7 +4237,7 @@ static struct lru_gen_mm_walk *set_mm_wa +@@ -4231,7 +4234,7 @@ static struct lru_gen_mm_walk *set_mm_walk(struct pglist_data *pgdat) VM_WARN_ON_ONCE(walk); walk = &pgdat->mm_walk; @@ -63,7 +71,7 @@ Signed-off-by: Andrew Morton VM_WARN_ON_ONCE(current_is_kswapd()); walk = kzalloc(sizeof(*walk), __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); -@@ -4420,7 +4423,7 @@ static bool try_to_inc_max_seq(struct lr +@@ -4417,7 +4420,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, goto done; } @@ -72,7 +80,7 @@ Signed-off-by: Andrew Morton if (!walk) { success = iterate_mm_list_nowalk(lruvec, max_seq); goto done; -@@ -4489,8 +4492,6 @@ static bool lruvec_is_reclaimable(struct +@@ -4486,8 +4489,6 @@ static bool lruvec_is_reclaimable(struct lruvec *lruvec, struct scan_control *sc struct mem_cgroup *memcg = lruvec_memcg(lruvec); DEFINE_MIN_SEQ(lruvec); @@ -81,7 +89,7 @@ Signed-off-by: Andrew Morton /* see the comment on lru_gen_folio */ gen = lru_gen_from_seq(min_seq[LRU_GEN_FILE]); birth = READ_ONCE(lruvec->lrugen.timestamps[gen]); -@@ -4746,12 +4747,8 @@ static bool isolate_folio(struct lruvec +@@ -4743,12 +4744,8 @@ static bool isolate_folio(struct lruvec *lruvec, struct folio *folio, struct sca { bool success; @@ -95,19 +103,19 @@ Signed-off-by: Andrew Morton (folio_test_dirty(folio) || (folio_test_anon(folio) && !folio_test_swapcache(folio)))) return false; -@@ -4848,9 +4845,8 @@ static int scan_folios(struct lruvec *lr +@@ -4845,9 +4842,8 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc, __count_vm_events(PGSCAN_ANON + type, isolated); /* - * There might not be eligible pages due to reclaim_idx, may_unmap and - * may_writepage. Check the remaining to prevent livelock if it's not - * making progress. -+ * There might not be eligible pages due to reclaim_idx. Check the ++ * There might not be eligible folios due to reclaim_idx. Check the + * remaining to prevent livelock if it's not making progress. */ return isolated || !remaining ? scanned : 0; } -@@ -5110,8 +5106,7 @@ static long get_nr_to_scan(struct lruvec +@@ -5107,8 +5103,7 @@ static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc, bool struct mem_cgroup *memcg = lruvec_memcg(lruvec); DEFINE_MAX_SEQ(lruvec); @@ -117,7 +125,7 @@ Signed-off-by: Andrew Morton return 0; if (!should_run_aging(lruvec, max_seq, sc, can_swap, &nr_to_scan)) -@@ -5139,17 +5134,14 @@ static bool try_to_shrink_lruvec(struct +@@ -5136,17 +5131,14 @@ static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) long nr_to_scan; unsigned long scanned = 0; unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); @@ -140,7 +148,7 @@ Signed-off-by: Andrew Morton nr_to_scan = get_nr_to_scan(lruvec, sc, swappiness); if (nr_to_scan <= 0) -@@ -5279,12 +5271,13 @@ static void lru_gen_shrink_lruvec(struct +@@ -5277,12 +5269,13 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc struct blk_plug plug; VM_WARN_ON_ONCE(global_reclaim(sc)); @@ -155,7 +163,7 @@ Signed-off-by: Andrew Morton if (try_to_shrink_lruvec(lruvec, sc)) lru_gen_rotate_memcg(lruvec, MEMCG_LRU_YOUNG); -@@ -5340,11 +5333,19 @@ static void lru_gen_shrink_node(struct p +@@ -5338,11 +5331,19 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control * VM_WARN_ON_ONCE(!global_reclaim(sc)); @@ -172,11 +180,11 @@ Signed-off-by: Andrew Morton blk_start_plug(&plug); - set_mm_walk(pgdat); -+ set_mm_walk(NULL, sc->proactive); ++ set_mm_walk(pgdat, sc->proactive); set_initial_priority(pgdat, sc); -@@ -5362,7 +5363,7 @@ static void lru_gen_shrink_node(struct p +@@ -5360,7 +5361,7 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control * clear_mm_walk(); blk_finish_plug(&plug); @@ -185,7 +193,7 @@ Signed-off-by: Andrew Morton /* kswapd should never fail */ pgdat->kswapd_failures = 0; } -@@ -5934,7 +5935,7 @@ static ssize_t lru_gen_seq_write(struct +@@ -5932,7 +5933,7 @@ static ssize_t lru_gen_seq_write(struct file *file, const char __user *src, set_task_reclaim_state(current, &sc.reclaim_state); flags = memalloc_noreclaim_save(); blk_start_plug(&plug); @@ -194,3 +202,6 @@ Signed-off-by: Andrew Morton err = -ENOMEM; goto done; } +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-28-mm-multi-gen-LRU-simplify-arch_has_hw_pte_young-chec.patch b/target/linux/generic/backport-6.1/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch similarity index 67% rename from target/linux/generic/backport-6.1/020-v6.3-28-mm-multi-gen-LRU-simplify-arch_has_hw_pte_young-chec.patch rename to target/linux/generic/backport-6.1/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch index 367f93363bb..adf85b616f4 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-28-mm-multi-gen-LRU-simplify-arch_has_hw_pte_young-chec.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-08-UPSTREAM-mm-multi-gen-LRU-simplify-arch_has_hw_pte_y.patch @@ -1,8 +1,8 @@ -From cf3297e4c7a928da8b2b2f0baff2f9c69ea57952 Mon Sep 17 00:00:00 2001 +From 25887d48dff860751a06caa4188bfaf6bfb6e4b2 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Wed, 21 Dec 2022 21:19:06 -0700 -Subject: [PATCH 28/29] mm: multi-gen LRU: simplify arch_has_hw_pte_young() - check +Subject: [PATCH 08/19] UPSTREAM: mm: multi-gen LRU: simplify + arch_has_hw_pte_young() check Scanning page tables when hardware does not set the accessed bit has no real use cases. @@ -17,13 +17,19 @@ Cc: Mike Rapoport Cc: Roman Gushchin Cc: Suren Baghdasaryan Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit f386e9314025ea99dae639ed2032560a92081430) +Change-Id: I84d97ab665b4e3bb862a9bc7d72f50dea7191a6b +Signed-off-by: T.J. Mercier --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 0a0e1250ffc87..aa9746f2bc80b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -4418,7 +4418,7 @@ static bool try_to_inc_max_seq(struct lr +@@ -4415,7 +4415,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, * handful of PTEs. Spreading the work out over a period of time usually * is less efficient, but it avoids bursty page faults. */ @@ -32,3 +38,6 @@ Signed-off-by: Andrew Morton success = iterate_mm_list_nowalk(lruvec, max_seq); goto done; } +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-29-mm-multi-gen-LRU-avoid-futile-retries.patch b/target/linux/generic/backport-6.1/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch similarity index 74% rename from target/linux/generic/backport-6.1/020-v6.3-29-mm-multi-gen-LRU-avoid-futile-retries.patch rename to target/linux/generic/backport-6.1/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch index b9eb5f694e7..2cf14d78166 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-29-mm-multi-gen-LRU-avoid-futile-retries.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-09-UPSTREAM-mm-multi-gen-LRU-avoid-futile-retries.patch @@ -1,7 +1,7 @@ -From cc67f962cc53f6e1dfa92eb85b7b26fe83a3c66f Mon Sep 17 00:00:00 2001 +From 620b0ee94455e48d124414cd06d8a53f69fb6453 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Mon, 13 Feb 2023 00:53:22 -0700 -Subject: [PATCH 29/29] mm: multi-gen LRU: avoid futile retries +Subject: [PATCH 09/19] UPSTREAM: mm: multi-gen LRU: avoid futile retries Recall that the per-node memcg LRU has two generations and they alternate when the last memcg (of a given node) is moved from one to the other. @@ -19,13 +19,19 @@ Fixes: e4dde56cd208 ("mm: multi-gen LRU: per-node lru_gen_folio lists") Signed-off-by: Yu Zhao Reported-by: T.J. Mercier Signed-off-by: Andrew Morton +Bug: 274865848 +(cherry picked from commit 9f550d78b40da21b4da515db4c37d8d7b12aa1a6) +Change-Id: Ie92535676b005ec9e7987632b742fdde8d54436f +Signed-off-by: T.J. Mercier --- mm/vmscan.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) +diff --git a/mm/vmscan.c b/mm/vmscan.c +index aa9746f2bc80b..49da02f841c81 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -5208,18 +5208,20 @@ static int shrink_one(struct lruvec *lru +@@ -5206,18 +5206,20 @@ static int shrink_one(struct lruvec *lruvec, struct scan_control *sc) static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) { @@ -41,14 +47,14 @@ Signed-off-by: Andrew Morton - struct mem_cgroup *memcg = NULL; unsigned long nr_to_reclaim = get_nr_to_reclaim(sc); - bin = first_bin = prandom_u32_max(MEMCG_NR_BINS); + bin = first_bin = get_random_u32_below(MEMCG_NR_BINS); restart: + op = 0; + memcg = NULL; gen = get_memcg_gen(READ_ONCE(pgdat->memcg_lru.seq)); rcu_read_lock(); -@@ -5243,14 +5245,22 @@ restart: +@@ -5241,14 +5243,22 @@ static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) op = shrink_one(lruvec, sc); @@ -74,7 +80,7 @@ Signed-off-by: Andrew Morton /* restart if raced with lru_gen_rotate_memcg() */ if (gen != get_nulls_value(pos)) goto restart; -@@ -5259,11 +5269,6 @@ restart: +@@ -5257,11 +5267,6 @@ static void shrink_many(struct pglist_data *pgdat, struct scan_control *sc) bin = get_memcg_bin(bin + 1); if (bin != first_bin) goto restart; @@ -86,3 +92,6 @@ Signed-off-by: Andrew Morton } static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-19-mm-add-vma_has_recency.patch b/target/linux/generic/backport-6.1/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch similarity index 75% rename from target/linux/generic/backport-6.1/020-v6.3-19-mm-add-vma_has_recency.patch rename to target/linux/generic/backport-6.1/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch index 5335b804880..0a0b439e25f 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-19-mm-add-vma_has_recency.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-10-UPSTREAM-mm-add-vma_has_recency.patch @@ -1,7 +1,7 @@ -From 6c7f552a48b49a8612786a28a2239fbc24fac289 Mon Sep 17 00:00:00 2001 +From 70d216c71ff5c5b17dd1da6294f97b91fb6aba7a Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Fri, 30 Dec 2022 14:52:51 -0700 -Subject: [PATCH 19/29] mm: add vma_has_recency() +Subject: [PATCH 10/19] UPSTREAM: mm: add vma_has_recency() Add vma_has_recency() to indicate whether a VMA may exhibit temporal locality that the LRU algorithm relies on. @@ -43,22 +43,28 @@ results are available in that thread. [1] https://lore.kernel.org/r/Y31s%2FK8T85jh05wH@google.com/ Link: https://lkml.kernel.org/r/20221230215252.2628425-1-yuzhao@google.com +Change-Id: I291dcb795197659e40e46539cd32b857677c34ad Signed-off-by: Yu Zhao Cc: Alexander Viro Cc: Andrea Righi Cc: Johannes Weiner Cc: Michael Larabel Signed-off-by: Andrew Morton +(cherry picked from commit 8788f6781486769d9598dcaedc3fe0eb12fc3e59) +Bug: 274865848 +Signed-off-by: T.J. Mercier --- - include/linux/mm_inline.h | 9 +++++++++ - mm/memory.c | 8 ++++---- + include/linux/mm_inline.h | 8 ++++++++ + mm/memory.c | 7 +++---- mm/rmap.c | 42 +++++++++++++++++---------------------- mm/vmscan.c | 5 ++++- - 4 files changed, 35 insertions(+), 29 deletions(-) + 4 files changed, 33 insertions(+), 29 deletions(-) +diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h +index c1fd3922dc5dd..7bb2e5f94734c 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h -@@ -578,4 +578,12 @@ pte_install_uffd_wp_if_needed(struct vm_ +@@ -595,4 +595,12 @@ pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr, #endif } @@ -71,9 +77,11 @@ Signed-off-by: Andrew Morton +} + #endif +diff --git a/mm/memory.c b/mm/memory.c +index 747b7ea30f890..c2f48f8003c2e 100644 --- a/mm/memory.c +++ b/mm/memory.c -@@ -1435,8 +1435,7 @@ again: +@@ -1435,8 +1435,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, force_flush = 1; set_page_dirty(page); } @@ -83,7 +91,7 @@ Signed-off-by: Andrew Morton mark_page_accessed(page); } rss[mm_counter(page)]--; -@@ -5170,8 +5169,8 @@ static inline void mm_account_fault(stru +@@ -5170,8 +5169,8 @@ static inline void mm_account_fault(struct pt_regs *regs, #ifdef CONFIG_LRU_GEN static void lru_gen_enter_fault(struct vm_area_struct *vma) { @@ -94,9 +102,11 @@ Signed-off-by: Andrew Morton } static void lru_gen_exit_fault(void) +diff --git a/mm/rmap.c b/mm/rmap.c +index 7da2d8d097d9b..825dac3caa1e5 100644 --- a/mm/rmap.c +++ b/mm/rmap.c -@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct +@@ -823,25 +823,14 @@ static bool folio_referenced_one(struct folio *folio, } if (pvmw.pte) { @@ -125,16 +135,16 @@ Signed-off-by: Andrew Morton } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { if (pmdp_clear_flush_young_notify(vma, address, pvmw.pmd)) -@@ -875,7 +864,20 @@ static bool invalid_folio_referenced_vma +@@ -875,7 +864,20 @@ static bool invalid_folio_referenced_vma(struct vm_area_struct *vma, void *arg) struct folio_referenced_arg *pra = arg; struct mem_cgroup *memcg = pra->memcg; - if (!mm_match_cgroup(vma->vm_mm, memcg)) + /* + * Ignore references from this mapping if it has no recency. If the -+ * page has been used in another mapping, we will catch it; if this ++ * folio has been used in another mapping, we will catch it; if this + * other mapping is already gone, the unmap path will have set the -+ * referenced flag or activated the page in zap_pte_range(). ++ * referenced flag or activated the folio in zap_pte_range(). + */ + if (!vma_has_recency(vma)) + return true; @@ -147,7 +157,7 @@ Signed-off-by: Andrew Morton return true; return false; -@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio +@@ -906,6 +908,7 @@ int folio_referenced(struct folio *folio, int is_locked, .arg = (void *)&pra, .anon_lock = folio_lock_anon_vma_read, .try_lock = true, @@ -155,7 +165,7 @@ Signed-off-by: Andrew Morton }; *vm_flags = 0; -@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio +@@ -921,15 +924,6 @@ int folio_referenced(struct folio *folio, int is_locked, return 1; } @@ -171,9 +181,11 @@ Signed-off-by: Andrew Morton rmap_walk(folio, &rwc); *vm_flags = pra.vm_flags; +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 49da02f841c81..596fed6ae0439 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c -@@ -3766,7 +3766,10 @@ static int should_skip_vma(unsigned long +@@ -3778,7 +3778,10 @@ static int should_skip_vma(unsigned long start, unsigned long end, struct mm_wal if (is_vm_hugetlb_page(vma)) return true; @@ -185,3 +197,6 @@ Signed-off-by: Andrew Morton return true; if (vma == get_gate_vma(vma->vm_mm)) +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-20-mm-support-POSIX_FADV_NOREUSE.patch b/target/linux/generic/backport-6.1/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch similarity index 78% rename from target/linux/generic/backport-6.1/020-v6.3-20-mm-support-POSIX_FADV_NOREUSE.patch rename to target/linux/generic/backport-6.1/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch index b2b7c605ca5..4c6fcecdac1 100644 --- a/target/linux/generic/backport-6.1/020-v6.3-20-mm-support-POSIX_FADV_NOREUSE.patch +++ b/target/linux/generic/backport-6.1/020-v6.3-11-UPSTREAM-mm-support-POSIX_FADV_NOREUSE.patch @@ -1,7 +1,7 @@ -From 686c3d4f71de9e0e7a27f03a5617a712385f90cd Mon Sep 17 00:00:00 2001 +From 9ca4e437a24dfc4ec6c362f319eb9850b9eca497 Mon Sep 17 00:00:00 2001 From: Yu Zhao Date: Fri, 30 Dec 2022 14:52:52 -0700 -Subject: [PATCH 20/29] mm: support POSIX_FADV_NOREUSE +Subject: [PATCH 11/19] UPSTREAM: mm: support POSIX_FADV_NOREUSE This patch adds POSIX_FADV_NOREUSE to vma_has_recency() so that the LRU algorithm can ignore access to mapped files marked by this flag. @@ -22,7 +22,7 @@ Its limitations are: by two users and one of them having set POSIX_FADV_NOREUSE on the file, this page will be activated upon the second user accessing it. This corner case can be covered by checking POSIX_FADV_NOREUSE - before calling mark_page_accessed() on the read path. But it is + before calling folio_mark_accessed() on the read path. But it is considered not worth the effort. There have been a few attempts to support POSIX_FADV_NOREUSE, e.g., [1]. @@ -67,32 +67,40 @@ which makes it on par with the active/inactive LRU. [2] https://openbenchmarking.org/result/2209259-PTS-MGLRU8GB57 Link: https://lkml.kernel.org/r/20221230215252.2628425-2-yuzhao@google.com +Change-Id: I0b7f5f971d78014ea1ba44cee6a8ec902a4330d0 Signed-off-by: Yu Zhao Cc: Alexander Viro Cc: Andrea Righi Cc: Johannes Weiner Cc: Michael Larabel Signed-off-by: Andrew Morton +(cherry picked from commit 17e810229cb3068b692fa078bd9b3a6527e0866a) +Bug: 274865848 +Signed-off-by: T.J. Mercier --- include/linux/fs.h | 2 ++ include/linux/mm_inline.h | 3 +++ mm/fadvise.c | 5 ++++- 3 files changed, 9 insertions(+), 1 deletion(-) +diff --git a/include/linux/fs.h b/include/linux/fs.h +index f14ecbeab2a9d..97f9c41c1a43a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb +@@ -166,6 +166,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* File supports DIRECT IO */ #define FMODE_CAN_ODIRECT ((__force fmode_t)0x400000) -+#define FMODE_NOREUSE ((__force fmode_t)0x400000) ++#define FMODE_NOREUSE ((__force fmode_t)0x800000) + /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) +diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h +index 7bb2e5f94734c..9a8e2049333c0 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h -@@ -583,6 +583,9 @@ static inline bool vma_has_recency(struc +@@ -600,6 +600,9 @@ static inline bool vma_has_recency(struct vm_area_struct *vma) if (vma->vm_flags & (VM_SEQ_READ | VM_RAND_READ)) return false; @@ -102,9 +110,11 @@ Signed-off-by: Andrew Morton return true; } +diff --git a/mm/fadvise.c b/mm/fadvise.c +index c76ee665355a4..2ba24d865bf5f 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c -@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, l +@@ -80,7 +80,7 @@ int generic_fadvise(struct file *file, loff_t offset, loff_t len, int advice) case POSIX_FADV_NORMAL: file->f_ra.ra_pages = bdi->ra_pages; spin_lock(&file->f_lock); @@ -113,7 +123,7 @@ Signed-off-by: Andrew Morton spin_unlock(&file->f_lock); break; case POSIX_FADV_RANDOM: -@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, l +@@ -107,6 +107,9 @@ int generic_fadvise(struct file *file, loff_t offset, loff_t len, int advice) force_page_cache_readahead(mapping, file, start_index, nrpages); break; case POSIX_FADV_NOREUSE: @@ -123,3 +133,6 @@ Signed-off-by: Andrew Morton break; case POSIX_FADV_DONTNEED: __filemap_fdatawrite_range(mapping, offset, endbyte, +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch b/target/linux/generic/backport-6.1/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch new file mode 100644 index 00000000000..08804e00235 --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-12-UPSTREAM-mm-multi-gen-LRU-section-for-working-set-pr.patch @@ -0,0 +1,74 @@ +From 1b5e4c317d80f4826eceb3781702d18d06b14394 Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:21 +0000 +Subject: [PATCH 12/19] UPSTREAM: mm: multi-gen LRU: section for working set + protection + +Patch series "mm: multi-gen LRU: improve". + +This patch series improves a few MGLRU functions, collects related +functions, and adds additional documentation. + +This patch (of 7): + +Add a section for working set protection in the code and the design doc. +The admin doc already contains its usage. + +Link: https://lkml.kernel.org/r/20230118001827.1040870-1-talumbau@google.com +Link: https://lkml.kernel.org/r/20230118001827.1040870-2-talumbau@google.com +Change-Id: I65599075fd42951db7739a2ab7cee78516e157b3 +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit 7b8144e63d84716f16a1b929e0c7e03ae5c4d5c1) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + Documentation/mm/multigen_lru.rst | 15 +++++++++++++++ + mm/vmscan.c | 4 ++++ + 2 files changed, 19 insertions(+) + +diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst +index d8f721f98868a..6e1483e70fdca 100644 +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -141,6 +141,21 @@ loop has detected outlying refaults from the tier this page is in. To + this end, the feedback loop uses the first tier as the baseline, for + the reason stated earlier. + ++Working set protection ++---------------------- ++Each generation is timestamped at birth. If ``lru_gen_min_ttl`` is ++set, an ``lruvec`` is protected from the eviction when its oldest ++generation was born within ``lru_gen_min_ttl`` milliseconds. In other ++words, it prevents the working set of ``lru_gen_min_ttl`` milliseconds ++from getting evicted. The OOM killer is triggered if this working set ++cannot be kept in memory. ++ ++This time-based approach has the following advantages: ++ ++1. It is easier to configure because it is agnostic to applications ++ and memory sizes. ++2. It is more reliable because it is directly wired to the OOM killer. ++ + Summary + ------- + The multi-gen LRU can be disassembled into the following parts: +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 596fed6ae0439..ab0b8d3b9d88f 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4459,6 +4459,10 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, + return true; + } + ++/****************************************************************************** ++ * working set protection ++ ******************************************************************************/ ++ + static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) + { + int gen, type, zone; +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch b/target/linux/generic/backport-6.1/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch new file mode 100644 index 00000000000..f80dedb4057 --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-13-UPSTREAM-mm-multi-gen-LRU-section-for-rmap-PT-walk-f.patch @@ -0,0 +1,64 @@ +From 5ddf9d53d375e42af49b744bd7c2f8247c6bce15 Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:22 +0000 +Subject: [PATCH 13/19] UPSTREAM: mm: multi-gen LRU: section for rmap/PT walk + feedback + +Add a section for lru_gen_look_around() in the code and the design doc. + +Link: https://lkml.kernel.org/r/20230118001827.1040870-3-talumbau@google.com +Change-Id: I5097af63f61b3b69ec2abee6cdbdc33c296df213 +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit db19a43d9b3a8876552f00f656008206ef9a5efa) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + Documentation/mm/multigen_lru.rst | 14 ++++++++++++++ + mm/vmscan.c | 4 ++++ + 2 files changed, 18 insertions(+) + +diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst +index 6e1483e70fdca..bd988a142bc2f 100644 +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -156,6 +156,20 @@ This time-based approach has the following advantages: + and memory sizes. + 2. It is more reliable because it is directly wired to the OOM killer. + ++Rmap/PT walk feedback ++--------------------- ++Searching the rmap for PTEs mapping each page on an LRU list (to test ++and clear the accessed bit) can be expensive because pages from ++different VMAs (PA space) are not cache friendly to the rmap (VA ++space). For workloads mostly using mapped pages, searching the rmap ++can incur the highest CPU cost in the reclaim path. ++ ++``lru_gen_look_around()`` exploits spatial locality to reduce the ++trips into the rmap. It scans the adjacent PTEs of a young PTE and ++promotes hot pages. If the scan was done cacheline efficiently, it ++adds the PMD entry pointing to the PTE table to the Bloom filter. This ++forms a feedback loop between the eviction and the aging. ++ + Summary + ------- + The multi-gen LRU can be disassembled into the following parts: +diff --git a/mm/vmscan.c b/mm/vmscan.c +index ab0b8d3b9d88f..8fa82630240d6 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4553,6 +4553,10 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) + } + } + ++/****************************************************************************** ++ * rmap/PT walk feedback ++ ******************************************************************************/ ++ + /* + * This function exploits spatial locality when shrink_folio_list() walks the + * rmap. It scans the adjacent PTEs of a young PTE and promotes hot pages. If +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch b/target/linux/generic/backport-6.1/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch new file mode 100644 index 00000000000..f98588c4d89 --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-14-UPSTREAM-mm-multi-gen-LRU-section-for-Bloom-filters.patch @@ -0,0 +1,250 @@ +From 397624e12244ec038f51cb1f178ccb7a2ec562e5 Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:23 +0000 +Subject: [PATCH 14/19] UPSTREAM: mm: multi-gen LRU: section for Bloom filters + +Move Bloom filters code into a dedicated section. Improve the design doc +to explain Bloom filter usage and connection between aging and eviction in +their use. + +Link: https://lkml.kernel.org/r/20230118001827.1040870-4-talumbau@google.com +Change-Id: I73e866f687c1ed9f5c8538086aa39408b79897db +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit ccbbbb85945d8f0255aa9dbc1b617017e2294f2c) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + Documentation/mm/multigen_lru.rst | 16 +++ + mm/vmscan.c | 180 +++++++++++++++--------------- + 2 files changed, 108 insertions(+), 88 deletions(-) + +diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst +index bd988a142bc2f..770b5d539856c 100644 +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -170,6 +170,22 @@ promotes hot pages. If the scan was done cacheline efficiently, it + adds the PMD entry pointing to the PTE table to the Bloom filter. This + forms a feedback loop between the eviction and the aging. + ++Bloom Filters ++------------- ++Bloom filters are a space and memory efficient data structure for set ++membership test, i.e., test if an element is not in the set or may be ++in the set. ++ ++In the eviction path, specifically, in ``lru_gen_look_around()``, if a ++PMD has a sufficient number of hot pages, its address is placed in the ++filter. In the aging path, set membership means that the PTE range ++will be scanned for young pages. ++ ++Note that Bloom filters are probabilistic on set membership. If a test ++is false positive, the cost is an additional scan of a range of PTEs, ++which may yield hot pages anyway. Parameters of the filter itself can ++control the false positive rate in the limit. ++ + Summary + ------- + The multi-gen LRU can be disassembled into the following parts: +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 8fa82630240d6..74b4f9d660b56 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3208,6 +3208,98 @@ static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) + get_nr_gens(lruvec, LRU_GEN_ANON) <= MAX_NR_GENS; + } + ++/****************************************************************************** ++ * Bloom filters ++ ******************************************************************************/ ++ ++/* ++ * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when ++ * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of ++ * bits in a bitmap, k is the number of hash functions and n is the number of ++ * inserted items. ++ * ++ * Page table walkers use one of the two filters to reduce their search space. ++ * To get rid of non-leaf entries that no longer have enough leaf entries, the ++ * aging uses the double-buffering technique to flip to the other filter each ++ * time it produces a new generation. For non-leaf entries that have enough ++ * leaf entries, the aging carries them over to the next generation in ++ * walk_pmd_range(); the eviction also report them when walking the rmap ++ * in lru_gen_look_around(). ++ * ++ * For future optimizations: ++ * 1. It's not necessary to keep both filters all the time. The spare one can be ++ * freed after the RCU grace period and reallocated if needed again. ++ * 2. And when reallocating, it's worth scaling its size according to the number ++ * of inserted entries in the other filter, to reduce the memory overhead on ++ * small systems and false positives on large systems. ++ * 3. Jenkins' hash function is an alternative to Knuth's. ++ */ ++#define BLOOM_FILTER_SHIFT 15 ++ ++static inline int filter_gen_from_seq(unsigned long seq) ++{ ++ return seq % NR_BLOOM_FILTERS; ++} ++ ++static void get_item_key(void *item, int *key) ++{ ++ u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2); ++ ++ BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32)); ++ ++ key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1); ++ key[1] = hash >> BLOOM_FILTER_SHIFT; ++} ++ ++static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) ++{ ++ int key[2]; ++ unsigned long *filter; ++ int gen = filter_gen_from_seq(seq); ++ ++ filter = READ_ONCE(lruvec->mm_state.filters[gen]); ++ if (!filter) ++ return true; ++ ++ get_item_key(item, key); ++ ++ return test_bit(key[0], filter) && test_bit(key[1], filter); ++} ++ ++static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) ++{ ++ int key[2]; ++ unsigned long *filter; ++ int gen = filter_gen_from_seq(seq); ++ ++ filter = READ_ONCE(lruvec->mm_state.filters[gen]); ++ if (!filter) ++ return; ++ ++ get_item_key(item, key); ++ ++ if (!test_bit(key[0], filter)) ++ set_bit(key[0], filter); ++ if (!test_bit(key[1], filter)) ++ set_bit(key[1], filter); ++} ++ ++static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq) ++{ ++ unsigned long *filter; ++ int gen = filter_gen_from_seq(seq); ++ ++ filter = lruvec->mm_state.filters[gen]; ++ if (filter) { ++ bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT)); ++ return; ++ } ++ ++ filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT), ++ __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); ++ WRITE_ONCE(lruvec->mm_state.filters[gen], filter); ++} ++ + /****************************************************************************** + * mm_struct list + ******************************************************************************/ +@@ -3333,94 +3425,6 @@ void lru_gen_migrate_mm(struct mm_struct *mm) + } + #endif + +-/* +- * Bloom filters with m=1<<15, k=2 and the false positive rates of ~1/5 when +- * n=10,000 and ~1/2 when n=20,000, where, conventionally, m is the number of +- * bits in a bitmap, k is the number of hash functions and n is the number of +- * inserted items. +- * +- * Page table walkers use one of the two filters to reduce their search space. +- * To get rid of non-leaf entries that no longer have enough leaf entries, the +- * aging uses the double-buffering technique to flip to the other filter each +- * time it produces a new generation. For non-leaf entries that have enough +- * leaf entries, the aging carries them over to the next generation in +- * walk_pmd_range(); the eviction also report them when walking the rmap +- * in lru_gen_look_around(). +- * +- * For future optimizations: +- * 1. It's not necessary to keep both filters all the time. The spare one can be +- * freed after the RCU grace period and reallocated if needed again. +- * 2. And when reallocating, it's worth scaling its size according to the number +- * of inserted entries in the other filter, to reduce the memory overhead on +- * small systems and false positives on large systems. +- * 3. Jenkins' hash function is an alternative to Knuth's. +- */ +-#define BLOOM_FILTER_SHIFT 15 +- +-static inline int filter_gen_from_seq(unsigned long seq) +-{ +- return seq % NR_BLOOM_FILTERS; +-} +- +-static void get_item_key(void *item, int *key) +-{ +- u32 hash = hash_ptr(item, BLOOM_FILTER_SHIFT * 2); +- +- BUILD_BUG_ON(BLOOM_FILTER_SHIFT * 2 > BITS_PER_TYPE(u32)); +- +- key[0] = hash & (BIT(BLOOM_FILTER_SHIFT) - 1); +- key[1] = hash >> BLOOM_FILTER_SHIFT; +-} +- +-static void reset_bloom_filter(struct lruvec *lruvec, unsigned long seq) +-{ +- unsigned long *filter; +- int gen = filter_gen_from_seq(seq); +- +- filter = lruvec->mm_state.filters[gen]; +- if (filter) { +- bitmap_clear(filter, 0, BIT(BLOOM_FILTER_SHIFT)); +- return; +- } +- +- filter = bitmap_zalloc(BIT(BLOOM_FILTER_SHIFT), +- __GFP_HIGH | __GFP_NOMEMALLOC | __GFP_NOWARN); +- WRITE_ONCE(lruvec->mm_state.filters[gen], filter); +-} +- +-static void update_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) +-{ +- int key[2]; +- unsigned long *filter; +- int gen = filter_gen_from_seq(seq); +- +- filter = READ_ONCE(lruvec->mm_state.filters[gen]); +- if (!filter) +- return; +- +- get_item_key(item, key); +- +- if (!test_bit(key[0], filter)) +- set_bit(key[0], filter); +- if (!test_bit(key[1], filter)) +- set_bit(key[1], filter); +-} +- +-static bool test_bloom_filter(struct lruvec *lruvec, unsigned long seq, void *item) +-{ +- int key[2]; +- unsigned long *filter; +- int gen = filter_gen_from_seq(seq); +- +- filter = READ_ONCE(lruvec->mm_state.filters[gen]); +- if (!filter) +- return true; +- +- get_item_key(item, key); +- +- return test_bit(key[0], filter) && test_bit(key[1], filter); +-} +- + static void reset_mm_stats(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, bool last) + { + int i; +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch b/target/linux/generic/backport-6.1/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch new file mode 100644 index 00000000000..c26e28c3cad --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-15-UPSTREAM-mm-multi-gen-LRU-section-for-memcg-LRU.patch @@ -0,0 +1,440 @@ +From 48c916b812652f9453be5bd45a703728926d41ca Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:24 +0000 +Subject: [PATCH 15/19] UPSTREAM: mm: multi-gen LRU: section for memcg LRU + +Move memcg LRU code into a dedicated section. Improve the design doc to +outline its architecture. + +Link: https://lkml.kernel.org/r/20230118001827.1040870-5-talumbau@google.com +Change-Id: Id252e420cff7a858acb098cf2b3642da5c40f602 +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit 36c7b4db7c942ae9e1b111f0c6b468c8b2e33842) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + Documentation/mm/multigen_lru.rst | 33 +++- + include/linux/mm_inline.h | 17 -- + include/linux/mmzone.h | 13 +- + mm/memcontrol.c | 8 +- + mm/vmscan.c | 250 +++++++++++++++++------------- + 5 files changed, 178 insertions(+), 143 deletions(-) + +diff --git a/Documentation/mm/multigen_lru.rst b/Documentation/mm/multigen_lru.rst +index 770b5d539856c..5f1f6ecbb79b9 100644 +--- a/Documentation/mm/multigen_lru.rst ++++ b/Documentation/mm/multigen_lru.rst +@@ -186,9 +186,40 @@ is false positive, the cost is an additional scan of a range of PTEs, + which may yield hot pages anyway. Parameters of the filter itself can + control the false positive rate in the limit. + ++Memcg LRU ++--------- ++An memcg LRU is a per-node LRU of memcgs. It is also an LRU of LRUs, ++since each node and memcg combination has an LRU of folios (see ++``mem_cgroup_lruvec()``). Its goal is to improve the scalability of ++global reclaim, which is critical to system-wide memory overcommit in ++data centers. Note that memcg LRU only applies to global reclaim. ++ ++The basic structure of an memcg LRU can be understood by an analogy to ++the active/inactive LRU (of folios): ++ ++1. It has the young and the old (generations), i.e., the counterparts ++ to the active and the inactive; ++2. The increment of ``max_seq`` triggers promotion, i.e., the ++ counterpart to activation; ++3. Other events trigger similar operations, e.g., offlining an memcg ++ triggers demotion, i.e., the counterpart to deactivation. ++ ++In terms of global reclaim, it has two distinct features: ++ ++1. Sharding, which allows each thread to start at a random memcg (in ++ the old generation) and improves parallelism; ++2. Eventual fairness, which allows direct reclaim to bail out at will ++ and reduces latency without affecting fairness over some time. ++ ++In terms of traversing memcgs during global reclaim, it improves the ++best-case complexity from O(n) to O(1) and does not affect the ++worst-case complexity O(n). Therefore, on average, it has a sublinear ++complexity. ++ + Summary + ------- +-The multi-gen LRU can be disassembled into the following parts: ++The multi-gen LRU (of folios) can be disassembled into the following ++parts: + + * Generations + * Rmap walks +diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h +index 9a8e2049333c0..5567f4850243b 100644 +--- a/include/linux/mm_inline.h ++++ b/include/linux/mm_inline.h +@@ -122,18 +122,6 @@ static inline bool lru_gen_in_fault(void) + return current->in_lru_fault; + } + +-#ifdef CONFIG_MEMCG +-static inline int lru_gen_memcg_seg(struct lruvec *lruvec) +-{ +- return READ_ONCE(lruvec->lrugen.seg); +-} +-#else +-static inline int lru_gen_memcg_seg(struct lruvec *lruvec) +-{ +- return 0; +-} +-#endif +- + static inline int lru_gen_from_seq(unsigned long seq) + { + return seq % MAX_NR_GENS; +@@ -309,11 +297,6 @@ static inline bool lru_gen_in_fault(void) + return false; + } + +-static inline int lru_gen_memcg_seg(struct lruvec *lruvec) +-{ +- return 0; +-} +- + static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *folio, bool reclaiming) + { + return false; +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index 66e067a635682..403c7461e7a70 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -368,15 +368,6 @@ struct page_vma_mapped_walk; + #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) + #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) + +-/* see the comment on MEMCG_NR_GENS */ +-enum { +- MEMCG_LRU_NOP, +- MEMCG_LRU_HEAD, +- MEMCG_LRU_TAIL, +- MEMCG_LRU_OLD, +- MEMCG_LRU_YOUNG, +-}; +- + #ifdef CONFIG_LRU_GEN + + enum { +@@ -557,7 +548,7 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg); + void lru_gen_online_memcg(struct mem_cgroup *memcg); + void lru_gen_offline_memcg(struct mem_cgroup *memcg); + void lru_gen_release_memcg(struct mem_cgroup *memcg); +-void lru_gen_rotate_memcg(struct lruvec *lruvec, int op); ++void lru_gen_soft_reclaim(struct lruvec *lruvec); + + #else /* !CONFIG_MEMCG */ + +@@ -608,7 +599,7 @@ static inline void lru_gen_release_memcg(struct mem_cgroup *memcg) + { + } + +-static inline void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) ++static inline void lru_gen_soft_reclaim(struct lruvec *lruvec) + { + } + +diff --git a/mm/memcontrol.c b/mm/memcontrol.c +index 7815d556e38cc..5397aeb43986d 100644 +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -478,12 +478,8 @@ static void mem_cgroup_update_tree(struct mem_cgroup *memcg, int nid) + struct mem_cgroup_tree_per_node *mctz; + + if (lru_gen_enabled()) { +- struct lruvec *lruvec = &memcg->nodeinfo[nid]->lruvec; +- +- /* see the comment on MEMCG_NR_GENS */ +- if (soft_limit_excess(memcg) && lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD) +- lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD); +- ++ if (soft_limit_excess(memcg)) ++ lru_gen_soft_reclaim(&memcg->nodeinfo[nid]->lruvec); + return; + } + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 74b4f9d660b56..ccde215c084ca 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4689,6 +4689,148 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) + mem_cgroup_unlock_pages(); + } + ++/****************************************************************************** ++ * memcg LRU ++ ******************************************************************************/ ++ ++/* see the comment on MEMCG_NR_GENS */ ++enum { ++ MEMCG_LRU_NOP, ++ MEMCG_LRU_HEAD, ++ MEMCG_LRU_TAIL, ++ MEMCG_LRU_OLD, ++ MEMCG_LRU_YOUNG, ++}; ++ ++#ifdef CONFIG_MEMCG ++ ++static int lru_gen_memcg_seg(struct lruvec *lruvec) ++{ ++ return READ_ONCE(lruvec->lrugen.seg); ++} ++ ++static void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) ++{ ++ int seg; ++ int old, new; ++ int bin = get_random_u32_below(MEMCG_NR_BINS); ++ struct pglist_data *pgdat = lruvec_pgdat(lruvec); ++ ++ spin_lock(&pgdat->memcg_lru.lock); ++ ++ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); ++ ++ seg = 0; ++ new = old = lruvec->lrugen.gen; ++ ++ /* see the comment on MEMCG_NR_GENS */ ++ if (op == MEMCG_LRU_HEAD) ++ seg = MEMCG_LRU_HEAD; ++ else if (op == MEMCG_LRU_TAIL) ++ seg = MEMCG_LRU_TAIL; ++ else if (op == MEMCG_LRU_OLD) ++ new = get_memcg_gen(pgdat->memcg_lru.seq); ++ else if (op == MEMCG_LRU_YOUNG) ++ new = get_memcg_gen(pgdat->memcg_lru.seq + 1); ++ else ++ VM_WARN_ON_ONCE(true); ++ ++ hlist_nulls_del_rcu(&lruvec->lrugen.list); ++ ++ if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD) ++ hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); ++ else ++ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); ++ ++ pgdat->memcg_lru.nr_memcgs[old]--; ++ pgdat->memcg_lru.nr_memcgs[new]++; ++ ++ lruvec->lrugen.gen = new; ++ WRITE_ONCE(lruvec->lrugen.seg, seg); ++ ++ if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq)) ++ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); ++ ++ spin_unlock(&pgdat->memcg_lru.lock); ++} ++ ++void lru_gen_online_memcg(struct mem_cgroup *memcg) ++{ ++ int gen; ++ int nid; ++ int bin = get_random_u32_below(MEMCG_NR_BINS); ++ ++ for_each_node(nid) { ++ struct pglist_data *pgdat = NODE_DATA(nid); ++ struct lruvec *lruvec = get_lruvec(memcg, nid); ++ ++ spin_lock(&pgdat->memcg_lru.lock); ++ ++ VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list)); ++ ++ gen = get_memcg_gen(pgdat->memcg_lru.seq); ++ ++ hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]); ++ pgdat->memcg_lru.nr_memcgs[gen]++; ++ ++ lruvec->lrugen.gen = gen; ++ ++ spin_unlock(&pgdat->memcg_lru.lock); ++ } ++} ++ ++void lru_gen_offline_memcg(struct mem_cgroup *memcg) ++{ ++ int nid; ++ ++ for_each_node(nid) { ++ struct lruvec *lruvec = get_lruvec(memcg, nid); ++ ++ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD); ++ } ++} ++ ++void lru_gen_release_memcg(struct mem_cgroup *memcg) ++{ ++ int gen; ++ int nid; ++ ++ for_each_node(nid) { ++ struct pglist_data *pgdat = NODE_DATA(nid); ++ struct lruvec *lruvec = get_lruvec(memcg, nid); ++ ++ spin_lock(&pgdat->memcg_lru.lock); ++ ++ VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); ++ ++ gen = lruvec->lrugen.gen; ++ ++ hlist_nulls_del_rcu(&lruvec->lrugen.list); ++ pgdat->memcg_lru.nr_memcgs[gen]--; ++ ++ if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq)) ++ WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); ++ ++ spin_unlock(&pgdat->memcg_lru.lock); ++ } ++} ++ ++void lru_gen_soft_reclaim(struct lruvec *lruvec) ++{ ++ /* see the comment on MEMCG_NR_GENS */ ++ if (lru_gen_memcg_seg(lruvec) != MEMCG_LRU_HEAD) ++ lru_gen_rotate_memcg(lruvec, MEMCG_LRU_HEAD); ++} ++ ++#else /* !CONFIG_MEMCG */ ++ ++static int lru_gen_memcg_seg(struct lruvec *lruvec) ++{ ++ return 0; ++} ++ ++#endif ++ + /****************************************************************************** + * the eviction + ******************************************************************************/ +@@ -5386,53 +5528,6 @@ static void lru_gen_shrink_node(struct pglist_data *pgdat, struct scan_control * + pgdat->kswapd_failures = 0; + } + +-#ifdef CONFIG_MEMCG +-void lru_gen_rotate_memcg(struct lruvec *lruvec, int op) +-{ +- int seg; +- int old, new; +- int bin = get_random_u32_below(MEMCG_NR_BINS); +- struct pglist_data *pgdat = lruvec_pgdat(lruvec); +- +- spin_lock(&pgdat->memcg_lru.lock); +- +- VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); +- +- seg = 0; +- new = old = lruvec->lrugen.gen; +- +- /* see the comment on MEMCG_NR_GENS */ +- if (op == MEMCG_LRU_HEAD) +- seg = MEMCG_LRU_HEAD; +- else if (op == MEMCG_LRU_TAIL) +- seg = MEMCG_LRU_TAIL; +- else if (op == MEMCG_LRU_OLD) +- new = get_memcg_gen(pgdat->memcg_lru.seq); +- else if (op == MEMCG_LRU_YOUNG) +- new = get_memcg_gen(pgdat->memcg_lru.seq + 1); +- else +- VM_WARN_ON_ONCE(true); +- +- hlist_nulls_del_rcu(&lruvec->lrugen.list); +- +- if (op == MEMCG_LRU_HEAD || op == MEMCG_LRU_OLD) +- hlist_nulls_add_head_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); +- else +- hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[new][bin]); +- +- pgdat->memcg_lru.nr_memcgs[old]--; +- pgdat->memcg_lru.nr_memcgs[new]++; +- +- lruvec->lrugen.gen = new; +- WRITE_ONCE(lruvec->lrugen.seg, seg); +- +- if (!pgdat->memcg_lru.nr_memcgs[old] && old == get_memcg_gen(pgdat->memcg_lru.seq)) +- WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); +- +- spin_unlock(&pgdat->memcg_lru.lock); +-} +-#endif +- + /****************************************************************************** + * state change + ******************************************************************************/ +@@ -6078,67 +6173,6 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg) + } + } + +-void lru_gen_online_memcg(struct mem_cgroup *memcg) +-{ +- int gen; +- int nid; +- int bin = get_random_u32_below(MEMCG_NR_BINS); +- +- for_each_node(nid) { +- struct pglist_data *pgdat = NODE_DATA(nid); +- struct lruvec *lruvec = get_lruvec(memcg, nid); +- +- spin_lock(&pgdat->memcg_lru.lock); +- +- VM_WARN_ON_ONCE(!hlist_nulls_unhashed(&lruvec->lrugen.list)); +- +- gen = get_memcg_gen(pgdat->memcg_lru.seq); +- +- hlist_nulls_add_tail_rcu(&lruvec->lrugen.list, &pgdat->memcg_lru.fifo[gen][bin]); +- pgdat->memcg_lru.nr_memcgs[gen]++; +- +- lruvec->lrugen.gen = gen; +- +- spin_unlock(&pgdat->memcg_lru.lock); +- } +-} +- +-void lru_gen_offline_memcg(struct mem_cgroup *memcg) +-{ +- int nid; +- +- for_each_node(nid) { +- struct lruvec *lruvec = get_lruvec(memcg, nid); +- +- lru_gen_rotate_memcg(lruvec, MEMCG_LRU_OLD); +- } +-} +- +-void lru_gen_release_memcg(struct mem_cgroup *memcg) +-{ +- int gen; +- int nid; +- +- for_each_node(nid) { +- struct pglist_data *pgdat = NODE_DATA(nid); +- struct lruvec *lruvec = get_lruvec(memcg, nid); +- +- spin_lock(&pgdat->memcg_lru.lock); +- +- VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); +- +- gen = lruvec->lrugen.gen; +- +- hlist_nulls_del_rcu(&lruvec->lrugen.list); +- pgdat->memcg_lru.nr_memcgs[gen]--; +- +- if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq)) +- WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); +- +- spin_unlock(&pgdat->memcg_lru.lock); +- } +-} +- + #endif /* CONFIG_MEMCG */ + + static int __init init_lru_gen(void) +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch b/target/linux/generic/backport-6.1/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch new file mode 100644 index 00000000000..1f3f8ffe6da --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-16-UPSTREAM-mm-multi-gen-LRU-improve-lru_gen_exit_memcg.patch @@ -0,0 +1,45 @@ +From bec433f29537652ed054148edfd7e2183ddcf7c3 Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:25 +0000 +Subject: [PATCH 16/19] UPSTREAM: mm: multi-gen LRU: improve + lru_gen_exit_memcg() + +Add warnings and poison ->next. + +Link: https://lkml.kernel.org/r/20230118001827.1040870-6-talumbau@google.com +Change-Id: I53de9e04c1ae941e122b33cd45d2bbb5f34aae0c +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit 37cc99979d04cca677c0ad5c0acd1149ec165d1b) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + mm/vmscan.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index ccde215c084ca..d5d6f8d94f58a 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -6160,12 +6160,17 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg) + int i; + int nid; + ++ VM_WARN_ON_ONCE(!list_empty(&memcg->mm_list.fifo)); ++ + for_each_node(nid) { + struct lruvec *lruvec = get_lruvec(memcg, nid); + ++ VM_WARN_ON_ONCE(lruvec->mm_state.nr_walkers); + VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, + sizeof(lruvec->lrugen.nr_pages))); + ++ lruvec->lrugen.list.next = LIST_POISON1; ++ + for (i = 0; i < NR_BLOOM_FILTERS; i++) { + bitmap_free(lruvec->mm_state.filters[i]); + lruvec->mm_state.filters[i] = NULL; +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch b/target/linux/generic/backport-6.1/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch new file mode 100644 index 00000000000..02dd920e54c --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-17-UPSTREAM-mm-multi-gen-LRU-improve-walk_pmd_range.patch @@ -0,0 +1,140 @@ +From fc0e3b06e0f19917b7ecad7967a72f61d4743644 Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:26 +0000 +Subject: [PATCH 17/19] UPSTREAM: mm: multi-gen LRU: improve walk_pmd_range() + +Improve readability of walk_pmd_range() and walk_pmd_range_locked(). + +Link: https://lkml.kernel.org/r/20230118001827.1040870-7-talumbau@google.com +Change-Id: Ia084fbf53fe989673b7804ca8ca520af12d7d52a +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit b5ff4133617d0eced35b685da0bd0929dd9fabb7) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + mm/vmscan.c | 40 ++++++++++++++++++++-------------------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index d5d6f8d94f58a..8f496c2e670a9 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3980,8 +3980,8 @@ static bool walk_pte_range(pmd_t *pmd, unsigned long start, unsigned long end, + } + + #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_ARCH_HAS_NONLEAF_PMD_YOUNG) +-static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, +- struct mm_walk *args, unsigned long *bitmap, unsigned long *start) ++static void walk_pmd_range_locked(pud_t *pud, unsigned long addr, struct vm_area_struct *vma, ++ struct mm_walk *args, unsigned long *bitmap, unsigned long *first) + { + int i; + pmd_t *pmd; +@@ -3994,18 +3994,19 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area + VM_WARN_ON_ONCE(pud_leaf(*pud)); + + /* try to batch at most 1+MIN_LRU_BATCH+1 entries */ +- if (*start == -1) { +- *start = next; ++ if (*first == -1) { ++ *first = addr; ++ bitmap_zero(bitmap, MIN_LRU_BATCH); + return; + } + +- i = next == -1 ? 0 : pmd_index(next) - pmd_index(*start); ++ i = addr == -1 ? 0 : pmd_index(addr) - pmd_index(*first); + if (i && i <= MIN_LRU_BATCH) { + __set_bit(i - 1, bitmap); + return; + } + +- pmd = pmd_offset(pud, *start); ++ pmd = pmd_offset(pud, *first); + + ptl = pmd_lockptr(args->mm, pmd); + if (!spin_trylock(ptl)) +@@ -4016,15 +4017,16 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area + do { + unsigned long pfn; + struct folio *folio; +- unsigned long addr = i ? (*start & PMD_MASK) + i * PMD_SIZE : *start; ++ ++ /* don't round down the first address */ ++ addr = i ? (*first & PMD_MASK) + i * PMD_SIZE : *first; + + pfn = get_pmd_pfn(pmd[i], vma, addr); + if (pfn == -1) + goto next; + + if (!pmd_trans_huge(pmd[i])) { +- if (arch_has_hw_nonleaf_pmd_young() && +- get_cap(LRU_GEN_NONLEAF_YOUNG)) ++ if (arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG)) + pmdp_test_and_clear_young(vma, addr, pmd + i); + goto next; + } +@@ -4053,12 +4055,11 @@ static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area + arch_leave_lazy_mmu_mode(); + spin_unlock(ptl); + done: +- *start = -1; +- bitmap_zero(bitmap, MIN_LRU_BATCH); ++ *first = -1; + } + #else +-static void walk_pmd_range_locked(pud_t *pud, unsigned long next, struct vm_area_struct *vma, +- struct mm_walk *args, unsigned long *bitmap, unsigned long *start) ++static void walk_pmd_range_locked(pud_t *pud, unsigned long addr, struct vm_area_struct *vma, ++ struct mm_walk *args, unsigned long *bitmap, unsigned long *first) + { + } + #endif +@@ -4071,9 +4072,9 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end, + unsigned long next; + unsigned long addr; + struct vm_area_struct *vma; +- unsigned long pos = -1; ++ unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)]; ++ unsigned long first = -1; + struct lru_gen_mm_walk *walk = args->private; +- unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; + + VM_WARN_ON_ONCE(pud_leaf(*pud)); + +@@ -4115,18 +4116,17 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end, + if (pfn < pgdat->node_start_pfn || pfn >= pgdat_end_pfn(pgdat)) + continue; + +- walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); ++ walk_pmd_range_locked(pud, addr, vma, args, bitmap, &first); + continue; + } + #endif + walk->mm_stats[MM_NONLEAF_TOTAL]++; + +- if (arch_has_hw_nonleaf_pmd_young() && +- get_cap(LRU_GEN_NONLEAF_YOUNG)) { ++ if (arch_has_hw_nonleaf_pmd_young() && get_cap(LRU_GEN_NONLEAF_YOUNG)) { + if (!pmd_young(val)) + continue; + +- walk_pmd_range_locked(pud, addr, vma, args, bitmap, &pos); ++ walk_pmd_range_locked(pud, addr, vma, args, bitmap, &first); + } + + if (!walk->force_scan && !test_bloom_filter(walk->lruvec, walk->max_seq, pmd + i)) +@@ -4143,7 +4143,7 @@ static void walk_pmd_range(pud_t *pud, unsigned long start, unsigned long end, + update_bloom_filter(walk->lruvec, walk->max_seq + 1, pmd + i); + } + +- walk_pmd_range_locked(pud, -1, vma, args, bitmap, &pos); ++ walk_pmd_range_locked(pud, -1, vma, args, bitmap, &first); + + if (i < PTRS_PER_PMD && get_next_vma(PUD_MASK, PMD_SIZE, args, &start, &end)) + goto restart; +-- +2.40.1 + diff --git a/target/linux/generic/backport-6.1/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch b/target/linux/generic/backport-6.1/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch new file mode 100644 index 00000000000..caee6b096f1 --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.3-18-UPSTREAM-mm-multi-gen-LRU-simplify-lru_gen_look_arou.patch @@ -0,0 +1,153 @@ +From e604c3ccb4dfbdde2467fccef9bb36170a392695 Mon Sep 17 00:00:00 2001 +From: "T.J. Alumbaugh" +Date: Wed, 18 Jan 2023 00:18:27 +0000 +Subject: [PATCH 18/19] UPSTREAM: mm: multi-gen LRU: simplify + lru_gen_look_around() + +Update the folio generation in place with or without +current->reclaim_state->mm_walk. The LRU lock is held for longer, if +mm_walk is NULL and the number of folios to update is more than +PAGEVEC_SIZE. + +This causes a measurable regression from the LRU lock contention during a +microbencmark. But a tiny regression is not worth the complexity. + +Link: https://lkml.kernel.org/r/20230118001827.1040870-8-talumbau@google.com +Change-Id: I9ce18b4f4062e6c1c13c98ece9422478eb8e1846 +Signed-off-by: T.J. Alumbaugh +Cc: Yu Zhao +Signed-off-by: Andrew Morton +(cherry picked from commit abf086721a2f1e6897c57796f7268df1b194c750) +Bug: 274865848 +Signed-off-by: T.J. Mercier +--- + mm/vmscan.c | 73 +++++++++++++++++------------------------------------ + 1 file changed, 23 insertions(+), 50 deletions(-) + +diff --git a/mm/vmscan.c b/mm/vmscan.c +index 8f496c2e670a9..f6ce7a1fd78a3 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -4571,13 +4571,12 @@ static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_control *sc) + void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) + { + int i; +- pte_t *pte; + unsigned long start; + unsigned long end; +- unsigned long addr; + struct lru_gen_mm_walk *walk; + int young = 0; +- unsigned long bitmap[BITS_TO_LONGS(MIN_LRU_BATCH)] = {}; ++ pte_t *pte = pvmw->pte; ++ unsigned long addr = pvmw->address; + struct folio *folio = pfn_folio(pvmw->pfn); + struct mem_cgroup *memcg = folio_memcg(folio); + struct pglist_data *pgdat = folio_pgdat(folio); +@@ -4594,25 +4593,28 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) + /* avoid taking the LRU lock under the PTL when possible */ + walk = current->reclaim_state ? current->reclaim_state->mm_walk : NULL; + +- start = max(pvmw->address & PMD_MASK, pvmw->vma->vm_start); +- end = min(pvmw->address | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; ++ start = max(addr & PMD_MASK, pvmw->vma->vm_start); ++ end = min(addr | ~PMD_MASK, pvmw->vma->vm_end - 1) + 1; + + if (end - start > MIN_LRU_BATCH * PAGE_SIZE) { +- if (pvmw->address - start < MIN_LRU_BATCH * PAGE_SIZE / 2) ++ if (addr - start < MIN_LRU_BATCH * PAGE_SIZE / 2) + end = start + MIN_LRU_BATCH * PAGE_SIZE; +- else if (end - pvmw->address < MIN_LRU_BATCH * PAGE_SIZE / 2) ++ else if (end - addr < MIN_LRU_BATCH * PAGE_SIZE / 2) + start = end - MIN_LRU_BATCH * PAGE_SIZE; + else { +- start = pvmw->address - MIN_LRU_BATCH * PAGE_SIZE / 2; +- end = pvmw->address + MIN_LRU_BATCH * PAGE_SIZE / 2; ++ start = addr - MIN_LRU_BATCH * PAGE_SIZE / 2; ++ end = addr + MIN_LRU_BATCH * PAGE_SIZE / 2; + } + } + +- pte = pvmw->pte - (pvmw->address - start) / PAGE_SIZE; ++ /* folio_update_gen() requires stable folio_memcg() */ ++ if (!mem_cgroup_trylock_pages(memcg)) ++ return; + +- rcu_read_lock(); + arch_enter_lazy_mmu_mode(); + ++ pte -= (addr - start) / PAGE_SIZE; ++ + for (i = 0, addr = start; addr != end; i++, addr += PAGE_SIZE) { + unsigned long pfn; + +@@ -4637,56 +4639,27 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw) + !folio_test_swapcache(folio))) + folio_mark_dirty(folio); + ++ if (walk) { ++ old_gen = folio_update_gen(folio, new_gen); ++ if (old_gen >= 0 && old_gen != new_gen) ++ update_batch_size(walk, folio, old_gen, new_gen); ++ ++ continue; ++ } ++ + old_gen = folio_lru_gen(folio); + if (old_gen < 0) + folio_set_referenced(folio); + else if (old_gen != new_gen) +- __set_bit(i, bitmap); ++ folio_activate(folio); + } + + arch_leave_lazy_mmu_mode(); +- rcu_read_unlock(); ++ mem_cgroup_unlock_pages(); + + /* feedback from rmap walkers to page table walkers */ + if (suitable_to_scan(i, young)) + update_bloom_filter(lruvec, max_seq, pvmw->pmd); +- +- if (!walk && bitmap_weight(bitmap, MIN_LRU_BATCH) < PAGEVEC_SIZE) { +- for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { +- folio = pfn_folio(pte_pfn(pte[i])); +- folio_activate(folio); +- } +- return; +- } +- +- /* folio_update_gen() requires stable folio_memcg() */ +- if (!mem_cgroup_trylock_pages(memcg)) +- return; +- +- if (!walk) { +- spin_lock_irq(&lruvec->lru_lock); +- new_gen = lru_gen_from_seq(lruvec->lrugen.max_seq); +- } +- +- for_each_set_bit(i, bitmap, MIN_LRU_BATCH) { +- folio = pfn_folio(pte_pfn(pte[i])); +- if (folio_memcg_rcu(folio) != memcg) +- continue; +- +- old_gen = folio_update_gen(folio, new_gen); +- if (old_gen < 0 || old_gen == new_gen) +- continue; +- +- if (walk) +- update_batch_size(walk, folio, old_gen, new_gen); +- else +- lru_gen_update_size(lruvec, folio, old_gen, new_gen); +- } +- +- if (!walk) +- spin_unlock_irq(&lruvec->lru_lock); +- +- mem_cgroup_unlock_pages(); + } + + /****************************************************************************** +-- +2.40.1 + From ae8db3941ce90f4b00dfeb36a428425cdc53144d Mon Sep 17 00:00:00 2001 From: Kazuki Hashimoto Date: Wed, 24 May 2023 23:58:03 +0900 Subject: [PATCH 42/43] kernel: Backport MGLRU patch from 6.4 This fixes a bug where the reclaim path could occasionally have long tail latency. Signed-off-by: Kazuki Hashimoto --- ...i-gen-LRU-remove-wait_event_killable.patch | 266 +++++++++++++++++ ...i-gen-LRU-remove-wait_event_killable.patch | 280 ++++++++++++++++++ 2 files changed, 546 insertions(+) create mode 100644 target/linux/generic/backport-5.15/021-v6.4-mm-Multi-gen-LRU-remove-wait_event_killable.patch create mode 100644 target/linux/generic/backport-6.1/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch diff --git a/target/linux/generic/backport-5.15/021-v6.4-mm-Multi-gen-LRU-remove-wait_event_killable.patch b/target/linux/generic/backport-5.15/021-v6.4-mm-Multi-gen-LRU-remove-wait_event_killable.patch new file mode 100644 index 00000000000..e154494a51e --- /dev/null +++ b/target/linux/generic/backport-5.15/021-v6.4-mm-Multi-gen-LRU-remove-wait_event_killable.patch @@ -0,0 +1,266 @@ +From 087ed25eaf5a78a678508e893f80addab9b1c103 Mon Sep 17 00:00:00 2001 +From: Kalesh Singh +Date: Thu, 13 Apr 2023 14:43:26 -0700 +Subject: [PATCH] mm: Multi-gen LRU: remove wait_event_killable() + +Android 14 and later default to MGLRU [1] and field telemetry showed +occasional long tail latency (>100ms) in the reclaim path. + +Tracing revealed priority inversion in the reclaim path. In +try_to_inc_max_seq(), when high priority tasks were blocked on +wait_event_killable(), the preemption of the low priority task to call +wake_up_all() caused those high priority tasks to wait longer than +necessary. In general, this problem is not different from others of its +kind, e.g., one caused by mutex_lock(). However, it is specific to MGLRU +because it introduced the new wait queue lruvec->mm_state.wait. + +The purpose of this new wait queue is to avoid the thundering herd +problem. If many direct reclaimers rush into try_to_inc_max_seq(), only +one can succeed, i.e., the one to wake up the rest, and the rest who +failed might cause premature OOM kills if they do not wait. So far there +is no evidence supporting this scenario, based on how often the wait has +been hit. And this begs the question how useful the wait queue is in +practice. + +Based on Minchan's recommendation, which is in line with his commit +6d4675e60135 ("mm: don't be stuck to rmap lock on reclaim path") and the +rest of the MGLRU code which also uses trylock when possible, remove the +wait queue. + +[1] https://android-review.googlesource.com/q/I7ed7fbfd6ef9ce10053347528125dd98c39e50bf + +Link: https://lkml.kernel.org/r/20230413214326.2147568-1-kaleshsingh@google.com +Fixes: bd74fdaea146 ("mm: multi-gen LRU: support page table walks") +Change-Id: I911f3968fd1adb25171279cc5b6f48ccb7efc8de +Signed-off-by: Kalesh Singh +Suggested-by: Minchan Kim +Reported-by: Wei Wang +Acked-by: Yu Zhao +Cc: Minchan Kim +Cc: Jan Alexander Steffens (heftig) +Cc: Oleksandr Natalenko +Cc: Suleiman Souhlal +Cc: Suren Baghdasaryan +Signed-off-by: Andrew Morton +--- + include/linux/mmzone.h | 8 +-- + mm/vmscan.c | 111 +++++++++++++++-------------------------- + 2 files changed, 42 insertions(+), 77 deletions(-) + +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -452,18 +452,14 @@ enum { + struct lru_gen_mm_state { + /* set to max_seq after each iteration */ + unsigned long seq; +- /* where the current iteration continues (inclusive) */ ++ /* where the current iteration continues after */ + struct list_head *head; +- /* where the last iteration ended (exclusive) */ ++ /* where the last iteration ended before */ + struct list_head *tail; +- /* to wait for the last page table walker to finish */ +- struct wait_queue_head wait; + /* Bloom filters flip after each iteration */ + unsigned long *filters[NR_BLOOM_FILTERS]; + /* the mm stats for debugging */ + unsigned long stats[NR_HIST_GENS][NR_MM_STATS]; +- /* the number of concurrent page table walkers */ +- int nr_walkers; + }; + + struct lru_gen_mm_walk { +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2999,18 +2999,13 @@ void lru_gen_del_mm(struct mm_struct *mm + if (!lruvec) + continue; + +- /* where the last iteration ended (exclusive) */ ++ /* where the current iteration continues after */ ++ if (lruvec->mm_state.head == &mm->lru_gen.list) ++ lruvec->mm_state.head = lruvec->mm_state.head->prev; ++ ++ /* where the last iteration ended before */ + if (lruvec->mm_state.tail == &mm->lru_gen.list) + lruvec->mm_state.tail = lruvec->mm_state.tail->next; +- +- /* where the current iteration continues (inclusive) */ +- if (lruvec->mm_state.head != &mm->lru_gen.list) +- continue; +- +- lruvec->mm_state.head = lruvec->mm_state.head->next; +- /* the deletion ends the current iteration */ +- if (lruvec->mm_state.head == &mm_list->fifo) +- WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1); + } + + list_del_init(&mm->lru_gen.list); +@@ -3194,68 +3189,54 @@ static bool iterate_mm_list(struct lruve + struct mm_struct **iter) + { + bool first = false; +- bool last = true; ++ bool last = false; + struct mm_struct *mm = NULL; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct lru_gen_mm_list *mm_list = get_mm_list(memcg); + struct lru_gen_mm_state *mm_state = &lruvec->mm_state; + + /* +- * There are four interesting cases for this page table walker: +- * 1. It tries to start a new iteration of mm_list with a stale max_seq; +- * there is nothing left to do. +- * 2. It's the first of the current generation, and it needs to reset +- * the Bloom filter for the next generation. +- * 3. It reaches the end of mm_list, and it needs to increment +- * mm_state->seq; the iteration is done. +- * 4. It's the last of the current generation, and it needs to reset the +- * mm stats counters for the next generation. ++ * mm_state->seq is incremented after each iteration of mm_list. There ++ * are three interesting cases for this page table walker: ++ * 1. It tries to start a new iteration with a stale max_seq: there is ++ * nothing left to do. ++ * 2. It started the next iteration: it needs to reset the Bloom filter ++ * so that a fresh set of PTE tables can be recorded. ++ * 3. It ended the current iteration: it needs to reset the mm stats ++ * counters and tell its caller to increment max_seq. + */ + spin_lock(&mm_list->lock); + + VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq); +- VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq); +- VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers); + +- if (walk->max_seq <= mm_state->seq) { +- if (!*iter) +- last = false; ++ if (walk->max_seq <= mm_state->seq) + goto done; +- } + +- if (!mm_state->nr_walkers) { +- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); ++ if (!mm_state->head) ++ mm_state->head = &mm_list->fifo; + +- mm_state->head = mm_list->fifo.next; ++ if (mm_state->head == &mm_list->fifo) + first = true; +- } +- +- while (!mm && mm_state->head != &mm_list->fifo) { +- mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); + ++ do { + mm_state->head = mm_state->head->next; ++ if (mm_state->head == &mm_list->fifo) { ++ WRITE_ONCE(mm_state->seq, mm_state->seq + 1); ++ last = true; ++ break; ++ } + + /* force scan for those added after the last iteration */ +- if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) { +- mm_state->tail = mm_state->head; ++ if (!mm_state->tail || mm_state->tail == mm_state->head) { ++ mm_state->tail = mm_state->head->next; + walk->force_scan = true; + } + ++ mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); + if (should_skip_mm(mm, walk)) + mm = NULL; +- } +- +- if (mm_state->head == &mm_list->fifo) +- WRITE_ONCE(mm_state->seq, mm_state->seq + 1); ++ } while (!mm); + done: +- if (*iter && !mm) +- mm_state->nr_walkers--; +- if (!*iter && mm) +- mm_state->nr_walkers++; +- +- if (mm_state->nr_walkers) +- last = false; +- + if (*iter || last) + reset_mm_stats(lruvec, walk, last); + +@@ -3283,9 +3264,9 @@ static bool iterate_mm_list_nowalk(struc + + VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq); + +- if (max_seq > mm_state->seq && !mm_state->nr_walkers) { +- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); +- ++ if (max_seq > mm_state->seq) { ++ mm_state->head = NULL; ++ mm_state->tail = NULL; + WRITE_ONCE(mm_state->seq, mm_state->seq + 1); + reset_mm_stats(lruvec, NULL, true); + success = true; +@@ -3894,10 +3875,6 @@ restart: + + walk_pmd_range(&val, addr, next, args); + +- /* a racy check to curtail the waiting time */ +- if (wq_has_sleeper(&walk->lruvec->mm_state.wait)) +- return 1; +- + if (need_resched() || walk->batched >= MAX_LRU_BATCH) { + end = (addr | ~PUD_MASK) + 1; + goto done; +@@ -3930,8 +3907,14 @@ static void walk_mm(struct lruvec *lruve + walk->next_addr = FIRST_USER_ADDRESS; + + do { ++ DEFINE_MAX_SEQ(lruvec); ++ + err = -EBUSY; + ++ /* another thread might have called inc_max_seq() */ ++ if (walk->max_seq != max_seq) ++ break; ++ + /* page_update_gen() requires stable page_memcg() */ + if (!mem_cgroup_trylock_pages(memcg)) + break; +@@ -4164,25 +4147,12 @@ static bool try_to_inc_max_seq(struct lr + success = iterate_mm_list(lruvec, walk, &mm); + if (mm) + walk_mm(lruvec, mm, walk); +- +- cond_resched(); + } while (mm); + done: +- if (!success) { +- if (sc->priority <= DEF_PRIORITY - 2) +- wait_event_killable(lruvec->mm_state.wait, +- max_seq < READ_ONCE(lrugen->max_seq)); +- return false; +- } ++ if (success) ++ inc_max_seq(lruvec, can_swap, force_scan); + +- VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); +- +- inc_max_seq(lruvec, can_swap, force_scan); +- /* either this sees any waiters or they will see updated max_seq */ +- if (wq_has_sleeper(&lruvec->mm_state.wait)) +- wake_up_all(&lruvec->mm_state.wait); +- +- return true; ++ return success; + } + + static bool lruvec_is_sizable(struct lruvec *lruvec, struct scan_control *sc) +@@ -5746,7 +5716,6 @@ void lru_gen_init_lruvec(struct lruvec * + INIT_LIST_HEAD(&lrugen->pages[gen][type][zone]); + + lruvec->mm_state.seq = MIN_NR_GENS; +- init_waitqueue_head(&lruvec->mm_state.wait); + } + + #ifdef CONFIG_MEMCG diff --git a/target/linux/generic/backport-6.1/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch b/target/linux/generic/backport-6.1/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch new file mode 100644 index 00000000000..4bf796c93d2 --- /dev/null +++ b/target/linux/generic/backport-6.1/020-v6.4-19-mm-Multi-gen-LRU-remove-wait_event_killable.patch @@ -0,0 +1,280 @@ +From 418038c22452df38cde519cc8c662bb15139764a Mon Sep 17 00:00:00 2001 +From: Kalesh Singh +Date: Thu, 13 Apr 2023 14:43:26 -0700 +Subject: [PATCH 19/19] mm: Multi-gen LRU: remove wait_event_killable() + +Android 14 and later default to MGLRU [1] and field telemetry showed +occasional long tail latency (>100ms) in the reclaim path. + +Tracing revealed priority inversion in the reclaim path. In +try_to_inc_max_seq(), when high priority tasks were blocked on +wait_event_killable(), the preemption of the low priority task to call +wake_up_all() caused those high priority tasks to wait longer than +necessary. In general, this problem is not different from others of its +kind, e.g., one caused by mutex_lock(). However, it is specific to MGLRU +because it introduced the new wait queue lruvec->mm_state.wait. + +The purpose of this new wait queue is to avoid the thundering herd +problem. If many direct reclaimers rush into try_to_inc_max_seq(), only +one can succeed, i.e., the one to wake up the rest, and the rest who +failed might cause premature OOM kills if they do not wait. So far there +is no evidence supporting this scenario, based on how often the wait has +been hit. And this begs the question how useful the wait queue is in +practice. + +Based on Minchan's recommendation, which is in line with his commit +6d4675e60135 ("mm: don't be stuck to rmap lock on reclaim path") and the +rest of the MGLRU code which also uses trylock when possible, remove the +wait queue. + +[1] https://android-review.googlesource.com/q/I7ed7fbfd6ef9ce10053347528125dd98c39e50bf + +Link: https://lkml.kernel.org/r/20230413214326.2147568-1-kaleshsingh@google.com +Fixes: bd74fdaea146 ("mm: multi-gen LRU: support page table walks") +Signed-off-by: Kalesh Singh +Suggested-by: Minchan Kim +Reported-by: Wei Wang +Acked-by: Yu Zhao +Cc: Minchan Kim +Cc: Jan Alexander Steffens (heftig) +Cc: Oleksandr Natalenko +Cc: Suleiman Souhlal +Cc: Suren Baghdasaryan +Signed-off-by: Andrew Morton +--- + include/linux/mmzone.h | 8 +-- + mm/vmscan.c | 112 +++++++++++++++-------------------------- + 2 files changed, 42 insertions(+), 78 deletions(-) + +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index 403c7461e7a70..d62a5accf1be4 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -453,18 +453,14 @@ enum { + struct lru_gen_mm_state { + /* set to max_seq after each iteration */ + unsigned long seq; +- /* where the current iteration continues (inclusive) */ ++ /* where the current iteration continues after */ + struct list_head *head; +- /* where the last iteration ended (exclusive) */ ++ /* where the last iteration ended before */ + struct list_head *tail; +- /* to wait for the last page table walker to finish */ +- struct wait_queue_head wait; + /* Bloom filters flip after each iteration */ + unsigned long *filters[NR_BLOOM_FILTERS]; + /* the mm stats for debugging */ + unsigned long stats[NR_HIST_GENS][NR_MM_STATS]; +- /* the number of concurrent page table walkers */ +- int nr_walkers; + }; + + struct lru_gen_mm_walk { +diff --git a/mm/vmscan.c b/mm/vmscan.c +index f6ce7a1fd78a3..851758303dbf4 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -3371,18 +3371,13 @@ void lru_gen_del_mm(struct mm_struct *mm) + if (!lruvec) + continue; + +- /* where the last iteration ended (exclusive) */ ++ /* where the current iteration continues after */ ++ if (lruvec->mm_state.head == &mm->lru_gen.list) ++ lruvec->mm_state.head = lruvec->mm_state.head->prev; ++ ++ /* where the last iteration ended before */ + if (lruvec->mm_state.tail == &mm->lru_gen.list) + lruvec->mm_state.tail = lruvec->mm_state.tail->next; +- +- /* where the current iteration continues (inclusive) */ +- if (lruvec->mm_state.head != &mm->lru_gen.list) +- continue; +- +- lruvec->mm_state.head = lruvec->mm_state.head->next; +- /* the deletion ends the current iteration */ +- if (lruvec->mm_state.head == &mm_list->fifo) +- WRITE_ONCE(lruvec->mm_state.seq, lruvec->mm_state.seq + 1); + } + + list_del_init(&mm->lru_gen.list); +@@ -3478,68 +3473,54 @@ static bool iterate_mm_list(struct lruvec *lruvec, struct lru_gen_mm_walk *walk, + struct mm_struct **iter) + { + bool first = false; +- bool last = true; ++ bool last = false; + struct mm_struct *mm = NULL; + struct mem_cgroup *memcg = lruvec_memcg(lruvec); + struct lru_gen_mm_list *mm_list = get_mm_list(memcg); + struct lru_gen_mm_state *mm_state = &lruvec->mm_state; + + /* +- * There are four interesting cases for this page table walker: +- * 1. It tries to start a new iteration of mm_list with a stale max_seq; +- * there is nothing left to do. +- * 2. It's the first of the current generation, and it needs to reset +- * the Bloom filter for the next generation. +- * 3. It reaches the end of mm_list, and it needs to increment +- * mm_state->seq; the iteration is done. +- * 4. It's the last of the current generation, and it needs to reset the +- * mm stats counters for the next generation. ++ * mm_state->seq is incremented after each iteration of mm_list. There ++ * are three interesting cases for this page table walker: ++ * 1. It tries to start a new iteration with a stale max_seq: there is ++ * nothing left to do. ++ * 2. It started the next iteration: it needs to reset the Bloom filter ++ * so that a fresh set of PTE tables can be recorded. ++ * 3. It ended the current iteration: it needs to reset the mm stats ++ * counters and tell its caller to increment max_seq. + */ + spin_lock(&mm_list->lock); + + VM_WARN_ON_ONCE(mm_state->seq + 1 < walk->max_seq); +- VM_WARN_ON_ONCE(*iter && mm_state->seq > walk->max_seq); +- VM_WARN_ON_ONCE(*iter && !mm_state->nr_walkers); + +- if (walk->max_seq <= mm_state->seq) { +- if (!*iter) +- last = false; ++ if (walk->max_seq <= mm_state->seq) + goto done; +- } + +- if (!mm_state->nr_walkers) { +- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); ++ if (!mm_state->head) ++ mm_state->head = &mm_list->fifo; + +- mm_state->head = mm_list->fifo.next; ++ if (mm_state->head == &mm_list->fifo) + first = true; +- } +- +- while (!mm && mm_state->head != &mm_list->fifo) { +- mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); + ++ do { + mm_state->head = mm_state->head->next; ++ if (mm_state->head == &mm_list->fifo) { ++ WRITE_ONCE(mm_state->seq, mm_state->seq + 1); ++ last = true; ++ break; ++ } + + /* force scan for those added after the last iteration */ +- if (!mm_state->tail || mm_state->tail == &mm->lru_gen.list) { +- mm_state->tail = mm_state->head; ++ if (!mm_state->tail || mm_state->tail == mm_state->head) { ++ mm_state->tail = mm_state->head->next; + walk->force_scan = true; + } + ++ mm = list_entry(mm_state->head, struct mm_struct, lru_gen.list); + if (should_skip_mm(mm, walk)) + mm = NULL; +- } +- +- if (mm_state->head == &mm_list->fifo) +- WRITE_ONCE(mm_state->seq, mm_state->seq + 1); ++ } while (!mm); + done: +- if (*iter && !mm) +- mm_state->nr_walkers--; +- if (!*iter && mm) +- mm_state->nr_walkers++; +- +- if (mm_state->nr_walkers) +- last = false; +- + if (*iter || last) + reset_mm_stats(lruvec, walk, last); + +@@ -3567,9 +3548,9 @@ static bool iterate_mm_list_nowalk(struct lruvec *lruvec, unsigned long max_seq) + + VM_WARN_ON_ONCE(mm_state->seq + 1 < max_seq); + +- if (max_seq > mm_state->seq && !mm_state->nr_walkers) { +- VM_WARN_ON_ONCE(mm_state->head && mm_state->head != &mm_list->fifo); +- ++ if (max_seq > mm_state->seq) { ++ mm_state->head = NULL; ++ mm_state->tail = NULL; + WRITE_ONCE(mm_state->seq, mm_state->seq + 1); + reset_mm_stats(lruvec, NULL, true); + success = true; +@@ -4172,10 +4153,6 @@ static int walk_pud_range(p4d_t *p4d, unsigned long start, unsigned long end, + + walk_pmd_range(&val, addr, next, args); + +- /* a racy check to curtail the waiting time */ +- if (wq_has_sleeper(&walk->lruvec->mm_state.wait)) +- return 1; +- + if (need_resched() || walk->batched >= MAX_LRU_BATCH) { + end = (addr | ~PUD_MASK) + 1; + goto done; +@@ -4208,8 +4185,14 @@ static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_ + walk->next_addr = FIRST_USER_ADDRESS; + + do { ++ DEFINE_MAX_SEQ(lruvec); ++ + err = -EBUSY; + ++ /* another thread might have called inc_max_seq() */ ++ if (walk->max_seq != max_seq) ++ break; ++ + /* folio_update_gen() requires stable folio_memcg() */ + if (!mem_cgroup_trylock_pages(memcg)) + break; +@@ -4442,25 +4425,12 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq, + success = iterate_mm_list(lruvec, walk, &mm); + if (mm) + walk_mm(lruvec, mm, walk); +- +- cond_resched(); + } while (mm); + done: +- if (!success) { +- if (sc->priority <= DEF_PRIORITY - 2) +- wait_event_killable(lruvec->mm_state.wait, +- max_seq < READ_ONCE(lrugen->max_seq)); +- return false; +- } ++ if (success) ++ inc_max_seq(lruvec, can_swap, force_scan); + +- VM_WARN_ON_ONCE(max_seq != READ_ONCE(lrugen->max_seq)); +- +- inc_max_seq(lruvec, can_swap, force_scan); +- /* either this sees any waiters or they will see updated max_seq */ +- if (wq_has_sleeper(&lruvec->mm_state.wait)) +- wake_up_all(&lruvec->mm_state.wait); +- +- return true; ++ return success; + } + + /****************************************************************************** +@@ -6105,7 +6075,6 @@ void lru_gen_init_lruvec(struct lruvec *lruvec) + INIT_LIST_HEAD(&lrugen->folios[gen][type][zone]); + + lruvec->mm_state.seq = MIN_NR_GENS; +- init_waitqueue_head(&lruvec->mm_state.wait); + } + + #ifdef CONFIG_MEMCG +@@ -6138,7 +6107,6 @@ void lru_gen_exit_memcg(struct mem_cgroup *memcg) + for_each_node(nid) { + struct lruvec *lruvec = get_lruvec(memcg, nid); + +- VM_WARN_ON_ONCE(lruvec->mm_state.nr_walkers); + VM_WARN_ON_ONCE(memchr_inv(lruvec->lrugen.nr_pages, 0, + sizeof(lruvec->lrugen.nr_pages))); + +-- +2.40.1 + From f2e1d373817c05aa9feac7fd67262010b4064d23 Mon Sep 17 00:00:00 2001 From: Andrzej Mialkowski Date: Fri, 19 May 2023 04:09:54 -0700 Subject: [PATCH 43/43] ipq806x: Add support for Netgear Nighthawk Pro Gaming XR450 Motivation: Firmware with platform ID "XR450" required for easy installation. Manufacturer pages: Product page: https://www.netgear.com/support/product/xr450 Product Data Sheet: https://www.netgear.com/images/datasheet/networking/wifirouter/XR450.pdf Current firmware: https://www.downloads.netgear.com/files/GDC/XR450/XR450-V2.3.2.134.zip Specifications: Almost identical to Netgear XR500(https://openwrt.org/toh/hwdata/netgear/netgear_xr500) Differences: Platform ID: XR450, utilized for firmware validation WLAN 2.4GHz: b/g/n Supports QAM64 (XR500 QAM256) SoC: Qualcomm Atheros IPQ8065 RAM: 512 MB Storage: 256 MiB Wireless: Qualcomm Atheros QCA9984 Switch: Qualcomm Atheros AR8337 rev. 2 Ethernet: 5x 1000/100/10 USB: 2x 3.0 Install via WEB GUI (recommended): 1. Navigate within GUI to firmware update section 2. Select openwrt-ipq806x-netgear_xr450-squashfs-factory.img 3. Dismiss downgrade warning Install via TFTP recovery (same as XR500/R7800): 1. Configure host PC to use static address 192.168.1.10 https://openwrt.org/toh/netgear/r7800#prerequisites_for_tftp_flashing 2. Flash openwrt-ipq806x-netgear_xr450-squashfs-factory.img using procedure https://openwrt.org/toh/netgear/r7800#tftp_flashing_process Revert to stock firmware 1. Download current manufacturer firmware, decompress zip file to obtain img file 2. Use TFTP recovery method flash img file (currently XR450-V2.3.2.134.img) ipq806x: add support to netgear_xr450 Signed-off-by: Andrzej Mialkowski --- .../ipq806x/base-files/etc/board.d/01_leds | 1 + .../ipq806x/base-files/etc/board.d/02_network | 1 + .../base-files/lib/upgrade/platform.sh | 1 + .../arch/arm/boot/dts/qcom-ipq8065-xr450.dts | 50 +++++++++++++++++++ target/linux/ipq806x/image/generic.mk | 14 ++++++ 5 files changed, 67 insertions(+) create mode 100644 target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8065-xr450.dts diff --git a/target/linux/ipq806x/base-files/etc/board.d/01_leds b/target/linux/ipq806x/base-files/etc/board.d/01_leds index 82ca270dd6b..d4d40bd6463 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/01_leds +++ b/target/linux/ipq806x/base-files/etc/board.d/01_leds @@ -37,6 +37,7 @@ netgear,d7800 |\ netgear,r7500 |\ netgear,r7500v2 |\ netgear,r7800 |\ +netgear,xr450 |\ netgear,xr500) ucidef_set_led_usbport "usb1" "USB 1" "white:usb1" "usb1-port1" "usb2-port1" ucidef_set_led_usbport "usb2" "USB 2" "white:usb2" "usb3-port1" "usb4-port1" diff --git a/target/linux/ipq806x/base-files/etc/board.d/02_network b/target/linux/ipq806x/base-files/etc/board.d/02_network index 8dd52452b17..70812a1013c 100644 --- a/target/linux/ipq806x/base-files/etc/board.d/02_network +++ b/target/linux/ipq806x/base-files/etc/board.d/02_network @@ -59,6 +59,7 @@ nec,wg2600hp3) "2:lan" "3:lan" "4:lan" "5:lan" "0@eth1" "1:wan" "6@eth0" ;; netgear,r7800 |\ +netgear,xr450 |\ netgear,xr500 |\ tplink,c2600 |\ tplink,vr2600v) diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh index 5ec4f513bd3..108b0b76307 100644 --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh @@ -17,6 +17,7 @@ platform_do_upgrade() { netgear,r7500 |\ netgear,r7500v2 |\ netgear,r7800 |\ + netgear,xr450 |\ netgear,xr500 |\ nokia,ac400i |\ qcom,ipq8064-ap148 |\ diff --git a/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8065-xr450.dts b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8065-xr450.dts new file mode 100644 index 00000000000..4353aec7ac0 --- /dev/null +++ b/target/linux/ipq806x/files-5.15/arch/arm/boot/dts/qcom-ipq8065-xr450.dts @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "qcom-ipq8065-nighthawk.dtsi" + +/ { + model = "Netgear Nighthawk XR450"; + compatible = "netgear,xr450", "qcom,ipq8065", "qcom,ipq8064"; + +}; + +&leds { + usb1 { + label = "white:usb1"; + gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>; + }; + + usb2 { + label = "white:usb2"; + gpios = <&qcom_pinmux 26 GPIO_ACTIVE_HIGH>; + }; +}; + +&partitions { + partition@1880000 { + label = "ubi"; + reg = <0x1880000 0xce00000>; + }; + + partition@e680000 { + label = "reserve"; + reg = <0xe680000 0x0780000>; + read-only; + }; +}; + +&wifi0 { + nvmem-cells = <&macaddr_art_c>, <&precal_art_1000>; + nvmem-cell-names = "mac-address", "pre-calibration"; +}; + +&wifi1 { + nvmem-cells = <&macaddr_art_0>, <&precal_art_5000>; + nvmem-cell-names = "mac-address", "pre-calibration"; +}; + +&art { + macaddr_art_c: macaddr@c { + reg = <0xc 0x6>; + }; +}; diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk index b83999dd00e..7ed2b808473 100644 --- a/target/linux/ipq806x/image/generic.mk +++ b/target/linux/ipq806x/image/generic.mk @@ -320,6 +320,20 @@ define Device/netgear_r7800 endef TARGET_DEVICES += netgear_r7800 +define Device/netgear_xr450 + $(call Device/DniImage) + DEVICE_VENDOR := NETGEAR + DEVICE_MODEL := Nighthawk XR450 + SOC := qcom-ipq8065 + KERNEL_SIZE := 4096k + NETGEAR_BOARD_ID := XR450 + NETGEAR_HW_ID := 29764958+0+256+512+4x4+4x4+cascade + BLOCKSIZE := 128k + PAGESIZE := 2048 + DEVICE_PACKAGES := ath10k-firmware-qca9984-ct kmod-ramoops +endef +TARGET_DEVICES += netgear_xr450 + define Device/netgear_xr500 $(call Device/DniImage) DEVICE_VENDOR := NETGEAR